Page MenuHomePhabricator

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
This document is not UTF8. It was detected as ISO-8859-1 (Latin 1) and converted to UTF8 for display.
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000..907841c668
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+*~
+CMakeLists.txt.user*
diff --git a/Applications/PluginGenerator/CMakeLists.txt b/Applications/PluginGenerator/CMakeLists.txt
index 0106f4fdcb..9dcb1ba2a4 100644
--- a/Applications/PluginGenerator/CMakeLists.txt
+++ b/Applications/PluginGenerator/CMakeLists.txt
@@ -1,70 +1,76 @@
cmake_minimum_required(VERSION 2.8.4)
project(MITKPluginGenerator)
set(VERSION_MAJOR 1)
-set(VERSION_MINOR 0)
-set(VERSION_PATCH 0)
+set(VERSION_MINOR 1)
+set(VERSION_PATCH 1)
+
+set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
set(standalone_build 1)
else()
set(standalone_build 0)
endif()
#-----------------------------------------------------------------------------
# Prerequesites
#-----------------------------------------------------------------------------
set(QT_DONT_USE_QTGUI 1)
find_package(Qt 4.6.2 REQUIRED)
include(${QT_USE_FILE})
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/PluginGeneratorConfig.h.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/PluginGeneratorConfig.h" @ONLY)
+include_directories("${CMAKE_CURRENT_BINARY_DIR}")
+
#-----------------------------------------------------------------------------
# Executable
#-----------------------------------------------------------------------------
set(src_files
PluginGenerator.cpp
ctkCommandLineParser.cpp
)
qt4_wrap_cpp(src_files ctkCommandLineParser.h)
qt4_add_resources(src_files plugin_template.qrc project_template.qrc)
set(exec_target ${PROJECT_NAME})
add_executable(${exec_target} ${src_files})
target_link_libraries(${exec_target} ${QT_LIBRARIES})
if(NOT standalone_build)
# subproject support
add_dependencies(MITK-CoreUI ${exec_target})
endif()
#-----------------------------------------------------------------------------
# Win32 Convenience
#-----------------------------------------------------------------------------
if(WIN32 AND NOT standalone_build)
file(TO_NATIVE_PATH "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}" native_runtime_dir)
add_custom_target(NewPlugin start "MITK PluginGenerator" /D "${native_runtime_dir}" cmd /K ${exec_target}.exe -h
DEPENDS ${exec_target})
endif()
#-----------------------------------------------------------------------------
# Testing
#-----------------------------------------------------------------------------
if(NOT standalone_build)
# Test the plugin generator
include(mitkTestPluginGenerator)
endif()
#-----------------------------------------------------------------------------
# Packaging support
#-----------------------------------------------------------------------------
if(standalone_build)
include(SetupPackaging.cmake)
endif()
diff --git a/Applications/PluginGenerator/Changelog.txt b/Applications/PluginGenerator/Changelog.txt
new file mode 100644
index 0000000000..383b22c38e
--- /dev/null
+++ b/Applications/PluginGenerator/Changelog.txt
@@ -0,0 +1,18 @@
+This is the change log for the MITK Plugin Generator
+
+
+Changes since version 1.0.0
+======================================================================
+
+Changes in the MITKPluginGenerator executable
+----------------------------------------------------------------------
+
+- Added printing the version number to the console.
+- Added hint how to get more help if something went wrong.
+
+Changes in the generated files
+----------------------------------------------------------------------
+
+- Fixed user manual for the generated plugin.
+- Added comments in the generated project's CMakeLists.txt file about
+ how to set-up the MITK module system.
diff --git a/Applications/PluginGenerator/PluginGenerator.cpp b/Applications/PluginGenerator/PluginGenerator.cpp
index 7663f9b7d1..326f548ecb 100644
--- a/Applications/PluginGenerator/PluginGenerator.cpp
+++ b/Applications/PluginGenerator/PluginGenerator.cpp
@@ -1,402 +1,407 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/ for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "ctkCommandLineParser.h"
+#include <PluginGeneratorConfig.h>
#include <QCoreApplication>
#include <QTextStream>
#include <QDebug>
#include <QFile>
#include <QDir>
#include <cstdlib>
#include <iostream>
#include <limits>
#include <cctype>
bool readAnswer(char defaultAnswer)
{
std::string line;
std::cin >> std::noskipws >> line;
// consume the new line character
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
char answer = defaultAnswer;
if (!line.empty() && line[0] != '\n')
{
answer = std::tolower(line[0]);
}
if (answer == 'y') return true;
if (answer == 'n') return false;
if (defaultAnswer == 'y') return true;
return false;
}
void createFilePathMapping(const QString& templateName, const QString& baseInDir, const QString& baseOutDir, QHash<QString, QString>& fileNameMapping)
{
QFileInfo info(templateName);
if (info.isDir())
{
QStringList subEntries = QDir(templateName).entryList();
foreach(QString subEntry, subEntries)
{
createFilePathMapping(templateName + "/" + subEntry, baseInDir, baseOutDir, fileNameMapping);
}
return;
}
fileNameMapping[templateName] = QString(templateName).replace(baseInDir, baseOutDir);
}
QHash<QString,QString> createTemplateFileMapping(const QString& qrcBase, const QString& baseOutDir, const QHash<QString, QString>& fileNameMapping)
{
QHash<QString,QString> filePathMapping;
createFilePathMapping(qrcBase, qrcBase, baseOutDir, filePathMapping);
QMutableHashIterator<QString,QString> i(filePathMapping);
while(i.hasNext())
{
i.next();
QHashIterator<QString,QString> j(fileNameMapping);
while(j.hasNext())
{
j.next();
i.setValue(i.value().replace(j.key(), j.value()));
}
}
return filePathMapping;
}
bool generateFiles(const QHash<QString, QString>& parameters,
const QHash<QString, QString>& filePathMapping)
{
QHashIterator<QString,QString> paths(filePathMapping);
while(paths.hasNext())
{
paths.next();
QFile templ(paths.key());
templ.open(QIODevice::ReadOnly);
QByteArray templContent = templ.readAll();
QHashIterator<QString,QString> i(parameters);
while (i.hasNext())
{
i.next();
templContent.replace(i.key(), QByteArray(i.value().toLatin1()));
}
QFile outTempl(paths.value());
QDir dir(QFileInfo(outTempl).dir());
if (!dir.exists())
{
if (!dir.mkpath(dir.absolutePath()))
{
qCritical() << "Could not create directory" << dir.absolutePath();
return EXIT_FAILURE;
}
}
if (!outTempl.open(QIODevice::WriteOnly))
{
qCritical() << outTempl.errorString();
return false;
}
outTempl.write(templContent);
}
return true;
}
int main(int argc, char** argv)
{
+ QString appName("MITKPluginGenerator");
+
QCoreApplication app(argc, argv);
- app.setApplicationName("PluginGenerator");
+ app.setApplicationName(appName);
app.setOrganizationName("DKFZ");
ctkCommandLineParser parser;
// Use Unix-style argument names
parser.setArgumentPrefix("--", "-");
parser.setStrictModeEnabled(true);
// Add command line argument names
parser.addArgument("help", "h", QVariant::Bool, "Show this help text");
parser.addArgument("out-dir", "o", QVariant::String, "Output directory", QDir::tempPath());
parser.addArgument("license", "l", QVariant::String, "Path to a file containing license information", ":/MITKLicense.txt");
parser.addArgument("vendor", "v", QVariant::String, "The vendor of the generated code", "DKFZ, Medical and Biological Informatics");
parser.addArgument("quiet", "q", QVariant::Bool, "Do not print additional information");
parser.addArgument("confirm-all", "y", QVariant::Bool, "Answer all questions with 'yes'");
parser.beginGroup("Plug-in options");
parser.addArgument("plugin-symbolic-name", "ps", QVariant::String, "The plugin's symbolic name");
parser.setExactMatchRegularExpression("-ps", "^[a-zA-Z]+\\.[a-zA-Z0-9._]+[^\\.]$", "Symbolic name invalid");
parser.addArgument("plugin-name", "pn", QVariant::String, "The plug-in's human readable name");
parser.beginGroup("Plug-in View options");
parser.addArgument("view-class", "vc", QVariant::String, "The View's' class name");
parser.addArgument("view-name", "vn", QVariant::String, "The View's human readable name");
parser.beginGroup("Project options");
parser.addArgument("project-copyright", "", QVariant::String, "Path to a file containing copyright information", ":/MITKCopyright.txt");
parser.addArgument("project-name", "", QVariant::String, "The project name");
parser.setExactMatchRegularExpression("--project-name", "^[a-zA-Z_\\-]+$", "Project name invalid");
parser.addArgument("project-app-name", "", QVariant::String, "The application name");
parser.setExactMatchRegularExpression("--project-app-name", "^[a-zA-Z_\\-]+$", "Project application name invalid");
parser.endGroup();
// Parse the command line arguments
bool ok = false;
QHash<QString, QVariant> parsedArgs = parser.parseArguments(QCoreApplication::arguments(), &ok);
if (!ok)
{
QTextStream(stderr, QIODevice::WriteOnly) << "Error parsing arguments: "
- << parser.errorString() << "\n";
+ << parser.errorString() << "\nType '" << appName << " -h' for help\n";
return EXIT_FAILURE;
}
QTextStream out(stdout, QIODevice::WriteOnly);
// Show a help message
if (parsedArgs.contains("help"))
{
- out << "A CTK plug-in generator for MITK\n\n"
+ out << "A CTK plug-in generator for MITK (version " PLUGIN_GENERATOR_VERSION ")\n\n"
<< parser.helpText();
return EXIT_SUCCESS;
}
// Check arguments
// Project options
QString projectName = parsedArgs["project-name"].toString();
QString projectAppName = parsedArgs["project-app-name"].toString();
QString copyrightPath = QDir::fromNativeSeparators(parsedArgs["project-copyright"].toString());
bool createProject = !projectName.isEmpty();
if (createProject && projectAppName.isEmpty())
{
projectAppName = projectName;
}
QString pluginSymbolicName = parsedArgs["plugin-symbolic-name"].toString();
if (pluginSymbolicName.isEmpty())
{
qCritical() << "Required argument 'plugin-symbolic-name' missing.";
+ qCritical("%s%s%s", "Type '", qPrintable(appName), " -h' for help");
return EXIT_FAILURE;
}
QString pluginTarget(pluginSymbolicName);
pluginTarget.replace('.', '_');
QString outDir = QDir::fromNativeSeparators(parsedArgs["out-dir"].toString());
QString licensePath = QDir::fromNativeSeparators(parsedArgs["license"].toString());
QString pluginExportDirective = pluginSymbolicName.split('.').last().toUpper() + "_EXPORT";
QString pluginName = parsedArgs["plugin-name"].toString();
if (pluginName.isEmpty())
{
QStringList toks = pluginSymbolicName.split('.');
pluginName = toks.last();
pluginName[0] = pluginName[0].toUpper();
}
QString vendor = parsedArgs["vendor"].toString();
QString viewName = parsedArgs["view-name"].toString();
if (viewName.isEmpty())
{
qCritical() << "Required argument 'view-name' missing.";
+ qCritical("%s%s%s", "Type '", qPrintable(appName), " -h' for help");
return EXIT_FAILURE;
}
QStringList toks = viewName.split(QRegExp("\\s"), QString::SkipEmptyParts);
QString viewClass = parsedArgs["view-class"].toString();
if (viewClass.isEmpty())
{
foreach(QString tok, toks)
{
QString tmp = tok;
tmp[0] = tmp[0].toUpper();
viewClass += tmp;
}
}
QString viewId;
if (viewId.isEmpty())
{
viewId = "org.mitk.views.";
foreach(QString tok, toks)
{
viewId += tok.toLower();
}
}
bool quiet = parsedArgs.contains("quiet");
bool autoConfirm = parsedArgs.contains("confirm-all");
if (!outDir.endsWith('/'))
outDir += '/';
if (createProject)
outDir += projectName;
else
outDir += pluginSymbolicName;
// Print the collected information
if(!quiet)
{
if (createProject)
{
out << "Using the following information to create a project:\n\n"
<< " Project Name: " << projectName << '\n'
<< " Application Name: " << projectAppName << '\n'
<< " Copyright File: " << QDir::toNativeSeparators(copyrightPath) << '\n';
}
else
{
out << "Using the following information to create a plug-in:\n\n";
}
out << " License File: " << QDir::toNativeSeparators(licensePath) << '\n'
<< " Plugin-SymbolicName: " << pluginSymbolicName << '\n'
<< " Plugin-Name: " << pluginName << '\n'
<< " Plugin-Vendor: " << vendor << '\n'
<< " View Name: " << viewName << '\n'
<< " View Id: " << viewId << '\n'
<< " View Class: " << viewClass << '\n' << '\n'
<< "Create in: " << outDir << '\n' << '\n';
if (!autoConfirm)
out << "Continue [Y/n]? ";
out.flush();
if(!autoConfirm && !readAnswer('y'))
{
out << "Aborting.\n";
return EXIT_SUCCESS;
}
}
// Check the output directory
if (!QDir(outDir).exists())
{
if (!autoConfirm)
{
out << "Directory '" << outDir << "' does not exist. Create it [Y/n]? ";
out.flush();
}
if (autoConfirm || readAnswer('y'))
{
if (!QDir().mkpath(outDir))
{
qCritical() << "Could not create directory:" << outDir;
return EXIT_FAILURE;
}
}
else
{
out << "Aborting.\n";
return EXIT_SUCCESS;
}
}
if (!QDir(outDir).entryList(QDir::AllEntries | QDir::NoDotAndDotDot).isEmpty())
{
if (!autoConfirm)
{
out << "Directory '" << outDir << "' is not empty. Continue [y/N]? ";
out.flush();
}
if (!autoConfirm && !readAnswer('n'))
{
out << "Aborting.\n";
return EXIT_SUCCESS;
}
}
// Extract the license text
QFile licenseFile(licensePath);
if (!licenseFile.open(QIODevice::ReadOnly))
{
qCritical() << "Cannot open file" << licenseFile.fileName();
return EXIT_FAILURE;
}
QString licenseText = licenseFile.readAll();
licenseFile.close();
QHash<QString,QString> parameters;
if (createProject)
{
// Extract the copyright
QFile copyrightFile(copyrightPath);
if (!copyrightFile.open(QIODevice::ReadOnly))
{
qCritical() << "Cannot open file" << copyrightFile.fileName();
return EXIT_FAILURE;
}
QString copyrighText = copyrightFile.readAll();
copyrightFile.close();
parameters["$(copyright)"] = copyrighText;
parameters["$(project-name)"] = projectName;
parameters["$(project-app-name)"] = projectAppName;
parameters["$(project-plugins)"] = QString("Plugins/") + pluginSymbolicName + ":ON";
QStringList toks = pluginTarget.split("_");
QString projectPluginBase = toks[0] + "_" + toks[1];
parameters["$(project-plugin-base)"] = projectPluginBase;
}
parameters["$(license)"] = licenseText;
parameters["$(plugin-name)"] = pluginName;
parameters["$(plugin-symbolic-name)"] = pluginSymbolicName;
parameters["$(vendor)"] = vendor;
parameters["$(plugin-target)"] = pluginTarget;
parameters["$(plugin-export-directive)"] = pluginExportDirective;
parameters["$(view-id)"] = viewId;
parameters["$(view-name)"] = viewName;
parameters["$(view-file-name)"] = viewClass;
parameters["$(view-class-name)"] = viewClass;
if (createProject)
{
QHash<QString,QString> projectFileNameMapping;
projectFileNameMapping["TemplateApp"] = projectAppName;
QHash<QString,QString> filePathMapping = createTemplateFileMapping(":/ProjectTemplate", outDir, projectFileNameMapping);
generateFiles(parameters, filePathMapping);
}
QHash<QString,QString> pluginFileNameMapping;
pluginFileNameMapping["QmitkTemplateView"] = viewClass;
if (createProject)
{
if (!outDir.endsWith('/'))
outDir += '/';
outDir += "Plugins/" + pluginSymbolicName;
}
QHash<QString,QString> filePathMapping = createTemplateFileMapping(":/PluginTemplate", outDir, pluginFileNameMapping);
generateFiles(parameters, filePathMapping);
return EXIT_SUCCESS;
}
diff --git a/Applications/PluginGenerator/PluginGeneratorConfig.h.in b/Applications/PluginGenerator/PluginGeneratorConfig.h.in
new file mode 100644
index 0000000000..2a1c287859
--- /dev/null
+++ b/Applications/PluginGenerator/PluginGeneratorConfig.h.in
@@ -0,0 +1,23 @@
+/*=========================================================================
+
+Program: Medical Imaging & Interaction Toolkit
+Language: C++
+Date: $Date$
+Version: $Revision$
+
+Copyright (c) German Cancer Research Center, Division of Medical and
+Biological Informatics. All rights reserved.
+See MITKCopyright.txt or http://www.mitk.org/ for details.
+
+This software is distributed WITHOUT ANY WARRANTY; without even
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the above copyright notices for more information.
+
+=========================================================================*/
+
+#ifndef PLUGINGENERATORCONFIG_H
+#define PLUGINGENERATORCONFIG_H
+
+#define PLUGIN_GENERATOR_VERSION "@VERSION_STRING@"
+
+#endif
diff --git a/Applications/PluginGenerator/PluginTemplate/documentation/Manual/icon.png b/Applications/PluginGenerator/PluginTemplate/documentation/Manual/icon.png
deleted file mode 100644
index 7a51d8cb11..0000000000
--- a/Applications/PluginGenerator/PluginTemplate/documentation/Manual/icon.png
+++ /dev/null
@@ -1,26 +0,0 @@
-‰PNG
-
-
-•|€©$¦Š@IQIaSR•TRPyUÀ/­dKÁ6ے‘eëe=VÒJûÞyõtߓÝ=ÓÓ;+Ù Nü©ÚšÙîž{ï9÷œÿ9çîÀ¯_¿~½ª_?ûÙÏ^ÑñåW=`î¾jŸèlºæ}~n‹ 7ˆÊZT‡Œh7*í¨"h‘9QpÐs®Øþvç‘gß=:bÓc<òÈ#ìÙ³çÕ©
-#EuÎ}ºà؇þzû±oýöö”Óó=úè£Üy睯8÷ ïíˆqßÂzU>%»DµSQƒÅ€Ò×fXÓe*ݞЩ€Zh™¯*WŠ–ñù™Rˆ0‚5¨¨v:á¿oé]øÒ÷>rý"¯ 0”°/DÜ¿àd-èçP½GròºeБ[‡\npèkT›'‰>‹D˜ó•ç.×xê‚ϱ‰šVj*µPUzrÁC¯˜¿o÷ÐÜS¿ÿŽ'æE>
-À°Ö222òÊ+@î/¢ñŽËýÅë>Šê'èõ`]·£;V¸²}¹KޅPÁ*¨*o_]p
-H®׀çÀ‚¯<9îóø™ªž› d¦’Â5…êßÝÚWü篼ó±'éýêÈ4
-ÀÁƒÙ½{÷¯Puዮ ßWÕ7·­ÏéÎ.9â]‹?4 ±H-¬ÁÈb|hVŽb¢i¨–GN”õ[O/ˆç ËÛkÿõ‘›ÆÿüÎóß²óîé—6¯­€/”àc¸¿ÔŽðª[;r»7zzû #ª &<R£‘MÖÔS×ëÂk›¬ ~¶I=}Oyþ²¯_98+Õ@Y‘¯=óñ­g?½¦à?1::rñ¥*aiÜWÇF¡؉ʏQÝÙ㉾ïOnpðÃxAdv±•Ég>g­d‘ÅÈÕ¬DG„““>ÿòجN­\W¨>óÉÛÎ~fu§ÿؔßvá7ïÚÍ¡C‡ð}Éa–ð±ðV
-¨|«;{Û ¼±M^ÛïPKÚ¬F›¡=õk!Öltßs Ëƒ¾ `¨
-®2¯E°
-A¨¼yk+{s\*¹«÷÷¼eÁw¶#˓qüñ«(à åÄ÷W¢úρmCŽôy±ð*XR“Ó
-—‹p©“e¨…K[G¢„î6xMoMl‹h£¤7CXћ“mëòz¹d:žœè¸£šMª¬IÆ=tèP£”oü€w:;–åÄ5B`#ݦwÅjŒâqҒ$/6YMJ¨¹*œœ†‹ ʗjÑsm `ÛJXÑÙ#’`M7¼0©¦’¥d-iÌ9ÂÖµž;_áç—:¶ýÖºéC+:üÓcccGFFæwíÚÕÂóùT½åyÑë» ~H“é7™=)ßO]³qî^®ÁÃ'áëÏFïO^€gàJ ¦Ë‘<;ß==»F‰BèÕ,®áŠUX՗“ Ë<­ïà…®×;ÂZ`ÅÒ ø±<<P*
-üD6£8×w;ØHOÆ÷ÓæGc‡Zùi+ì°
-¾…U]°®§u¨L¬æâ|sHm…͘¥H«Úpå…éüÏè Â`†ÀÞ½{›¢ÀZ”•
-С‚'´9ˆÆhºÈücM‡×ÐÌÎ.Š ™1Bj„·lŒB\@fRã§'¢ÈÑï3•Í l¬¸Á#hhŜšm[™3Ú£ªûöíË&B:€Ò×ëI¼pi65myuPÊ,¨é+"+ïÂ;n„›VÑJø‰"ì;í~2V¨-\¡Ed
--t\Œˆ Êø‚7àºE¤ÓÄ5rʤlwG.šÉ&¦¤©Ê+ÅèÔÍ?6E£ÍæŸv‹º+ÅBåspÏXۓ2ÛLÁ$ >|õp#é²)’5Ô¨@ۘ7Læ«_¾Pð 3>2Su»Œh§ªv¨ªl]F5oi3 $šý8Ê&B¦h­0QBê;Mø'H>>»ë%J_6
-¥MìRj\kã I¯%‹Ñ¼‚µÐî(ÕL»@ȋH³¨ª àˆÔ‰ˆ¹4ÃÓ©¶XP, \å¾kà]7GyýRi/DdÈwŽE™¢#`M›ÚEŠÐFyî:Q8,9 '"^B¸ÉEUµ ÐÒDG3¶0ñ¥îÇ߯†ð–õ°y¨µðɵssðÍ£è¹&Us¤ mme¶Nž¦Ö'l¢`¢àSUטh‹
-@k
-|õHôϓ ¥æëJ¯ÛµÀ"(í®EµÎꈪ¦]@Š A%P×jJ“×P6’8}ßƶ—°8¡Â꘻ôíc0UŽwÞ6*Á¦¹¤a‹Ö•YK̅r5ª¹»<Zƒ‘ªŠHCFìŒ*³Åš„4£kS‹K»¶¦Ò÷“d*´ÐíET×RLÕ(Þ{i³×Œk%}„Ôçì¼MkA¨øà×,F` _óCÈꄷI¹
-Ûü¼M‘"M|‚f®i‹’ܶ(Ém\#¤X©Ë3UJå@E`Ûʅ™š•i`(íÝ»w1+<ñG}.”“3AœnjƒŠ¶
-<!$ìb¢$¹–°H* ÚîD­±v'ª Úݨ0rœÆXš¢¿Cm¦Ä[­ES
- “Ï—&+,”C¹eYÙvæìe«2)"SªZJºÇn—?XûÆLÍÝzz®&7ôåÄÄH¥éŒ, F™L0 F‚'ð¡­ù‘
-°gϞ†8p
-³ Jƒ`lÂKž<“殏f‘VN¶3”¥àj5ˉ³s„Ê]¯™«xŽž΋ÈxŒWï þñ¦S_l3vz¶jå̜¯ ªÚĈÕÅDH؂H¹V3ޑ¥Q½•5´ŠV£¨uîb‘K“U¹y°Â¦þÊ%#zô,p~dd¤’îšìqT€ßÛ|bü֞…ÏZ gg}™)‡1Òj=üeim›ª¼Òi¢®Ñtd1Ël[)¶`„R½ÁJ%àȱiÍç`çêbiyGí pxQU/%ó%=Â&ìÙ³‡ýû÷#ëï±÷¬ºðÍe^õÀ‚rjºŠ¨*B˜tˆS´vØ"¤i)›Ê—T€ÓºšØfоѓˆ6&´Ê“G®Z+¯*Û«.Xå¸*'EäÔèèhñšíñä áGo¸xñ ˦>ßéÚKç檜­Öµ¬hK0²KðtFççáôÌâ¿ssQhiAr.Jp·Â”ˆù9z|š©™
-C…·n˜™î̅Ï[•€"r> öK7GcW›÷„OúñÁ3Åö/ý|ºûS'&+y× k{ÛŪÔOfd‰p‰b©\ƒ|:s™SI-`R¬oúûM,šj(¼X…3gç8{~^syû¦éò¦ÊñrÍ=&"ÏWðƒÔÁþª
-HŽ–m½ã'³Ÿ®æþõ“G6^ÿËùÂRkaÝ@;֦θ]ƒ(‘¸U5]Y|f0Ý6©Z>!ZÉtMº ×hî³ãsœ|qF«È‡·N¿±jád%# ¿‘_ŠÈ€žžž—qJ ùKní?÷W·{ð†ŽÒ÷ §§Êzâr9&&‘·•©fk„ô¹ô)¥D–¥úiWh
diff --git a/Applications/PluginGenerator/PluginTemplate/documentation/Manual/Manual.dox b/Applications/PluginGenerator/PluginTemplate/documentation/UserManual/Manual.dox
similarity index 87%
rename from Applications/PluginGenerator/PluginTemplate/documentation/Manual/Manual.dox
rename to Applications/PluginGenerator/PluginTemplate/documentation/UserManual/Manual.dox
index 84b8b5dd98..ae83208851 100755
--- a/Applications/PluginGenerator/PluginTemplate/documentation/Manual/Manual.dox
+++ b/Applications/PluginGenerator/PluginTemplate/documentation/UserManual/Manual.dox
@@ -1,19 +1,19 @@
/**
\bundlemainpage{$(plugin-symbolic-name)} $(plugin-name)
-\image html icon.png "Icon of $(plugin-name)"
+\image html icon.xpm "Icon of $(plugin-name)"
Available sections:
- \ref $(plugin-symbolic-name)Overview
\section $(plugin-symbolic-name)Overview
Describe the features of your awesome plugin here
<ul>
<li>Increases productivity
<li>Creates beautiful images
<li>Generates PhD thesis
<li>Brings world peace
</ul>
*/
diff --git a/Applications/PluginGenerator/PluginTemplate/documentation/UserManual/icon.xpm b/Applications/PluginGenerator/PluginTemplate/documentation/UserManual/icon.xpm
new file mode 100644
index 0000000000..9057c20bc6
--- /dev/null
+++ b/Applications/PluginGenerator/PluginTemplate/documentation/UserManual/icon.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * icon_xpm[] = {
+"16 16 2 1",
+" c #FF0000",
+". c #000000",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" "};
diff --git a/Applications/PluginGenerator/ProjectTemplate/CMakeLists.txt b/Applications/PluginGenerator/ProjectTemplate/CMakeLists.txt
index 1177f382ad..91522ee770 100644
--- a/Applications/PluginGenerator/ProjectTemplate/CMakeLists.txt
+++ b/Applications/PluginGenerator/ProjectTemplate/CMakeLists.txt
@@ -1,364 +1,378 @@
cmake_minimum_required(VERSION 2.8.4)
# Change project and application name to your own
set(MY_PROJECT_NAME $(project-name))
set(MY_APP_NAME $(project-app-name))
#-----------------------------------------------------------------------------
# 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(${MY_PROJECT_NAME}_USE_SUPERBUILD "Build ${MY_PROJECT_NAME} and the projects it depends on via SuperBuild.cmake." ON)
if(${MY_PROJECT_NAME}_USE_SUPERBUILD)
project(${MY_PROJECT_NAME}-superbuild)
set(${MY_PROJECT_NAME}_SOURCE_DIR ${PROJECT_SOURCE_DIR})
set(${MY_PROJECT_NAME}_BINARY_DIR ${PROJECT_BINARY_DIR})
else()
project(${MY_PROJECT_NAME})
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
${${MY_PROJECT_NAME}_SOURCE_DIR}/CMake
${CMAKE_MODULE_PATH}
)
#-----------------------------------------------------------------------------
# CMake Function(s) and Macro(s)
#-----------------------------------------------------------------------------
include(MacroEmptyExternalProject)
#-----------------------------------------------------------------------------
# Output directories.
#-----------------------------------------------------------------------------
foreach(type LIBRARY RUNTIME ARCHIVE)
set(output_dir ${${MY_PROJECT_NAME}_BINARY_DIR}/bin)
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 Options (also shown during superbuild)
#-----------------------------------------------------------------------------
option(BUILD_SHARED_LIBS "Build ${MY_PROJECT_NAME} with shared libraries" ON)
option(WITH_COVERAGE "Enable/Disable coverage" OFF)
option(BUILD_TESTING "Test the project" ON)
option(${MY_PROJECT_NAME}_BUILD_ALL_PLUGINS "Build all ${MY_PROJECT_NAME} plugins" OFF)
mark_as_advanced(${MY_PROJECT_NAME}_INSTALL_RPATH_RELATIVE
${MY_PROJECT_NAME}_BUILD_ALL_PLUGINS
)
#-----------------------------------------------------------------------------
# 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)
#-----------------------------------------------------------------------------
# Superbuild script
#-----------------------------------------------------------------------------
if(${MY_PROJECT_NAME}_USE_SUPERBUILD)
include("${CMAKE_CURRENT_SOURCE_DIR}/SuperBuild.cmake")
return()
endif()
#*****************************************************************************
#**************************** END OF SUPERBUILD ****************************
#*****************************************************************************
#-----------------------------------------------------------------------------
# Prerequesites
#-----------------------------------------------------------------------------
find_package(MITK REQUIRED)
link_directories(${MITK_LINK_DIRECTORIES})
#-----------------------------------------------------------------------------
# CMake Function(s) and Macro(s)
#-----------------------------------------------------------------------------
set(CMAKE_MODULE_PATH
${MITK_SOURCE_DIR}/CMake
${CMAKE_MODULE_PATH}
)
include(mitkFunctionCheckCompilerFlags)
include(mitkFunctionGetGccVersion)
include(mitkFunctionGetVersion)
#-----------------------------------------------------------------------------
# Set project specific options and variables (NOT available during superbuild)
#-----------------------------------------------------------------------------
set(${PROJECT_NAME}_VERSION_MAJOR "0")
set(${PROJECT_NAME}_VERSION_MINOR "1")
set(${PROJECT_NAME}_VERSION_PATCH "1")
set(${PROJECT_NAME}_VERSION_STRING "${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}.${${PROJECT_NAME}_VERSION_PATCH}")
# Ask the user if a console window should be shown with the applications
option(${PROJECT_NAME}_SHOW_CONSOLE_WINDOW "Use this to enable or disable the console window when starting GUI Applications" ON)
mark_as_advanced(${PROJECT_NAME}_SHOW_CONSOLE_WINDOW)
if(NOT UNIX AND NOT MINGW)
set(MITK_WIN32_FORCE_STATIC "STATIC")
endif()
set(${PROJECT_NAME}_MODULES_PACKAGE_DEPENDS_DIR "${PROJECT_SOURCE_DIR}/CMake/PackageDepends")
list(APPEND MODULES_PACKAGE_DEPENDS_DIRS ${${PROJECT_NAME}_MODULES_PACKAGE_DEPENDS_DIR})
#-----------------------------------------------------------------------------
# Get project version info
#-----------------------------------------------------------------------------
mitkFunctionGetVersion(${PROJECT_SOURCE_DIR} ${PROJECT_NAME})
#-----------------------------------------------------------------------------
# Installation preparation
#
# These should be set before any MITK install macros are used
#-----------------------------------------------------------------------------
# on Mac OSX all CTK plugins get copied into every
# application bundle (.app directory) specified here
set(MACOSX_BUNDLE_NAMES)
if(APPLE)
list(APPEND MACOSX_BUNDLE_NAMES ${MY_APP_NAME})
endif(APPLE)
#-----------------------------------------------------------------------------
# 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)
# The MITK module build system does not yet support default hidden visibility
set(VISIBILITY_CXX_FLAGS ) # "-fvisibility=hidden -fvisibility-inlines-hidden")
endif()
#-----------------------------------------------------------------------------
# Set coverage Flags
#-----------------------------------------------------------------------------
if(WITH_COVERAGE)
if(CMAKE_COMPILER_IS_GNUCXX)
set(coverage_flags "-g -fprofile-arcs -ftest-coverage -O0 -DNDEBUG")
set(COVERAGE_CXX_FLAGS ${coverage_flags})
set(COVERAGE_C_FLAGS ${coverage_flags})
endif()
endif()
#-----------------------------------------------------------------------------
# Project C/CXX Flags
#-----------------------------------------------------------------------------
set(${PROJECT_NAME}_C_FLAGS "${COVERAGE_C_FLAGS} ${ADDITIONAL_C_FLAGS}")
set(${PROJECT_NAME}_CXX_FLAGS "${VISIBILITY_CXX_FLAGS} ${COVERAGE_CXX_FLAGS} ${ADDITIONAL_CXX_FLAGS}")
if(CMAKE_COMPILER_IS_GNUCXX)
set(cflags "-Wall -Wextra -Wpointer-arith -Winvalid-pch -Wcast-align -Wwrite-strings -D_FORTIFY_SOURCE=2")
mitkFunctionCheckCompilerFlags("-fdiagnostics-show-option" cflags)
mitkFunctionCheckCompilerFlags("-Wl,--no-undefined" cflags)
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(${PROJECT_NAME}_CXX_FLAGS "-Wl,--enable-auto-import ${${PROJECT_NAME}_CXX_FLAGS}")
# we need to define a Windows version
set(${PROJECT_NAME}_CXX_FLAGS "-D_WIN32_WINNT=0x0500 ${${PROJECT_NAME}_CXX_FLAGS}")
endif()
set(${PROJECT_NAME}_C_FLAGS "${cflags} ${${PROJECT_NAME}_C_FLAGS}")
set(${PROJECT_NAME}_CXX_FLAGS "${cflags} -Woverloaded-virtual -Wstrict-null-sentinel -Wsign-promo ${${PROJECT_NAME}_CXX_FLAGS}")
# The following line produces a lot of warnings in MITK header files...
#set(${PROJECT_NAME}_CXX_FLAGS "${cflags} -Woverloaded-virtual -Wold-style-cast -Wstrict-null-sentinel -Wsign-promo ${${PROJECT_NAME}_CXX_FLAGS}")
endif()
#-----------------------------------------------------------------------------
# Set C/CXX Flags
#-----------------------------------------------------------------------------
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${${PROJECT_NAME}_CXX_FLAGS}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${${PROJECT_NAME}_C_FLAGS}")
#-----------------------------------------------------------------------------
# Testing
#-----------------------------------------------------------------------------
if(BUILD_TESTING)
enable_testing()
include(CTest)
mark_as_advanced(TCL_TCLSH DART_ROOT)
# Setup file for setting custom ctest vars
configure_file(
CMake/CTestCustom.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake
@ONLY
)
# Configuration for the CMake-generated test driver
set(CMAKE_TESTDRIVER_EXTRA_INCLUDES "#include <stdexcept>")
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;
}
")
endif()
#-----------------------------------------------------------------------------
# ${MY_PROJECT_NAME}_SUPERBUILD_BINARY_DIR
#-----------------------------------------------------------------------------
# If ${MY_PROJECT_NAME}_SUPERBUILD_BINARY_DIR isn't defined, it means this project is
# *NOT* build using Superbuild. In that specific case, ${MY_PROJECT_NAME}_SUPERBUILD_BINARY_DIR
# should default to PROJECT_BINARY_DIR
if(NOT DEFINED ${PROJECT_NAME}_SUPERBUILD_BINARY_DIR)
set(${PROJECT_NAME}_SUPERBUILD_BINARY_DIR ${PROJECT_BINARY_DIR})
endif()
#-----------------------------------------------------------------------------
# Qt support
#-----------------------------------------------------------------------------
if(MITK_USE_QT)
set(QT_QMAKE_EXECUTABLE ${MITK_QMAKE_EXECUTABLE})
add_definitions(-DQWT_DLL)
endif()
#-----------------------------------------------------------------------------
# MITK modules
#-----------------------------------------------------------------------------
+# This project's directory holding module config files
+#set(${PROJECT_NAME}_MODULES_CONF_DIR "${PROJECT_BINARY_DIR}/${MODULES_CONF_DIRNAME}")
+
+# Append this projects's module config directory to the global list
+# (This is used to get include directories for the <module_name>Exports.h files right)
+#list(APPEND MODULES_CONF_DIRS ${${PROJECT_NAME}_MODULES_CONF_DIR})
+
+# Clean the modulesConf directory. This ensures that modules are sorted
+# according to their dependencies in the Modules/CMakeLists.txt file
+#file(GLOB _modules_conf_files ${${PROJECT_NAME}_MODULES_CONF_DIR}/*.cmake)
+#if(_modules_conf_files)
+# file(REMOVE ${_modules_conf_files})
+#endif()
+
#add_subdirectory(Modules)
#-----------------------------------------------------------------------------
# CTK plugins
#-----------------------------------------------------------------------------
# The CMake code in this section *must* be in the top-level CMakeLists.txt file
macro(GetMyTargetLibraries all_target_libraries varname)
set(re_ctkplugin "^$(project-plugin-base)_[a-zA-Z0-9_]+$")
set(_tmp_list)
list(APPEND _tmp_list ${all_target_libraries})
ctkMacroListFilter(_tmp_list re_ctkplugin OUTPUT_VARIABLE ${varname})
endmacro()
include(${CMAKE_CURRENT_SOURCE_DIR}/Plugins/Plugins.cmake)
ctkMacroSetupExternalPlugins(${PROJECT_PLUGINS}
BUILD_OPTION_PREFIX ${MY_PROJECT_NAME}_
BUILD_ALL ${${MY_PROJECT_NAME}_BUILD_ALL_PLUGINS})
#-----------------------------------------------------------------------------
# Add subdirectories
#-----------------------------------------------------------------------------
add_subdirectory(Apps/$(project-app-name))
#-----------------------------------------------------------------------------
# Installation
#-----------------------------------------------------------------------------
# set MITK cpack variables
include(mitkSetupCPack)
# Customize CPack variables for this project
include(CPackSetup)
list(APPEND CPACK_CREATE_DESKTOP_LINKS "${MY_APP_NAME}")
configure_file(${MITK_SOURCE_DIR}/MITKCPackOptions.cmake.in
${PROJECT_BINARY_DIR}/${PROJECT_NAME}CPackOptions.cmake @ONLY)
set(CPACK_PROJECT_CONFIG_FILE "${PROJECT_BINARY_DIR}/${PROJECT_NAME}CPackOptions.cmake")
# include CPack model once all variables are set
include(CPack)
# Additional installation rules
include(mitkInstallRules)
#-----------------------------------------------------------------------------
# Last configuration steps
#-----------------------------------------------------------------------------
# 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("${PROJECT_SOURCE_DIR}/CMake/StartVS.bat.in"
${PROJECT_BINARY_DIR}/StartVS_${VS_BUILD_TYPE}.bat
${VS_BUILD_TYPE})
endforeach()
endif(WIN32)
diff --git a/Applications/PluginGenerator/SetupPackaging.cmake b/Applications/PluginGenerator/SetupPackaging.cmake
index 48cbf89818..bdebf58d77 100644
--- a/Applications/PluginGenerator/SetupPackaging.cmake
+++ b/Applications/PluginGenerator/SetupPackaging.cmake
@@ -1,50 +1,52 @@
#-----------------------------------------------------------------------------
# Installation
#-----------------------------------------------------------------------------
install(TARGETS ${exec_target} DESTINATION .)
+install(FILES "${PROJECT_SOURCE_DIR}/Changelog.txt" DESTINATION .)
+
install(CODE "
set(DIRS
${QT_LIBRARY_DIR}
${QT_LIBRARY_DIR}/../bin
${CTK_LIBRARY_DIRS}
)
include(BundleUtilities)
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/${exec_target}${CMAKE_EXECUTABLE_SUFFIX}\" \"\" \"\${DIRS}\")
")
#-----------------------------------------------------------------------------
# Packaging
#-----------------------------------------------------------------------------
#
# First, set the generator variable
#
if(WIN32)
set(CPACK_GENERATOR ZIP)
elseif(APPLE)
set(CPACK_GENERATOR DragNDrop)
else()
set(CPACK_GENERATOR TGZ)
endif()
# include required mfc libraries
include(InstallRequiredSystemLibraries)
set(CPACK_PACKAGE_NAME "MITKPluginGenerator")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "MITK PluginGenerator bootstraps MITK-based projects")
set(CPACK_PACKAGE_VENDOR "German Cancer Research Center (DKFZ)")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/MITKCopyright.txt")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/MITKCopyright.txt")
set(CPACK_PACKAGE_VERSION_MAJOR "${VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${VERSION_MINOR}")
set(CPACK_PACKAGE_VERSION_PATCH "${VERSION_PATCH}")
# tell cpack to strip all debug symbols from all files
set(CPACK_STRIP_FILES ON)
include(CPack)
diff --git a/Applications/PluginGenerator/plugin_template.qrc b/Applications/PluginGenerator/plugin_template.qrc
index 6a59da691f..b205118c45 100644
--- a/Applications/PluginGenerator/plugin_template.qrc
+++ b/Applications/PluginGenerator/plugin_template.qrc
@@ -1,18 +1,18 @@
<RCC>
<qresource prefix="/">
<file>PluginTemplate/CMakeLists.txt</file>
<file>PluginTemplate/files.cmake</file>
<file>PluginTemplate/manifest_headers.cmake</file>
<file>PluginTemplate/plugin.xml</file>
<file>PluginTemplate/documentation/doxygen/modules.dox</file>
- <file>PluginTemplate/documentation/Manual/icon.png</file>
- <file>PluginTemplate/documentation/Manual/Manual.dox</file>
+ <file>PluginTemplate/documentation/UserManual/icon.xpm</file>
+ <file>PluginTemplate/documentation/UserManual/Manual.dox</file>
<file>PluginTemplate/resources/icon.xpm</file>
<file>PluginTemplate/src/internal/mitkPluginActivator.cpp</file>
<file>PluginTemplate/src/internal/mitkPluginActivator.h</file>
<file>PluginTemplate/src/internal/QmitkTemplateView.cpp</file>
<file>PluginTemplate/src/internal/QmitkTemplateView.h</file>
<file>PluginTemplate/src/internal/QmitkTemplateViewControls.ui</file>
<file>MITKLicense.txt</file>
</qresource>
</RCC>
diff --git a/CMake/mitkTestProjectTemplate.cmake b/CMake/mitkTestProjectTemplate.cmake
index cedc6394e0..d7d8b3f39a 100644
--- a/CMake/mitkTestProjectTemplate.cmake
+++ b/CMake/mitkTestProjectTemplate.cmake
@@ -1,66 +1,65 @@
if(BUILD_TESTING)
include(ExternalProject)
set(proj MITK-ProjectTemplate)
set(MITK-ProjectTemplate_BINARY_DIR "${MITK_BINARY_DIR}/${proj}-build")
ExternalProject_Add(${proj}
GIT_REPOSITORY http://git.mitk.org/MITK-ProjectTemplate.git
GIT_TAG origin/master
SOURCE_DIR "${MITK_BINARY_DIR}/${proj}"
BINARY_DIR "${MITK-ProjectTemplate_BINARY_DIR}"
PREFIX "${proj}-cmake"
- UPDATE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
CMAKE_GENERATOR "${CMAKE_GENERATOR}"
CMAKE_ARGS
-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}
-DMITK_DIR:PATH=${MITK_BINARY_DIR}
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DAwesomeProject_BUILD_ALL_PLUGINS:BOOL=ON
)
if(CMAKE_CONFIGURATION_TYPES)
foreach(config ${CMAKE_CONFIGURATION_TYPES})
add_test(NAME mitkProjectTemplateBuildTest-${config} CONFIGURATIONS ${config}
COMMAND ${CMAKE_COMMAND} --build ${MITK-ProjectTemplate_BINARY_DIR} --config ${config})
set_tests_properties(mitkProjectTemplateBuildTest-${config} PROPERTIES
LABELS "MITK;BlueBerry")
endforeach()
else()
add_test(mitkProjectTemplateBuildTest-${CMAKE_BUILD_TYPE}
${CMAKE_COMMAND} --build ${MITK-ProjectTemplate_BINARY_DIR} --config ${CMAKE_BUILD_TYPE})
set_tests_properties(mitkProjectTemplateBuildTest-${CMAKE_BUILD_TYPE} PROPERTIES
LABELS "MITK;BlueBerry")
endif()
set(package_test_configurations)
if(WIN32)
# Only test packaging if build type is "Release" on Windows
set(package_test_configurations CONFIGURATIONS Release)
endif()
if(NOT MITK_FAST_TESTING)
if(WIN32)
# Only test packaging if build type is "Release" on Windows
add_test(NAME mitkProjectTemplatePackageTest CONFIGURATIONS Release
COMMAND ${CMAKE_COMMAND} --build ${MITK-ProjectTemplate_BINARY_DIR}/AwesomeProject-build --config Release --target package)
set_tests_properties(mitkProjectTemplatePackageTest PROPERTIES
DEPENDS mitkProjectTemplateBuildTest-Release
TIMEOUT 1800
LABELS "MITK;BlueBerry")
elseif(CMAKE_BUILD_TYPE)
add_test(mitkProjectTemplatePackageTest
${CMAKE_COMMAND} --build ${MITK-ProjectTemplate_BINARY_DIR}/AwesomeProject-build --config ${CMAKE_BUILD_TYPE} --target package)
set_tests_properties(mitkProjectTemplatePackageTest PROPERTIES
DEPENDS mitkProjectTemplateBuildTest-${CMAKE_BUILD_TYPE}
TIMEOUT 1800
LABELS "MITK;BlueBerry")
endif()
endif()
endif()
diff --git a/Core/Code/DataManagement/mitkDataNode.cpp b/Core/Code/DataManagement/mitkDataNode.cpp
index 0d78b6267e..14f49007ff 100644
--- a/Core/Code/DataManagement/mitkDataNode.cpp
+++ b/Core/Code/DataManagement/mitkDataNode.cpp
@@ -1,573 +1,553 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "mitkDataNode.h"
#include "mitkCoreObjectFactory.h"
#include <vtkTransform.h>
#include "mitkProperties.h"
#include "mitkStringProperty.h"
#include "mitkGroupTagProperty.h"
#include "mitkSmartPointerProperty.h"
//#include "mitkMaterialProperty.h"
#include "mitkColorProperty.h"
#include "mitkLevelWindowProperty.h"
#include "mitkGeometry3D.h"
#include "mitkRenderingManager.h"
#include "mitkGlobalInteraction.h"
#include "mitkEventMapper.h"
#include "mitkGenericProperty.h"
#include "mitkCoreObjectFactory.h"
mitk::Mapper* mitk::DataNode::GetMapper(MapperSlotId id) const
{
if( (id >= m_Mappers.size()) || (m_Mappers[id].IsNull()) )
{
if(id >= m_Mappers.capacity())
{
// int i, size=id-m_Mappers.capacity()+10;
m_Mappers.resize(id+10);
}
m_Mappers[id] = CoreObjectFactory::GetInstance()->CreateMapper(const_cast<DataNode*>(this),id);
}
return m_Mappers[id];
}
mitk::BaseData* mitk::DataNode::GetData() const
{
return m_Data;
}
mitk::Interactor* mitk::DataNode::GetInteractor() const
{
return m_Interactor;
}
void mitk::DataNode::SetData(mitk::BaseData* baseData)
{
if(m_Data!=baseData)
{
m_Data=baseData;
m_Mappers.clear();
m_Mappers.resize(10);
mitk::CoreObjectFactory::GetInstance()->SetDefaultProperties(this);
m_DataReferenceChangedTime.Modified();
Modified();
//inform the interactor about the change
if (m_Interactor.IsNotNull())
m_Interactor->DataChanged();
}
}
void mitk::DataNode::SetInteractor(mitk::Interactor* interactor)
{
m_Interactor = interactor;
if(m_Interactor.IsNotNull())
m_Interactor->SetDataNode(this);
}
mitk::DataNode::DataNode() : m_Data(NULL), m_PropertyListModifiedObserverTag(0)
{
m_Mappers.resize(10);
m_PropertyList = PropertyList::New();
// subscribe for modified event
itk::MemberCommand<mitk::DataNode>::Pointer _PropertyListModifiedCommand =
itk::MemberCommand<mitk::DataNode>::New();
_PropertyListModifiedCommand->SetCallbackFunction(this, &mitk::DataNode::PropertyListModified);
m_PropertyListModifiedObserverTag = m_PropertyList->AddObserver(itk::ModifiedEvent(), _PropertyListModifiedCommand);
}
mitk::DataNode::~DataNode()
{
if(m_PropertyList.IsNotNull())
// remove modified event listener
m_PropertyList->RemoveObserver(m_PropertyListModifiedObserverTag);
Interactor* interactor = this->GetInteractor();
if ( interactor )
{
mitk::GlobalInteraction::GetInstance()->RemoveInteractor( interactor );
}
m_Mappers.clear();
m_Data = NULL;
}
mitk::DataNode& mitk::DataNode::operator=(const DataNode& right)
{
mitk::DataNode* node=mitk::DataNode::New();
node->SetData(right.GetData());
return *node;
}
mitk::DataNode& mitk::DataNode::operator=(mitk::BaseData* right)
{
mitk::DataNode* node=mitk::DataNode::New();
node->SetData(right);
return *node;
}
#if (_MSC_VER > 1200) || !defined(_MSC_VER)
MBI_STD::istream& mitk::operator>>( MBI_STD::istream& i, mitk::DataNode::Pointer& dtn )
#endif
#if ((defined(_MSC_VER)) && (_MSC_VER <= 1200))
MBI_STD::istream& operator>>( MBI_STD::istream& i, mitk::DataNode::Pointer& dtn )
#endif
{
dtn = mitk::DataNode::New();
//i >> av.get();
return i;
}
#if (_MSC_VER > 1200) || !defined(_MSC_VER)
MBI_STD::ostream& mitk::operator<<( MBI_STD::ostream& o, mitk::DataNode::Pointer& dtn)
#endif
#if ((defined(_MSC_VER)) && (_MSC_VER <= 1200))
MBI_STD::ostream& operator<<( MBI_STD::ostream& o, mitk::DataNode::Pointer& dtn)
#endif
{
if(dtn->GetData()!=NULL)
o<<dtn->GetData()->GetNameOfClass();
else
o<<"empty data";
return o;
}
void mitk::DataNode::SetMapper(MapperSlotId id, mitk::Mapper* mapper)
{
m_Mappers[id] = mapper;
if (mapper!=NULL)
mapper->SetDataNode(this);
}
void mitk::DataNode::UpdateOutputInformation()
{
if (this->GetSource())
{
this->GetSource()->UpdateOutputInformation();
}
}
void mitk::DataNode::SetRequestedRegionToLargestPossibleRegion()
{
}
bool mitk::DataNode::RequestedRegionIsOutsideOfTheBufferedRegion()
{
return false;
}
bool mitk::DataNode::VerifyRequestedRegion()
{
return true;
}
void mitk::DataNode::SetRequestedRegion(itk::DataObject * /*data*/)
{
}
void mitk::DataNode::CopyInformation(const itk::DataObject * /*data*/)
{
}
mitk::PropertyList* mitk::DataNode::GetPropertyList(const mitk::BaseRenderer* renderer) const
{
if(renderer==NULL)
return m_PropertyList;
mitk::PropertyList::Pointer & propertyList = m_MapOfPropertyLists[renderer];
if(propertyList.IsNull())
propertyList = mitk::PropertyList::New();
assert(m_MapOfPropertyLists[renderer].IsNotNull());
return propertyList;
}
void mitk::DataNode::ConcatenatePropertyList(PropertyList *pList, bool replace)
{
m_PropertyList->ConcatenatePropertyList(pList, replace);
}
mitk::BaseProperty* mitk::DataNode::GetProperty(const char *propertyKey, const mitk::BaseRenderer* renderer) const
{
if(propertyKey==NULL)
return NULL;
//renderer specified?
if (renderer)
{
std::map<const mitk::BaseRenderer*,mitk::PropertyList::Pointer>::const_iterator it;
//check for the renderer specific property
it=m_MapOfPropertyLists.find(renderer);
if(it!=m_MapOfPropertyLists.end()) //found
{
mitk::BaseProperty::Pointer property;
property=it->second->GetProperty(propertyKey);
if(property.IsNotNull())//found an enabled property in the render specific list
return property;
else //found a renderer specific list, but not the desired property
return m_PropertyList->GetProperty(propertyKey); //return renderer unspecific property
}
else //didn't find the property list of the given renderer
{
//return the renderer unspecific property if there is one
return m_PropertyList->GetProperty(propertyKey);
}
}
else //no specific renderer given; use the renderer independent one
{
mitk::BaseProperty::Pointer property;
property=m_PropertyList->GetProperty(propertyKey);
if(property.IsNotNull())
return property;
}
//only to satisfy compiler!
return NULL;
}
mitk::DataNode::GroupTagList mitk::DataNode::GetGroupTags() const
{
GroupTagList groups;
const PropertyList::PropertyMap* propertyMap = m_PropertyList->GetMap();
for ( PropertyList::PropertyMap::const_iterator groupIter = propertyMap->begin(); // m_PropertyList is created in the constructor, so we don't check it here
groupIter != propertyMap->end();
++groupIter )
{
const BaseProperty* bp = groupIter->second;
if ( dynamic_cast<const GroupTagProperty*>(bp) )
{
groups.insert( groupIter->first );
}
}
return groups;
}
bool mitk::DataNode::GetBoolProperty(const char* propertyKey, bool& boolValue, mitk::BaseRenderer* renderer) const
{
mitk::BoolProperty::Pointer boolprop = dynamic_cast<mitk::BoolProperty*>(GetProperty(propertyKey, renderer));
if(boolprop.IsNull())
return false;
boolValue = boolprop->GetValue();
return true;
}
bool mitk::DataNode::GetIntProperty(const char* propertyKey, int &intValue, mitk::BaseRenderer* renderer) const
{
mitk::IntProperty::Pointer intprop = dynamic_cast<mitk::IntProperty*>(GetProperty(propertyKey, renderer));
if(intprop.IsNull())
return false;
intValue = intprop->GetValue();
return true;
}
bool mitk::DataNode::GetFloatProperty(const char* propertyKey, float &floatValue, mitk::BaseRenderer* renderer) const
{
mitk::FloatProperty::Pointer floatprop = dynamic_cast<mitk::FloatProperty*>(GetProperty(propertyKey, renderer));
if(floatprop.IsNull())
return false;
floatValue = floatprop->GetValue();
return true;
}
bool mitk::DataNode::GetStringProperty(const char* propertyKey, std::string& string, mitk::BaseRenderer* renderer) const
{
mitk::StringProperty::Pointer stringProp = dynamic_cast<mitk::StringProperty*>(GetProperty(propertyKey, renderer));
if(stringProp.IsNull())
{
return false;
}
else
{
//memcpy((void*)string, stringProp->GetValue(), strlen(stringProp->GetValue()) + 1 ); // looks dangerous
string = stringProp->GetValue();
return true;
}
}
bool mitk::DataNode::GetColor(float rgb[3], mitk::BaseRenderer* renderer, const char* propertyKey) const
{
mitk::ColorProperty::Pointer colorprop = dynamic_cast<mitk::ColorProperty*>(GetProperty(propertyKey, renderer));
if(colorprop.IsNull())
return false;
memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float));
return true;
}
bool mitk::DataNode::GetOpacity(float &opacity, mitk::BaseRenderer* renderer, const char* propertyKey) const
{
mitk::FloatProperty::Pointer opacityprop = dynamic_cast<mitk::FloatProperty*>(GetProperty(propertyKey, renderer));
if(opacityprop.IsNull())
return false;
opacity=opacityprop->GetValue();
return true;
}
bool mitk::DataNode::GetLevelWindow(mitk::LevelWindow &levelWindow, mitk::BaseRenderer* renderer, const char* propertyKey) const
{
mitk::LevelWindowProperty::Pointer levWinProp = dynamic_cast<mitk::LevelWindowProperty*>(GetProperty(propertyKey, renderer));
if(levWinProp.IsNull())
return false;
levelWindow=levWinProp->GetLevelWindow();
return true;
}
void mitk::DataNode::SetColor(const mitk::Color &color, mitk::BaseRenderer* renderer, const char* propertyKey)
{
mitk::ColorProperty::Pointer prop;
prop = mitk::ColorProperty::New(color);
GetPropertyList(renderer)->SetProperty(propertyKey, prop);
}
void mitk::DataNode::SetColor(float red, float green, float blue, mitk::BaseRenderer* renderer, const char* propertyKey)
{
float color[3];
color[0]=red;
color[1]=green;
color[2]=blue;
SetColor(color, renderer, propertyKey);
}
void mitk::DataNode::SetColor(const float rgb[3], mitk::BaseRenderer* renderer, const char* propertyKey)
{
mitk::ColorProperty::Pointer prop;
prop = mitk::ColorProperty::New(rgb);
GetPropertyList(renderer)->SetProperty(propertyKey, prop);
}
void mitk::DataNode::SetVisibility(bool visible, mitk::BaseRenderer* renderer, const char* propertyKey)
{
mitk::BoolProperty::Pointer prop;
prop = mitk::BoolProperty::New(visible);
GetPropertyList(renderer)->SetProperty(propertyKey, prop);
}
void mitk::DataNode::SetOpacity(float opacity, mitk::BaseRenderer* renderer, const char* propertyKey)
{
mitk::FloatProperty::Pointer prop;
prop = mitk::FloatProperty::New(opacity);
GetPropertyList(renderer)->SetProperty(propertyKey, prop);
}
void mitk::DataNode::SetLevelWindow(mitk::LevelWindow levelWindow, mitk::BaseRenderer* renderer, const char* propertyKey)
{
mitk::LevelWindowProperty::Pointer prop;
prop = mitk::LevelWindowProperty::New(levelWindow);
GetPropertyList(renderer)->SetProperty(propertyKey, prop);
}
void mitk::DataNode::SetIntProperty(const char* propertyKey, int intValue, mitk::BaseRenderer* renderer)
{
GetPropertyList(renderer)->SetProperty(propertyKey, mitk::IntProperty::New(intValue));
}
void mitk::DataNode::SetBoolProperty( const char* propertyKey, bool boolValue, mitk::BaseRenderer* renderer/*=NULL*/ )
{
GetPropertyList(renderer)->SetProperty(propertyKey, mitk::BoolProperty::New(boolValue));
}
void mitk::DataNode::SetFloatProperty( const char* propertyKey, float floatValue, mitk::BaseRenderer* renderer/*=NULL*/ )
{
GetPropertyList(renderer)->SetProperty(propertyKey, mitk::FloatProperty::New(floatValue));
}
void mitk::DataNode::SetStringProperty( const char* propertyKey, const char* stringValue, mitk::BaseRenderer* renderer/*=NULL*/ )
{
GetPropertyList(renderer)->SetProperty(propertyKey, mitk::StringProperty::New(stringValue));
}
void mitk::DataNode::SetProperty(const char *propertyKey,
BaseProperty* propertyValue,
const mitk::BaseRenderer* renderer)
{
GetPropertyList(renderer)->SetProperty(propertyKey, propertyValue);
}
void mitk::DataNode::ReplaceProperty(const char *propertyKey,
BaseProperty* propertyValue,
const mitk::BaseRenderer* renderer)
{
GetPropertyList(renderer)->ReplaceProperty(propertyKey, propertyValue);
}
void mitk::DataNode::AddProperty(const char *propertyKey,
BaseProperty* propertyValue,
const mitk::BaseRenderer* renderer,
bool overwrite)
{
if((overwrite) || (GetProperty(propertyKey, renderer) == NULL))
{
SetProperty(propertyKey, propertyValue, renderer);
}
}
vtkLinearTransform* mitk::DataNode::GetVtkTransform(int t) const
{
assert(m_Data.IsNotNull());
mitk::Geometry3D* geometry = m_Data->GetGeometry(t);
if(geometry == NULL)
return NULL;
return geometry->GetVtkTransform();
}
unsigned long mitk::DataNode::GetMTime() const
{
unsigned long time = Superclass::GetMTime();
if(m_Data.IsNotNull())
{
if((time < m_Data->GetMTime()) ||
((m_Data->GetSource().IsNotNull()) && (time < m_Data->GetSource()->GetMTime()))
)
{
Modified();
return Superclass::GetMTime();
}
}
return time;
}
void mitk::DataNode::SetSelected(bool selected, mitk::BaseRenderer* renderer)
{
mitk::BoolProperty::Pointer selectedProperty = dynamic_cast<mitk::BoolProperty*>(GetProperty("selected"));
if ( selectedProperty.IsNull() )
{
selectedProperty = mitk::BoolProperty::New();
selectedProperty->SetValue(false);
SetProperty("selected", selectedProperty, renderer);
}
if( selectedProperty->GetValue() != selected )
{
selectedProperty->SetValue(selected);
itk::ModifiedEvent event;
InvokeEvent( event );
}
}
/*
class SelectedEvent : public itk::ModifiedEvent
{
public:
typedef SelectedEvent Self;
typedef itk::ModifiedEvent Superclass;
SelectedEvent(DataNode* dataNode)
{ m_DataNode = dataNode; };
DataNode* GetDataNode()
{ return m_DataNode; };
virtual const char * GetEventName() const
{ return "SelectedEvent"; }
virtual bool CheckEvent(const ::itk::EventObject* e) const
{ return dynamic_cast<const Self*>(e); }
virtual ::itk::EventObject* MakeObject() const
{ return new Self(m_DataNode); }
private:
DataNode* m_DataNode;
SelectedEvent(const Self& event)
{ m_DataNode = event.m_DataNode; };
void operator=(const Self& event)
{ m_DataNode = event.m_DataNode; }
};
*/
bool mitk::DataNode::IsSelected(mitk::BaseRenderer* renderer)
{
bool selected;
if ( !GetBoolProperty("selected", selected, renderer) )
return false;
return selected;
}
void mitk::DataNode::SetInteractorEnabled( const bool& enabled )
{
if ( m_Interactor.IsNull() )
{
itkWarningMacro("Interactor is NULL. Couldn't enable or disable interaction.");
return;
}
if ( enabled )
mitk::GlobalInteraction::GetInstance()->AddInteractor( m_Interactor.GetPointer() );
else
mitk::GlobalInteraction::GetInstance()->RemoveInteractor( m_Interactor.GetPointer() );
}
void mitk::DataNode::EnableInteractor()
{
SetInteractorEnabled( true );
}
void mitk::DataNode::DisableInteractor()
{
SetInteractorEnabled( false );
}
bool mitk::DataNode::IsInteractorEnabled() const
{
return mitk::GlobalInteraction::GetInstance()->InteractorRegistered( m_Interactor.GetPointer() );
}
void mitk::DataNode::PropertyListModified( const itk::Object* /*caller*/, const itk::EventObject& )
{
Modified();
}
-#ifndef _MSC_VER
-template <typename T>
-bool mitk::DataNode::GetPropertyValue(const char* propertyKey, T & value, mitk::BaseRenderer* renderer) const
-{
- GenericProperty<T>* gp= dynamic_cast<GenericProperty<T>*>(GetProperty(propertyKey, renderer) );
- if ( gp != NULL )
- {
- value = gp->GetValue();
- return true;
- }
- return false;
-}
-
-template bool mitk::DataNode::GetPropertyValue<double>(char const*, double&, mitk::BaseRenderer*) const;
-template bool mitk::DataNode::GetPropertyValue<float>(char const*, float&, mitk::BaseRenderer*) const;
-template bool mitk::DataNode::GetPropertyValue<int>(char const*, int&, mitk::BaseRenderer*) const;
-template bool mitk::DataNode::GetPropertyValue<bool>(char const*, bool&, mitk::BaseRenderer*) const;
-
-#endif
-
diff --git a/Core/Code/DataManagement/mitkDataNode.h b/Core/Code/DataManagement/mitkDataNode.h
index 342a35a597..52e92c6126 100644
--- a/Core/Code/DataManagement/mitkDataNode.h
+++ b/Core/Code/DataManagement/mitkDataNode.h
@@ -1,529 +1,525 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef DATATREENODE_H_HEADER_INCLUDED_C1E14338
#define DATATREENODE_H_HEADER_INCLUDED_C1E14338
#include "mitkImageSource.h"
#include "mitkBaseData.h"
//#include "mitkMapper.h"
#include "mitkInteractor.h"
#ifdef MBI_NO_STD_NAMESPACE
#define MBI_STD
#include <iostream.h>
#include <fstream.h>
#else
#define MBI_STD std
#include <iostream>
#include <fstream>
#endif
#include "mitkStringProperty.h"
#include "mitkColorProperty.h"
#include "mitkPropertyList.h"
//#include "mitkMapper.h"
#include <map>
#include <set>
#include "mitkLevelWindow.h"
class vtkLinearTransform;
namespace mitk {
class BaseRenderer;
class Mapper;
//##Documentation
//## @brief Class for nodes of the DataTree
//##
//## Contains the data (instance of BaseData), a list of mappers, which can
//## draw the data, a transform (vtkTransform) and a list of properties
//## (PropertyList).
//## @ingroup DataManagement
//##
//## @todo clean up all the GetProperty methods. There are too many different flavours... Can most probably be reduced to <tt>bool GetProperty<type>(type&)</tt>
//##
//## @warning Change in semantics of SetProperty() since Aug 25th 2006. Check your usage of this method if you do
//## more with properties than just call <tt>SetProperty( "key", new SomeProperty("value") )</tt>.
class MITK_CORE_EXPORT DataNode : public itk::DataObject
{
public:
typedef mitk::Geometry3D::Pointer Geometry3DPointer;
typedef std::vector< itk::SmartPointer< Mapper > > MapperVector;
typedef std::map<const mitk::BaseRenderer*,mitk::PropertyList::Pointer> MapOfPropertyLists;
typedef std::set<std::string> GroupTagList;
mitkClassMacro(DataNode, itk::DataObject);
itkNewMacro(Self);
mitk::Mapper* GetMapper(MapperSlotId id) const;
//##Documentation
//## @brief Get the data object (instance of BaseData, e.g., an Image)
//## managed by this DataNode
BaseData* GetData() const;
//##Documentation
//## @brief Get the transformation applied prior to displaying the data as
//## a vtkTransform
//## \deprecated use GetData()->GetGeometry()->GetVtkTransform() instead
vtkLinearTransform* GetVtkTransform(int t=0) const;
//##Documentation
//## @brief Get the Interactor
Interactor* GetInteractor() const;
//##Documentation
//## @brief Set the data object (instance of BaseData, e.g., an Image)
//## managed by this DataNode
//## @warning the actor-mode of the vtkInteractor does not work any more, if the transform of the
//## data-tree-node is connected to the transform of the basedata via vtkTransform->SetInput.
virtual void SetData(mitk::BaseData* baseData);
//##Documentation
//## @brief Set the Interactor
virtual void SetInteractor(Interactor* interactor);
mitk::DataNode& operator=(const DataNode& right);
mitk::DataNode& operator=(BaseData* right);
virtual void SetMapper(MapperSlotId id, mitk::Mapper* mapper);
virtual void UpdateOutputInformation();
virtual void SetRequestedRegionToLargestPossibleRegion();
virtual bool RequestedRegionIsOutsideOfTheBufferedRegion();
virtual bool VerifyRequestedRegion();
virtual void SetRequestedRegion(itk::DataObject *data);
virtual void CopyInformation(const itk::DataObject *data);
//##Documentation
//## @brief Set the property (instance of BaseProperty) with key @a propertyKey in the PropertyList
//## of the @a renderer (if NULL, use BaseRenderer-independent PropertyList). This is set-by-value.
//##
//## @warning Change in semantics since Aug 25th 2006. Check your usage of this method if you do
//## more with properties than just call <tt>SetProperty( "key", new SomeProperty("value") )</tt>.
//##
//## @sa GetProperty
//## @sa m_PropertyList
//## @sa m_MapOfPropertyLists
void SetProperty(const char *propertyKey, BaseProperty* property, const mitk::BaseRenderer* renderer = NULL);
//##Documentation
//## @brief Replace the property (instance of BaseProperty) with key @a propertyKey in the PropertyList
//## of the @a renderer (if NULL, use BaseRenderer-independent PropertyList). This is set-by-reference.
//##
//## If @a renderer is @a NULL the property is set in the BaseRenderer-independent
//## PropertyList of this DataNode.
//## @sa GetProperty
//## @sa m_PropertyList
//## @sa m_MapOfPropertyLists
void ReplaceProperty(const char *propertyKey, BaseProperty* property, const mitk::BaseRenderer* renderer = NULL);
//##Documentation
//## @brief Add the property (instance of BaseProperty) if it does
//## not exist (or always if \a overwrite is \a true)
//## with key @a propertyKey in the PropertyList
//## of the @a renderer (if NULL, use BaseRenderer-independent
//## PropertyList). This is set-by-value.
//##
//## For \a overwrite == \a false the property is \em not changed
//## if it already exists. For \a overwrite == \a true the method
//## is identical to SetProperty.
//##
//## @sa SetProperty
//## @sa GetProperty
//## @sa m_PropertyList
//## @sa m_MapOfPropertyLists
void AddProperty(const char *propertyKey, BaseProperty* property, const mitk::BaseRenderer* renderer = NULL, bool overwrite = false);
//##Documentation
//## @brief Get the PropertyList of the @a renderer. If @a renderer is @a
//## NULL, the BaseRenderer-independent PropertyList of this DataNode
//## is returned.
//## @sa GetProperty
//## @sa m_PropertyList
//## @sa m_MapOfPropertyLists
mitk::PropertyList* GetPropertyList(const mitk::BaseRenderer* renderer = NULL) const;
//##Documentation
//## @brief Add values from another PropertyList.
//##
//## Overwrites values in m_PropertyList only when possible (i.e. when types are compatible).
//## If you want to allow for object type changes (replacing a "visible":BoolProperty with "visible":IntProperty,
//## set the @param replace.
//##
//## @param replace true: if @param pList contains a property "visible" of type ColorProperty and our m_PropertyList also has a "visible" property of a different type (e.g. BoolProperty), change the type, i.e. replace the objects behind the pointer.
//##
//## @sa SetProperty
//## @sa ReplaceProperty
//## @sa m_PropertyList
void ConcatenatePropertyList(PropertyList* pList, bool replace = false);
//##Documentation
//## @brief Get the property (instance of BaseProperty) with key @a propertyKey from the PropertyList
//## of the @a renderer, if available there, otherwise use the BaseRenderer-independent PropertyList.
//##
//## If @a renderer is @a NULL or the @a propertyKey cannot be found
//## in the PropertyList specific to @a renderer or is disabled there, the BaseRenderer-independent
//## PropertyList of this DataNode is queried.
//## @sa GetPropertyList
//## @sa m_PropertyList
//## @sa m_MapOfPropertyLists
mitk::BaseProperty* GetProperty(const char *propertyKey, const mitk::BaseRenderer* renderer = NULL) const;
//##Documentation
//## @brief Get the property of type T with key @a propertyKey from the PropertyList
//## of the @a renderer, if available there, otherwise use the BaseRenderer-independent PropertyList.
//##
//## If @a renderer is @a NULL or the @a propertyKey cannot be found
//## in the PropertyList specific to @a renderer or is disabled there, the BaseRenderer-independent
//## PropertyList of this DataNode is queried.
//## @sa GetPropertyList
//## @sa m_PropertyList
//## @sa m_MapOfPropertyLists
template <typename T>
bool GetProperty(itk::SmartPointer<T> &property, const char *propertyKey, const mitk::BaseRenderer* renderer = NULL) const
{
property = dynamic_cast<T *>(GetProperty(propertyKey, renderer));
return property.IsNotNull();
}
//##Documentation
//## @brief Get the property of type T with key @a propertyKey from the PropertyList
//## of the @a renderer, if available there, otherwise use the BaseRenderer-independent PropertyList.
//##
//## If @a renderer is @a NULL or the @a propertyKey cannot be found
//## in the PropertyList specific to @a renderer or is disabled there, the BaseRenderer-independent
//## PropertyList of this DataNode is queried.
//## @sa GetPropertyList
//## @sa m_PropertyList
//## @sa m_MapOfPropertyLists
template <typename T>
bool GetProperty(T* &property, const char *propertyKey, const mitk::BaseRenderer* renderer = NULL) const
{
property = dynamic_cast<T *>(GetProperty(propertyKey, renderer));
return property!=NULL;
}
//##Documentation
//## @brief Convenience access method for GenericProperty<T> properties
//## (T being the type of the second parameter)
//## @return @a true property was found
template <typename T>
bool GetPropertyValue(const char* propertyKey, T & value, mitk::BaseRenderer* renderer=NULL) const
-#ifdef _MSC_VER
{
GenericProperty<T>* gp= dynamic_cast<GenericProperty<T>*>(GetProperty(propertyKey, renderer));
if ( gp != NULL )
{
value = gp->GetValue();
return true;
}
return false;
}
-#else
- ;
-#endif
// @brief Get a set of all group tags from this node's property list
GroupTagList GetGroupTags() const;
//##Documentation
//## @brief Convenience access method for bool properties (instances of
//## BoolProperty)
//## @return @a true property was found
bool GetBoolProperty(const char* propertyKey, bool &boolValue, mitk::BaseRenderer* renderer = NULL) const;
//##Documentation
//## @brief Convenience access method for int properties (instances of
//## IntProperty)
//## @return @a true property was found
bool GetIntProperty(const char* propertyKey, int &intValue, mitk::BaseRenderer* renderer=NULL) const;
//##Documentation
//## @brief Convenience access method for float properties (instances of
//## FloatProperty)
//## @return @a true property was found
bool GetFloatProperty(const char* propertyKey, float &floatValue, mitk::BaseRenderer* renderer = NULL) const;
//##Documentation
//## @brief Convenience access method for string properties (instances of
//## StringProperty)
//## @return @a true property was found
bool GetStringProperty(const char* propertyKey, std::string& string, mitk::BaseRenderer* renderer = NULL) const;
//##Documentation
//## @brief Convenience access method for color properties (instances of
//## ColorProperty)
//## @return @a true property was found
bool GetColor(float rgb[3], mitk::BaseRenderer* renderer = NULL, const char* propertyKey = "color") const;
//##Documentation
//## @brief Convenience access method for level-window properties (instances of
//## LevelWindowProperty)
//## @return @a true property was found
bool GetLevelWindow(mitk::LevelWindow &levelWindow, mitk::BaseRenderer* renderer = NULL, const char* propertyKey = "levelwindow") const;
//##
//##Documentation
//## @brief set the node as selected
void SetSelected(bool selected, mitk::BaseRenderer* renderer=NULL);
//##
//##Documentation
//## @brief set the node as selected
//## @return @a true node is selected
bool IsSelected(mitk::BaseRenderer* renderer=NULL);
//##Documentation
//## @brief Convenience access method for accessing the name of an object (instance of
//## StringProperty with property-key "name")
//## @return @a true property was found
bool GetName(std::string& nodeName, mitk::BaseRenderer* renderer = NULL, const char* propertyKey = "name") const
{
return GetStringProperty(propertyKey, nodeName, renderer);
}
//##Documentation
//## @brief Extra convenience access method for accessing the name of an object (instance of
//## StringProperty with property-key "name").
//##
//## This method does not take the renderer specific
//## propertylists into account, because the name of an object should never be renderer specific.
//## @returns a std::string with the name of the object (content of "name" Property).
//## If there is no "name" Property, an empty string will be returned.
virtual std::string GetName() const
{
mitk::StringProperty* sp = dynamic_cast<mitk::StringProperty*>(this->GetProperty("name"));
if (sp == NULL)
return "";
return sp->GetValue();
}
//##Documentation
//## @brief Extra convenience access method to set the name of an object.
//##
//## The name will be stored in the non-renderer-specific PropertyList in a StringProperty named "name".
virtual void SetName( const char* name)
{
if (name == NULL)
return;
this->SetProperty("name", StringProperty::New(name));
}
//##Documentation
//## @brief Extra convenience access method to set the name of an object.
//##
//## The name will be stored in the non-renderer-specific PropertyList in a StringProperty named "name".
virtual void SetName( const std::string name)
{
this->SetName(name.c_str());
}
//##Documentation
//## @brief Convenience access method for visibility properties (instances
//## of BoolProperty with property-key "visible")
//## @return @a true property was found
//## @sa IsVisible
bool GetVisibility(bool &visible, mitk::BaseRenderer* renderer, const char* propertyKey = "visible") const
{
return GetBoolProperty(propertyKey, visible, renderer);
}
//##Documentation
//## @brief Convenience access method for opacity properties (instances of
//## FloatProperty)
//## @return @a true property was found
bool GetOpacity(float &opacity, mitk::BaseRenderer* renderer, const char* propertyKey = "opacity") const;
//##Documentation
//## @brief Convenience access method for boolean properties (instances
//## of BoolProperty). Return value is the value of the property. If the property is
//## not found, the value of @a defaultIsOn is returned.
//##
//## Thus, the return value has a different meaning than in the
//## GetBoolProperty method!
//## @sa GetBoolProperty
bool IsOn(const char* propertyKey, mitk::BaseRenderer* renderer, bool defaultIsOn = true) const
{
if(propertyKey==NULL)
return defaultIsOn;
GetBoolProperty(propertyKey, defaultIsOn, renderer);
return defaultIsOn;
}
//##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
//## @sa IsOn
bool IsVisible(mitk::BaseRenderer* renderer, const char* propertyKey = "visible", bool defaultIsOn = true) const
{
return IsOn(propertyKey, renderer, defaultIsOn);
}
//##Documentation
//## @brief Convenience method for setting color properties (instances of
//## ColorProperty)
void SetColor(const mitk::Color &color, mitk::BaseRenderer* renderer = NULL, const char* propertyKey = "color");
//##Documentation
//## @brief Convenience method for setting color properties (instances of
//## ColorProperty)
void SetColor(float red, float green, float blue, mitk::BaseRenderer* renderer = NULL, const char* propertyKey = "color");
//##Documentation
//## @brief Convenience method for setting color properties (instances of
//## ColorProperty)
void SetColor(const float rgb[3], mitk::BaseRenderer* renderer = NULL, const char* propertyKey = "color");
//##Documentation
//## @brief Convenience method for setting visibility properties (instances
//## of BoolProperty)
//## @param visible If set to true, the data will be rendered. If false, the render will skip this data.
//## @param renderer Specify a renderer if the visibility shall be specific to a renderer
//## @param propertykey Can be used to specify a user defined name of the visibility propery.
void SetVisibility(bool visible, mitk::BaseRenderer* renderer = NULL, const char* propertyKey = "visible");
//##Documentation
//## @brief Convenience method for setting opacity properties (instances of
//## FloatProperty)
void SetOpacity(float opacity, mitk::BaseRenderer* renderer = NULL, const char* propertyKey = "opacity");
//##Documentation
//## @brief Convenience method for setting level-window properties
//## (instances of LevelWindowProperty)
void SetLevelWindow(mitk::LevelWindow levelWindow, mitk::BaseRenderer* renderer = NULL, const char* propertyKey = "levelwindow");
//##Documentation
//## @brief Convenience method for setting int properties (instances of
//## IntProperty)
void SetIntProperty(const char* propertyKey, int intValue, mitk::BaseRenderer* renderer=NULL);
//##Documentation
//## @brief Convenience method for setting int properties (instances of
//## IntProperty)
void SetBoolProperty(const char* propertyKey, bool boolValue, mitk::BaseRenderer* renderer=NULL);
//##Documentation
//## @brief Convenience method for setting int properties (instances of
//## IntProperty)
void SetFloatProperty(const char* propertyKey, float floatValue, mitk::BaseRenderer* renderer=NULL);
//##Documentation
//## @brief Convenience method for setting int properties (instances of
//## IntProperty)
void SetStringProperty(const char* propertyKey, const char* string, mitk::BaseRenderer* renderer=NULL);
//##Documentation
//## @brief Get the timestamp of the last change of the contents of this node or
//## the referenced BaseData.
virtual unsigned long GetMTime() const;
//##Documentation
//## @brief Get the timestamp of the last change of the reference to the
//## BaseData.
unsigned long GetDataReferenceChangedTime() const
{
return m_DataReferenceChangedTime.GetMTime();
}
//##Documentation
//## @brief Adds or removes the associated interactor to mitk::GLobalInteraction.
//##
virtual void SetInteractorEnabled( const bool& enabled );
//##Documentation
//## @brief Adds the interactor to mitk::GlobalInteraction
//##
virtual void EnableInteractor();
//##Documentation
//## @brief Removes the Interactor from mitk::GlobalInteraction
//##
virtual void DisableInteractor();
//##Documentation
//## @brief Tests, if the interactor is already added to mitk::GlobalInteraction
//##
virtual bool IsInteractorEnabled() const;
protected:
DataNode();
virtual ~DataNode();
//##
//## Invoked when the property list was modified. Calls Modified() of the DataNode
virtual void PropertyListModified(const itk::Object *caller, const itk::EventObject &event);
//##Documentation
//## @brief Mapper-slots
mutable MapperVector m_Mappers;
//##Documentation
//## @brief The data object (instance of BaseData, e.g., an Image) managed
//## by this DataNode
BaseData::Pointer m_Data;
//##Documentation
//## @brief BaseRenderer-independent PropertyList
//##
//## Properties herein can be overwritten specifically for each BaseRenderer
//## by the BaseRenderer-specific properties defined in m_MapOfPropertyLists.
PropertyList::Pointer m_PropertyList;
//##Documentation
//## @brief Map associating each BaseRenderer with its own PropertyList
mutable MapOfPropertyLists m_MapOfPropertyLists;
//##Documentation
//## @brief Interactor, that handles the Interaction
Interactor::Pointer m_Interactor;
//##Documentation
//## @brief Timestamp of the last change of m_Data
itk::TimeStamp m_DataReferenceChangedTime;
unsigned long m_PropertyListModifiedObserverTag;
};
#if (_MSC_VER > 1200) || !defined(_MSC_VER)
MITK_CORE_EXPORT MBI_STD::istream& operator>>( MBI_STD::istream& i, DataNode::Pointer& dtn );
MITK_CORE_EXPORT MBI_STD::ostream& operator<<( MBI_STD::ostream& o, DataNode::Pointer& dtn);
#endif
} // namespace mitk
#if ((defined(_MSC_VER)) && (_MSC_VER <= 1200))
MITK_CORE_EXPORT MBI_STD::istream& operator>>( MBI_STD::istream& i, mitk::DataNode::Pointer& dtn );
MITK_CORE_EXPORT MBI_STD::ostream& operator<<( MBI_STD::ostream& o, mitk::DataNode::Pointer& dtn);
#endif
#endif /* DATATREENODE_H_HEADER_INCLUDED_C1E14338 */
diff --git a/Core/Code/IO/mitkImageWriter.cpp b/Core/Code/IO/mitkImageWriter.cpp
index 0448a3c66c..f97c2af03d 100644
--- a/Core/Code/IO/mitkImageWriter.cpp
+++ b/Core/Code/IO/mitkImageWriter.cpp
@@ -1,304 +1,328 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "mitkImageWriter.h"
#include "mitkItkPictureWrite.h"
#include "mitkImage.h"
#include "mitkImageTimeSelector.h"
#include "mitkPicFileWriter.h"
#include "mitkImageAccessByItk.h"
#include <itkImageIOBase.h>
#include <itkImageIOFactory.h>
mitk::ImageWriter::ImageWriter()
{
this->SetNumberOfRequiredInputs( 1 );
m_MimeType = "";
SetDefaultExtension();
}
mitk::ImageWriter::~ImageWriter()
{
}
void mitk::ImageWriter::SetDefaultExtension()
{
m_Extension = ".mhd";
}
#include <vtkConfigure.h>
#include <vtkImageData.h>
#include <vtkXMLImageDataWriter.h>
static void writeVti(const char * filename, mitk::Image* image, int t=0)
{
vtkXMLImageDataWriter * vtkwriter = vtkXMLImageDataWriter::New();
vtkwriter->SetFileName( filename );
vtkwriter->SetInput(image->GetVtkImageData(t));
vtkwriter->Write();
vtkwriter->Delete();
}
void mitk::ImageWriter::WriteByITK(mitk::Image* image, const std::string& fileName)
{
// Pictures and picture series like .png are written via a different mechanism then volume images.
// So, they are still multiplexed and thus not support vector images.
if (fileName.find(".png") != std::string::npos || fileName.find(".tif") != std::string::npos || fileName.find(".jpg") != std::string::npos)
{
AccessByItk_1( image, _mitkItkPictureWrite, fileName );
return;
}
// Implementation of writer using itkImageIO directly. This skips the use
// of templated itkImageFileWriter, which saves the multiplexing on MITK side.
unsigned int dimension = image->GetDimension();
unsigned int* dimensions = image->GetDimensions();
mitk::PixelType pixelType = image->GetPixelType();
mitk::Vector3D spacing = image->GetGeometry()->GetSpacing();
mitk::Point3D origin = image->GetGeometry()->GetOrigin();
- itk::ImageIOBase::Pointer imageIO = itk::ImageIOFactory::CreateImageIO( fileName.c_str(),
+ itk::ImageIOBase::Pointer imageIO = itk::ImageIOFactory::CreateImageIO( fileName.c_str(),
itk::ImageIOFactory::WriteMode );
if(imageIO.IsNull())
{
itkExceptionMacro(<< "Error: Could not create itkImageIO via factory for file " << fileName);
}
// Set the necessary information for imageIO
imageIO->SetNumberOfDimensions(dimension);
imageIO->SetPixelTypeInfo( *(pixelType.GetTypeId()) );
if(pixelType.GetNumberOfComponents() > 1)
imageIO->SetNumberOfComponents(pixelType.GetNumberOfComponents());
itk::ImageIORegion ioRegion( dimension );
for(unsigned int i=0; i<dimension; i++)
{
imageIO->SetDimensions(i,dimensions[i]);
imageIO->SetSpacing(i,spacing[i]);
imageIO->SetOrigin(i,origin[i]);
mitk::Vector3D direction;
direction.Set_vnl_vector(image->GetGeometry()->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(i));
vnl_vector< double > axisDirection(dimension);
for(unsigned int j=0; j<dimension; j++)
{
axisDirection[j] = direction[j]/spacing[i];
}
imageIO->SetDirection( i, axisDirection );
ioRegion.SetSize(i, image->GetLargestPossibleRegion().GetSize(i) );
ioRegion.SetIndex(i, image->GetLargestPossibleRegion().GetIndex(i) );
}
imageIO->SetIORegion(ioRegion);
imageIO->SetFileName(fileName);
const void * data = image->GetData();
imageIO->Write(data);
}
void mitk::ImageWriter::GenerateData()
{
+ const std::string& locale = "C";
+ const std::string& currLocale = setlocale( LC_ALL, NULL );
+
+ if ( locale.compare(currLocale)!=0 )
+ {
+ try
+ {
+ setlocale(LC_ALL, locale.c_str());
+ }
+ catch(...)
+ {
+ MITK_INFO << "Could not set locale " << locale;
+ }
+ }
+
if ( m_FileName == "" )
{
itkWarningMacro( << "Sorry, filename has not been set!" );
return ;
}
FILE* tempFile = fopen(m_FileName.c_str(),"w");
if (tempFile==NULL)
{
itkExceptionMacro(<<"File location not writeable");
return;
}
fclose(tempFile);
remove(m_FileName.c_str());
mitk::Image::Pointer input = const_cast<mitk::Image*>(this->GetInput());
bool vti = (m_Extension.find(".vti") != std::string::npos);
// If the extension is NOT .pic and NOT .nrrd the following block is entered
if ( m_Extension.find(".pic") == std::string::npos
&& m_Extension.find(".nrrd") == std::string::npos)
{
if(input->GetDimension() > 3)
{
int t, timesteps;
timesteps = input->GetDimension(3);
ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New();
timeSelector->SetInput(input);
mitk::Image::Pointer image = timeSelector->GetOutput();
for(t = 0; t < timesteps; ++t)
{
::itk::OStringStream filename;
timeSelector->SetTimeNr(t);
timeSelector->Update();
if(input->GetTimeSlicedGeometry()->IsValidTime(t))
{
const mitk::TimeBounds& timebounds = input->GetTimeSlicedGeometry()->GetGeometry3D(t)->GetTimeBounds();
filename << m_FileName.c_str() << "_S" << std::setprecision(0) << timebounds[0] << "_E" << std::setprecision(0) << timebounds[1] << "_T" << t << m_Extension;
}
else
{
itkWarningMacro(<<"Error on write: TimeSlicedGeometry invalid of image " << filename << ".");
filename << m_FileName.c_str() << "_T" << t << m_Extension;
}
if ( vti )
{
writeVti(filename.str().c_str(), input, t);
}
else
- {
+ {
WriteByITK(input, filename.str());
}
}
}
else if ( vti )
{
::itk::OStringStream filename;
filename << m_FileName.c_str() << m_Extension;
writeVti(filename.str().c_str(), input);
}
else
{
::itk::OStringStream filename;
filename << m_FileName.c_str() << m_Extension;
WriteByITK(input, filename.str());
}
}
else
{
// use the PicFileWriter for the .pic data type
if( m_Extension.find(".pic") != std::string::npos )
{
PicFileWriter::Pointer picWriter = PicFileWriter::New();
size_t found;
found = m_FileName.find( m_Extension ); // !!! HAS to be at the very end of the filename (not somewhere in the middle)
if( m_FileName.length() > 3 && found != m_FileName.length() - 4 )
{
//if Extension not in Filename
::itk::OStringStream filename;
filename << m_FileName.c_str() << m_Extension;
picWriter->SetFileName( filename.str().c_str() );
}
else
{
picWriter->SetFileName( m_FileName.c_str() );
}
picWriter->SetInputImage( input );
picWriter->Write();
}
// use the ITK .nrrd Image writer
if( m_Extension.find(".nrrd") != std::string::npos )
{
::itk::OStringStream filename;
filename << this->m_FileName.c_str() << this->m_Extension;
WriteByITK(input, filename.str());
}
}
m_MimeType = "application/MITK.Pic";
+
+ try
+ {
+ setlocale(LC_ALL, currLocale.c_str());
+ }
+ catch(...)
+ {
+ MITK_INFO << "Could not reset locale " << currLocale;
+ }
}
bool mitk::ImageWriter::CanWriteDataType( DataNode* input )
{
if ( input )
{
mitk::BaseData* data = input->GetData();
if ( data )
{
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>( data );
if( image.IsNotNull() )
{
//"SetDefaultExtension()" set m_Extension to ".mhd" ?????
m_Extension = ".pic";
return true;
}
}
}
return false;
}
void mitk::ImageWriter::SetInput( DataNode* input )
{
if( input && CanWriteDataType( input ) )
this->ProcessObject::SetNthInput( 0, dynamic_cast<mitk::Image*>( input->GetData() ) );
}
std::string mitk::ImageWriter::GetWritenMIMEType()
{
return m_MimeType;
}
std::vector<std::string> mitk::ImageWriter::GetPossibleFileExtensions()
{
std::vector<std::string> possibleFileExtensions;
possibleFileExtensions.push_back(".pic");
possibleFileExtensions.push_back(".bmp");
possibleFileExtensions.push_back(".dcm");
possibleFileExtensions.push_back(".DCM");
possibleFileExtensions.push_back(".dicom");
possibleFileExtensions.push_back(".DICOM");
possibleFileExtensions.push_back(".gipl");
possibleFileExtensions.push_back(".gipl.gz");
possibleFileExtensions.push_back(".mha");
possibleFileExtensions.push_back(".nii");
possibleFileExtensions.push_back(".nrrd");
possibleFileExtensions.push_back(".nhdr");
possibleFileExtensions.push_back(".png");
possibleFileExtensions.push_back(".PNG");
possibleFileExtensions.push_back(".spr");
possibleFileExtensions.push_back(".mhd");
possibleFileExtensions.push_back(".vtk");
possibleFileExtensions.push_back(".vti");
possibleFileExtensions.push_back(".hdr");
possibleFileExtensions.push_back(".png");
possibleFileExtensions.push_back(".tif");
possibleFileExtensions.push_back(".jpg");
return possibleFileExtensions;
}
std::string mitk::ImageWriter::GetFileExtension()
{
return m_Extension;
}
void mitk::ImageWriter::SetInput( mitk::Image* image )
{
this->ProcessObject::SetNthInput( 0, image );
}
const mitk::Image* mitk::ImageWriter::GetInput()
{
if ( this->GetNumberOfInputs() < 1 )
{
return NULL;
}
else
{
return static_cast< const mitk::Image * >( this->ProcessObject::GetInput( 0 ) );
}
}
diff --git a/Core/Code/IO/mitkItkImageFileReader.cpp b/Core/Code/IO/mitkItkImageFileReader.cpp
index dfb1714cda..449eed6ccf 100644
--- a/Core/Code/IO/mitkItkImageFileReader.cpp
+++ b/Core/Code/IO/mitkItkImageFileReader.cpp
@@ -1,185 +1,209 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "mitkItkImageFileReader.h"
#include "mitkConfig.h"
#include <itkImageFileReader.h>
#include <itksys/SystemTools.hxx>
#include <itksys/Directory.hxx>
#include <itkImage.h>
//#include <itkImageSeriesReader.h>
#include <itkImageFileReader.h>
#include <itkImageIOFactory.h>
#include <itkImageIORegion.h>
//#include <itkImageSeriesReader.h>
//#include <itkDICOMImageIO2.h>
//#include <itkDICOMSeriesFileNames.h>
//#include <itkGDCMImageIO.h>
//#include <itkGDCMSeriesFileNames.h>
//#include <itkNumericSeriesFileNames.h>
void mitk::ItkImageFileReader::GenerateData()
{
+ const std::string& locale = "C";
+ const std::string& currLocale = setlocale( LC_ALL, NULL );
+
+ if ( locale.compare(currLocale)!=0 )
+ {
+ try
+ {
+ setlocale(LC_ALL, locale.c_str());
+ }
+ catch(...)
+ {
+ MITK_INFO << "Could not set locale " << locale;
+ }
+ }
+
mitk::Image::Pointer image = this->GetOutput();
const unsigned int MINDIM = 2;
const unsigned int MAXDIM = 4;
MITK_INFO << "loading " << m_FileName << " via itk::ImageIOFactory... " << std::endl;
// Check to see if we can read the file given the name or prefix
if ( m_FileName == "" )
{
itkWarningMacro( << "File Type not supported!" );
return ;
}
itk::ImageIOBase::Pointer imageIO = itk::ImageIOFactory::CreateImageIO( m_FileName.c_str(), itk::ImageIOFactory::ReadMode );
if ( imageIO.IsNull() )
{
itkWarningMacro( << "File Type not supported!" );
return ;
}
// Got to allocate space for the image. Determine the characteristics of
// the image.
imageIO->SetFileName( m_FileName.c_str() );
imageIO->ReadImageInformation();
unsigned int ndim = imageIO->GetNumberOfDimensions();
if ( ndim < MINDIM || ndim > MAXDIM )
{
itkWarningMacro( << "Sorry, only dimensions 2, 3 and 4 are supported. The given file has " << ndim << " dimensions! Reading as 4D." );
ndim = MAXDIM;
}
itk::ImageIORegion ioRegion( ndim );
itk::ImageIORegion::SizeType ioSize = ioRegion.GetSize();
itk::ImageIORegion::IndexType ioStart = ioRegion.GetIndex();
unsigned int dimensions[ MAXDIM ];
dimensions[ 0 ] = 0;
dimensions[ 1 ] = 0;
dimensions[ 2 ] = 0;
dimensions[ 3 ] = 0;
float spacing[ MAXDIM ];
spacing[ 0 ] = 1.0f;
spacing[ 1 ] = 1.0f;
spacing[ 2 ] = 1.0f;
spacing[ 3 ] = 1.0f;
Point3D origin;
origin.Fill(0);
unsigned int i;
for ( i = 0; i < ndim ; ++i )
{
ioStart[ i ] = 0;
ioSize[ i ] = imageIO->GetDimensions( i );
if(i<MAXDIM)
{
dimensions[ i ] = imageIO->GetDimensions( i );
spacing[ i ] = imageIO->GetSpacing( i );
if(spacing[ i ] <= 0)
spacing[ i ] = 1.0f;
}
if(i<3)
{
origin[ i ] = imageIO->GetOrigin( i );
}
}
ioRegion.SetSize( ioSize );
ioRegion.SetIndex( ioStart );
MITK_INFO << "ioRegion: " << ioRegion << std::endl;
imageIO->SetIORegion( ioRegion );
void* buffer = new unsigned char[imageIO->GetImageSizeInBytes()];
imageIO->Read( buffer );
//mitk::Image::Pointer image = mitk::Image::New();
if((ndim==4) && (dimensions[3]<=1))
ndim = 3;
if((ndim==3) && (dimensions[2]<=1))
ndim = 2;
mitk::PixelType pixelType( imageIO->GetComponentTypeInfo(), imageIO->GetNumberOfComponents(), imageIO->GetPixelType() );
image->Initialize( pixelType, ndim, dimensions );
image->SetImportChannel( buffer, 0, Image::ManageMemory );
// access direction of itk::Image and include spacing
mitk::Matrix3D matrix;
matrix.SetIdentity();
unsigned int j, itkDimMax3 = (ndim >= 3? 3 : ndim);
for ( i=0; i < itkDimMax3; ++i)
for( j=0; j < itkDimMax3; ++j )
matrix[i][j] = imageIO->GetDirection(j)[i];
// re-initialize PlaneGeometry with origin and direction
PlaneGeometry* planeGeometry = static_cast<PlaneGeometry*>(image->GetSlicedGeometry(0)->GetGeometry2D(0));
planeGeometry->SetOrigin(origin);
planeGeometry->GetIndexToWorldTransform()->SetMatrix(matrix);
// re-initialize SlicedGeometry3D
SlicedGeometry3D* slicedGeometry = image->GetSlicedGeometry(0);
slicedGeometry->InitializeEvenlySpaced(planeGeometry, image->GetDimension(2));
slicedGeometry->SetSpacing(spacing);
// re-initialize TimeSlicedGeometry
image->GetTimeSlicedGeometry()->InitializeEvenlyTimed(slicedGeometry, image->GetDimension(3));
buffer = NULL;
MITK_INFO << "number of image components: "<< image->GetPixelType().GetNumberOfComponents() << std::endl;
// mitk::DataNode::Pointer node = this->GetOutput();
// node->SetData( image );
// add level-window property
//if ( image->GetPixelType().GetNumberOfComponents() == 1 )
//{
// SetDefaultImageProperties( node );
- //}
+ //}
MITK_INFO << "...finished!" << std::endl;
+
+ try
+ {
+ setlocale(LC_ALL, currLocale.c_str());
+ }
+ catch(...)
+ {
+ MITK_INFO << "Could not reset locale " << currLocale;
+ }
}
-bool mitk::ItkImageFileReader::CanReadFile(const std::string filename, const std::string filePrefix, const std::string filePattern)
+bool mitk::ItkImageFileReader::CanReadFile(const std::string filename, const std::string filePrefix, const std::string filePattern)
{
// First check the extension
if( filename == "" )
return false;
// check if image is serie
if( filePattern != "" && filePrefix != "" )
return false;
itk::ImageIOBase::Pointer imageIO = itk::ImageIOFactory::CreateImageIO( filename.c_str(), itk::ImageIOFactory::ReadMode );
if ( imageIO.IsNull() )
return false;
return true;
}
mitk::ItkImageFileReader::ItkImageFileReader()
: m_FileName(""), m_FilePrefix(""), m_FilePattern("")
{
}
mitk::ItkImageFileReader::~ItkImageFileReader()
{
}
diff --git a/Core/Code/Interactions/StateMachine.xml b/Core/Code/Interactions/StateMachine.xml
index fd3f3ddaef..e67dbf4b6d 100644
--- a/Core/Code/Interactions/StateMachine.xml
+++ b/Core/Code/Interactions/StateMachine.xml
@@ -1,3766 +1,3841 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Event_Id = 0: this is a * transition with all other eventId's not declared in that state -->
<mitkInteraktionStates xmlns="http://tempuri.org/StateMachine.xsd" STYLE="User001">
<!-- ***WARNING*** do not use any &, % and so on in NAME -->
<!-- -->
<!-- -->
<!-- EventDescriptions -->
<events STYLE="standard">
<!-- Null Event -->
<!-- not here defined, cause this will never be send from external to mitk (to be mapped in mitkEventMapper to an mitk-event)-->
<!-- left MouseButton -->
<event NAME="left MouseBN" ID="1" TYPE="Type_MouseButtonPress" BUTTON="BS_LeftButton" BUTTONSTATE="0x0000" KEY="Key_none" />
<!-- right MouseButton -->
<event NAME="right MouseBN" ID="2" TYPE="Type_MouseButtonPress" BUTTON="BS_RightButton" BUTTONSTATE="0x0000" KEY="Key_none" />
<!-- Shift + left MouseButton -->
<event NAME="left MouseBN + Shift" ID="3" TYPE="Type_MouseButtonPress" BUTTON="BS_LeftButton" BUTTONSTATE="0x0100" KEY="Key_none" />
<!-- middle MouseButton -->
<event NAME="middle MouseBN" ID="4" TYPE="Type_MouseButtonPress" BUTTON="BS_MidButton" BUTTONSTATE="0x0000" KEY="Key_none" />
<!-- Ctrl + left MouseButton -->
<event NAME="CTRL+leftBN" ID="5" TYPE="Type_MouseButtonPress" BUTTON="BS_LeftButton" BUTTONSTATE="0x0200" KEY="Key_none" />
<!-- Ctrl + middle MouseButton -->
<event NAME="CTRL+middleBN" ID="6" TYPE="Type_MouseButtonPress" BUTTON="BS_MidButton" BUTTONSTATE="0x0200" KEY="Key_none" />
<!-- Ctrl + right MouseButton -->
<event NAME="CTRL+rightBN" ID="7" TYPE="Type_MouseButtonPress" BUTTON="BS_RightButton" BUTTONSTATE="0x0200" KEY="Key_none" />
<!-- left MouseButton DoubleClick-->
<event NAME="left MouseBN DC" ID="8" TYPE="Type_MouseButtonDblClick" BUTTON="BS_LeftButton" BUTTONSTATE="0x0000" KEY="Key_none" />
<!-- MouseWheel-->
<event NAME="MouseWheel" ID="9" TYPE="Type_Wheel" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_none" />
<!-- Strg + N -->
<event NAME="Strg + N" ID="10" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0200" KEY="Key_N" />
<!-- Strg + E -->
<event NAME="Strg + E" ID="11" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0200" KEY="Key_E" />
<!-- Delete -->
<event NAME="Delete" ID="12" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_Delete" />
<!-- Esc -->
<event NAME="Escape" ID="14" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_Escape" />
<!-- N-->
<event NAME="N" ID="13" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_N" />
<!-- P-->
<event NAME="P" ID="15" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_P" />
<!-- R-->
<event NAME="R" ID="16" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_R" />
<!-- T-->
<event NAME="T" ID="17" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_T" />
<!-- S-->
<event NAME="S" ID="18" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_S" />
<!-- E -->
<event NAME="E" ID="19" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_E" />
<!-- Strg + Alt + A -->
<event NAME="Strg+Alt+A" ID="20" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0600" KEY="Key_A" />
<!-- Strg + Alt + B -->
<event NAME="Strg+Alt+B" ID="21" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0600" KEY="Key_B" />
<!-- H-->
<event NAME="H" ID="22" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_H" />
<!-- Return -->
<event NAME="Return" ID="23" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_Return" />
<!-- Enter -->
<event NAME="Enter" ID="24" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_Enter" />
<!-- Space -->
<event NAME="Space" ID="25" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_Space" />
<!-- Plus -->
<event NAME="Plus" ID="26" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_Plus" />
<!-- Minus -->
<event NAME="Minus" ID="27" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_Minus" />
<!-- Strg + Alt + H -->
<event NAME="Strg+Alt+H" ID="30" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0600" KEY="Key_H" />
<!-- Strg + Alt + I -->
<event NAME="Strg+Alt+I" ID="31" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0600" KEY="Key_I" />
<!-- Strg + Alt + S -->
<event NAME="Strg+Alt+S" ID="40" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0600" KEY="Key_S" />
<!-- ArrowUp -->
<event NAME="ArrowUp" ID="50" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_Up" />
<!-- ArrowDown -->
<event NAME="ArrowDown" ID="51" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_Down" />
<!-- ArrowLeft -->
<event NAME="ArrowLeft" ID="52" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_Left" />
<!-- ArrowRight -->
<event NAME="ArrowRight" ID="53" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_Right" />
<!-- ArrowUp + Shift -->
<event NAME="ArrowUp+Shift" ID="54" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0100" KEY="Key_Up" />
<!-- ArrowDown +Shift -->
<event NAME="ArrowDown+Shift" ID="55" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0100" KEY="Key_Down" />
<!-- Alt -->
<event NAME="Alt" ID="90" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0400" KEY="Key_Alt" />
<!-- Strg + B -->
<event NAME="Strg+B" ID="91" TYPE="Type_KeyPress" BUTTON="BS_NoButton" BUTTONSTATE="0x0200" KEY="Key_B" />
<!-- leftMouseButtonRelease -->
<event NAME="leftMouseRelease" ID="505" TYPE="Type_MouseButtonRelease" BUTTON="BS_LeftButton" BUTTONSTATE="0x0001" KEY="Key_none" />
<!-- MiddleMouseButtonRelease -->
<event NAME="MiddleMouseRelease" ID="506" TYPE="Type_MouseButtonRelease" BUTTON="BS_MidButton" BUTTONSTATE="0x0004" KEY="Key_none" />
<!-- RightMouseButtonRelease -->
<event NAME="RightMouseRelease" ID="507" TYPE="Type_MouseButtonRelease" BUTTON="BS_RightButton" BUTTONSTATE="0x0002" KEY="Key_none" />
<!-- Shift + left MouseButtonRelease -->
<event NAME="left MouseBNRelease+Shift" ID="508" TYPE="Type_MouseButtonRelease" BUTTON="BS_LeftButton" BUTTONSTATE="0x0101" KEY="Key_none" />
<!-- MouseMove -->
<event NAME="MouseMove" ID="520" TYPE="Type_MouseMove" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_none" />
<!-- left MouseButton and MouseWheel -->
<event NAME="leftBN+MouseWheel" ID="521" TYPE="Type_Wheel" BUTTON="BS_LeftButton" BUTTONSTATE="0x0001" KEY="Key_none" />
<!-- right MouseButton and MouseWheel -->
<event NAME="rightBN+MouseWheel" ID="522" TYPE="Type_Wheel" BUTTON="BS_RightButton" BUTTONSTATE="0x0002" KEY="Key_none" />
<!-- middle MouseButton and MouseWheel -->
<event NAME="middleBN+MouseWheel" ID="523" TYPE="Type_Wheel" BUTTON="BS_MidButton" BUTTONSTATE="0x0004" KEY="Key_none" />
<!-- left MouseButton and MouseMove -->
<event NAME="leftBN+MouseMove" ID="530" TYPE="Type_MouseMove" BUTTON="BS_NoButton" BUTTONSTATE="0x0001" KEY="Key_none" />
<!-- right MouseButton and MouseMove -->
<event NAME="rightBN+MouseMove" ID="531" TYPE="Type_MouseMove" BUTTON="BS_NoButton" BUTTONSTATE="0x0002" KEY="Key_none" />
<!-- middle MouseButton and MouseMove -->
<event NAME="middleBN+MouseMove" ID="533" TYPE="Type_MouseMove" BUTTON="BS_NoButton" BUTTONSTATE="0x0004" KEY="Key_none" />
<!-- CTRL + left MouseButton and MouseMove -->
<event NAME="CTRL+leftBN+MouseMove" ID="534" TYPE="Type_MouseMove" BUTTON="BS_NoButton" BUTTONSTATE="0x0201" KEY="Key_none" />
<!-- CTRL + right MouseButton and MouseMove -->
<event NAME="CTRL+rightBN+MouseMove" ID="535" TYPE="Type_MouseMove" BUTTON="BS_NoButton" BUTTONSTATE="0x0202" KEY="Key_none" />
<!-- CTRL + middle MouseButton and MouseMove -->
<event NAME="CTRL+middleBN+MouseMove" ID="536" TYPE="Type_MouseMove" BUTTON="BS_NoButton" BUTTONSTATE="0x0204" KEY="Key_none" />
<!-- CTRL + left MouseButtonRelease -->
<event NAME="CTRL+leftBNRelease" ID="537" TYPE="Type_MouseButtonRelease" BUTTON="BS_LeftButton" BUTTONSTATE="0x0201" KEY="Key_none" />
<!-- CTRL + right MouseButtonRelease -->
<event NAME="CTRL+rightBNRelease" ID="538" TYPE="Type_MouseButtonRelease" BUTTON="BS_RightButton" BUTTONSTATE="0x0202" KEY="Key_none" />
<!-- CTRL + middle MouseButtonRelease -->
<event NAME="CTRL+middleBNRelease" ID="539" TYPE="Type_MouseButtonRelease" BUTTON="BS_MidButton" BUTTONSTATE="0x0204" KEY="Key_none" />
<!-- Shift + Ctrl + left MouseButton -->
<event NAME="SHIFT+CTRL+MousePress" ID="540" TYPE="Type_MouseButtonPress" BUTTON="BS_LeftButton" BUTTONSTATE="0x0300" KEY="Key_none" />
<!-- Shift + Ctrl + left MouseButtonMove -->
<event NAME="SHIFT+CTRL+MouseMove" ID="542" TYPE="Type_MouseMove" BUTTON="BS_NoButton" BUTTONSTATE="0x0301" KEY="Key_none" />
<!-- Shift + Ctrl + left MouseButtonRelease -->
<event NAME="SHIFT+CTRL+MouseRelease" ID="543" TYPE="Type_MouseButtonRelease" BUTTON="BS_LeftButton" BUTTONSTATE="0x0301" KEY="Key_none" />
<!-- Shift + left MouseButton and MouseMove -->
<event NAME="Shift+leftBN+MouseMove" ID="541" TYPE="Type_MouseMove" BUTTON="BS_NoButton" BUTTONSTATE="0x0101" KEY="Key_none" />
<!-- ALT + left MouseButton -->
<event NAME="ALT+leftBN" ID="600" TYPE="Type_MouseButtonPress" BUTTON="BS_LeftButton" BUTTONSTATE="0x0400" KEY="Key_none" />
<!-- ALT + left MouseButton and MouseMove -->
<event NAME="ALT+leftBN+MouseMove" ID="610" TYPE="Type_MouseMove" BUTTON="BS_NoButton" BUTTONSTATE="0x0401" KEY="Key_none" />
<!-- ALT + leftMouseButtonRelease -->
<event NAME="ALT+leftMouseRelease" ID="620" TYPE="Type_MouseButtonRelease" BUTTON="BS_LeftButton" BUTTONSTATE="0x0401" KEY="Key_none" />
+ <!-- CTRL + MouseWheel -->
+ <event NAME="CTRL+MouseWheel" ID="630" TYPE="Type_Wheel" BUTTON="BS_NoButton" BUTTONSTATE="0x0200" KEY="Key_none" />
+ <!-- ALT + MouseWheel -->
+ <event NAME="ALT+MouseWheel" ID="640" TYPE="Type_Wheel" BUTTON="BS_NoButton" BUTTONSTATE="0x0400" KEY="Key_none" />
+ <!-- ALT + middle MouseButton -->
+ <event NAME="ALT+middleBN" ID="641" TYPE="Type_MouseButtonPress" BUTTON="BS_MidButton" BUTTONSTATE="0x0400" KEY="Key_none" />
+ <!-- ALT + middle MouseButton and MouseMove -->
+ <event NAME="ALT+middleBN+MouseMove" ID="642" TYPE="Type_MouseMove" BUTTON="BS_NoButton" BUTTONSTATE="0x0404" KEY="Key_none" />
+ <!-- ALT + middle MouseButtonRelease -->
+ <event NAME="ALT+middleBNRelease" ID="643" TYPE="Type_MouseButtonRelease" BUTTON="BS_MidButton" BUTTONSTATE="0x0404" KEY="Key_none" />
+ <!-- ALT + SHIFT + right MouseButton -->
+ <event NAME="ALT+SHIFT+rightBN" ID="644" TYPE="Type_MouseButtonPress" BUTTON="BS_RightButton" BUTTONSTATE="0x0500" KEY="Key_none" />
+ <!-- ALT + SHIFT + right MouseButton and MouseMove -->
+ <event NAME="ALT+SHIFT+rightBN+MouseMove" ID="645" TYPE="Type_MouseMove" BUTTON="BS_NoButton" BUTTONSTATE="0x0502" KEY="Key_none" />
+ <!-- ALT + SHIFT + right MouseButtonRelease -->
+ <event NAME="ALT+SHIFT+rightBN" ID="646" TYPE="Type_MouseButtonRelease" BUTTON="BS_RightButton" BUTTONSTATE="0x0502" KEY="Key_none" />
<!-- SHIFT + rightMouseButtonPress -->
<event NAME="Shift+rightMousePress" ID="2000" TYPE="Type_MouseButtonPress" BUTTON="BS_RightButton" BUTTONSTATE="0x0100" KEY="Key_none" />
<!-- SHIFT + rightMouseButtonMove -->
<event NAME="Shift+rightMouseMove" ID="2001" TYPE="Type_MouseMove" BUTTON="BS_NoButton" BUTTONSTATE="0x0102" KEY="Key_none" />
<!-- SHIFT + rightMouseButtonRelease -->
<event NAME="Shift+rightMouseRelease" ID="2002" TYPE="Type_MouseButtonRelease" BUTTON="BS_RightButton" BUTTONSTATE="0x0102" KEY="Key_none" />
<!-- SHIFT + middleMouseButtonPress -->
<event NAME="Shift+middleMousePress" ID="2003" TYPE="Type_MouseButtonPress" BUTTON="BS_MidButton" BUTTONSTATE="0x0100" KEY="Key_none" />
<!-- SHIFT + middleMouseButtonMove -->
<event NAME="Shift+middleMouseMove" ID="2004" TYPE="Type_MouseMove" BUTTON="BS_NoButton" BUTTONSTATE="0x0104" KEY="Key_none" />
<!-- SHIFT + middleMouseButtonRelease -->
<event NAME="Shift+middleMouseRelease" ID="2005" TYPE="Type_MouseButtonRelease" BUTTON="BS_MidButton" BUTTONSTATE="0x0104" KEY="Key_none" />
<!-- -->
<!-- -->
<!-- own thrown events -->
<!-- *****Important*****: has to be set in mitkInteractionConst.h-->
<event NAME="new" ID="1000" TYPE="Type_User" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_none" />
<event NAME="old" ID="1001" TYPE="Type_User" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_none" />
<event NAME="finished" ID="1002" TYPE="Type_User" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_none" />
<event NAME="StSELECT" ID="1003" TYPE="Type_User" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_none" />
<event NAME="StDESELECT" ID="1004" TYPE="Type_User" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_none" />
<event NAME="EIDNO" ID="1003" TYPE="Type_User" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_none" />
<event NAME="EIDYES" ID="1004" TYPE="Type_User" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_none" />
<event NAME="same" ID="1005" TYPE="Type_User" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_none" />
<event NAME="no and last object" ID="1006" TYPE="Type_User" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_none" />
<event NAME="no and not last object" ID="1007" TYPE="Type_User" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_none" />
<event NAME="last" ID="1008" TYPE="Type_User" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_none" />
<event NAME="not last" ID="1009" TYPE="Type_User" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_none" />
<event NAME="SetStateMachineToSelectedMode" ID="1030" TYPE="Type_User" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_none" />
<event NAME="SetStateMachineToDeselectedMode" ID="1031" TYPE="Type_User" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_none" />
<!-- for n-PointRoi-->
<event NAME="StSMALERNMINUS1 " ID="1010" TYPE="Type_User" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_none" />
<event NAME="StLARGERNMINUS1" ID="1011" TYPE="Type_User" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_none" />
<!-- -->
<event NAME="ActivateTool" ID="1300" TYPE="Type_User" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_none" />
<!-- -->
<!-- Sonstiges -->
<!--<event NAME="PositionEvent" ID="1012" TYPE="Type_MouseButtonPress" BUTTON="BS_LeftButton" BUTTONSTATE="0x0000" KEY="Key_none" />-->
<!-- DoubleClick <event NAME="PositionEvent" ID="510" TYPE="4" BUTTON="0x0001" BUTTONSTATE="0x0000" KEY="0xffff" />-->
<!--<event NAME="StSmallerN" ID="1014" TYPE="Type_User" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_none" />-->
<!--<event NAME="StEqualsN" ID="1015" TYPE="Type_User" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_none" />-->
<!--<event NAME="StLargerN" ID="1016" TYPE="Type_User" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_none" />-->
<!-- for external thrown Events-->
<event NAME="clear" ID="1100" TYPE="Type_User" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_none" />
<!-- Puncture Application -->
<event NAME="print" ID="3001" TYPE="Type_Application" BUTTON="BS_NoButton" BUTTONSTATE="0x0000" KEY="Key_none" />
</events>
<!-- Beginning of state machine patterns-->
<!-- TutorialStep10Begin -->
<stateMachine NAME="SelectAndMoveObjectWithArrowKeys">
<state NAME="start" ID="1" START_STATE="TRUE" X_POS="3" Y_POS="40" WIDTH="100" HEIGHT="50">
<transition NAME="CheckIfObjectIsPicked" NEXT_STATE_ID="2" EVENT_ID="1">
<action ID="30" />
<!-- 30 = AcCHECKELEMENT -->
</transition>
</state>
<state NAME="Guard_IsObjectPicked" ID="2" X_POS="282" Y_POS="23" WIDTH="126" HEIGHT="50">
<transition NAME="yes" NEXT_STATE_ID="10" EVENT_ID="1004">
<action ID="65" />
<!-- AcSELECT -->
<action ID="1101" />
<!--AcMODE_SELECT-->
</transition>
<transition NAME="no" NEXT_STATE_ID="1" EVENT_ID="1003">
<action ID="75" />
<!-- AcDESELECT -->
<action ID="1100" />
<!--AcMODE_DESELECT-->
</transition>
</state>
<state NAME="object selected" ID="10" X_POS="714" Y_POS="85" WIDTH="100" HEIGHT="50">
<transition NAME="CheckIfObjectIsPicked" NEXT_STATE_ID="2" EVENT_ID="1">
<action ID="30" />
<!-- AcCHECKELEMENT -->
</transition>
<transition NAME="z+" NEXT_STATE_ID="10" EVENT_ID="50">
<action ID="92">
<!-- AcMove -->
<intParameter NAME="DIRECTION_X" VALUE="0" />
<intParameter NAME="DIRECTION_Y" VALUE="0" />
<intParameter NAME="DIRECTION_Z" VALUE="1" />
</action>
</transition>
<transition NAME="z-" NEXT_STATE_ID="10" EVENT_ID="51">
<action ID="92">
<!-- AcMove -->
<intParameter NAME="DIRECTION_X" VALUE="0" />
<intParameter NAME="DIRECTION_Y" VALUE="0" />
<intParameter NAME="DIRECTION_Z" VALUE="-1" />
</action>
</transition>
<transition NAME="x+" NEXT_STATE_ID="10" EVENT_ID="52">
<action ID="92">
<!-- AcMove -->
<intParameter NAME="DIRECTION_X" VALUE="1" />
<intParameter NAME="DIRECTION_Y" VALUE="0" />
<intParameter NAME="DIRECTION_Z" VALUE="0" />
</action>
</transition>
<transition NAME="x-" NEXT_STATE_ID="10" EVENT_ID="53">
<action ID="92">
<!-- AcMove -->
<intParameter NAME="DIRECTION_X" VALUE="-1" />
<intParameter NAME="DIRECTION_Y" VALUE="0" />
<intParameter NAME="DIRECTION_Z" VALUE="0" />
</action>
</transition>
<transition NAME="y+" NEXT_STATE_ID="10" EVENT_ID="54">
<action ID="92">
<!-- AcMove -->
<intParameter NAME="DIRECTION_X" VALUE="0" />
<intParameter NAME="DIRECTION_Y" VALUE="1" />
<intParameter NAME="DIRECTION_Z" VALUE="0" />
</action>
</transition>
<transition NAME="y-" NEXT_STATE_ID="10" EVENT_ID="55">
<action ID="92">
<!-- AcMove -->
<intParameter NAME="DIRECTION_X" VALUE="0" />
<intParameter NAME="DIRECTION_Y" VALUE="-1" />
<intParameter NAME="DIRECTION_Z" VALUE="0" />
</action>
</transition>
</state>
</stateMachine>
<!-- TutorialStep10End -->
<stateMachine NAME="AffineInteractions click to select">
<state NAME="start" ID="1" START_STATE="TRUE" X_POS="3" Y_POS="40" WIDTH="100" HEIGHT="50">
<transition NAME="leftButtonPress" NEXT_STATE_ID="2" EVENT_ID="1">
<!-- 30 = SeCHECKELEMENT -->
<action ID="30" />
</transition>
</state>
<state NAME="object selected check" ID="2" X_POS="282" Y_POS="23" WIDTH="126" HEIGHT="50">
<transition NAME="yes" NEXT_STATE_ID="10" EVENT_ID="1004">
<!-- EIDYES -->
<action ID="0" />
</transition>
<transition NAME="no" NEXT_STATE_ID="1" EVENT_ID="1003">
<!-- EIDNO -->
<action ID="0" />
</transition>
</state>
<state NAME="neutral" ID="10" X_POS="714" Y_POS="85" WIDTH="100" HEIGHT="50">
<transition NAME="leftButtonPress" NEXT_STATE_ID="20" EVENT_ID="1">
<!-- 30 = SeCHECKELEMENT -->
<action ID="30" />
</transition>
<transition NAME="rightButtonPress" NEXT_STATE_ID="31" EVENT_ID="2">
<!-- 1002 = SeSCALESTART -->
<action ID="1002" />
</transition>
<transition NAME="middleButtonPress" NEXT_STATE_ID="41" EVENT_ID="4">
<!-- 1004 = SeROTATESTART -->
<action ID="1004" />
</transition>
</state>
<state NAME="object deselect check" ID="20" X_POS="57" Y_POS="396" WIDTH="122" HEIGHT="50">
<transition NAME="yes" NEXT_STATE_ID="21" EVENT_ID="1004">
<!-- 1000 = SeTRANSLATESTART -->
<action ID="1000" />
</transition>
<transition NAME="no" NEXT_STATE_ID="1" EVENT_ID="1003">
<!-- EIDNO -->
<action ID="0" />
</transition>
</state>
<state NAME="translating" ID="21" X_POS="203" Y_POS="150" WIDTH="100" HEIGHT="50">
<transition NAME="leftButtonMove" NEXT_STATE_ID="21" EVENT_ID="530">
<!-- 1001 = SeTRANSLATE -->
<action ID="1000" />
</transition>
<transition NAME="leftButtonRelease" NEXT_STATE_ID="10" EVENT_ID="505">
<!-- 0 = no action -->
<action ID="0" />
</transition>
</state>
<state NAME="scaling" ID="31" X_POS="347" Y_POS="459" WIDTH="100" HEIGHT="50">
<transition NAME="rightButtonMove" NEXT_STATE_ID="31" EVENT_ID="531">
<!-- 1003 = SeSCALE -->
<action ID="1003" />
</transition>
<transition NAME="rightButtonRelease" NEXT_STATE_ID="10" EVENT_ID="507">
<!-- 0 = no action -->
<action ID="0" />
</transition>
</state>
<state NAME="rotating" ID="41" X_POS="657" Y_POS="465" WIDTH="100" HEIGHT="50">
<transition NAME="middleButtonMove" NEXT_STATE_ID="41" EVENT_ID="533">
<!-- 1005 = SeROTATE -->
<action ID="1005" />
</transition>
<transition NAME="middleButtonRelease" NEXT_STATE_ID="10" EVENT_ID="506">
<!-- 0 = no action -->
<action ID="0" />
</transition>
</state>
</stateMachine>
<stateMachine NAME="AffineInteractions ctrl-drag">
<!-- affine interactions standard statemachine -->
<state NAME="start" ID="0" START_STATE="TRUE" X_POS="29" Y_POS="70" WIDTH="100" HEIGHT="50">
<transition NAME="leftButtonPress" NEXT_STATE_ID="12" EVENT_ID="5">
<!-- CTRL+LBM_Down -->
<action ID="30">
<!--AcCHECKELEMENT-->
</action>
</transition>
<transition NAME="leftButtonPress" NEXT_STATE_ID="12" EVENT_ID="540">
<!-- SHIFT+CTRL+LBM_Down -->
<action ID="11">
<!--AcADD-->
</action>
</transition>
<transition NAME="middleButtonPress" NEXT_STATE_ID="14" EVENT_ID="6">
<!-- CTRL+MBM_Down -->
<action ID="30">
<!--AcCHECKELEMENT-->
</action>
</transition>
<transition NAME="rightButtonPress" NEXT_STATE_ID="13" EVENT_ID="7">
<!-- CTRL+RBM_Down -->
<action ID="30">
<!--AcCHECKELEMENT-->
</action>
</transition>
</state>
<state NAME="picked guard Translate" ID="12" X_POS="376" Y_POS="34" WIDTH="151" HEIGHT="50">
<transition NAME="yes" NEXT_STATE_ID="2" EVENT_ID="1004">
<!-- EIDYES -->
<action ID="1101">
<!--AcMODE_SELECT-->
</action>
<action ID="1000">
<!--AcTRANSLATESTART-->
</action>
</transition>
<transition NAME="no" NEXT_STATE_ID="0" EVENT_ID="1003">
<!-- StNO -->
</transition>
</state>
<state NAME="picked guard Scale" ID="13" X_POS="647" Y_POS="312" WIDTH="100" HEIGHT="50">
<transition NAME="yes" NEXT_STATE_ID="3" EVENT_ID="1004">
<!-- EIDYES -->
<action ID="1101">
<!--AcMODE_SELECT-->
</action>
<action ID="1002">
<!--AcSCALESTART-->
</action>
</transition>
<transition NAME="no" NEXT_STATE_ID="0" EVENT_ID="1003">
<!-- StNO -->
<action ID="0" />
</transition>
</state>
<state NAME="picked guard Rotate" ID="14" X_POS="33" Y_POS="467" WIDTH="110" HEIGHT="50">
<transition NAME="yes" NEXT_STATE_ID="4" EVENT_ID="1004">
<!-- EIDYES -->
<action ID="1101">
<!--AcMODE_SELECT-->
</action>
<action ID="1004" />
</transition>
<transition NAME="no" NEXT_STATE_ID="0" EVENT_ID="1003">
<!-- StNO -->
<action ID="0" />
</transition>
</state>
<state NAME="translating" ID="2" X_POS="724" Y_POS="59" WIDTH="100" HEIGHT="50">
<transition NAME="leftButtonMove" NEXT_STATE_ID="2" EVENT_ID="534">
<!-- CTRL+LBM_Move -->
<action ID="1001">
<!--AcTRANSLATE-->
</action>
</transition>
<transition NAME="leftButtonRelease" NEXT_STATE_ID="0" EVENT_ID="505">
<!-- LBM_Release-->
<action ID="1100">
<!--AcMODE_DESELECT-->
</action>
<action ID="1008">
<!--AcTRANSLATEEND-->
</action>
</transition>
<transition NAME="leftButtonRelease" NEXT_STATE_ID="0" EVENT_ID="537">
<!-- CTRL+LBM_Release -->
<action ID="1100">
<!--AcMODE_DESELECT-->
</action>
<action ID="1008">
<!--AcTRANSLATEEND-->
</action>
</transition>
</state>
<state NAME="rotating" ID="4" X_POS="371" Y_POS="481" WIDTH="100" HEIGHT="50">
<transition NAME="middleButtonMove" NEXT_STATE_ID="4" EVENT_ID="536">
<!-- CTRL+MBM_Move-->
<action ID="1005">
<!--AcROTATE-->
</action>
</transition>
<transition NAME="middleButtonRelease" NEXT_STATE_ID="0" EVENT_ID="506">
<!-- MBM_Release-->
<action ID="1100">
<!--AcMODE_DESELECT-->
</action>
<action ID="1010">
<!--AcROTATEEEND-->
</action>
</transition>
<transition NAME="middleButtonRelease" NEXT_STATE_ID="0" EVENT_ID="539">
<!-- CTRL+MBM_Release-->
<action ID="1100">
<!--AcMODE_DESELECT-->
</action>
<action ID="1010">
<!--AcROTATEEEND-->
</action>
</transition>
</state>
<state NAME="scaling" ID="3" X_POS="710" Y_POS="432" WIDTH="100" HEIGHT="50">
<transition NAME="rightButtonMove" NEXT_STATE_ID="3" EVENT_ID="535">
<!-- CTRL+RBM_Move -->
<action ID="1003">
<!--AcROTATE -->
</action>
</transition>
<transition NAME="rightButtonRelease" NEXT_STATE_ID="0" EVENT_ID="507">
<!-- RBM_Release ==> SeSCALE -->
<action ID="1100">
<!--AcMODE_DESELECT-->
</action>
<action ID="1009">
<!--AcSCALEEND-->
</action>
</transition>
<transition NAME="rightButtonRelease" NEXT_STATE_ID="0" EVENT_ID="538">
<!-- CTRL+RBM_Release ==> SeSCALE -->
<action ID="1100">
<!--AcMODE_DESELECT-->
</action>
<action ID="1009">
<!--AcSCALEEND-->
</action>
</transition>
</state>
</stateMachine>
<!-- obsolete state machine pattern to be removed in future releases
<stateMachine NAME="drag">
<state NAME="neutral" ID="1" START_STATE="TRUE" X_POS="232" Y_POS="131" WIDTH="100" HEIGHT="50">
<transition NAME="check picked" NEXT_STATE_ID="1" EVENT_ID="1">
<action ID="80" />
</transition>
<transition NAME="continue" NEXT_STATE_ID="1" EVENT_ID="530">
<action ID="90" />
</transition>
<transition NAME="exit" NEXT_STATE_ID="1" EVENT_ID="505">
<action ID="42" />
</transition>
</state>
<state NAME="picked guard" ID="2" X_POS="94" Y_POS="360" WIDTH="100" HEIGHT="50">
<transition NAME="yes" NEXT_STATE_ID="3" EVENT_ID="1004">
<action ID="0" />
</transition>
<transition NAME="no" NEXT_STATE_ID="3" EVENT_ID="1003">
<action ID="0" />
</transition>
</state>
<state NAME="move" ID="3" X_POS="368" Y_POS="289" WIDTH="100" HEIGHT="50">
<transition NAME="continue" NEXT_STATE_ID="3" EVENT_ID="530">
<action ID="90" />
</transition>
<transition NAME="exit" NEXT_STATE_ID="1" EVENT_ID="505">
<action ID="42" />
</transition>
</state>
</stateMachine>
-->
<stateMachine NAME="dragWithCtrl">
<state NAME="neutral" ID="1" START_STATE="TRUE" X_POS="439" Y_POS="166" WIDTH="100" HEIGHT="50">
<transition NAME="check picked" NEXT_STATE_ID="1" EVENT_ID="5">
<action ID="80" />
</transition>
<transition NAME="continue" NEXT_STATE_ID="1" EVENT_ID="534">
<action ID="90" />
</transition>
<transition NAME="exit" NEXT_STATE_ID="1" EVENT_ID="537">
<action ID="42" />
</transition>
<transition NAME="exit" NEXT_STATE_ID="1" EVENT_ID="505">
<action ID="42" />
</transition>
<transition NAME="remove" NEXT_STATE_ID="1" EVENT_ID="12">
<action ID="100">
<!--AcREMOVEPOINT-->
</action>
</transition>
</state>
<!-- not reached so removed!
<state NAME="picked guard" ID="2" X_POS="141" Y_POS="427" WIDTH="100" HEIGHT="50">
<transition NAME="yes" NEXT_STATE_ID="3" EVENT_ID="1004">
<action ID="0" />
</transition>
<transition NAME="no" NEXT_STATE_ID="3" EVENT_ID="1003">
<action ID="0" />
</transition>
</state>
<state NAME="move" ID="3" X_POS="560" Y_POS="381" WIDTH="100" HEIGHT="50">
<transition NAME="continue" NEXT_STATE_ID="3" EVENT_ID="534">
<action ID="90" />
</transition>
<transition NAME="exit" NEXT_STATE_ID="1" EVENT_ID="505">
<action ID="42" />
</transition>
<transition NAME="exit" NEXT_STATE_ID="1" EVENT_ID="537">
<action ID="42" />
</transition>
</state>
-->
</stateMachine>
<stateMachine NAME="focus">
<state NAME="neutral" ID="1" START_STATE="TRUE" X_POS="250" Y_POS="191" WIDTH="100" HEIGHT="50">
<transition NAME="changefocus" NEXT_STATE_ID="1" EVENT_ID="1">
<action ID="0" />
</transition>
</state>
</stateMachine>
<stateMachine NAME="global">
<!-- Behaviour the global statemachine -->
<state NAME="neutral" ID="1" START_STATE="TRUE" X_POS="203" Y_POS="168" WIDTH="100" HEIGHT="50">
<transition NAME="edit objects" NEXT_STATE_ID="2" EVENT_ID="1013" />
<!--EIDEDIT-->
<transition NAME="transmitt to all" NEXT_STATE_ID="1" EVENT_ID="0">
<!--EventId = 0-> all other events not defined here-->
<action ID="1200">
<!--AcINFORMLISTENERS-->
</action>
<action ID="1201">
<!--AcASKINTERACTORS-->
</action>
</transition>
</state>
<state NAME="edit object" ID="2" X_POS="508" Y_POS="404" WIDTH="100" HEIGHT="50">
<transition NAME="ready" NEXT_STATE_ID="1" EVENT_ID="1002" />
<!--EIDFINISHED-->
<transition NAME="transmitt to interactors only" NEXT_STATE_ID="2" EVENT_ID="0">
<action ID="1201">
<!--AcASKINTERACTORS-->
</action>
</transition>
</state>
</stateMachine>
<stateMachine NAME="leftmouse">
<state NAME="neutral" ID="1" START_STATE="TRUE" X_POS="197" Y_POS="164" WIDTH="100" HEIGHT="50">
<transition NAME="send Koordinates" NEXT_STATE_ID="1" EVENT_ID="1" SIDE_EFFECT_ID="80">
<action ID="80" />
</transition>
<transition NAME="send Koordinates Move" NEXT_STATE_ID="1" EVENT_ID="530" SIDE_EFFECT_ID="80">
<action ID="80" />
</transition>
</state>
</stateMachine>
<stateMachine NAME="measureinteractor">
<!-- Behaviour for measuring a length with lines-->
<state NAME="unbuild" ID="0" START_STATE="TRUE" X_POS="167" Y_POS="49" WIDTH="100" HEIGHT="50">
<transition NAME="forceSSD" NEXT_STATE_ID="1" EVENT_ID="3">
<action ID="5">
<!--AcINITNEWOBJECT-->
</action>
<action ID="1550">
<!--AcFORCESUBINTERACTORS-->
</action>
<action ID="1102">
<!--AcMODESUBSELECT-->
</action>
<action ID="2000">
<!--AcTRANSMITEVENT-->
</action>
</transition>
</state>
<state NAME="BuildUpSSD" ID="1" X_POS="433" Y_POS="329" WIDTH="100" HEIGHT="50">
<transition NAME="SubInteractorDeselect" NEXT_STATE_ID="10" EVENT_ID="1020">
<!-- necessary transition of the state subSelected. the event will produced from the hirachical interactor -->
<action ID="1101">
<!--AcMODEDESELECT-->
</action>
</transition>
<transition NAME="reinit" NEXT_STATE_ID="0" EVENT_ID="2">
<action ID="101" />
<action ID="1100">
<!--AcMODEDESELECT-->
</action>
</transition>
</state>
<state NAME="selected" ID="10" X_POS="617" Y_POS="56" WIDTH="100" HEIGHT="50">
<transition NAME="remove" NEXT_STATE_ID="0" EVENT_ID="12">
<action ID="101" />
<action ID="1100">
<!--AcMODEDESELECT-->
</action>
</transition>
<transition NAME="reinit" NEXT_STATE_ID="0" EVENT_ID="2">
<action ID="101" />
<action ID="1100">
<!--AcMODEDESELECT-->
</action>
</transition>
</state>
</stateMachine>
<stateMachine NAME="meshmove">
<state NAME="neutral" ID="1" START_STATE="TRUE" X_POS="193" Y_POS="74" WIDTH="100" HEIGHT="50">
<transition NAME="check picked" NEXT_STATE_ID="2" EVENT_ID="1">
<action ID="30" />
</transition>
</state>
<state NAME="picked guard" ID="2" X_POS="98" Y_POS="296" WIDTH="100" HEIGHT="50">
<transition NAME="yes" NEXT_STATE_ID="3" EVENT_ID="1004">
<action ID="0" />
</transition>
<transition NAME="no" NEXT_STATE_ID="1" EVENT_ID="1003">
<action ID="0" />
</transition>
</state>
<state NAME="move" ID="3" X_POS="467" Y_POS="276" WIDTH="100" HEIGHT="50">
<transition NAME="continue" NEXT_STATE_ID="3" EVENT_ID="530">
<action ID="90" />
</transition>
<transition NAME="exit" NEXT_STATE_ID="1" EVENT_ID="505">
<action ID="666" />
</transition>
</state>
</stateMachine>
<stateMachine NAME="navigation">
<state NAME="neutral" ID="1" START_STATE="TRUE" X_POS="189" Y_POS="175" WIDTH="100" HEIGHT="50">
<transition NAME="send Koordinates press" NEXT_STATE_ID="1" EVENT_ID="1">
<action ID="92" />
</transition>
<transition NAME="send Koordinates move" NEXT_STATE_ID="1" EVENT_ID="530">
<action ID="92" />
</transition>
<transition NAME="send Koordinates release" NEXT_STATE_ID="1" EVENT_ID="505">
<action ID="42" />
</transition>
</state>
</stateMachine>
<stateMachine NAME="PositionTracker">
<state NAME="neutral" ID="1" START_STATE="TRUE" X_POS="212" Y_POS="188" WIDTH="100" HEIGHT="50">
<transition NAME="Mouse Move" EVENT_ID="520" NEXT_STATE_ID="1">
<action ID="92">
<!--AcMove-->
</action>
</transition>
</state>
</stateMachine>
<stateMachine NAME="picking">
<state NAME="neutral" ID="1" START_STATE="TRUE" X_POS="264" Y_POS="239" WIDTH="100" HEIGHT="50">
<transition NAME="do picking" NEXT_STATE_ID="1" EVENT_ID="3">
<action ID="1003" />
</transition>
</state>
</stateMachine>
<stateMachine NAME="PressMoveRelease">
<state NAME="neutral" ID="1" START_STATE="TRUE" X_POS="197" Y_POS="183" WIDTH="100" HEIGHT="50">
<transition NAME="send Koordinates press" NEXT_STATE_ID="1" EVENT_ID="1">
<action ID="80" />
</transition>
<transition NAME="send Koordinates move" NEXT_STATE_ID="1" EVENT_ID="530">
<action ID="90" />
</transition>
<transition NAME="send Koordinates release" NEXT_STATE_ID="1" EVENT_ID="505">
<action ID="42" />
</transition>
</state>
</stateMachine>
<stateMachine NAME="PressMoveReleaseAndPointSetting">
<state NAME="neutral" ID="1" START_STATE="TRUE">
<transition NAME="press" NEXT_STATE_ID="1" EVENT_ID="1">
<action ID="80" />
</transition>
<transition NAME="Shift+press" NEXT_STATE_ID="1" EVENT_ID="3">
<action ID="10" />
</transition>
<transition NAME="move" NEXT_STATE_ID="1" EVENT_ID="530">
<action ID="90" />
</transition>
<transition NAME="release" NEXT_STATE_ID="1" EVENT_ID="505">
<action ID="42" />
</transition>
<transition NAME="ENTF" NEXT_STATE_ID="1" EVENT_ID="12">
<action ID="100" />
</transition>
</state>
</stateMachine>
<stateMachine NAME="PressMoveReleaseWithCTRLInversionAllMouseMoves">
<state NAME="neutral" ID="1" START_STATE="TRUE">
<transition NAME="press" NEXT_STATE_ID="1" EVENT_ID="1">
<action ID="80" />
</transition>
<transition NAME="CTRL+press" NEXT_STATE_ID="2" EVENT_ID="5">
<action ID="80" />
<action ID="49014" />
</transition>
<transition NAME="move w/ left button" NEXT_STATE_ID="1" EVENT_ID="530">
<action ID="90" />
</transition>
<transition NAME="move" NEXT_STATE_ID="1" EVENT_ID="520">
<action ID="90" />
</transition>
<transition NAME="CTRL+move" NEXT_STATE_ID="2" EVENT_ID="534">
<action ID="90" />
<action ID="49014" />
</transition>
<transition NAME="release" NEXT_STATE_ID="1" EVENT_ID="505">
<action ID="42" />
</transition>
<transition NAME="CTRL+release" NEXT_STATE_ID="1" EVENT_ID="537">
<action ID="49014" />
<action ID="42" />
<action ID="49014" />
</transition>
</state>
<state NAME="inverted" ID="2">
<transition NAME="CTRL+move" NEXT_STATE_ID="2" EVENT_ID="534">
<action ID="90" />
</transition>
<transition NAME="move w/o left button" NEXT_STATE_ID="1" EVENT_ID="520">
<action ID="90" />
<action ID="49014" />
</transition>
<transition NAME="move" NEXT_STATE_ID="1" EVENT_ID="530">
<action ID="90" />
<action ID="49014" />
</transition>
<transition NAME="CTRL+release" NEXT_STATE_ID="1" EVENT_ID="537">
<action ID="42" />
<action ID="49014" />
</transition>
<transition NAME="release" NEXT_STATE_ID="1" EVENT_ID="505">
<action ID="42" />
<action ID="49014" />
</transition>
</state>
</stateMachine>
<stateMachine NAME="PressMoveReleaseWithCTRLInversion">
<state NAME="neutral" ID="1" START_STATE="TRUE">
<transition NAME="press" NEXT_STATE_ID="1" EVENT_ID="1">
<action ID="80" />
</transition>
<transition NAME="CTRL+press" NEXT_STATE_ID="2" EVENT_ID="5">
<action ID="80" />
<action ID="49014" />
</transition>
<transition NAME="move w/ left button" NEXT_STATE_ID="1" EVENT_ID="530">
<action ID="90" />
</transition>
<transition NAME="CTRL+move" NEXT_STATE_ID="2" EVENT_ID="534">
<action ID="90" />
<action ID="49014" />
</transition>
<transition NAME="release" NEXT_STATE_ID="1" EVENT_ID="505">
<action ID="42" />
</transition>
<transition NAME="CTRL+release" NEXT_STATE_ID="1" EVENT_ID="537">
<action ID="49014" />
<action ID="42" />
<action ID="49014" />
</transition>
</state>
<state NAME="inverted" ID="2">
<transition NAME="CTRL+move" NEXT_STATE_ID="2" EVENT_ID="534">
<action ID="90" />
</transition>
<transition NAME="move" NEXT_STATE_ID="1" EVENT_ID="530">
<action ID="90" />
<action ID="49014" />
</transition>
<transition NAME="CTRL+release" NEXT_STATE_ID="1" EVENT_ID="537">
<action ID="42" />
<action ID="49014" />
</transition>
<transition NAME="release" NEXT_STATE_ID="1" EVENT_ID="505">
<action ID="42" />
<action ID="49014" />
</transition>
</state>
</stateMachine>
<stateMachine NAME="seedroi">
<state NAME="neutral" ID="1" START_STATE="TRUE" X_POS="381" Y_POS="315" WIDTH="100" HEIGHT="50">
<transition NAME="send Koordinates" NEXT_STATE_ID="1" EVENT_ID="3">
<action ID="80" />
</transition>
</state>
</stateMachine>
<stateMachine NAME="seedsinteractor">
<!-- Behaviour of Seed Points -->
<state NAME="drawSeeds" ID="0" START_STATE="TRUE" X_POS="125" Y_POS="102" WIDTH="100" HEIGHT="50">
<transition NAME="drawForegroundSeed" NEXT_STATE_ID="1" EVENT_ID="3">
<action ID="1101">
<!--AcMODE_SELECT-->
</action>
<action ID="45">
<!--AcINITFOREGROUND-->
</action>
<action ID="11">
<!--AcADD-->
</action>
</transition>
<transition NAME="drawBackgroundSeed" NEXT_STATE_ID="2" EVENT_ID="2000">
<action ID="1101">
<!--AcMODE_SELECT-->
</action>
<action ID="46">
<!--AcINITBACKGROUND-->
</action>
<action ID="11">
<!--AcADD-->
</action>
</transition>
<transition NAME="drawNeutralSeed" NEXT_STATE_ID="3" EVENT_ID="2003">
<action ID="1101">
<!--AcMODE_SELECT-->
</action>
<action ID="47">
<!--AcINITNEUTRAL-->
</action>
<action ID="11">
<!--AcADD-->
</action>
</transition>
</state>
<state NAME="drawForeground" ID="1" X_POS="515" Y_POS="108" WIDTH="100" HEIGHT="50">
<transition NAME="drawForegroundSeeds" NEXT_STATE_ID="1" EVENT_ID="541">
<action ID="92">
<!--AcMOVE-->
</action>
</transition>
<transition NAME="drawSeeds" NEXT_STATE_ID="0" EVENT_ID="508">
<action ID="44">
<!--AcFINISH-->
</action>
<action ID="1100">
<!--AcMODE_DESELECT-->
</action>
</transition>
</state>
<state NAME="drawBackground" ID="2" X_POS="510" Y_POS="323" WIDTH="100" HEIGHT="50">
<transition NAME="drawBackgroundSeeds" NEXT_STATE_ID="2" EVENT_ID="2001">
<action ID="92">
<!--AcMOVE-->
</action>
</transition>
<transition NAME="drawSeeds" NEXT_STATE_ID="0" EVENT_ID="2002">
<action ID="44">
<!--AcFINISH-->
</action>
<action ID="1100">
<!--AcMODE_DESELECT-->
</action>
</transition>
</state>
<state NAME="drawNeutral" ID="3" X_POS="290" Y_POS="478" WIDTH="100" HEIGHT="50">
<transition NAME="drawNeutralSeeds" NEXT_STATE_ID="3" EVENT_ID="2004">
<action ID="92">
<!--AcMOVE-->
</action>
</transition>
<transition NAME="drawSeeds" NEXT_STATE_ID="0" EVENT_ID="2005">
<action ID="44">
<!--AcFINISH-->
</action>
<action ID="1100">
<!--AcMODE_DESELECT-->
</action>
</transition>
</state>
</stateMachine>
<stateMachine NAME="vesseltreeinteraction">
<state NAME="neutral" ID="1" START_STATE="TRUE" X_POS="268" Y_POS="260" WIDTH="100" HEIGHT="50">
<transition NAME="do picking" NEXT_STATE_ID="1" EVENT_ID="5">
<action ID="1600" />
</transition>
<transition NAME="do picking" NEXT_STATE_ID="1" EVENT_ID="8">
<action ID="1600" />
</transition>
</state>
</stateMachine>
<stateMachine NAME="YetAnotherVesselTreeInteractor">
<!-- state machine for vessel TREE interaction -->
<state NAME="no-vessel-picked" ID="0" START_STATE="TRUE" X_POS="282" Y_POS="146" WIDTH="100" HEIGHT="50">
<transition NAME="checkpicked" NEXT_STATE_ID="1" EVENT_ID="5">
<action ID="30">
<!--AcCHECKELEMENT-->
</action>
</transition>
<transition NAME="checkpicked" NEXT_STATE_ID="1" EVENT_ID="8">
<action ID="30">
<!--AcCHECKELEMENT-->
</action>
</transition>
</state>
<state NAME="check-guard" ID="1" X_POS="91" Y_POS="347" WIDTH="100" HEIGHT="50">
<transition NAME="check-successful" NEXT_STATE_ID="2" EVENT_ID="1004">
<action ID="65">
<!--AcSELECT-->
</action>
</transition>
<transition NAME="check-not-successful" NEXT_STATE_ID="0" EVENT_ID="1003">
<action ID="75">
<!--AcDESELECT-->
</action>
</transition>
</state>
<state NAME="vessel-picked" ID="2" X_POS="419" Y_POS="340" WIDTH="100" HEIGHT="50">
<transition NAME="checkpicked" NEXT_STATE_ID="1" EVENT_ID="5">
<action ID="30">
<!--AcCHECKELEMENT-->
</action>
</transition>
<transition NAME="checkpicked" NEXT_STATE_ID="1" EVENT_ID="8">
<action ID="30">
<!--AcCHECKELEMENT-->
</action>
</transition>
</state>
</stateMachine>
<!-- state machine for vessel TREE interaction with multiple selection -->
<stateMachine NAME="YetAnotherVesselTreeInteractorMultipleSelection">
<state NAME="no-vessel-picked" ID="0" START_STATE="TRUE" X_POS="282" Y_POS="146" WIDTH="100" HEIGHT="50">
<transition NAME="checkpicked" NEXT_STATE_ID="1" EVENT_ID="5">
<action ID="30">
<!--AcCHECKELEMENT-->
</action>
</transition>
<transition NAME="checkpicked" NEXT_STATE_ID="1" EVENT_ID="8">
<action ID="30">
<!--AcCHECKELEMENT-->
</action>
</transition>
</state>
<state NAME="CheckPicked-GuardState" ID="1" X_POS="91" Y_POS="347" WIDTH="100" HEIGHT="50">
<transition NAME="picked-vessel" NEXT_STATE_ID="2" EVENT_ID="1004">
<action ID="65">
<!--AcSELECT-->
</action>
</transition>
<transition NAME="no-vessel-picked" NEXT_STATE_ID="0" EVENT_ID="1003">
<action ID="75">
<!--AcDESELECT-->
</action>
</transition>
</state>
<state NAME="vessel-selected" ID="2" X_POS="419" Y_POS="340" WIDTH="100" HEIGHT="50">
<transition NAME="checkpicked" NEXT_STATE_ID="3" EVENT_ID="5">
<action ID="30">
<!--AcCHECKELEMENT-->
</action>
</transition>
<transition NAME="checkpicked" NEXT_STATE_ID="1" EVENT_ID="8">
<action ID="30">
<!--AcCHECKELEMENT-->
</action>
</transition>
</state>
<state NAME="guard-add-vessel2selection" ID="3" X_POS="419" Y_POS="340" WIDTH="100" HEIGHT="50">
<transition NAME="vessel-picked" NEXT_STATE_ID="2" EVENT_ID="1004">
<action ID="61">
<!--AcSELECTANOTHEROBJECT-->
</action>
</transition>
<transition NAME="no-vessel-picked" NEXT_STATE_ID="2" EVENT_ID="1003" />
</state>
</stateMachine>
<stateMachine NAME="AriadneAssistent">
<!-- Behaviour of the AriadneAssistent -->
<state NAME="start" ID="1" START_STATE="TRUE" X_POS="500" Y_POS="530" WIDTH="100" HEIGHT="50">
<transition NAME="EV_INIT" NEXT_STATE_ID="2" EVENT_ID="5551001">
<action ID="55500010">
<!--AC_INIT-->
</action>
</transition>
</state>
<state NAME="chooseApplication" ID="2" X_POS="616" Y_POS="351" WIDTH="100" HEIGHT="50">
<transition NAME="EV_PATH_COLLECTION_SELECTED" NEXT_STATE_ID="3" EVENT_ID="5551003">
<action ID="5550001">
<!--AC_SET_NEXT_BUTTON_VISIBLE-->
</action>
</transition>
<transition NAME="EV_NAVIGATION_SELECTED" NEXT_STATE_ID="40" EVENT_ID="5551004">
<action ID="5550001">
<!--AC_SET_NEXT_BUTTON_VISIBLE-->
</action>
</transition>
</state>
<state NAME="choosePathCollection" ID="3" X_POS="657" Y_POS="23" WIDTH="126" HEIGHT="50">
<transition NAME="EV_NEXT" NEXT_STATE_ID="4" EVENT_ID="5551007">
<action ID="5550003">
<!--AC_SET_PREVIOUS_BUTTON_VISIBLE-->
</action>
<action ID="5550002">
<!--AC_SET_NEXT_BUTTON_INVISIBLE-->
</action>
<action ID="5550005">
<!--AC_SET_ASSISTAND_WIDGET_STECK-->
<intParameter NAME="WIDGET_ID" VALUE="1" />
</action>
</transition>
<transition NAME="EV_NAVIGATION_SELECTED" NEXT_STATE_ID="40" EVENT_ID="5551004" />
<transition NAME="EV_INIT" NEXT_STATE_ID="2" EVENT_ID="5551001">
<action ID="55500010">
<!--AC_INIT-->
</action>
</transition>
</state>
<state NAME="mountSensorForPathCollection" ID="4" X_POS="331" Y_POS="11" WIDTH="167" HEIGHT="50">
<transition NAME="EV_DONE" NEXT_STATE_ID="5" EVENT_ID="5551008">
<action ID="5550001">
<!--AC_SET_NEXT_BUTTON_VISIBLE-->
</action>
</transition>
<transition NAME="EV_PREVIOUS" NEXT_STATE_ID="2" EVENT_ID="5551002">
<action ID="5550004">
<!--AC_SET_PREVIOUS_BUTTON_INVISIBLE-->
</action>
<action ID="5550001">
<!--AC_SET_NEXT_BUTTON_VISIBLE-->
</action>
<action ID="55500011">
<!--AC_SET_APPLICATION_SELECTED_FALSE-->
</action>
<action ID="5550005">
<!--AC_SET_ASSISTAND_WIDGET_STECK-->
<intParameter NAME="WIDGET_ID" VALUE="0" />
</action>
</transition>
<transition NAME="EV_INIT" NEXT_STATE_ID="2" EVENT_ID="5551001">
<action ID="55500010">
<!--AC_INIT-->
</action>
</transition>
</state>
<state NAME="sensorMountedForPathCollection" ID="5" X_POS="7" Y_POS="26" WIDTH="191" HEIGHT="50">
<transition NAME="EV_NEXT" NEXT_STATE_ID="7" EVENT_ID="5551007">
<action ID="5550002">
<!--AC_SET_NEXT_BUTTON_INVISIBLE-->
</action>
<action ID="55500012">
<!--AC_SENSOR_ATTACHED-->
</action>
<action ID="5550005">
<!--AC_SET_ASSISTAND_WIDGET_STECK-->
<intParameter NAME="WIDGET_ID" VALUE="2" />
</action>
<action ID="5550008">
<!--AC_CHECK_LANDMARK_COUNT-->
<intParameter NAME="MIN_COUNT" VALUE="3" />
</action>
</transition>
<transition NAME="EV_PREVIOUS" NEXT_STATE_ID="4" EVENT_ID="5551002">
<action ID="5550009">
<!--AC_SET_DONE_FALSE-->
</action>
<action ID="5550002">
<!--AC_SET_NEXT_BUTTON_INVISIBLE-->
</action>
</transition>
<transition NAME="EV_INIT" NEXT_STATE_ID="2" EVENT_ID="5551001">
<action ID="55500010">
<!--AC_INIT-->
</action>
</transition>
</state>
<state NAME="setLandmarks" ID="6" X_POS="229" Y_POS="369" WIDTH="100" HEIGHT="50">
<transition NAME="EV_NEW_LANDMARK" NEXT_STATE_ID="7" EVENT_ID="5551009">
<action ID="5550008">
<!--AC_CHECK_LANDMARK_COUNT-->
<intParameter NAME="MIN_COUNT" VALUE="3" />
</action>
</transition>
<transition NAME="EV_PREVIOUS" NEXT_STATE_ID="4" EVENT_ID="5551002">
<action ID="5550005">
<!--AC_SET_ASSISTAND_WIDGET_STECK-->
<intParameter NAME="WIDGET_ID" VALUE="1" />
</action>
<action ID="5550009">
<!--AC_SET_DONE_FALSE-->
</action>
</transition>
<transition NAME="EV_INIT" NEXT_STATE_ID="2" EVENT_ID="5551001">
<action ID="55500010">
<!--AC_INIT-->
</action>
</transition>
</state>
<state NAME="checkCount" ID="7" X_POS="-5" Y_POS="255" WIDTH="100" HEIGHT="50">
<transition NAME="EV_READY_FOR_COLLECTING_PATH" NEXT_STATE_ID="8" EVENT_ID="5551006">
<action ID="5550001">
<!--AC_SET_NEXT_BUTTON_VISIBLE-->
</action>
</transition>
<transition NAME="EV_LESS_THEN_MIN_COUNT" NEXT_STATE_ID="6" EVENT_ID="5551005" />
<transition NAME="EV_INIT" NEXT_STATE_ID="2" EVENT_ID="5551001">
<action ID="55500010">
<!--AC_INIT-->
</action>
</transition>
</state>
<state NAME="readyForCollectingPath" ID="8" X_POS="-5" Y_POS="462" WIDTH="146" HEIGHT="50">
<transition NAME="EV_NEXT" NEXT_STATE_ID="9" EVENT_ID="5551007">
<action ID="5550005">
<!--AC_SET_ASSISTAND_WIDGET_STECK-->
<intParameter NAME="WIDGET_ID" VALUE="4" />
</action>
<action ID="55500014">
<!--AC_START_APPLICATION_TEXT-->
<stringParameter NAME="START_APPLICATION_TEXT" VALUE="Ariadne is now ready for path collection" />
</action>
<action ID="5550007">
<!--AC_SET_NEXT_BUTTON_TEXT-->
<stringParameter NAME="BUTTON_TEXT" VALUE="Start" />
</action>
</transition>
<transition NAME="EV_PREVIOUS" NEXT_STATE_ID="4" EVENT_ID="5551002">
<action ID="5550005">
<!--AC_SET_ASSISTAND_WIDGET_STECK-->
<intParameter NAME="WIDGET_ID" VALUE="1" />
</action>
<action ID="5550002">
<!--AC_SET_NEXT_BUTTON_INVISIBLE-->
</action>
<action ID="5550009">
<!--AC_SET_DONE_FALSE-->
</action>
</transition>
<transition NAME="EV_REMOVE_LANDMARK" NEXT_STATE_ID="7" EVENT_ID="5551010">
<action ID="5550002">
<!--AC_SET_NEXT_BUTTON_INVISIBLE-->
</action>
<action ID="5550007">
<!--AC_SET_NEXT_BUTTON_TEXT-->
<stringParameter NAME="BUTTON_TEXT" VALUE="&gt;" />
</action>
<action ID="5550008">
<!--AC_CHECK_LANDMARK_COUNT-->
<intParameter NAME="MIN_COUNT" VALUE="3" />
</action>
</transition>
<transition NAME="EV_INIT" NEXT_STATE_ID="2" EVENT_ID="5551001">
<action ID="55500010">
<!--AC_INIT-->
</action>
</transition>
</state>
<state NAME="collectingPath" ID="9" X_POS="30" Y_POS="607" WIDTH="100" HEIGHT="50">
<transition NAME="EV_NEXT" NEXT_STATE_ID="2" EVENT_ID="5551007">
<action ID="55500013">
<!--AC_CLOSE_ASSISTENT-->
</action>
<action ID="55500011">
<!--AC_SET_APPLICATION_SELECTED_FALSE-->
</action>
<action ID="5550002">
<!--AC_SET_NEXT_BUTTON_INVISIBLE-->
</action>
<action ID="5550004">
<!--AC_SET_PREVIOUS_BUTTON_INVISIBLE-->
</action>
<action ID="55500016">
<!--AC_START_PATHCOLLECTION-->
</action>
<action ID="5550005">
<!--AC_SET_ASSISTAND_WIDGET_STECK-->
<intParameter NAME="WIDGET_ID" VALUE="0" />
</action>
<action ID="5550007">
<!--AC_SET_NEXT_BUTTON_TEXT-->
<stringParameter NAME="BUTTON_TEXT" VALUE="&gt;" />
</action>
</transition>
<transition NAME="EV_PREVIOUS" NEXT_STATE_ID="8" EVENT_ID="5551002">
<action ID="5550005">
<!--AC_SET_ASSISTAND_WIDGET_STECK-->
<intParameter NAME="WIDGET_ID" VALUE="2" />
</action>
<action ID="5550007">
<!--AC_SET_NEXT_BUTTON_TEXT-->
<stringParameter NAME="BUTTON_TEXT" VALUE="&gt;" />
</action>
</transition>
<transition NAME="EV_INIT" NEXT_STATE_ID="2" EVENT_ID="5551001">
<action ID="55500010">
<!--AC_INIT-->
</action>
<action ID="5550007">
<!--AC_SET_NEXT_BUTTON_TEXT-->
<stringParameter NAME="BUTTON_TEXT" VALUE="&gt;" />
</action>
</transition>
</state>
<state NAME="chooseNavigation" ID="40" X_POS="1080" Y_POS="38" WIDTH="100" HEIGHT="50">
<transition NAME="EV_PATH_COLLECTION_SELECTED" NEXT_STATE_ID="3" EVENT_ID="5551003" />
<transition NAME="EV_INIT" NEXT_STATE_ID="2" EVENT_ID="5551001">
<action ID="55500010">
<!--AC_INIT-->
</action>
</transition>
<transition NAME="EV_NEXT" NEXT_STATE_ID="41" EVENT_ID="5551007">
<action ID="5550003">
<!--AC_SET_PREVIOUS_BUTTON_VISIBLE-->
</action>
<action ID="5550002">
<!--AC_SET_NEXT_BUTTON_INVISIBLE-->
</action>
<action ID="5550005">
<!--AC_SET_ASSISTAND_WIDGET_STECK-->
<intParameter NAME="WIDGET_ID" VALUE="3" />
</action>
</transition>
<transition NAME="EV_INIT" NEXT_STATE_ID="2" EVENT_ID="5551001">
<action ID="55500010">
<!--AC_INIT-->
</action>
</transition>
</state>
<state NAME="chooseData" ID="41" X_POS="1100" Y_POS="199" WIDTH="100" HEIGHT="50">
<transition NAME="EV_DONE" NEXT_STATE_ID="42" EVENT_ID="5551008">
<action ID="5550001">
<!--AC_SET_NEXT_BUTTON_VISIBLE-->
</action>
</transition>
<transition NAME="EV_PREVIOUS" NEXT_STATE_ID="2" EVENT_ID="5551002">
<action ID="5550004">
<!--AC_SET_PREVIOUS_BUTTON_INVISIBLE-->
</action>
<action ID="5550001">
<!--AC_SET_NEXT_BUTTON_VISIBLE-->
</action>
<action ID="55500011">
<!--AC_SET_APPLICATION_SELECTED_FALSE-->
</action>
<action ID="5550005">
<!--AC_SET_ASSISTAND_WIDGET_STECK-->
<intParameter NAME="WIDGET_ID" VALUE="0" />
</action>
</transition>
<transition NAME="EV_INIT" NEXT_STATE_ID="2" EVENT_ID="5551001">
<action ID="55500010">
<!--AC_INIT-->
</action>
</transition>
</state>
<state NAME="dataChoosed" ID="42" X_POS="1111" Y_POS="353" WIDTH="100" HEIGHT="50">
<transition NAME="EV_NEXT" NEXT_STATE_ID="43" EVENT_ID="5551007">
<action ID="55500017">
<!--AC_LOAD_LANDMARKS-->
</action>
<action ID="5550002">
<!--AC_SET_NEXT_BUTTON_INVISIBLE-->
</action>
<action ID="5550005">
<!--AC_SET_ASSISTAND_WIDGET_STECK-->
<intParameter NAME="WIDGET_ID" VALUE="1" />
</action>
</transition>
<transition NAME="EV_PREVIOUS" NEXT_STATE_ID="2" EVENT_ID="5551002">
<action ID="5550004">
<!--AC_SET_PREVIOUS_BUTTON_INVISIBLE-->
</action>
<action ID="5550001">
<!--AC_SET_NEXT_BUTTON_VISIBLE-->
</action>
<action ID="55500011">
<!--AC_SET_APPLICATION_SELECTED_FALSE-->
</action>
<action ID="5550005">
<!--AC_SET_ASSISTAND_WIDGET_STECK-->
<intParameter NAME="WIDGET_ID" VALUE="0" />
</action>
</transition>
<transition NAME="EV_INIT" NEXT_STATE_ID="2" EVENT_ID="5551001">
<action ID="55500010">
<!--AC_INIT-->
</action>
</transition>
</state>
<state NAME="mountSensorForNavigation" ID="43" X_POS="1059" Y_POS="473" WIDTH="144" HEIGHT="50">
<transition NAME="EV_DONE" NEXT_STATE_ID="44" EVENT_ID="5551008">
<action ID="5550001">
<!--AC_SET_NEXT_BUTTON_VISIBLE-->
</action>
</transition>
<transition NAME="EV_PREVIOUS" NEXT_STATE_ID="42" EVENT_ID="5551002">
<action ID="5550001">
<!--AC_SET_NEXT_BUTTON_VISIBLE-->
</action>
<action ID="5550005">
<!--AC_SET_ASSISTAND_WIDGET_STECK-->
<intParameter NAME="WIDGET_ID" VALUE="3" />
</action>
</transition>
<transition NAME="EV_INIT" NEXT_STATE_ID="2" EVENT_ID="5551001">
<action ID="55500010">
<!--AC_INIT-->
</action>
</transition>
</state>
<state NAME="sensorMountedForNavigation" ID="44" X_POS="844" Y_POS="613" WIDTH="100" HEIGHT="50">
<transition NAME="EV_NEXT" NEXT_STATE_ID="46" EVENT_ID="5551007">
<action ID="5550002">
<!--AC_SET_NEXT_BUTTON_INVISIBLE-->
</action>
<action ID="55500012">
<!--AC_SENSOR_ATTACHED-->
</action>
<action ID="5550005">
<!--AC_SET_ASSISTAND_WIDGET_STECK-->
<intParameter NAME="WIDGET_ID" VALUE="2" />
</action>
<action ID="5550008">
<!--AC_CHECK_LANDMARK_COUNT-->
<intParameter NAME="MIN_COUNT" VALUE="3" />
</action>
</transition>
<transition NAME="EV_PREVIOUS" NEXT_STATE_ID="43" EVENT_ID="5551002">
<action ID="5550009">
<!--AC_SET_DONE_FALSE-->
</action>
<action ID="5550002">
<!--AC_SET_NEXT_BUTTON_INVISIBLE-->
</action>
</transition>
<transition NAME="EV_INIT" NEXT_STATE_ID="2" EVENT_ID="5551001">
<action ID="55500010">
<!--AC_INIT-->
</action>
</transition>
</state>
<state NAME="setLandmarks" ID="45" X_POS="1110" Y_POS="754" WIDTH="100" HEIGHT="50">
<transition NAME="EV_NEW_LANDMARK" NEXT_STATE_ID="46" EVENT_ID="5551009">
<action ID="5550008">
<!--AC_CHECK_LANDMARK_COUNT-->
<intParameter NAME="MIN_COUNT" VALUE="3" />
</action>
</transition>
<transition NAME="EV_PREVIOUS" NEXT_STATE_ID="43" EVENT_ID="5551002">
<action ID="5550005">
<!--AC_SET_ASSISTAND_WIDGET_STECK-->
<intParameter NAME="WIDGET_ID" VALUE="3" />
</action>
<action ID="5550009">
<!--AC_SET_DONE_FALSE-->
</action>
</transition>
<transition NAME="EV_INIT" NEXT_STATE_ID="2" EVENT_ID="5551001">
<action ID="55500010">
<!--AC_INIT-->
</action>
</transition>
</state>
<state NAME="checkCount" ID="46" X_POS="615" Y_POS="748" WIDTH="100" HEIGHT="50">
<transition NAME="EV_READY_FOR_COLLECTING_PATH" NEXT_STATE_ID="47" EVENT_ID="5551006">
<action ID="5550001">
<!--AC_SET_NEXT_BUTTON_VISIBLE-->
</action>
</transition>
<transition NAME="EV_LESS_THEN_MIN_COUNT" NEXT_STATE_ID="45" EVENT_ID="5551005" />
<transition NAME="EV_INIT" NEXT_STATE_ID="2" EVENT_ID="5551001">
<action ID="55500010">
<!--AC_INIT-->
</action>
</transition>
</state>
<state NAME="readyForNavigation" ID="47" X_POS="120" Y_POS="750" WIDTH="115" HEIGHT="50">
<transition NAME="EV_NEXT" NEXT_STATE_ID="48" EVENT_ID="5551007">
<action ID="55500018">
<!--AC_CALCULATE_LANDMARK_TRANSFORM-->
</action>
<action ID="5550005">
<!--AC_SET_ASSISTAND_WIDGET_STECK-->
<intParameter NAME="WIDGET_ID" VALUE="4" />
</action>
<action ID="55500014">
<!--AC_START_APPLICATION_TEXT-->
<stringParameter NAME="START_APPLICATION_TEXT" VALUE="Ariadne is now ready for navigation" />
</action>
<action ID="5550007">
<!--AC_SET_NEXT_BUTTON_TEXT-->
<stringParameter NAME="BUTTON_TEXT" VALUE="Start" />
</action>
</transition>
<transition NAME="EV_PREVIOUS" NEXT_STATE_ID="43" EVENT_ID="5551002">
<action ID="5550005">
<!--AC_SET_ASSISTAND_WIDGET_STECK-->
<intParameter NAME="WIDGET_ID" VALUE="3" />
</action>
<action ID="5550002">
<!--AC_SET_NEXT_BUTTON_INVISIBLE-->
</action>
<action ID="5550009">
<!--AC_SET_DONE_FALSE-->
</action>
</transition>
<transition NAME="EV_REMOVE_LANDMARK" NEXT_STATE_ID="46" EVENT_ID="5551010">
<action ID="5550002">
<!--AC_SET_NEXT_BUTTON_INVISIBLE-->
</action>
<action ID="5550007">
<!--AC_SET_NEXT_BUTTON_TEXT-->
<stringParameter NAME="BUTTON_TEXT" VALUE="&gt;" />
</action>
<action ID="5550008">
<!--AC_CHECK_LANDMARK_COUNT-->
<intParameter NAME="MIN_COUNT" VALUE="3" />
</action>
</transition>
<transition NAME="EV_INIT" NEXT_STATE_ID="2" EVENT_ID="5551001">
<action ID="55500010">
<!--AC_INIT-->
</action>
</transition>
</state>
<state NAME="Navigation" ID="48" X_POS="164" Y_POS="623" WIDTH="100" HEIGHT="50">
<transition NAME="EV_NEXT" NEXT_STATE_ID="2" EVENT_ID="5551007">
<action ID="55500013">
<!--AC_CLOSE_ASSISTENT-->
</action>
<action ID="55500011">
<!--AC_SET_APPLICATION_SELECTED_FALSE-->
</action>
<action ID="5550002">
<!--AC_SET_NEXT_BUTTON_INVISIBLE-->
</action>
<action ID="5550004">
<!--AC_SET_PREVIOUS_BUTTON_INVISIBLE-->
</action>
<action ID="55500015">
<!--AC_START_NAVIGATION-->
</action>
<action ID="5550005">
<!--AC_SET_ASSISTAND_WIDGET_STECK-->
<intParameter NAME="WIDGET_ID" VALUE="0" />
</action>
<action ID="5550007">
<!--AC_SET_NEXT_BUTTON_TEXT-->
<stringParameter NAME="BUTTON_TEXT" VALUE="&gt;" />
</action>
</transition>
<transition NAME="EV_PREVIOUS" NEXT_STATE_ID="47" EVENT_ID="5551002">
<action ID="5550005">
<!--AC_SET_ASSISTAND_WIDGET_STECK-->
<intParameter NAME="WIDGET_ID" VALUE="2" />
</action>
<action ID="5550007">
<!--AC_SET_NEXT_BUTTON_TEXT-->
<stringParameter NAME="BUTTON_TEXT" VALUE="&gt;" />
</action>
</transition>
<transition NAME="EV_INIT" NEXT_STATE_ID="2" EVENT_ID="5551001">
<action ID="55500010">
<!--AC_INIT-->
</action>
<action ID="5550007">
<!--AC_SET_NEXT_BUTTON_TEXT-->
<stringParameter NAME="BUTTON_TEXT" VALUE="&gt;" />
</action>
</transition>
</state>
</stateMachine>
<stateMachine NAME="AffineInteractions ctrl-drag_marcus">
<state NAME="start" ID="0" START_STATE="TRUE" X_POS="314" Y_POS="214" WIDTH="100" HEIGHT="50">
<transition NAME="leftButtonPress" NEXT_STATE_ID="12" EVENT_ID="1">
<!-- 30 = SeCHECKELEMENT -->
<action ID="30" />
</transition>
<transition NAME="rightButtonPress" NEXT_STATE_ID="13" EVENT_ID="2">
<!-- 1002 = SeSCALESTART -->
<action ID="30" />
</transition>
<transition NAME="middleButtonPress" NEXT_STATE_ID="14" EVENT_ID="4">
<!-- 1004 = SeROTATESTART -->
<action ID="30" />
</transition>
</state>
<state NAME="picked guard Translate" ID="12" X_POS="52" Y_POS="62" WIDTH="143" HEIGHT="50">
<transition NAME="yes" NEXT_STATE_ID="2" EVENT_ID="1004">
<!-- EIDYES -->
<action ID="1000" />
</transition>
<transition NAME="no" NEXT_STATE_ID="0" EVENT_ID="1003">
<!-- StNO -->
<action ID="0" />
</transition>
</state>
<state NAME="picked guard Scale" ID="13" X_POS="848" Y_POS="233" WIDTH="100" HEIGHT="50">
<transition NAME="yes" NEXT_STATE_ID="3" EVENT_ID="1004">
<!-- EIDYES -->
<action ID="1002" />
</transition>
<transition NAME="no" NEXT_STATE_ID="0" EVENT_ID="1003">
<!-- StNO -->
<action ID="0" />
</transition>
</state>
<state NAME="picked guard Rotate" ID="14" X_POS="37" Y_POS="334" WIDTH="100" HEIGHT="50">
<transition NAME="yes" NEXT_STATE_ID="4" EVENT_ID="1004">
<!-- EIDYES -->
<action ID="1004" />
</transition>
<transition NAME="no" NEXT_STATE_ID="0" EVENT_ID="1003">
<!-- StNO -->
<action ID="0" />
</transition>
</state>
<state NAME="translating" ID="2" X_POS="481" Y_POS="47" WIDTH="100" HEIGHT="50">
<transition NAME="leftButtonMove" NEXT_STATE_ID="2" EVENT_ID="530">
<!-- 1000 = SeTRANSLATE -->
<action ID="1001" />
</transition>
<transition NAME="leftButtonRelease" NEXT_STATE_ID="0" EVENT_ID="505">
<!-- 1000 = SeTRANSLATE -->
<action ID="1001" />
</transition>
<transition NAME="leftButtonRelease" NEXT_STATE_ID="0" EVENT_ID="537">
<!-- CTRL+LBM_Release ==> SeTRANSLATE -->
<action ID="1001" />
</transition>
</state>
<state NAME="scaling" ID="3" X_POS="630" Y_POS="461" WIDTH="100" HEIGHT="50">
<transition NAME="rightButtonMove" NEXT_STATE_ID="3" EVENT_ID="531">
<!-- 1003 = SeSCALE -->
<action ID="1003" />
</transition>
<transition NAME="rightButtonRelease" NEXT_STATE_ID="0" EVENT_ID="507">
<!-- 1003 = SeSCALE -->
<action ID="1003" />
</transition>
<transition NAME="rightButtonRelease" NEXT_STATE_ID="0" EVENT_ID="538">
<!-- CTRL+RBM_Release ==> SeSCALE -->
<action ID="1003" />
</transition>
</state>
<state NAME="rotating" ID="4" X_POS="295" Y_POS="487" WIDTH="100" HEIGHT="50">
<transition NAME="middleButtonMove" NEXT_STATE_ID="4" EVENT_ID="533">
<!-- 1005 = SeROTATE -->
<action ID="1005" />
</transition>
<transition NAME="middleButtonRelease" NEXT_STATE_ID="0" EVENT_ID="506">
<!-- 1005 = SeROTATE -->
<action ID="1005" />
</transition>
<transition NAME="middleButtonRelease" NEXT_STATE_ID="0" EVENT_ID="539">
<!-- 1005 = SeROTATE -->
<action ID="1005" />
</transition>
</state>
</stateMachine>
<stateMachine NAME="connectpointsinteractor">
<!-- Behaviour for connecting points using mitk::ConnectPointsInteractor -->
<state NAME="ready" ID="1" START_STATE="TRUE" X_POS="357" Y_POS="236" WIDTH="100" HEIGHT="50">
<transition NAME="addPoint but check n" NEXT_STATE_ID="1" EVENT_ID="3">
<action ID="10">
<!--AcADDPOINT-->
</action>
</transition>
<transition NAME="remove" NEXT_STATE_ID="1" EVENT_ID="12">
<action ID="100">
<!--AcREMOVEPOINT-->
</action>
</transition>
</state>
</stateMachine>
<stateMachine NAME="coordinate-supply">
<state NAME="neutral" ID="1" START_STATE="TRUE" X_POS="439" Y_POS="228" WIDTH="100" HEIGHT="50">
<transition NAME="send Koordinates release" NEXT_STATE_ID="1" EVENT_ID="505">
<action ID="42" />
</transition>
</state>
</stateMachine>
<stateMachine NAME="EasySegmentation">
<state NAME="Checking for ActivateToolEvents" ID="0" START_STATE="TRUE" X_POS="193" Y_POS="206" WIDTH="174" HEIGHT="50">
<transition NAME="OnActivateToolEvent" EVENT_ID="1300" NEXT_STATE_ID="0">
<action ID="48009">
<!-- AcActivateTool -->
</action>
</transition>
</state>
</stateMachine>
<stateMachine NAME="segmentation-interactor-tool:movenzoom">
<state NAME="Ready to start" ID="0" START_STATE="TRUE">
<transition NAME="OnLeftMouseDown" EVENT_ID="1" NEXT_STATE_ID="3" />
<transition NAME="OnMiddleMouseDown" EVENT_ID="4" NEXT_STATE_ID="1">
<action ID="9">
<!-- AcInitMove -->
</action>
</transition>
<transition NAME="OnRightMouseDown" EVENT_ID="2" NEXT_STATE_ID="2">
<action ID="1011">
<!-- AcInitZoom -->
</action>
</transition>
</state>
<state NAME="Moving" ID="1">
<transition NAME="OnMouseMove" EVENT_ID="533" NEXT_STATE_ID="1">
<action ID="92">
<!-- AcMove -->
</action>
</transition>
<transition NAME="OnMiddleMouseUp" EVENT_ID="506" NEXT_STATE_ID="0" />
</state>
<state NAME="Zooming" ID="2">
<transition NAME="OnMouseMove" EVENT_ID="531" NEXT_STATE_ID="2">
<action ID="1012">
<!-- AcZoom -->
</action>
</transition>
<transition NAME="OnRightMouseUp" EVENT_ID="507" NEXT_STATE_ID="0" />
</state>
<state NAME="Click" ID="3">
<transition NAME="OnLeftMouseUp" EVENT_ID="505" NEXT_STATE_ID="0">
<action ID="31">
<!-- AcCheckObject -->
</action>
</transition>
</state>
</stateMachine>
<stateMachine NAME="segmentation-interactor-tool:needle">
<state NAME="Ready to start" ID="0" START_STATE="TRUE">
<transition NAME="OnMouseMove" EVENT_ID="520" NEXT_STATE_ID="0">
<action ID="49006">
<!-- AcUpdatePoint -->
</action>
</transition>
<transition NAME="OnKeyH" EVENT_ID="22" NEXT_STATE_ID="0">
<action ID="49004">
<!-- AcMovePoint1 -->
</action>
</transition>
<transition NAME="OnKeyT" EVENT_ID="17" NEXT_STATE_ID="0">
<action ID="49005">
<!-- AcMovePoint2 -->
</action>
</transition>
<transition NAME="OnKeyEsc" EVENT_ID="14" NEXT_STATE_ID="7">
<action ID="49009">
<!-- AcDisplayOptions -->
</action>
<action ID="49010">
<!-- AcCycle (cycle to first different needle) -->
</action>
</transition>
<transition NAME="OnLeftMouseDown" EVENT_ID="1" NEXT_STATE_ID="3">
<action ID="31">
<!-- AcCheckObject -->
</action>
</transition>
<transition NAME="OnMiddleMouseDown" EVENT_ID="4" NEXT_STATE_ID="1">
<action ID="9">
<!-- AcInitMove -->
</action>
</transition>
<transition NAME="OnRightMouseDown" EVENT_ID="2" NEXT_STATE_ID="2">
<action ID="1011">
<!-- AcInitZoom -->
</action>
</transition>
<transition NAME="OnShiftLeftMouseDown" EVENT_ID="3" NEXT_STATE_ID="0">
<action ID="21">
<!-- AcCheckPoint -->
</action>
</transition>
</state>
<state NAME="Moving" ID="1">
<transition NAME="OnMouseMove" EVENT_ID="533" NEXT_STATE_ID="1">
<action ID="92">
<!-- AcMove -->
</action>
</transition>
<transition NAME="OnMiddleMouseUp" EVENT_ID="506" NEXT_STATE_ID="0" />
</state>
<state NAME="Zooming" ID="2">
<transition NAME="OnMouseMove" EVENT_ID="531" NEXT_STATE_ID="2">
<action ID="1012">
<!-- AcZoom -->
</action>
</transition>
<transition NAME="OnRightMouseUp" EVENT_ID="507" NEXT_STATE_ID="0" />
</state>
<state NAME="Descision: what to drag?" ID="3">
<transition NAME="OnTip" EVENT_ID="1050" NEXT_STATE_ID="4" />
<transition NAME="OnHead" EVENT_ID="1051" NEXT_STATE_ID="5" />
<transition NAME="OnBody" EVENT_ID="1052" NEXT_STATE_ID="6" />
<transition NAME="OnNothing" EVENT_ID="1003" NEXT_STATE_ID="0" />
</state>
<state NAME="Tip dragging" ID="4">
<transition NAME="OnMouseMove" EVENT_ID="530" NEXT_STATE_ID="4">
<action ID="49002">
<!-- AcRotateAroundHead (Point1)-->
</action>
</transition>
<transition NAME="OnLeftMouseUp" EVENT_ID="505" NEXT_STATE_ID="0" />
</state>
<state NAME="Head dragging" ID="5">
<transition NAME="OnMouseMove" EVENT_ID="530" NEXT_STATE_ID="5">
<action ID="49003">
<!-- AcRotateAroundTip (Point2)-->
</action>
</transition>
<transition NAME="OnLeftMouseUp" EVENT_ID="505" NEXT_STATE_ID="0" />
</state>
<state NAME="Body dragging" ID="6">
<transition NAME="OnMouseMove" EVENT_ID="530" NEXT_STATE_ID="6">
<action ID="1001">
<!-- AcTranslate -->
</action>
</transition>
<transition NAME="OnLeftMouseUp" EVENT_ID="505" NEXT_STATE_ID="0" />
</state>
<state NAME="Needle choosing" ID="7">
<transition NAME="OnKeyEsc" EVENT_ID="14" NEXT_STATE_ID="7">
<action ID="49010">
<!-- AcCycle -->
</action>
</transition>
<transition NAME="OnKeyReturn" EVENT_ID="23" NEXT_STATE_ID="0">
<action ID="49011">
<!-- AcAccept -->
</action>
</transition>
<transition NAME="OnKeyReturn" EVENT_ID="24" NEXT_STATE_ID="0">
<action ID="49011">
<!-- AcAccept -->
</action>
</transition>
<transition NAME="OnKeySpace" EVENT_ID="25" NEXT_STATE_ID="0">
<action ID="49011">
<!-- AcAccept -->
</action>
</transition>
</state>
</stateMachine>
<stateMachine NAME="segmentation-interactor-tool:bubble">
<state NAME="Ready to start" ID="0" START_STATE="TRUE">
<!-- initial state: outside anything and checking for collisions -->
<transition NAME="OnLeftMouseDown" EVENT_ID="1" NEXT_STATE_ID="2">
<action ID="31">
<!-- AcCheckObject -->
</action>
</transition>
</state>
<state NAME="Drawing line" ID="1">
<!-- line drawing started, now always update the end point of the line -->
<transition NAME="OnEscape" EVENT_ID="14" NEXT_STATE_ID="0">
<action ID="48008">
<!-- AcCancel -->
</action>
</transition>
<transition NAME="OnMouseMove" EVENT_ID="530" NEXT_STATE_ID="1">
<action ID="48003">
<!-- AcUpdateLine -->
</action>
</transition>
<transition NAME="OnLeftMouseUp" EVENT_ID="505" NEXT_STATE_ID="0">
<action ID="48005">
<!-- AcTerminateLine -->
</action>
<action ID="48007">
<!-- AcCreateObjectFromLine -->
</action>
<action ID="48008">
<!-- AcCancel -->
</action>
</transition>
</state>
<state NAME="Decide between creating and modifying. modify?" ID="2">
<transition NAME="OnNo" EVENT_ID="1003" NEXT_STATE_ID="1">
<action ID="48004">
<!-- AcInitLine -->
</action>
</transition>
<transition NAME="OnYes" EVENT_ID="1004" NEXT_STATE_ID="6" />
</state>
<state NAME="Decide between left and right movement. Left?" ID="5">
<transition NAME="OnNo" EVENT_ID="1003" NEXT_STATE_ID="6">
<action ID="49012">
<!-- AcIncrease -->
</action>
</transition>
<transition NAME="OnYes" EVENT_ID="1004" NEXT_STATE_ID="6">
<action ID="49013">
<!-- AcDecrease -->
</action>
</transition>
</state>
<state NAME="Decide between left and right movement. Left?" ID="6">
<transition NAME="OnMouseMove" EVENT_ID="530" NEXT_STATE_ID="5">
<action ID="8">
<!-- AcInitMovement -->
</action>
</transition>
<transition NAME="OnMouseUp" EVENT_ID="505" NEXT_STATE_ID="0" />
</state>
</stateMachine>
<stateMachine NAME="pointinteractor">
<state NAME="unselected" ID="0" START_STATE="TRUE" X_POS="17" Y_POS="23" WIDTH="100" HEIGHT="50">
<transition NAME="addPoint" NEXT_STATE_ID="1" EVENT_ID="3">
<action ID="1101">
<!--AcMODESELECT-->
</action>
<action ID="10">
<!--AcADDPOINT-->
</action>
<action ID="30">
<!--AcCHECKELEMENT-->
<intParameter NAME="precision" VALUE="4" />
</action>
</transition>
<transition NAME="checkpicked" NEXT_STATE_ID="2" EVENT_ID="1">
<action ID="30">
<!--AcCHECKELEMENT-->
<intParameter NAME="precision" VALUE="4" />
</action>
</transition>
</state>
<state NAME="selected" ID="1" X_POS="663" Y_POS="89" WIDTH="100" HEIGHT="50">
<transition NAME="deselect all and add point" NEXT_STATE_ID="1" EVENT_ID="3">
<action ID="72">
<!--AcDESELECTALL-->
</action>
<action ID="10">
<!--AcADDPOINT-->
</action>
<action ID="30">
<!--AcCHECKELEMENT-->
<intParameter NAME="precision" VALUE="4" />
</action>
</transition>
<transition NAME="remove" NEXT_STATE_ID="5" EVENT_ID="12">
<action ID="1500">
<!--AcCHECKGREATERONE-->
</action>
</transition>
<transition NAME="checkSamePick" NEXT_STATE_ID="3" EVENT_ID="1">
<action ID="34">
<!--AcCHECKSELECTED-->
<intParameter NAME="precision" VALUE="4" />
</action>
</transition>
<transition NAME="deselect all" NEXT_STATE_ID="0" EVENT_ID="2000">
<action ID="72">
<!--AcDESELECTALL-->
</action>
<action ID="1100">
<!--AcMODEDESELECT-->
</action>
</transition>
</state>
<state NAME="checkpicked" ID="2" X_POS="385" Y_POS="221" WIDTH="100" HEIGHT="50">
<transition NAME="EIDNo" NEXT_STATE_ID="0" EVENT_ID="1003" />
<transition NAME="EIDYes" NEXT_STATE_ID="1" EVENT_ID="1004">
<action ID="1101">
<!--AcMODESELECT-->
</action>
<action ID="65">
<!--AcSELECT-->
</action>
</transition>
</state>
<state NAME="checkStillPicked" ID="3" X_POS="417" Y_POS="497" WIDTH="100" HEIGHT="50">
<transition NAME="EIDNo" NEXT_STATE_ID="0" EVENT_ID="1003">
<action ID="72">
<!--AcDESELECTALL-->
</action>
<action ID="1100">
<!--AcMODEDESELECT-->
</action>
</transition>
<transition NAME="EIDYes" NEXT_STATE_ID="4" EVENT_ID="1004">
<action ID="8">
<!--AcINITMOVEMENT-->
</action>
</transition>
</state>
<state NAME="moves" ID="4" X_POS="799" Y_POS="483" WIDTH="100" HEIGHT="50">
<transition NAME="mousemove" NEXT_STATE_ID="4" EVENT_ID="530">
<action ID="91">
<!--AcMOVESELECTED-->
</action>
</transition>
<transition NAME="finishmove" NEXT_STATE_ID="1" EVENT_ID="505">
<action ID="42">
<!--AcFINISHMOVEMENT-->
</action>
</transition>
</state>
<state NAME="checkGreaterOne" ID="5" X_POS="416" Y_POS="344" WIDTH="100" HEIGHT="50">
<transition NAME="StYes" NEXT_STATE_ID="1" EVENT_ID="1004">
<action ID="100">
<!--AcREMOVEPOINT-->
</action>
<action ID="61">
<!--AcSELECTANOTHEROBJECT-->
</action>
</transition>
<transition NAME="StNo" NEXT_STATE_ID="0" EVENT_ID="1003">
<action ID="100">
<!--AcREMOVEPOINT-->
</action>
<action ID="1100">
<!--AcMODEDESELECT-->
</action>
</transition>
</state>
</stateMachine>
<stateMachine NAME="pointselectorinteractor">
<state NAME="unselected" ID="0" START_STATE="TRUE" X_POS="17" Y_POS="23" WIDTH="100" HEIGHT="50">
<transition NAME="addPoint" NEXT_STATE_ID="1" EVENT_ID="3">
<action ID="1101">
<!--AcMODESELECT-->
</action>
<action ID="10">
<!--AcADDPOINT-->
</action>
<action ID="30">
<!--AcCHECKELEMENT-->
<intParameter NAME="precision" VALUE="4" />
</action>
</transition>
<transition NAME="checkpicked" NEXT_STATE_ID="2" EVENT_ID="1">
<action ID="30">
<!--AcCHECKELEMENT-->
<intParameter NAME="precision" VALUE="4" />
</action>
</transition>
</state>
<state NAME="selected" ID="1" X_POS="663" Y_POS="89" WIDTH="100" HEIGHT="50">
<transition NAME="deselect all and add point" NEXT_STATE_ID="1" EVENT_ID="3">
<action ID="72">
<!--AcDESELECTALL-->
</action>
<action ID="10">
<!--AcADDPOINT-->
</action>
<action ID="30">
<!--AcCHECKELEMENT-->
<intParameter NAME="precision" VALUE="4" />
</action>
</transition>
<transition NAME="remove" NEXT_STATE_ID="5" EVENT_ID="12">
<action ID="1500">
<!--AcCHECKGREATERONE-->
</action>
</transition>
<transition NAME="checkSamePick" NEXT_STATE_ID="3" EVENT_ID="1">
<action ID="34">
<!--AcCHECKSELECTED-->
<intParameter NAME="precision" VALUE="4" />
</action>
</transition>
<transition NAME="deselect all" NEXT_STATE_ID="0" EVENT_ID="2000">
<action ID="72">
<!--AcDESELECTALL-->
</action>
<action ID="1100">
<!--AcMODEDESELECT-->
</action>
</transition>
</state>
<state NAME="checkpicked" ID="2" X_POS="385" Y_POS="221" WIDTH="100" HEIGHT="50">
<transition NAME="EIDNo" NEXT_STATE_ID="0" EVENT_ID="1003" />
<transition NAME="EIDYes" NEXT_STATE_ID="1" EVENT_ID="1004">
<action ID="1101">
<!--AcMODESELECT-->
</action>
<action ID="65">
<!--AcSELECT-->
</action>
</transition>
</state>
<state NAME="checkStillPicked" ID="3" X_POS="417" Y_POS="497" WIDTH="100" HEIGHT="50">
<transition NAME="EIDNo" NEXT_STATE_ID="0" EVENT_ID="1003">
<action ID="72">
<!--AcDESELECTALL-->
</action>
<action ID="1100">
<!--AcMODEDESELECT-->
</action>
</transition>
<transition NAME="EIDYes" NEXT_STATE_ID="4" EVENT_ID="1004">
<action ID="8">
<!--AcINITMOVEMENT-->
</action>
</transition>
</state>
<state NAME="moves" ID="4" X_POS="799" Y_POS="483" WIDTH="100" HEIGHT="50">
<transition NAME="mousemove" NEXT_STATE_ID="4" EVENT_ID="530">
<action ID="91">
<!--AcMOVESELECTED-->
</action>
</transition>
<transition NAME="finishmove" NEXT_STATE_ID="1" EVENT_ID="505">
<action ID="42">
<!--AcFINISHMOVEMENT-->
</action>
</transition>
</state>
<state NAME="checkGreaterOne" ID="5" X_POS="416" Y_POS="344" WIDTH="100" HEIGHT="50">
<transition NAME="StYes" NEXT_STATE_ID="1" EVENT_ID="1004">
<action ID="100">
<!--AcREMOVEPOINT-->
</action>
<action ID="61">
<!--AcSELECTANOTHEROBJECT-->
</action>
</transition>
<transition NAME="StNo" NEXT_STATE_ID="0" EVENT_ID="1003">
<action ID="100">
<!--AcREMOVEPOINT-->
</action>
<action ID="1100">
<!--AcMODEDESELECT-->
</action>
</transition>
</state>
</stateMachine>
<stateMachine NAME="pointsetinteractor">
<!-- Behaviour of a set of Points. a defined number of points can be set/removed/selected/deselectd/moved -->
<state NAME="no points or loaded points" ID="1" START_STATE="TRUE" X_POS="1066" Y_POS="281" WIDTH="100" HEIGHT="50">
<transition NAME="0SmallerPointsLoadedSmallerN" NEXT_STATE_ID="2" EVENT_ID="1014" />
<!-- If points have been loaded, goto right state; checked in constructor -->
<transition NAME="PointsLoadedGreaterEqualsN" NEXT_STATE_ID="4" EVENT_ID="1015" />
<!-- If points have been loaded, goto right state; checked in constructor -->
<transition NAME="addPoint but check n" NEXT_STATE_ID="3" EVENT_ID="3">
<action ID="1101" />
<!--AcMODE_SELECT-->
<action ID="32" />
</transition>
<transition NAME="checkn Delete" NEXT_STATE_ID="30" EVENT_ID="12">
<action ID="330" />
<!--AcCHECKNUMBEROFPOINTS-->
</transition>
<transition NAME="SetThisStatemachineOnSelected" NEXT_STATE_ID="1" EVENT_ID="1030">
<action ID="1101" />
<!--AcMODE_SELECT-->
</transition>
<transition NAME="SetThisStatemachineOnDeselected" NEXT_STATE_ID="1" EVENT_ID="1031">
<action ID="1100" />
<!--AcMODE_DESELECT-->
</transition>
</state>
<state NAME="space left" ID="2" X_POS="659" Y_POS="257" WIDTH="100" HEIGHT="50">
<transition NAME="addPoint but check n" NEXT_STATE_ID="3" EVENT_ID="3">
<action ID="32" />
</transition>
<transition NAME="Select or move point Space" NEXT_STATE_ID="10" EVENT_ID="1">
<action ID="30" />
</transition>
<transition NAME="check selected and Delete" NEXT_STATE_ID="31" EVENT_ID="12">
<action ID="340" />
<!--AcCHECKONESELECTED-->
</transition>
<transition NAME="DeselectAll" NEXT_STATE_ID="2" EVENT_ID="14">
<!--Event = ESC-->
<action ID="72" />
<!--AcDESELECTALL-->
<action ID="1100" />
<!--AcMODE_DESELECT-->
</transition>
</state>
<state NAME="checkedN" ID="3" X_POS="745" Y_POS="744" WIDTH="100" HEIGHT="50">
<transition NAME="n smaller N" NEXT_STATE_ID="40" EVENT_ID="1010">
<action ID="37" />
</transition>
<transition NAME="n greater equals N" NEXT_STATE_ID="41" EVENT_ID="1011">
<action ID="37" />
</transition>
</state>
<state NAME="set full" ID="4" X_POS="267" Y_POS="633" WIDTH="100" HEIGHT="50">
<transition NAME="Select or move point FULL" NEXT_STATE_ID="20" EVENT_ID="1">
<action ID="30" />
<!--AcCHECKELEMENT-->
</transition>
<transition NAME="checkn Delete selected Point" NEXT_STATE_ID="30" EVENT_ID="12">
<action ID="330" />
<!--AcCHECKNUMBEROFPOINTS-->
</transition>
<transition NAME="DeselectAll" NEXT_STATE_ID="2" EVENT_ID="14">
<!--Event = ESC-->
<action ID="72" />
<!--AcDESELECTALL-->
<action ID="1100" />
<!--AcMODEDESELECT-->
</transition>
</state>
<state NAME="picked NotFull" ID="10" X_POS="903" Y_POS="38" WIDTH="100" HEIGHT="50">
<transition NAME="StNo" NEXT_STATE_ID="2" EVENT_ID="1003">
<action ID="72" />
<!--AcDESELECTALL-->
<action ID="1100" />
<!--AcMODEDESELECT-->
</transition>
<transition NAME="StYes" NEXT_STATE_ID="11" EVENT_ID="1004">
<action ID="34" />
<!--AcCHECKSELECTED-->
<action ID="1101" />
<!--AcMODESELECT-->
</transition>
</state>
<state NAME="already selected Space" ID="11" X_POS="391" Y_POS="11" WIDTH="100" HEIGHT="50">
<transition NAME="StNo" NEXT_STATE_ID="2" EVENT_ID="1003">
<action ID="60" />
</transition>
<transition NAME="StYes" NEXT_STATE_ID="12" EVENT_ID="1004">
<action ID="8" />
</transition>
</state>
<state NAME="move Point Space" ID="12" X_POS="100" Y_POS="99" WIDTH="100" HEIGHT="50">
<transition NAME="move point" NEXT_STATE_ID="12" EVENT_ID="530">
<action ID="91" />
</transition>
<transition NAME="finish move" NEXT_STATE_ID="2" EVENT_ID="505">
<action ID="42" />
</transition>
<transition NAME="Safety init" NEXT_STATE_ID="12" EVENT_ID="1">
<action ID="8" />
</transition>
</state>
<state NAME="picked Full" ID="20" X_POS="122" Y_POS="766" WIDTH="100" HEIGHT="50">
<transition NAME="StNO" NEXT_STATE_ID="4" EVENT_ID="1003">
<action ID="72" />
<!--AcDESELECTALL-->
<action ID="1100" />
<!--AcMODEDESELECT-->
</transition>
<transition NAME="StYES" NEXT_STATE_ID="21" EVENT_ID="1004">
<action ID="34" />
<!--AcCHECKSELECTED-->
<action ID="1101" />
<!--AcMODESELECT-->
</transition>
</state>
<state NAME="selected Full" ID="21" X_POS="23" Y_POS="485" WIDTH="100" HEIGHT="50">
<transition NAME="StNo" NEXT_STATE_ID="4" EVENT_ID="1003">
<action ID="60" />
<!--AcSELECTPICKEDOBJECT-->
</transition>
<transition NAME="StYes" NEXT_STATE_ID="22" EVENT_ID="1004">
<action ID="8" />
<!--AcINITMOVEMENT-->
</transition>
</state>
<state NAME="move Point Full" ID="22" X_POS="67" Y_POS="255" WIDTH="100" HEIGHT="50">
<!-- since the MouseMove Event is send by QT we don't have the information about the position of the point in the list. we had it before, when we checked, if it was picked, or if it was selected -->
<transition NAME="move point" NEXT_STATE_ID="22" EVENT_ID="530">
<action ID="91" />
</transition>
<transition NAME="finish move" NEXT_STATE_ID="4" EVENT_ID="505">
<action ID="42" />
</transition>
<transition NAME="Safety init" NEXT_STATE_ID="22" EVENT_ID="1">
<action ID="8" />
</transition>
</state>
<state NAME="checkn Delete" ID="30" X_POS="1124" Y_POS="708" WIDTH="100" HEIGHT="50">
<transition NAME="StillFull" NEXT_STATE_ID="4" EVENT_ID="1015">
<action ID="100" />
<!--AcREMOVEPOINT-->
</transition>
<transition NAME="NotEmptyNotFull" NEXT_STATE_ID="2" EVENT_ID="1014">
<action ID="100" />
<!--AcREMOVEPOINT-->
</transition>
<transition NAME="WillBeEmpty" NEXT_STATE_ID="1" EVENT_ID="1017">
<action ID="100" />
<!--AcREMOVEPOINT-->
<action ID="1100" />
<!--AcMODEDESELECT-->
</transition>
</state>
<state NAME="selected space left" ID="31" X_POS="22" Y_POS="480" WIDTH="90" HEIGHT="50">
<transition NAME="StNo" NEXT_STATE_ID="2" EVENT_ID="1003" />
<transition NAME="StYes" NEXT_STATE_ID="30" EVENT_ID="1004">
<action ID="330" />
<!--AcCHECKNUMBEROFPOINTS-->
</transition>
</state>
<state NAME="checkedPositionEventSmallerN" ID="40" X_POS="267" Y_POS="301" WIDTH="173" HEIGHT="50">
<transition NAME="PositionEvent" NEXT_STATE_ID="2" EVENT_ID="1004">
<action ID="10" />
<!--AcADDPOINT-->
<action ID="1100" />
<!--AcMODE_DESELECT-->
</transition>
<transition NAME="others" NEXT_STATE_ID="2" EVENT_ID="1003">
<action ID="1100" />
<!--AcMODE_DESELECT-->
</transition>
</state>
<state NAME="checkedPositionEventGreaterN" ID="41" X_POS="562" Y_POS="424" WIDTH="168" HEIGHT="50">
<transition NAME="PositionEvent" NEXT_STATE_ID="4" EVENT_ID="1004">
<action ID="10" />
<!--AcADDPOINT-->
<action ID="1100" />
<!--AcMODE_DESELECT-->
</transition>
<transition NAME="others" NEXT_STATE_ID="2" EVENT_ID="1003">
<action ID="1100" />
<!--AcMODE_DESELECT-->
</transition>
</state>
</stateMachine>
<stateMachine NAME="onlymovepointsetinteractor">
<!-- Behaviour of a set of Points. The points can only be selected and moved.-->
<state NAME="no points or loaded points" ID="1" START_STATE="TRUE" X_POS="1066" Y_POS="281" WIDTH="100" HEIGHT="50">
<transition NAME="0SmallerPointsLoadedSmallerN" NEXT_STATE_ID="2" EVENT_ID="1014" />
<!-- If points have been loaded, goto right state; checked in constructor -->
<transition NAME="PointsLoadedGreaterEqualsN" NEXT_STATE_ID="2" EVENT_ID="1015" />
<!-- If points have been loaded, goto right state; checked in constructor -->
<transition NAME="SetThisStatemachineOnSelected" NEXT_STATE_ID="1" EVENT_ID="1030">
<action ID="1101">
<!--AcMODE_SELECT-->
</action>
</transition>
<transition NAME="SetThisStatemachineOnDeselected" NEXT_STATE_ID="1" EVENT_ID="1031">
<action ID="1100">
<!--AcMODE_DESELECT-->
</action>
</transition>
</state>
<state NAME="loaded points" ID="2" X_POS="659" Y_POS="257" WIDTH="100" HEIGHT="50">
<transition NAME="Select or move point" NEXT_STATE_ID="10" EVENT_ID="1">
<action ID="30" />
</transition>
<transition NAME="DeselectAll" NEXT_STATE_ID="2" EVENT_ID="14">
<!--Event = ESC-->
<action ID="72">
<!--AcDESELECTALL-->
</action>
<action ID="1100">
<!--AcMODE_DESELECT-->
</action>
</transition>
</state>
<state NAME="picked point" ID="10" X_POS="903" Y_POS="38" WIDTH="100" HEIGHT="50">
<transition NAME="StNo" NEXT_STATE_ID="2" EVENT_ID="1003">
<action ID="72">
<!--AcDESELECTALL-->
</action>
<action ID="1100">
<!--AcMODEDESELECT-->
</action>
</transition>
<transition NAME="StYes" NEXT_STATE_ID="11" EVENT_ID="1004">
<action ID="34">
<!--AcCHECKSELECTED-->
</action>
<action ID="1101">
<!--AcMODESELECT-->
</action>
</transition>
</state>
<state NAME="already selected point" ID="11" X_POS="391" Y_POS="11" WIDTH="100" HEIGHT="50">
<transition NAME="StNo" NEXT_STATE_ID="2" EVENT_ID="1003">
<action ID="60" />
</transition>
<transition NAME="StYes" NEXT_STATE_ID="12" EVENT_ID="1004">
<action ID="8" />
</transition>
</state>
<state NAME="move point" ID="12" X_POS="100" Y_POS="99" WIDTH="100" HEIGHT="50">
<transition NAME="move point" NEXT_STATE_ID="12" EVENT_ID="530">
<action ID="91" />
</transition>
<transition NAME="finish move" NEXT_STATE_ID="2" EVENT_ID="505">
<action ID="42" />
</transition>
<transition NAME="Safety init" NEXT_STATE_ID="12" EVENT_ID="1">
<action ID="8" />
</transition>
</state>
</stateMachine>
<stateMachine NAME="seedpointsetinteractor">
<!-- Behaviour of one Point. Point is added by clicking left Mouse Button and holding Shift-->
<state NAME="no point" ID="1" START_STATE="TRUE" X_POS="59" Y_POS="45" WIDTH="169" HEIGHT="50">
<transition NAME="0SmallerPointsLoadedSmallerN" NEXT_STATE_ID="10" EVENT_ID="1014" />
<!-- If point has been loaded, goto right state; checked in constructor -->
<transition NAME="PointsLoadedGreaterEqualsN" NEXT_STATE_ID="10" EVENT_ID="1015" />
<!-- If point has been loaded, goto right state; checked in constructor -->
<transition NAME="addPoint" NEXT_STATE_ID="2" EVENT_ID="3">
<action ID="1101">
<!--AcMODESELECT-->
</action>
<action ID="37" />
<!--AcCHECKOPERATION-->
</transition>
</state>
<state NAME="checkPositionEvent" ID="2" X_POS="164" Y_POS="334" WIDTH="166" HEIGHT="50">
<transition NAME="PositionEvent" NEXT_STATE_ID="10" EVENT_ID="1004">
<action ID="10" />
<!--AcADDPOINT-->
</transition>
<transition NAME="others" NEXT_STATE_ID="1" EVENT_ID="1003">
<action ID="0" />
</transition>
</state>
<state NAME="point" ID="10" X_POS="914" Y_POS="734" WIDTH="100" HEIGHT="50">
<transition NAME="insertPoint" NEXT_STATE_ID="11" EVENT_ID="3">
<action ID="37" />
<!--AcCHECKOPERATION-->
</transition>
<transition NAME="Select or move point" NEXT_STATE_ID="12" EVENT_ID="1">
<action ID="30" />
<!--AcCHECKELEMENT-->
</transition>
<transition NAME="check selected and delete" NEXT_STATE_ID="15" EVENT_ID="12">
<action ID="340" />
<!--AcCHECKONESELECTED-->
</transition>
</state>
<state NAME="checkedPositionEventPoint" ID="11" X_POS="758" Y_POS="478" WIDTH="100" HEIGHT="50">
<transition NAME="PositionEvent" NEXT_STATE_ID="10" EVENT_ID="1004">
<action ID="103" />
<!--AcREMOVEALL-->
<action ID="10" />
<!--AcADDPOINT-->
</transition>
<transition NAME="others" NEXT_STATE_ID="10" EVENT_ID="1003">
<action ID="0" />
</transition>
</state>
<state NAME="picked point" ID="12" X_POS="23" Y_POS="560" WIDTH="150" HEIGHT="50">
<transition NAME="StNo" NEXT_STATE_ID="10" EVENT_ID="1003">
<action ID="72" />
<!--AcDESELECTALL-->
<action ID="1100" />
<!--AcMODEDESELECT-->
</transition>
<transition NAME="StYes" NEXT_STATE_ID="13" EVENT_ID="1004">
<action ID="34" />
<!--AcCHECKSELECTED-->
<action ID="1101" />
<!--AcMODESELECT-->
</transition>
</state>
<state NAME="selected" ID="13" X_POS="23" Y_POS="485" WIDTH="100" HEIGHT="50">
<transition NAME="StNo" NEXT_STATE_ID="10" EVENT_ID="1003">
<action ID="60" />
<!--AcSELECTPICKEDOBJECT-->
</transition>
<transition NAME="StYes" NEXT_STATE_ID="14" EVENT_ID="1004">
<action ID="8" />
<!--AcINITMOVEMENT-->
</transition>
</state>
<state NAME="move Point" ID="14" X_POS="76" Y_POS="731" WIDTH="100" HEIGHT="50">
<transition NAME="move point" NEXT_STATE_ID="14" EVENT_ID="530">
<action ID="91" />
<!--AcMOVESELECTED-->
</transition>
<transition NAME="finish move" NEXT_STATE_ID="10" EVENT_ID="505">
<action ID="42" />
<!--AcFINISHMOVEMENT-->
</transition>
<transition NAME="Safety init" NEXT_STATE_ID="14" EVENT_ID="1">
<action ID="8" />
<!--AcINITMOVEMENT-->
</transition>
</state>
<state NAME="already selected" ID="15" X_POS="23" Y_POS="560" WIDTH="150" HEIGHT="50">
<transition NAME="StNo" NEXT_STATE_ID="10" EVENT_ID="1003" />
<transition NAME="StYes" NEXT_STATE_ID="16" EVENT_ID="1004">
<action ID="33" />
<!--AcCHECKEQUALS1-->
</transition>
</state>
<state NAME="delete" ID="16" X_POS="1151" Y_POS="19" WIDTH="100" HEIGHT="50">
<transition NAME="equalsOne" NEXT_STATE_ID="1" EVENT_ID="1004">
<action ID="100" />
<!--AcREMOVEPOINT-->
<action ID="1100" />
<!--AcMODEDESELECT-->
</transition>
<transition NAME="largerOne" NEXT_STATE_ID="10" EVENT_ID="1003">
<action ID="100" />
<!--AcREMOVEPOINT-->
</transition>
</state>
</stateMachine>
<stateMachine NAME="VesselGraphInteractor">
<state NAME="Start" ID="1" START_STATE="TRUE" X_POS="1390" Y_POS="-1" WIDTH="100" HEIGHT="50">
<transition NAME="goToCheckPicking" NEXT_STATE_ID="2" EVENT_ID="5">
<action ID="31">
<!--AcCHECKOBJECT-->
</action>
</transition>
<transition NAME="goToCheckPicking" NEXT_STATE_ID="2" EVENT_ID="8">
<action ID="31">
<!--AcCHECKOBJECT-->
</action>
</transition>
</state>
<state NAME="CheckPicking" ID="2" X_POS="515" Y_POS="263" WIDTH="100" HEIGHT="50">
<transition NAME="noPicked" NEXT_STATE_ID="4" EVENT_ID="1003">
<action ID="66">
<!-- AcSELECTPOINT -->
</action>
</transition>
<transition NAME="yesPicked" NEXT_STATE_ID="3" EVENT_ID="1004">
<action ID="69">
<!-- AcSELECTSUBOBJECT -->
</action>
</transition>
</state>
<state NAME="OneVesselPicked" ID="3" X_POS="1488" Y_POS="350" WIDTH="100" HEIGHT="50">
<transition NAME="goToCheckPicking" NEXT_STATE_ID="5" EVENT_ID="5">
<action ID="31">
<!-- AcCHECKOBJECT -->
</action>
</transition>
<transition NAME="goToCheckPicking" NEXT_STATE_ID="5" EVENT_ID="8">
<action ID="31">
<!-- AcCHECKOBJECT -->
</action>
</transition>
<transition NAME="delete" NEXT_STATE_ID="1" EVENT_ID="12">
<action ID="104">
<!-- AcREMOVESELECTEDSUBOBJECT -->
</action>
</transition>
<transition NAME="deselectAll" NEXT_STATE_ID="1" EVENT_ID="14">
<action ID="72">
<!-- AcDESELECTALL -->
</action>
</transition>
<transition NAME="searchPeriphery" NEXT_STATE_ID="11" EVENT_ID="15">
<action ID="3000">
<!-- AcPERIPHERYSEARCH -->
</action>
</transition>
<transition NAME="searchToRoot" NEXT_STATE_ID="11" EVENT_ID="16">
<action ID="3001">
<!-- AcROOTSEARCH -->
</action>
</transition>
<transition NAME="searchToThickstVessel" NEXT_STATE_ID="11" EVENT_ID="17">
<action ID="3002">
<!-- AcTHICKSTVESSELSEARCH -->
</action>
</transition>
<!--now follow the attibutations for different vessel types-->
<transition NAME="attributation" NEXT_STATE_ID="3" EVENT_ID="20">
<action ID="3005">
<!-- AcATTRIBUTATION -->
<intParameter NAME="attribute_id" VALUE="0" />
</action>
</transition>
<transition NAME="attributation" NEXT_STATE_ID="3" EVENT_ID="21">
<action ID="3005">
<!-- AcATTRIBUTATION -->
<intParameter NAME="attribute_id" VALUE="1" />
</action>
</transition>
<transition NAME="attributation" NEXT_STATE_ID="3" EVENT_ID="30">
<action ID="3005">
<!-- AcATTRIBUTATION -->
<intParameter NAME="attribute_id" VALUE="2" />
</action>
</transition>
<transition NAME="attributation" NEXT_STATE_ID="3" EVENT_ID="31">
<action ID="3005">
<!-- AcATTRIBUTATION -->
<intParameter NAME="attribute_id" VALUE="3" />
</action>
</transition>
<transition NAME="attributation" NEXT_STATE_ID="3" EVENT_ID="40">
<action ID="3005">
<!-- AcATTRIBUTATION -->
<intParameter NAME="attribute_id" VALUE="4" />
</action>
</transition>
<transition NAME="default" NEXT_STATE_ID="1" EVENT_ID="90">
<action ID="3007">
<!-- AcDEFAULT -->
</action>
</transition>
</state>
<state NAME="OnePointPicked" ID="4" X_POS="339" Y_POS="103" WIDTH="100" HEIGHT="50">
<transition NAME="goToCheckPicking" NEXT_STATE_ID="6" EVENT_ID="5">
<action ID="31">
<!-- AcCHECKOBJECT -->
</action>
</transition>
<transition NAME="goToCheckPicking" NEXT_STATE_ID="6" EVENT_ID="8">
<action ID="31">
<!-- AcCHECKOBJECT -->
</action>
</transition>
<transition NAME="deselectAll" NEXT_STATE_ID="1" EVENT_ID="14">
<action ID="72">
<!-- AcDESELECTALL -->
</action>
</transition>
</state>
<state NAME="CheckPicking" ID="5" X_POS="43" Y_POS="721" WIDTH="100" HEIGHT="50">
<transition NAME="noPicked" NEXT_STATE_ID="7" EVENT_ID="1003">
<action ID="66">
<!-- AcSELECTPOINT -->
</action>
</transition>
<transition NAME="yesPicked" NEXT_STATE_ID="13" EVENT_ID="1004">
<action ID="69">
<!-- AcSELECTSUBOBJECT -->
</action>
<action ID="3010">
<!-- AcCHECKBARRIERSTATUS -->
</action>
</transition>
</state>
<state NAME="CheckPicking" ID="6" X_POS="552" Y_POS="156" WIDTH="100" HEIGHT="50">
<transition NAME="noPicked" NEXT_STATE_ID="9" EVENT_ID="1003">
<action ID="66">
<!-- AcSELECTPOINT -->
</action>
</transition>
<transition NAME="yesPicked" NEXT_STATE_ID="7" EVENT_ID="1004">
<action ID="69">
<!-- AcSELECTSUBOBJECT -->
</action>
</transition>
</state>
<state NAME="OneVesselOnePointPicked" ID="7" X_POS="665" Y_POS="378" WIDTH="151" HEIGHT="50">
<transition NAME="ENew" NEXT_STATE_ID="1" EVENT_ID="13">
<action ID="81">
<!-- AcNEWSUBOBJECT -->
</action>
<action ID="72">
<!-- AcDESELECTALL -->
</action>
</transition>
<transition NAME="deselectAll" NEXT_STATE_ID="1" EVENT_ID="14">
<action ID="72">
<!-- AcDESELECTALL -->
</action>
</transition>
<transition NAME="delete" NEXT_STATE_ID="1" EVENT_ID="12">
<action ID="104">
<!-- AcREMOVESELECTEDSUBOBJECT -->
</action>
</transition>
<transition NAME="setVesselElement" NEXT_STATE_ID="7" EVENT_ID="91">
<action ID="3008">
<!-- AcSETVESSELELEMENT-->
</action>
</transition>
<!--now follow the attibutations for different vessel types-->
<transition NAME="attributation" NEXT_STATE_ID="7" EVENT_ID="20">
<action ID="3005">
<!-- AcATTRIBUTATION -->
<intParameter NAME="attribute_id" VALUE="0" />
</action>
</transition>
<transition NAME="attributation" NEXT_STATE_ID="7" EVENT_ID="21">
<action ID="3005">
<!-- AcATTRIBUTATION -->
<intParameter NAME="attribute_id" VALUE="1" />
</action>
</transition>
<transition NAME="attributation" NEXT_STATE_ID="7" EVENT_ID="30">
<action ID="3005">
<!-- AcATTRIBUTATION -->
<intParameter NAME="attribute_id" VALUE="2" />
</action>
</transition>
<transition NAME="attributation" NEXT_STATE_ID="7" EVENT_ID="31">
<action ID="3005">
<!-- AcATTRIBUTATION -->
<intParameter NAME="attribute_id" VALUE="3" />
</action>
</transition>
<transition NAME="attributation" NEXT_STATE_ID="7" EVENT_ID="40">
<action ID="3005">
<!-- AcATTRIBUTATION -->
<intParameter NAME="attribute_id" VALUE="4" />
</action>
</transition>
<transition NAME="default" NEXT_STATE_ID="1" EVENT_ID="90">
<action ID="3007">
<!-- AcDEFAULT -->
</action>
</transition>
</state>
<state NAME="TwoVesselsPicked" ID="8" X_POS="77" Y_POS="79" WIDTH="100" HEIGHT="50">
<transition NAME="ENew" NEXT_STATE_ID="1" EVENT_ID="13">
<action ID="81">
<!-- AcNEWSUBOBJECT -->
</action>
<action ID="72">
<!-- AcDESELECTALL -->
</action>
</transition>
<transition NAME="goToCheckPicking" NEXT_STATE_ID="10" EVENT_ID="5">
<action ID="31">
<!-- AcCHECKOBJECT -->
</action>
</transition>
<transition NAME="goToCheckPicking" NEXT_STATE_ID="10" EVENT_ID="8">
<action ID="31">
<!-- AcCHECKOBJECT -->
</action>
</transition>
<transition NAME="searchShortestPathBetween2Edges" NEXT_STATE_ID="11" EVENT_ID="18">
<action ID="3003">
<!-- AcSHORTESTPATHSEARCH -->
</action>
</transition>
<transition NAME="deselectAll" NEXT_STATE_ID="1" EVENT_ID="14">
<action ID="72">
<!-- AcDESELECTALL -->
</action>
</transition>
<transition NAME="delete" NEXT_STATE_ID="1" EVENT_ID="12">
<action ID="104">
<!-- AcREMOVESELECTEDSUBOBJECT -->
</action>
</transition>
<transition NAME="setVesselElement" NEXT_STATE_ID="8" EVENT_ID="91">
<action ID="3008">
<!-- AcSETVESSELELEMENT-->
</action>
</transition>
<!--now follow the attibutations for different vessel types-->
<transition NAME="attributation" NEXT_STATE_ID="8" EVENT_ID="20">
<action ID="3005">
<!-- AcATTRIBUTATION -->
<intParameter NAME="attribute_id" VALUE="0" />
</action>
</transition>
<transition NAME="attributation" NEXT_STATE_ID="8" EVENT_ID="21">
<action ID="3005">
<!-- AcATTRIBUTATION -->
<intParameter NAME="attribute_id" VALUE="1" />
</action>
</transition>
<transition NAME="attributation" NEXT_STATE_ID="8" EVENT_ID="30">
<action ID="3005">
<!-- AcATTRIBUTATION -->
<intParameter NAME="attribute_id" VALUE="2" />
</action>
</transition>
<transition NAME="attributation" NEXT_STATE_ID="8" EVENT_ID="31">
<action ID="3005">
<!-- AcATTRIBUTATION -->
<intParameter NAME="attribute_id" VALUE="3" />
</action>
</transition>
<transition NAME="attributation" NEXT_STATE_ID="8" EVENT_ID="40">
<action ID="3005">
<!-- AcATTRIBUTATION -->
<intParameter NAME="attribute_id" VALUE="4" />
</action>
</transition>
<transition NAME="default" NEXT_STATE_ID="1" EVENT_ID="90">
<action ID="3007">
<!-- AcDEFAULT -->
</action>
</transition>
</state>
<state NAME="TwoPointsPicked" ID="9" X_POS="748" Y_POS="140" WIDTH="100" HEIGHT="50">
<transition NAME="ENew" NEXT_STATE_ID="1" EVENT_ID="13">
<action ID="81">
<!-- AcNEWSUBOBJECT -->
</action>
</transition>
<transition NAME="deselectAll" NEXT_STATE_ID="1" EVENT_ID="14">
<action ID="72">
<!-- AcDESELECTALL -->
</action>
</transition>
<transition NAME="setVesselElement" NEXT_STATE_ID="9" EVENT_ID="91">
<action ID="3008">
<!-- AcSETVESSELELEMENT-->
</action>
</transition>
</state>
<state NAME="CheckPicking" ID="10" X_POS="642" Y_POS="805" WIDTH="100" HEIGHT="50">
<transition NAME="noPicked" NEXT_STATE_ID="12" EVENT_ID="1003">
<action ID="36">
<!--AcCHECKGREATERTWO-->
</action>
</transition>
<transition NAME="yesPicked" NEXT_STATE_ID="14" EVENT_ID="1004">
<action ID="69">
<!-- AcSELECTSUBOBJECT -->
</action>
<action ID="3010">
<!-- AcCHECKBARRIERSTATUS -->
</action>
</transition>
</state>
<state NAME="MoreVesselsPicked" ID="11" X_POS="933" Y_POS="754" WIDTH="100" HEIGHT="50">
<transition NAME="delete" NEXT_STATE_ID="1" EVENT_ID="12">
<action ID="104">
<!-- AcDESELECTALL -->
</action>
</transition>
<transition NAME="goToCheckPicking" NEXT_STATE_ID="10" EVENT_ID="5">
<action ID="31">
<!-- AcCHECKOBJECT -->
</action>
</transition>
<transition NAME="goToCheckPicking" NEXT_STATE_ID="10" EVENT_ID="8">
<action ID="31">
<!-- AcCHECKOBJECT -->
</action>
</transition>
<transition NAME="deselectAll" NEXT_STATE_ID="1" EVENT_ID="14">
<action ID="72">
<!-- AcDESELECTALL -->
</action>
</transition>
<transition NAME="singleSignal" NEXT_STATE_ID="3" EVENT_ID="19">
<action ID="3004">
<!-- AcSINGLE -->
</action>
</transition>
<!--now follow the attibutations for different vessel types-->
<transition NAME="attributation" NEXT_STATE_ID="11" EVENT_ID="20">
<action ID="3005">
<!-- AcATTRIBUTATION -->
<intParameter NAME="attribute_id" VALUE="0" />
</action>
</transition>
<transition NAME="attributation" NEXT_STATE_ID="11" EVENT_ID="21">
<action ID="3005">
<!-- AcATTRIBUTATION -->
<intParameter NAME="attribute_id" VALUE="1" />
</action>
</transition>
<transition NAME="attributation" NEXT_STATE_ID="11" EVENT_ID="30">
<action ID="3005">
<!-- AcATTRIBUTATION -->
<intParameter NAME="attribute_id" VALUE="2" />
</action>
</transition>
<transition NAME="attributation" NEXT_STATE_ID="11" EVENT_ID="31">
<action ID="3005">
<!-- AcATTRIBUTATION -->
<intParameter NAME="attribute_id" VALUE="3" />
</action>
</transition>
<transition NAME="attributation" NEXT_STATE_ID="11" EVENT_ID="40">
<action ID="3005">
<!-- AcATTRIBUTATION -->
<intParameter NAME="attribute_id" VALUE="4" />
</action>
</transition>
<transition NAME="default" NEXT_STATE_ID="1" EVENT_ID="90">
<action ID="3007">
<!-- AcDEFAULT -->
</action>
</transition>
</state>
<state NAME="CheckNumberPickedVesselsSmaller2" ID="12" X_POS="259" Y_POS="707" WIDTH="188" HEIGHT="50">
<transition NAME="yes" NEXT_STATE_ID="8" EVENT_ID="1004" />
<transition NAME="no" NEXT_STATE_ID="11" EVENT_ID="1003">
<action ID="69">
<!-- AcSELECTSUBOBJECT -->
</action>
</transition>
</state>
<state NAME="CheckBarrierStatus" ID="13" X_POS="8" Y_POS="318" WIDTH="100" HEIGHT="50">
<transition NAME="yes" NEXT_STATE_ID="3" EVENT_ID="1004" />
<transition NAME="no" NEXT_STATE_ID="8" EVENT_ID="1003" />
</state>
<state NAME="CheckBarrierStatus" ID="14" X_POS="557" Y_POS="510" WIDTH="100" HEIGHT="50">
<transition NAME="yes" NEXT_STATE_ID="8" EVENT_ID="1004" />
<transition NAME="no" NEXT_STATE_ID="11" EVENT_ID="1003" />
</state>
</stateMachine>
<stateMachine NAME="slices-rotator">
<state NAME="neutral" ID="1" START_STATE="TRUE">
<!-- mouse down: jump to decision state -->
<transition NAME="mouse down" NEXT_STATE_ID="2" EVENT_ID="1">
<action ID="21">
<!-- AcCheckPoint -->
</action>
</transition>
<transition NAME="mouse move" NEXT_STATE_ID="5" EVENT_ID="520">
<action ID="21">
<!-- AcCheckPoint -->
</action>
</transition>
</state>
<state NAME="rotate?" ID="2">
<transition NAME="yes" NEXT_STATE_ID="3" EVENT_ID="1004" />
<transition NAME="no" NEXT_STATE_ID="4" EVENT_ID="1003">
<action ID="92">
<!--AcMove-->
</action>
</transition>
</state>
<state NAME="rotate" ID="3">
<!-- send rotate events -->
<transition NAME="mouse move" NEXT_STATE_ID="3" EVENT_ID="530">
<action ID="1005">
<!--AcRotate-->
</action>
</transition>
<transition NAME="mouse release" NEXT_STATE_ID="1" EVENT_ID="505">
<action ID="1010">
<!--AcRotateEnd-->
</action>
</transition>
</state>
<state NAME="move" ID="4">
<!-- send move events -->
<transition NAME="mouse move" NEXT_STATE_ID="4" EVENT_ID="530">
<action ID="92">
<!--AcMove-->
</action>
</transition>
<transition NAME="mouse release" NEXT_STATE_ID="1" EVENT_ID="505" />
</state>
<state NAME="rotation possible?" ID="5">
<transition NAME="yes" NEXT_STATE_ID="6" EVENT_ID="1004">
<action ID="1004">
<!--AcRotateStart-->
</action>
</transition>
<transition NAME="no" NEXT_STATE_ID="1" EVENT_ID="1003" />
</state>
<state NAME="rotation possible!" ID="6">
<!-- mouse down: jump to decision state -->
<transition NAME="mouse down" NEXT_STATE_ID="2" EVENT_ID="1">
<action ID="21">
<!-- AcCheckPoint -->
</action>
</transition>
<transition NAME="mouse move" NEXT_STATE_ID="7" EVENT_ID="520">
<action ID="21">
<!-- AcCheckPoint -->
</action>
</transition>
</state>
<state NAME="rotation possible?" ID="7">
<transition NAME="yes" NEXT_STATE_ID="6" EVENT_ID="1004" />
<transition NAME="no" NEXT_STATE_ID="1" EVENT_ID="1003">
<action ID="1010">
<!--AcRotateEnd-->
</action>
</transition>
</state>
</stateMachine>
<stateMachine NAME="dummy">
<!-- Dummy for a null interaction -->
<state NAME="neutral" ID="0" START_STATE="TRUE">
<transition NAME="stay in dummy" NEXT_STATE_ID="0" EVENT_ID="0" />
</state>
</stateMachine>
<stateMachine NAME="SpaceNavigatorInteraction">
<state NAME="neutral" ID="1" START_STATE="TRUE">
<transition NAME="stay in dummy" NEXT_STATE_ID="1" EVENT_ID="4001">
<action ID="4001" />
<!--AcONTDMOUSEINPUT-->
</transition>
<transition NAME="stay with button down" NEXT_STATE_ID="1" EVENT_ID="4002">
<action ID="4002" />
<!--AcONTDMOUSEKEYDOWN-->
</transition>
</state>
</stateMachine>
<stateMachine NAME="WiiMoteHeadtracking">
<state NAME="headtracking" ID="1" START_STATE="TRUE">
<transition NAME="startState" NEXT_STATE_ID="1" EVENT_ID="4003">
<!--EIDWIIMOTEINPUT-->
<action ID="4003" />
<!--AcONWIIMOTEINPUT-->
</transition>
<transition NAME="buttonState" NEXT_STATE_ID="1" EVENT_ID="4004">
<!--EIDWIIMOTEBUTTON-->
<action ID="4004" />
<!--AcRESETVIEW-->
</transition>
<transition NAME="initCalibration" NEXT_STATE_ID="2" EVENT_ID="5551001">
<!--EV_INIT-->
<action ID="55500010" />
<!--AC_INIT-->
</transition>
</state>
<state NAME="calibration" ID="2">
<transition NAME="collectIRData" NEXT_STATE_ID="2" EVENT_ID="4003">
<!--EIDWIIMOTEINPUT-->
<action ID="21" />
<!--AcCHECKPOINT-->
</transition>
<transition NAME="endCalibration" NEXT_STATE_ID="1" EVENT_ID="5551001">
<!--EV_INIT-->
<action ID="44" />
<!--AcFINISH-->
</transition>
</state>
</stateMachine>
<stateMachine NAME="WiiMoteSurfaceInteraction">
<state NAME="start" ID="1" START_STATE="TRUE">
<transition NAME="initial state" NEXT_STATE_ID="2" EVENT_ID="4005" />
<!--EIDWIIMOTEBUTTONB-->
<transition NAME="reset object" NEXT_STATE_ID="1" EVENT_ID="4004">
<!--EIDWIIMOTEBUTTON-->
<action ID="4004" />
<!--AcRESETVIEW-->
</transition>
</state>
<state NAME="Surface Interaction" ID="2">
<transition NAME="stop Surface Interaction" NEXT_STATE_ID="1" EVENT_ID="5551008">
<!--EV_DONE-->
<action ID="4005">
<!-- AcONWIIMOTEBUTTONRELEASED -->
</action>
</transition>
<transition NAME="Input for Surface Interaction" NEXT_STATE_ID="2" EVENT_ID="4003">
<!--EIDWIIMOTEINPUT-->
<action ID="4003">
<!--AcONWIIMOTEINPUT-->
</action>
</transition>
</state>
</stateMachine>
<stateMachine NAME="InteractorTestPattern">
<!-- To Test an Interactor for the right behavior -->
<state NAME="neutral" ID="0" START_STATE="TRUE">
<transition NAME="to1" NEXT_STATE_ID="1" EVENT_ID="4">
<action ID="1101" />
<!--AcMODESELECT-->
</transition>
<transition NAME="to2" NEXT_STATE_ID="2" EVENT_ID="2">
<action ID="1011" />
<!--AcMODESELECT-->
</transition>
</state>
<state NAME="State1" ID="1">
<transition NAME="StayIn1" NEXT_STATE_ID="1" EVENT_ID="533" />
<transition NAME="to0" NEXT_STATE_ID="0" EVENT_ID="506">
<action ID="1100" />
<!--AcMODEDESELECT-->
</transition>
</state>
<state NAME="State2" ID="2">
<transition NAME="StayIn2" NEXT_STATE_ID="2" EVENT_ID="531" />
<transition NAME="finish" NEXT_STATE_ID="0" EVENT_ID="507">
<action ID="1100" />
<!--AcMODEDESELECT-->
</transition>
</state>
</stateMachine>
<stateMachine NAME="shapemodelpointsetinteractor">
<state NAME="Interaction Activated, no point loaded yet" ID="1" START_STATE="TRUE" X_POS="457" Y_POS="506" WIDTH="226" HEIGHT="56">
<transition NAME="SetStateMachineOnDeselected" EVENT_ID="1031" NEXT_STATE_ID="1">
<action ID="1100" />
</transition>
<transition NAME="SetStateMachineOnSelected" EVENT_ID="1030" NEXT_STATE_ID="1">
<action ID="1101" />
</transition>
<transition NAME="Add Point" EVENT_ID="3" NEXT_STATE_ID="2">
<action ID="10" />
</transition>
</state>
<state NAME="One Point" ID="2" X_POS="567" Y_POS="145" WIDTH="100" HEIGHT="50">
<transition NAME="Move Point" EVENT_ID="3" NEXT_STATE_ID="2">
<action ID="103" />
<action ID="10" />
</transition>
<transition NAME="Remove Point" EVENT_ID="12" NEXT_STATE_ID="1">
<action ID="100" />
</transition>
<transition NAME="Check if point is hit by mouse click" EVENT_ID="1" NEXT_STATE_ID="3">
<action ID="30" />
</transition>
<transition NAME="name" EVENT_ID="14" NEXT_STATE_ID="2">
<action ID="72" />
<action ID="1100" />
</transition>
</state>
<state NAME="CheckPoint" ID="3" X_POS="64" Y_POS="52" WIDTH="100" HEIGHT="50">
<transition NAME="Point not hit" EVENT_ID="1003" NEXT_STATE_ID="2">
<action ID="72" />
<action ID="1100" />
</transition>
<transition NAME="Point is hit, check if is selected or not" EVENT_ID="1004" NEXT_STATE_ID="5">
<action ID="34" />
<action ID="1101" />
</transition>
</state>
<state NAME="PointMove" ID="4" X_POS="278" Y_POS="422" WIDTH="100" HEIGHT="50">
<transition NAME="Adjust the Mesh according to point move" EVENT_ID="505" NEXT_STATE_ID="2">
<action ID="42" />
</transition>
<transition NAME="name" EVENT_ID="530" NEXT_STATE_ID="4">
<action ID="1236" />
<action ID="91" />
<action ID="1234" />
</transition>
<transition NAME="name" EVENT_ID="1" NEXT_STATE_ID="4">
<action ID="8" />
</transition>
</state>
<state NAME="Already Selected?" ID="5" X_POS="187" Y_POS="247" WIDTH="100" HEIGHT="50">
<transition NAME="Initialize Movement" EVENT_ID="1004" NEXT_STATE_ID="4">
<action ID="8" />
<action ID="1235" />
</transition>
<transition NAME="name" EVENT_ID="1003" NEXT_STATE_ID="2">
<action ID="60" />
</transition>
</state>
</stateMachine>
<stateMachine NAME="singlepointinteractor">
<!-- Behaviour of one point. This single point can be set, selected and then moved and removed. A setting of a new point will delete the old one.-->
<state NAME="no point or loaded point not selected" ID="1" START_STATE="TRUE" X_POS="18" Y_POS="336" WIDTH="197" HEIGHT="50">
<transition NAME="SetThisStatemachineOnSelected" NEXT_STATE_ID="1" EVENT_ID="1030">
<action ID="1101">
<!--AcMODE_SELECT-->
</action>
</transition>
<transition NAME="SetThisStatemachineOnDeselected" NEXT_STATE_ID="1" EVENT_ID="1031">
<action ID="1100">
<!--AcMODE_DESELECT-->
</action>
</transition>
<transition NAME="addPoint but check n" NEXT_STATE_ID="42" EVENT_ID="3">
<action ID="1101">
<!--AcMODE_SELECT-->
</action>
<action ID="103" />
<action ID="10" />
</transition>
<transition NAME="name" EVENT_ID="1" NEXT_STATE_ID="43">
<action ID="30" />
</transition>
</state>
<state NAME="picked" ID="20" X_POS="693" Y_POS="587" WIDTH="100" HEIGHT="50">
<transition NAME="StNO" NEXT_STATE_ID="1" EVENT_ID="1003">
<action ID="72">
<!--AcDESELECTALL-->
</action>
<action ID="1100">
<!--AcMODEDESELECT-->
</action>
</transition>
<transition NAME="StYes" NEXT_STATE_ID="22" EVENT_ID="1004">
<action ID="8">
<!--AcINITMOVEMENT-->
</action>
<action ID="1101" />
</transition>
</state>
<state NAME="move point" ID="22" X_POS="1135" Y_POS="449" WIDTH="100" HEIGHT="50">
<!-- since the MouseMove Event is send by QT we don't have the information about the position of the point in the list. we had it before, when we checked, if it was picked, or if it was selected -->
<transition NAME="move point" NEXT_STATE_ID="22" EVENT_ID="530">
<action ID="91" />
</transition>
<transition NAME="Safety init" NEXT_STATE_ID="22" EVENT_ID="1">
<action ID="8" />
</transition>
<transition NAME="finish move" NEXT_STATE_ID="42" EVENT_ID="505">
<action ID="42" />
</transition>
</state>
<state NAME="point selected" ID="42" X_POS="674" Y_POS="341" WIDTH="100" HEIGHT="50">
<transition NAME="Select or move point FULL" NEXT_STATE_ID="20" EVENT_ID="1">
<action ID="30">
<!--AcCHECKELEMENT-->
</action>
</transition>
<transition NAME="StYes" NEXT_STATE_ID="1" EVENT_ID="12">
<action ID="100" />
<action ID="1100">
<!--AcMODEDESELECT-->
</action>
</transition>
<transition NAME="name" EVENT_ID="3" NEXT_STATE_ID="42">
<action ID="103" />
<action ID="10" />
</transition>
</state>
<state NAME="picked not yet selected" ID="43" X_POS="681" Y_POS="158" WIDTH="126" HEIGHT="50">
<transition NAME="name" EVENT_ID="1004" NEXT_STATE_ID="42">
<action ID="60" />
</transition>
<transition NAME="name" EVENT_ID="1003" NEXT_STATE_ID="1">
<action ID="72" />
</transition>
</state>
</stateMachine>
<stateMachine NAME="moveNzoom">
<state NAME="neutral" ID="0" START_STATE="TRUE" X_POS="288" Y_POS="81" WIDTH="100" HEIGHT="50">
<transition NAME="initmove" NEXT_STATE_ID="1" EVENT_ID="4">
<action ID="9" />
</transition>
<transition NAME="initzoom" NEXT_STATE_ID="2" EVENT_ID="2">
<action ID="1011" />
</transition>
</state>
<state NAME="move" ID="1" X_POS="170" Y_POS="413" WIDTH="100" HEIGHT="50">
<transition NAME="move" NEXT_STATE_ID="1" EVENT_ID="533">
<action ID="92" />
</transition>
<transition NAME="finish" NEXT_STATE_ID="0" EVENT_ID="506">
<action ID="43" />
</transition>
</state>
<state NAME="zoom" ID="2" X_POS="584" Y_POS="432" WIDTH="100" HEIGHT="50">
<transition NAME="zoom" NEXT_STATE_ID="2" EVENT_ID="531">
<action ID="1012" />
</transition>
<transition NAME="finish" NEXT_STATE_ID="0" EVENT_ID="507" />
</state>
</stateMachine>
<stateMachine NAME="OnePointDoubleClickInteraction">
<state NAME="empty" ID="0" START_STATE="TRUE">
<transition NAME="doubleclick" NEXT_STATE_ID="1" EVENT_ID="8">
<action ID="10" />
</transition>
<transition NAME="delete" NEXT_STATE_ID="0" EVENT_ID="12">
<action ID="103" />
</transition>
</state>
<state NAME="point available" ID="1">
<transition NAME="doubleclick" NEXT_STATE_ID="1" EVENT_ID="8">
<action ID="103" />
<action ID="10" />
</transition>
<transition NAME="delete" NEXT_STATE_ID="0" EVENT_ID="12">
<action ID="103" />
</transition>
</state>
</stateMachine>
<stateMachine NAME="OnePointMouseMoveInteraction">
<state NAME="empty" ID="0" START_STATE="TRUE">
<transition NAME="mousemove" NEXT_STATE_ID="1" EVENT_ID="520">
<action ID="1101" />
<!--AcMODE_SELECT-->
<action ID="10" />
<!-- Add Point -->
</transition>
<transition NAME="mousewheelmove" NEXT_STATE_ID="1" EVENT_ID="9">
<action ID="1101" />
<!--AcMODE_SELECT-->
<action ID="10" />
<!-- Add Point -->
</transition>
<transition NAME="deleteSafety" NEXT_STATE_ID="0" EVENT_ID="12">
<action ID="103" />
<!-- Remove Point -->
<action ID="1100" />
<!--AcMODEDESELECT-->
</transition>
</state>
<state NAME="point available" ID="1">
<transition NAME="mousemove" NEXT_STATE_ID="1" EVENT_ID="520">
<action ID="1101" />
<!--AcMODE_SELECT-->
<action ID="103" />
<!-- Remove Point -->
<action ID="10" />
<!-- Add Point -->
</transition>
<transition NAME="mousewheelmove" NEXT_STATE_ID="1" EVENT_ID="9">
<action ID="1101" />
<!--AcMODE_SELECT-->
<action ID="103" />
<!-- Remove Point -->
<action ID="10" />
<!-- Add Point -->
</transition>
<transition NAME="delete" NEXT_STATE_ID="0" EVENT_ID="12">
<action ID="103" />
<!-- Remove Point -->
<action ID="1100" />
<!--AcMODEDESELECT-->
</transition>
</state>
</stateMachine>
<stateMachine NAME="CurveModelInteractor">
<!-- Behaviour of a set of Points. a defined number of points can be set/removed/selected/deselectd/moved -->
<state NAME="Start" ID="42" START_STATE="TRUE" X_POS="918" Y_POS="441" WIDTH="100" HEIGHT="50">
<transition NAME="name" EVENT_ID="1" NEXT_STATE_ID="43">
<action ID="21" />
</transition>
</state>
<state NAME="IsPointSelected" ID="43" X_POS="470" Y_POS="441" WIDTH="100" HEIGHT="50">
<transition NAME="name" EVENT_ID="1003" NEXT_STATE_ID="42">
<action ID="72" />
</transition>
<transition NAME="name" EVENT_ID="1004" NEXT_STATE_ID="44" />
</state>
<state NAME="PointSelected" ID="44" X_POS="690" Y_POS="204" WIDTH="100" HEIGHT="50">
<transition NAME="name" EVENT_ID="530" NEXT_STATE_ID="44">
<action ID="91" />
</transition>
<transition NAME="name" EVENT_ID="505" NEXT_STATE_ID="42">
<action ID="43" />
</transition>
</state>
</stateMachine>
<stateMachine NAME="singlepointinteractorwithoutshiftclick">
<!-- Behaviour of one point. This single point can be set, selected and then moved and removed. A setting of a new point will delete the old one.-->
<state NAME="no point or loaded point not selected" ID="1" START_STATE="TRUE" X_POS="18" Y_POS="336" WIDTH="197" HEIGHT="50">
<transition NAME="SetThisStatemachineOnSelected" NEXT_STATE_ID="1" EVENT_ID="1030">
<action ID="1101">
<!--AcMODE_SELECT-->
</action>
</transition>
<transition NAME="SetThisStatemachineOnDeselected" NEXT_STATE_ID="1" EVENT_ID="1031">
<action ID="1100">
<!--AcMODE_DESELECT-->
</action>
</transition>
<transition NAME="addPoint" NEXT_STATE_ID="2" EVENT_ID="1">
<action ID="1101" />
<!--AcMODE_SELECT-->
<action ID="103" />
<!--AcREMOVEALL-->
<action ID="10" />
<!--AcADDPOINT-->
</transition>
</state>
<state NAME="point selected" ID="2" X_POS="674" Y_POS="341" WIDTH="100" HEIGHT="50">
<transition NAME="delete point" NEXT_STATE_ID="1" EVENT_ID="12">
<action ID="100" />
<!--AcREMOVEPOINT-->
<action ID="1100">
<!--AcMODEDESELECT-->
</action>
</transition>
<transition NAME="set point" NEXT_STATE_ID="2" EVENT_ID="1">
<action ID="103" />
<!--AcREMOVEALL-->
<action ID="10" />
<!--AcADDPOINT-->
</transition>
</state>
</stateMachine>
<stateMachine NAME="SeedpointCorrection">
<state NAME="position check" ID="0" START_STATE="TRUE" X_POS="18" Y_POS="336" WIDTH="197" HEIGHT="50">
<transition NAME="nothing found" NEXT_STATE_ID="0" EVENT_ID="1003">
<action ID="48008" />
</transition>
<transition NAME="inside" NEXT_STATE_ID="1" EVENT_ID="1004">
<action ID="31" />
<transition NAME="check position" NEXT_STATE_ID="0" EVENT_ID="520">
<action ID="5000" />
</transition>
<transition NAME="check position 2" NEXT_STATE_ID="0" EVENT_ID="530">
<action ID="5000" />
</transition>
<transition NAME="change BoundingBox" NEXT_STATE_ID="3" EVENT_ID="1013">
<action ID="65" />
</transition>
</transition>
</state>
<state NAME="edit seedpoints" ID="1" X_POS="18" Y_POS="336" WIDTH="197" HEIGHT="50">
<transition NAME="back to start" NEXT_STATE_ID="0" EVENT_ID="520">
<action ID="12" />
</transition>
<transition NAME="initialize correction" NEXT_STATE_ID="2" EVENT_ID="530">
<action ID="5001" />
</transition>
</state>
<state NAME="correct segmentation" ID="2" X_POS="18" Y_POS="336" WIDTH="197" HEIGHT="50">
<transition NAME="draw contour" NEXT_STATE_ID="2" EVENT_ID="530">
<action ID="92" />
</transition>
<transition NAME="calculate result" NEXT_STATE_ID="0" EVENT_ID="505">
<action ID="5002" />
</transition>
</state>
<state NAME="init BoundingBox Resizing" ID="3" X_POS="18" Y_POS="336" WIDTH="197" HEIGHT="50">
<transition NAME="back to start 2" NEXT_STATE_ID="0" EVENT_ID="520">
<action ID="5000" />
</transition>
<transition NAME="add boundingboxinteractor" NEXT_STATE_ID="4" EVENT_ID="1">
<action ID="5003" />
</transition>
</state>
<state NAME="BoundingBox Resizing" ID="4" X_POS="18" Y_POS="336" WIDTH="197" HEIGHT="50">
<transition NAME="calculate result 2" NEXT_STATE_ID="0" EVENT_ID="23">
<action ID="5004" />
</transition>
</state>
</stateMachine>
<stateMachine NAME="BoundingBox Interaction">
<state NAME="position check" ID="0" START_STATE="TRUE" X_POS="18" Y_POS="336" WIDTH="197" HEIGHT="50">
<transition NAME="test" NEXT_STATE_ID="1" EVENT_ID="1">
<action ID="5000" />
</transition>
<transition NAME="test" NEXT_STATE_ID="3" EVENT_ID="520">
<action ID="5000" />
</transition>
</state>
<state NAME="boundingbox resizing initialization" ID="1" X_POS="18" Y_POS="336" WIDTH="197" HEIGHT="50">
<transition NAME="nothing found" NEXT_STATE_ID="0" EVENT_ID="1003">
<action ID="47" />
</transition>
<transition NAME="something found" NEXT_STATE_ID="2" EVENT_ID="1004">
<action ID="94" />
<action ID="110" />
</transition>
</state>
<state NAME="teststate" ID="2" X_POS="18" Y_POS="336" WIDTH="197" HEIGHT="50">
<transition NAME="test 2" NEXT_STATE_ID="2" EVENT_ID="530">
<action ID="11" />
</transition>
<transition NAME="test 3" NEXT_STATE_ID="0" EVENT_ID="505">
<action ID="5" />
</transition>
<transition NAME="test 9" NEXT_STATE_ID="4" EVENT_ID="1003">
<action ID="0" />
</transition>
</state>
<state NAME="teststate 2" ID="3" X_POS="18" Y_POS="336" WIDTH="197" HEIGHT="50">
<transition NAME="test 4" NEXT_STATE_ID="3" EVENT_ID="1004">
<action ID="94" />
</transition>
<transition NAME="test 5" NEXT_STATE_ID="0" EVENT_ID="520">
<action ID="5000" />
</transition>
<transition NAME="test 6" NEXT_STATE_ID="0" EVENT_ID="1003">
<action ID="47" />
</transition>
<transition NAME="test 7" NEXT_STATE_ID="1" EVENT_ID="1">
<action ID="5000" />
</transition>
</state>
<state NAME="teststate 2" ID="4" X_POS="18" Y_POS="336" WIDTH="197" HEIGHT="50">
<transition NAME="test 8" NEXT_STATE_ID="4" EVENT_ID="530">
<action ID="0" />
</transition>
<transition NAME="test 9" NEXT_STATE_ID="0" EVENT_ID="505">
<action ID="0" />
</transition>
</state>
</stateMachine>
<stateMachine NAME="ToolWithWheelInteraction">
<state NAME="ToolIdle" ID="1" START_STATE="TRUE" X_POS="167" Y_POS="365" WIDTH="100" HEIGHT="50">
<transition NAME="MouseWheel" EVENT_ID="9" NEXT_STATE_ID="1">
<action ID="105" />
</transition>
<transition NAME="send Koordinates press" NEXT_STATE_ID="2" EVENT_ID="1">
<action ID="80" />
</transition>
<transition NAME="MouseMove" EVENT_ID="520" NEXT_STATE_ID="1">
<action ID="92" />
</transition>
<transition NAME="name" EVENT_ID="26" NEXT_STATE_ID="1">
<action ID="106" />
</transition>
<transition NAME="name" EVENT_ID="27" NEXT_STATE_ID="1">
<action ID="107" />
</transition>
</state>
<state NAME="ToolInUse" ID="2" X_POS="511" Y_POS="372" WIDTH="100" HEIGHT="50">
<transition NAME="send Koordinates move" NEXT_STATE_ID="2" EVENT_ID="530">
<action ID="90" />
</transition>
<transition NAME="send Koordinates release" NEXT_STATE_ID="1" EVENT_ID="505">
<action ID="42" />
</transition>
<transition NAME="MouseWheel" EVENT_ID="9" NEXT_STATE_ID="2">
<action ID="105" />
</transition>
<transition NAME="name" EVENT_ID="26" NEXT_STATE_ID="2">
<action ID="106" />
</transition>
<transition NAME="name" EVENT_ID="27" NEXT_STATE_ID="2">
<action ID="107" />
</transition>
</state>
</stateMachine>
<stateMachine NAME="AffineInteractor3D">
<state NAME="Start" ID="1" START_STATE="TRUE" X_POS="65" Y_POS="267" WIDTH="100" HEIGHT="50">
<transition NAME="name" EVENT_ID="520" NEXT_STATE_ID="2">
<action ID="31" />
</transition>
</state>
<state NAME="IsOverObject" ID="2" X_POS="352" Y_POS="267" WIDTH="100" HEIGHT="50">
<transition NAME="name" EVENT_ID="1003" NEXT_STATE_ID="1">
<action ID="70" />
</transition>
<transition NAME="name" EVENT_ID="1004" NEXT_STATE_ID="3">
<action ID="60" />
</transition>
<transition NAME="name" EVENT_ID="9" NEXT_STATE_ID="2">
<action ID="49014" />
</transition>
</state>
<state NAME="ObjectSelected" ID="3" X_POS="719" Y_POS="268" WIDTH="100" HEIGHT="50">
<transition NAME="name" EVENT_ID="520" NEXT_STATE_ID="2">
<action ID="31" />
</transition>
<transition NAME="name" EVENT_ID="1" NEXT_STATE_ID="4">
<action ID="9" />
</transition>
<transition NAME="name" EVENT_ID="9" NEXT_STATE_ID="3">
<action ID="49014" />
</transition>
</state>
<state NAME="ObjectInteraction" ID="4" X_POS="598" Y_POS="629" WIDTH="100" HEIGHT="50">
<transition NAME="name" EVENT_ID="530" NEXT_STATE_ID="4">
<action ID="92" />
</transition>
<transition NAME="name" EVENT_ID="505" NEXT_STATE_ID="2">
<action ID="31" />
</transition>
<transition NAME="name" EVENT_ID="521" NEXT_STATE_ID="4">
<action ID="49014" />
<action ID="92" />
</transition>
</state>
</stateMachine>
- <stateMachine NAME="Zoom">
- <state NAME="neutral" ID="0" START_STATE="TRUE" X_POS="288" Y_POS="81" WIDTH="100" HEIGHT="50">
- <transition NAME="initzoom" NEXT_STATE_ID="2" EVENT_ID="1">
- <action ID="1011" />
- </transition>
- </state>
- <state NAME="zoom" ID="2" X_POS="584" Y_POS="432" WIDTH="100" HEIGHT="50">
- <transition NAME="zoom" NEXT_STATE_ID="2" EVENT_ID="530">
- <action ID="1012" />
- </transition>
- <transition NAME="finish" NEXT_STATE_ID="0" EVENT_ID="505" />
- </state>
- </stateMachine>
<stateMachine NAME="CtrlZoom">
<state NAME="neutral" ID="0" START_STATE="TRUE" X_POS="288" Y_POS="81" WIDTH="100" HEIGHT="50">
<transition NAME="initzoom" NEXT_STATE_ID="1" EVENT_ID="7">
<action ID="1011" />
</transition>
</state>
<state NAME="zoom" ID="1" X_POS="584" Y_POS="432" WIDTH="100" HEIGHT="50">
<transition NAME="CtrlZoom" NEXT_STATE_ID="1" EVENT_ID="535">
<action ID="1012" />
</transition>
<transition NAME="finish" NEXT_STATE_ID="0" EVENT_ID="538" />
</state>
</stateMachine>
- <stateMachine NAME="LeftClickScroll">
- <state NAME="neutral" ID="0" START_STATE="TRUE" X_POS="288" Y_POS="81" WIDTH="100" HEIGHT="50">
- <transition NAME="initmove" NEXT_STATE_ID="1" EVENT_ID="1">
- <action ID="9" />
- </transition>
- </state>
- <state NAME="scroll" ID="1" X_POS="170" Y_POS="413" WIDTH="100" HEIGHT="50">
- <transition NAME="scroll" NEXT_STATE_ID="1" EVENT_ID="530">
- <action ID="1013" />
- </transition>
- <transition NAME="finish" NEXT_STATE_ID="0" EVENT_ID="505">
- <action ID="43" />
- </transition>
- </state>
- </stateMachine>
- <stateMachine NAME="MiddleClickScroll">
+ <stateMachine NAME="ShiftClickPan">
<state NAME="neutral" ID="0" START_STATE="TRUE" X_POS="288" Y_POS="81" WIDTH="100" HEIGHT="50">
- <transition NAME="initmove" NEXT_STATE_ID="1" EVENT_ID="4">
+ <transition NAME="initshiftmove" NEXT_STATE_ID="1" EVENT_ID="644">
<action ID="9" />
</transition>
- </state>
- <state NAME="scroll" ID="1" X_POS="170" Y_POS="413" WIDTH="100" HEIGHT="50">
- <transition NAME="scroll" NEXT_STATE_ID="1" EVENT_ID="533">
- <action ID="1013" />
- </transition>
- <transition NAME="finish" NEXT_STATE_ID="0" EVENT_ID="506">
- <action ID="43" />
- </transition>
- </state>
- </stateMachine>
- <stateMachine NAME="Pan">
- <state NAME="neutral" ID="0" START_STATE="TRUE" X_POS="288" Y_POS="81" WIDTH="100" HEIGHT="50">
- <transition NAME="initmove" NEXT_STATE_ID="1" EVENT_ID="1">
+ <transition NAME="altinitshiftmove" NEXT_STATE_ID="1" EVENT_ID="2000">
<action ID="9" />
</transition>
</state>
- <state NAME="move" ID="1" X_POS="170" Y_POS="413" WIDTH="100" HEIGHT="50">
- <transition NAME="move" NEXT_STATE_ID="1" EVENT_ID="530">
+ <state NAME="shiftmove" ID="1" X_POS="170" Y_POS="413" WIDTH="100" HEIGHT="50">
+ <transition NAME="shiftmove" NEXT_STATE_ID="1" EVENT_ID="2001">
<action ID="92" />
</transition>
- <transition NAME="finish" NEXT_STATE_ID="0" EVENT_ID="505">
+ <transition NAME="finish" NEXT_STATE_ID="0" EVENT_ID="2002">
<action ID="43" />
</transition>
- </state>
- </stateMachine>
- <stateMachine NAME="ShiftClickPan">
- <state NAME="neutral" ID="0" START_STATE="TRUE" X_POS="288" Y_POS="81" WIDTH="100" HEIGHT="50">
- <transition NAME="initshiftmove" NEXT_STATE_ID="1" EVENT_ID="2000">
- <action ID="9" />
- </transition>
- </state>
- <state NAME="shiftmove" ID="1" X_POS="170" Y_POS="413" WIDTH="100" HEIGHT="50">
- <transition NAME="shiftmove" NEXT_STATE_ID="1" EVENT_ID="2001">
+ <transition NAME="altshiftmove" NEXT_STATE_ID="1" EVENT_ID="645">
<action ID="92" />
</transition>
- <transition NAME="finish" NEXT_STATE_ID="0" EVENT_ID="2002">
+ <transition NAME="altfinish" NEXT_STATE_ID="0" EVENT_ID="646">
<action ID="43" />
</transition>
</state>
</stateMachine>
<stateMachine NAME="RightClickLevelWindow">
<state NAME="neutral" ID="0" START_STATE="TRUE" X_POS="288" Y_POS="81" WIDTH="100" HEIGHT="50">
<transition NAME="initmove" NEXT_STATE_ID="1" EVENT_ID="2">
<action ID="9" />
</transition>
</state>
<state NAME="levelwindow" ID="1" X_POS="584" Y_POS="432" WIDTH="100" HEIGHT="50">
<transition NAME="levelwindow" NEXT_STATE_ID="1" EVENT_ID="531">
<action ID="1014" />
</transition>
<transition NAME="finish" NEXT_STATE_ID="0" EVENT_ID="507" />
</state>
</stateMachine>
<stateMachine NAME="LeftClickLevelWindow">
<state NAME="neutral" ID="0" START_STATE="TRUE" X_POS="288" Y_POS="81" WIDTH="100" HEIGHT="50">
<transition NAME="initmove" NEXT_STATE_ID="1" EVENT_ID="1">
<action ID="9" />
</transition>
</state>
<state NAME="levelwindow" ID="1" X_POS="584" Y_POS="432" WIDTH="100" HEIGHT="50">
<transition NAME="levelwindow" NEXT_STATE_ID="1" EVENT_ID="530">
<action ID="1014" />
</transition>
<transition NAME="finish" NEXT_STATE_ID="0" EVENT_ID="505" />
</state>
</stateMachine>
<stateMachine NAME="PlanarFigureInteractor">
<!-- Behaviour of a set of Points. a defined number of points can be set/removed/selected/deselectd/moved -->
<state NAME="Start" ID="42" START_STATE="TRUE" X_POS="1368" Y_POS="736" WIDTH="100" HEIGHT="50">
<transition NAME="name" EVENT_ID="0" NEXT_STATE_ID="49">
<action ID="31" />
</transition>
</state>
<state NAME="FigurePlaced" ID="45" X_POS="836" Y_POS="715" WIDTH="100" HEIGHT="50">
<transition NAME="name" EVENT_ID="520" NEXT_STATE_ID="45">
<action ID="90" />
</transition>
<transition NAME="name" EVENT_ID="8" NEXT_STATE_ID="54">
<action ID="33" />
</transition>
<transition NAME="name" EVENT_ID="530" NEXT_STATE_ID="57">
<action ID="90" />
</transition>
<transition NAME="name" EVENT_ID="1" NEXT_STATE_ID="58">
<action ID="21" />
</transition>
</state>
<state NAME="ControlPointSelected" ID="47" X_POS="74" Y_POS="665" WIDTH="128" HEIGHT="50">
<transition NAME="name" EVENT_ID="530" NEXT_STATE_ID="47">
<action ID="90" />
</transition>
<transition NAME="name" EVENT_ID="505" NEXT_STATE_ID="52">
<action ID="76" />
</transition>
</state>
<state NAME="IsLastControlPoint" ID="48" X_POS="1102" Y_POS="732" WIDTH="100" HEIGHT="50">
<transition NAME="name" EVENT_ID="1004" NEXT_STATE_ID="42" />
<transition NAME="name" EVENT_ID="1003" NEXT_STATE_ID="45">
<action ID="10" />
</transition>
</state>
<state NAME="IsPlaced" ID="49" X_POS="1302" Y_POS="201" WIDTH="100" HEIGHT="50">
<transition NAME="name" EVENT_ID="1003" NEXT_STATE_ID="50" />
<transition NAME="name" EVENT_ID="1004" NEXT_STATE_ID="51" />
</state>
<state NAME="PlaceFigure" ID="50" X_POS="868" Y_POS="293" WIDTH="100" HEIGHT="50">
<transition NAME="name" EVENT_ID="1" NEXT_STATE_ID="45">
<action ID="11" />
</transition>
</state>
<state NAME="EditFigure" ID="51" X_POS="804" Y_POS="199" WIDTH="100" HEIGHT="50">
<transition NAME="name" EVENT_ID="520" NEXT_STATE_ID="52">
<action ID="341" />
</transition>
</state>
<state NAME="IsOverFigure" ID="52" X_POS="340" Y_POS="170" WIDTH="100" HEIGHT="50">
<transition NAME="name" EVENT_ID="1003" NEXT_STATE_ID="51" />
<transition NAME="name" EVENT_ID="1004" NEXT_STATE_ID="53" />
</state>
<state NAME="FigureHover" ID="53" X_POS="563" Y_POS="326" WIDTH="115" HEIGHT="50">
<transition NAME="name" EVENT_ID="520" NEXT_STATE_ID="52">
<action ID="341" />
</transition>
<transition NAME="name" EVENT_ID="2" NEXT_STATE_ID="60">
<action ID="60" />
</transition>
<transition NAME="name" EVENT_ID="1" NEXT_STATE_ID="65">
<action ID="34" />
</transition>
</state>
<state NAME="IsMinFigureFinished" ID="54" X_POS="972" Y_POS="929" WIDTH="110" HEIGHT="50">
<transition NAME="name" EVENT_ID="1004" NEXT_STATE_ID="42" />
<transition NAME="name" EVENT_ID="1003" NEXT_STATE_ID="45" />
</state>
<state NAME="ResetFigure" ID="55" X_POS="610" Y_POS="934" WIDTH="100" HEIGHT="50">
<transition NAME="name" EVENT_ID="1003" NEXT_STATE_ID="47" />
<transition NAME="name" EVENT_ID="1004" NEXT_STATE_ID="45" />
</state>
<state NAME="FigurePlacedByDrag" ID="57" X_POS="1047" Y_POS="391" WIDTH="138" HEIGHT="50">
<transition NAME="name" EVENT_ID="530" NEXT_STATE_ID="57">
<action ID="90" />
</transition>
<transition NAME="name" EVENT_ID="505" NEXT_STATE_ID="58">
<action ID="21" />
</transition>
</state>
<state NAME="IsPointValid" ID="58" X_POS="1212" Y_POS="555" WIDTH="100" HEIGHT="50">
<transition NAME="name" EVENT_ID="1004" NEXT_STATE_ID="48">
<action ID="32" />
</transition>
<transition NAME="name" EVENT_ID="1003" NEXT_STATE_ID="45" />
</state>
<state NAME="FigureSelectedForDelete" ID="60" X_POS="308" Y_POS="532" WIDTH="132" HEIGHT="50">
<transition NAME="name" EVENT_ID="1004" NEXT_STATE_ID="52">
<action ID="100" />
</transition>
<transition NAME="name" EVENT_ID="1003" NEXT_STATE_ID="53" />
</state>
<state NAME="IsOverControlPoint" ID="59" X_POS="586" Y_POS="636" WIDTH="120" HEIGHT="50">
<transition NAME="name" EVENT_ID="1004" NEXT_STATE_ID="55">
<action ID="66" />
</transition>
<transition NAME="name" EVENT_ID="1003" NEXT_STATE_ID="47">
<action ID="10" />
</transition>
</state>
<state NAME="FigureSeleced" ID="65" X_POS="740" Y_POS="487" WIDTH="100" HEIGHT="50">
<transition NAME="name" EVENT_ID="1003" NEXT_STATE_ID="53" />
<transition NAME="name" EVENT_ID="1004" NEXT_STATE_ID="59">
<action ID="60" />
</transition>
</state>
</stateMachine>
<stateMachine NAME="FiberBundleInteractor">
<!-- working with mitk::FiberBundles -->
<state NAME="Start" ID="123451" START_STATE="TRUE" X_POS="1368" Y_POS="736" WIDTH="100" HEIGHT="50">
<transition NAME="name" EVENT_ID="520" NEXT_STATE_ID="123451">
<!-- on EIDMOUSEMOVE keep in state and do AcCHECKHOVERING (which throws EIDFIGUREHOVER or EIDNOFIGUREHOVER if applicable) -->
<action ID="341" />
</transition>
<transition NAME="name" EVENT_ID="12340" NEXT_STATE_ID="123452">
<!-- on EIDFIGUREHOVER go to HoverFiber and do nothing -->
<!-- previously: AcSELECTPICKEDOBJECT -->
<action ID="0" />
</transition>
</state>
<state NAME="HoverFiber" ID="123452" X_POS="340" Y_POS="170" WIDTH="100" HEIGHT="50">
<transition NAME="name" EVENT_ID="520" NEXT_STATE_ID="123452">
<!-- on EIDMOUSEMOVE keep state and do AcCHECKHOVERING (which throws EIDFIGUREHOVER or EIDNOFIGUREHOVER if applicable) -->
<action ID="341" />
</transition>
<transition NAME="name" EVENT_ID="12340" NEXT_STATE_ID="123452">
<!-- on EIDFIGUREHOVER keep state and do nothing -->
<!-- previously: AcSELECTPICKEDOBJECT -->
<action ID="0" />
</transition>
<transition NAME="name" EVENT_ID="12341" NEXT_STATE_ID="123451">
<!-- on EIDNOFIGUREHOVER go to Start and do nothing -->
<!-- previously: AcDESELECTALL -->
<action ID="0" />
</transition>
<transition NAME="name" EVENT_ID="1" NEXT_STATE_ID="123452">
<!-- on EIDLEFTMOUSEBTN keep state and do AcREMOVE -->
<action ID="101" />
</transition>
</state>
</stateMachine>
<stateMachine NAME="BinaryImageInteractor">
<state START_STATE="TRUE" NAME="UndecidedState" ID="2" X_POS="374" Y_POS="98" WIDTH="139" HEIGHT="50">
<transition NAME="name" EVENT_ID="1" NEXT_STATE_ID="11">
<action ID="60" />
</transition>
<transition NAME="name" EVENT_ID="520" NEXT_STATE_ID="2">
<action ID="30" />
</transition>
<transition NAME="name" EVENT_ID="1013" NEXT_STATE_ID="6">
<action ID="6" />
</transition>
</state>
<state NAME="CorrectionMode" ID="6" X_POS="749" Y_POS="498" WIDTH="188" HEIGHT="51">
<transition NAME="name" EVENT_ID="1" NEXT_STATE_ID="7">
<action ID="8" />
</transition>
<transition NAME="name" EVENT_ID="1002" NEXT_STATE_ID="2">
<action ID="40">
<!--End of correction mode - hide sphere-->
</action>
</transition>
<transition NAME="name" EVENT_ID="27" NEXT_STATE_ID="6">
<action ID="107" />
</transition>
<transition NAME="name" EVENT_ID="26" NEXT_STATE_ID="6">
<action ID="106" />
</transition>
<transition NAME="name" EVENT_ID="520" NEXT_STATE_ID="6">
<action ID="49006" />
</transition>
+ <transition NAME="name" EVENT_ID="9" NEXT_STATE_ID="6">
+ <action ID="49006" />
+ </transition>
+ <transition NAME="name" EVENT_ID="630" NEXT_STATE_ID="6">
+ <action ID="49007" />
+ </transition>
</state>
<state NAME="DragSegmentationSurface" ID="7" X_POS="95" Y_POS="473" WIDTH="202" HEIGHT="50">
<transition NAME="name" EVENT_ID="530" NEXT_STATE_ID="7">
<action ID="90" />
</transition>
<transition NAME="name" EVENT_ID="505" NEXT_STATE_ID="7">
<action ID="43" />
</transition>
<transition NAME="name" EVENT_ID="1002" NEXT_STATE_ID="2">
<action ID="40" />
</transition>
</state>
<state NAME="CheckIfImageIsSelected" ID="11" X_POS="771" Y_POS="201" WIDTH="255" HEIGHT="50">
<transition NAME="name" EVENT_ID="1003" NEXT_STATE_ID="2" />
<transition NAME="name" EVENT_ID="1004" NEXT_STATE_ID="6">
<action ID="6">
<!--Initialize correction mode, visualize a sphere-->
</action>
</transition>
</state>
</stateMachine>
+ <stateMachine NAME="Pan">
+ <state NAME="neutral" ID="0" START_STATE="TRUE" X_POS="288" Y_POS="81" WIDTH="100" HEIGHT="50">
+ <transition NAME="initmove" NEXT_STATE_ID="1" EVENT_ID="1">
+ <action ID="9" />
+ </transition>
+ <transition NAME="initaltmove" NEXT_STATE_ID="1" EVENT_ID="600">
+ <action ID="9" />
+ </transition>
+ </state>
+ <state NAME="move" ID="1" X_POS="242" Y_POS="382" WIDTH="100" HEIGHT="50">
+ <transition NAME="move" NEXT_STATE_ID="1" EVENT_ID="530">
+ <action ID="92" />
+ </transition>
+ <transition NAME="altmove" NEXT_STATE_ID="1" EVENT_ID="610">
+ <action ID="92" />
+ </transition>
+ <transition NAME="finish" NEXT_STATE_ID="0" EVENT_ID="505">
+ <action ID="43" />
+ </transition>
+ <transition NAME="altfinish" NEXT_STATE_ID="0" EVENT_ID="620">
+ <action ID="43" />
+ </transition>
+ </state>
+ </stateMachine>
+ <stateMachine NAME="LeftClickScroll">
+ <state NAME="neutral" ID="0" START_STATE="TRUE" X_POS="288" Y_POS="81" WIDTH="100" HEIGHT="50">
+ <transition NAME="initmove" NEXT_STATE_ID="1" EVENT_ID="1">
+ <action ID="9" />
+ </transition>
+ <transition NAME="altinitmove" EVENT_ID="600" NEXT_STATE_ID="1">
+ <action ID="9" />
+ </transition>
+ </state>
+ <state NAME="scroll" ID="1" X_POS="170" Y_POS="413" WIDTH="100" HEIGHT="50">
+ <transition NAME="scroll" NEXT_STATE_ID="1" EVENT_ID="530">
+ <action ID="1013" />
+ </transition>
+ <transition NAME="finish" NEXT_STATE_ID="0" EVENT_ID="505">
+ <action ID="43" />
+ </transition>
+ <transition NAME="altfinish" EVENT_ID="620" NEXT_STATE_ID="0">
+ <action ID="43" />
+ </transition>
+ <transition NAME="altscroll" EVENT_ID="610" NEXT_STATE_ID="1">
+ <action ID="1013" />
+ </transition>
+ </state>
+ </stateMachine>
+ <stateMachine NAME="Zoom">
+ <state NAME="neutral" ID="0" START_STATE="TRUE" X_POS="288" Y_POS="81" WIDTH="100" HEIGHT="50">
+ <transition NAME="initzoom" NEXT_STATE_ID="2" EVENT_ID="1">
+ <action ID="1011" />
+ </transition>
+ <transition NAME="name" EVENT_ID="600" NEXT_STATE_ID="2">
+ <action ID="1011" />
+ </transition>
+ </state>
+ <state NAME="zoom" ID="2" X_POS="584" Y_POS="432" WIDTH="100" HEIGHT="50">
+ <transition NAME="zoom" NEXT_STATE_ID="2" EVENT_ID="530">
+ <action ID="1012" />
+ </transition>
+ <transition NAME="finish" NEXT_STATE_ID="0" EVENT_ID="505" />
+ <transition NAME="name" EVENT_ID="620" NEXT_STATE_ID="0" />
+ <transition NAME="name" EVENT_ID="610" NEXT_STATE_ID="2">
+ <action ID="1012" />
+ </transition>
+ </state>
+ </stateMachine>
+ <stateMachine NAME="MouseWheelScroll">
+ <state NAME="neutral" ID="0" START_STATE="TRUE" X_POS="288" Y_POS="81" WIDTH="100" HEIGHT="50">
+ <transition NAME="name" EVENT_ID="9" NEXT_STATE_ID="0">
+ <action ID="1015" />
+ </transition>
+ <transition NAME="name" EVENT_ID="640" NEXT_STATE_ID="0">
+ <action ID="1015" />
+ </transition>
+ </state>
+ </stateMachine>
+ <stateMachine NAME="MiddleClickScroll">
+ <state NAME="neutral" ID="0" START_STATE="TRUE" X_POS="288" Y_POS="81" WIDTH="100" HEIGHT="50">
+ <transition NAME="initmove" NEXT_STATE_ID="1" EVENT_ID="4">
+ <action ID="9" />
+ </transition>
+ <transition NAME="altinitmove" EVENT_ID="641" NEXT_STATE_ID="1">
+ <action ID="9" />
+ </transition>
+ </state>
+ <state NAME="scroll" ID="1" X_POS="170" Y_POS="413" WIDTH="100" HEIGHT="50">
+ <transition NAME="scroll" NEXT_STATE_ID="1" EVENT_ID="533">
+ <action ID="1013" />
+ </transition>
+ <transition NAME="finish" NEXT_STATE_ID="0" EVENT_ID="506">
+ <action ID="43" />
+ </transition>
+ <transition NAME="altfinish" EVENT_ID="643" NEXT_STATE_ID="0">
+ <action ID="43" />
+ </transition>
+ <transition NAME="altscroll" EVENT_ID="642" NEXT_STATE_ID="1">
+ <action ID="1013" />
+ </transition>
+ </state>
+ </stateMachine>
</mitkInteraktionStates>
<!-- DOCUMENTATION -->
<!-- This is StateMachine.xml. Includes Information about different StateMachines and Events. Used by EventMapper and StateMachineFactory -->
<!-- /** \example StateMachine.xml -->
<!-- -->
<!-- -->
<!-- FAQ -->
<!-- Question: the Application, that is loading this file doesn't act on the Interaction. Why? -->
<!-- The QXMLFileLoader probably isn't able to load the file due to an error.-->
<!-- Check the file for XML-Syntax like "<" at beginning and "/>" at end -->
diff --git a/Core/Code/Interactions/mitkDisplayVectorInteractorScroll.cpp b/Core/Code/Interactions/mitkDisplayVectorInteractorScroll.cpp
index f7e266fa44..f087294717 100644
--- a/Core/Code/Interactions/mitkDisplayVectorInteractorScroll.cpp
+++ b/Core/Code/Interactions/mitkDisplayVectorInteractorScroll.cpp
@@ -1,161 +1,225 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date: 2010-01-14 14:20:26 +0100 (Thu, 14 Jan 2010) $
Version: $Revision: 21047 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "mitkDisplayVectorInteractorScroll.h"
#include "mitkOperation.h"
#include "mitkDisplayCoordinateOperation.h"
//#include "mitkDisplayPositionEvent.h"
#include "mitkUndoController.h"
#include "mitkStateEvent.h"
#include "mitkInteractionConst.h"
#include "mitkAction.h"
void mitk::DisplayVectorInteractorScroll::ExecuteOperation(Operation* itkNotUsed( operation ) )
{
}
bool mitk::DisplayVectorInteractorScroll::ExecuteAction(Action* action, mitk::StateEvent const* stateEvent)
{
bool ok=false;
-
+
+
const DisplayPositionEvent* posEvent=dynamic_cast<const DisplayPositionEvent*>(stateEvent->GetEvent());
- if(posEvent==NULL) return false;
+
+ m_IsAltModifierActive = false;
int actionId = action->GetActionId();
switch(actionId)
{
case AcINITMOVE:
{
+ if(posEvent==NULL) return false;
+
m_Sender=posEvent->GetSender();
m_StartDisplayCoordinate=posEvent->GetDisplayPosition();
m_LastDisplayCoordinate=posEvent->GetDisplayPosition();
m_CurrentDisplayCoordinate=posEvent->GetDisplayPosition();
ok = true;
break;
}
- case AcSCROLL:
+ case AcSCROLLMOUSEWHEEL:
+ {
+ const WheelEvent* wheelEvent=dynamic_cast<const WheelEvent*>(stateEvent->GetEvent());
+
+ if(wheelEvent != NULL)
{
+ int buttonState = stateEvent->GetEvent()->GetButtonState();
+ if(buttonState == 1024)
+ {
+ m_IsAltModifierActive = true;
+ }
+ mitk::SliceNavigationController::Pointer sliceNaviController = wheelEvent->GetSender()->GetSliceNavigationController();
+
+ if ( !sliceNaviController->GetSliceLocked() )
+ {
+ this->InvokeEvent( StartScrollInteractionEvent() );
+ mitk::Stepper* stepper = sliceNaviController->GetSlice();
+
+ if (stepper->GetSteps() <= 1)
+ {
+ stepper = sliceNaviController->GetTime();
+ }
+
+ // get the desired delta
+ int delta = wheelEvent->GetDelta();
+ if ( m_InvertScrollingDirection )
+ delta *= -1; // If we want to invert the scrolling direction -> delta * -1
+
+ if ( delta < 0 )
+ {
+ stepper->Next();
+ }
+ else
+ {
+ stepper->Previous();
+ }
+ }
+ this->InvokeEvent( EndScrollInteractionEvent() );
+ }
+ ok = true;
+ break;
+ }
+ case AcSCROLL:
+ {
+ if(posEvent==NULL) return false;
+
+ int buttonState = stateEvent->GetEvent()->GetButtonState();
+ //1025 = Alt+LeftMouseButton+Move
+ //1028 = Alt+MiddleMouseButton+Move
+ if(buttonState == 1025 || buttonState == 1028 )
+ {
+ m_IsAltModifierActive = true;
+ }
+
mitk::SliceNavigationController::Pointer sliceNaviController = m_Sender->GetSliceNavigationController();
if(sliceNaviController)
{
- this->InvokeEvent( StartInteractionEvent() );
+ this->InvokeEvent( StartScrollInteractionEvent() );
+
+ int delta = 0;
- int delta = m_LastDisplayCoordinate[1]-posEvent->GetDisplayPosition()[1];
+ delta = m_LastDisplayCoordinate[1]-posEvent->GetDisplayPosition()[1];
// 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;
if ( m_InvertScrollingDirection )
delta *= -1;
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 );
- this->InvokeEvent( EndInteractionEvent() );
+ this->InvokeEvent( EndScrollInteractionEvent() );
}
m_LastDisplayCoordinate=m_CurrentDisplayCoordinate;
- m_CurrentDisplayCoordinate=posEvent->GetDisplayPosition();
+ m_CurrentDisplayCoordinate=posEvent->GetDisplayPosition();
}
case AcFINISHMOVE:
{
ok = true;
break;
}
default:
ok = false;
break;
}
return ok;
}
void mitk::DisplayVectorInteractorScroll::SetIndexToSliceModifier( int modifier )
{
m_IndexToSliceModifier = modifier;
}
void mitk::DisplayVectorInteractorScroll::SetAutoRepeat( bool autoRepeat )
{
m_AutoRepeat = autoRepeat;
}
mitk::DisplayVectorInteractorScroll::DisplayVectorInteractorScroll(const char * type, mitk::OperationActor* destination)
: mitk::StateMachine(type)
, m_Sender(NULL)
, m_Destination(destination)
, m_IndexToSliceModifier(4)
, m_AutoRepeat( false )
, m_InvertScrollingDirection( false )
+ , m_IsAltModifierActive( false )
{
m_StartDisplayCoordinate.Fill(0);
m_LastDisplayCoordinate.Fill(0);
m_CurrentDisplayCoordinate.Fill(0);
m_UndoEnabled = false;
//if(m_Destination==NULL)
// m_Destination=this;
}
mitk::DisplayVectorInteractorScroll::~DisplayVectorInteractorScroll()
{
if ( m_Destination != this )
delete m_Destination;
}
void mitk::DisplayVectorInteractorScroll::SetInvertScrollingDirection( bool invert )
{
m_InvertScrollingDirection = invert;
}
+bool mitk::DisplayVectorInteractorScroll::IsAltModifierActive() const
+{
+ return m_IsAltModifierActive;
+}
+
diff --git a/Core/Code/Interactions/mitkDisplayVectorInteractorScroll.h b/Core/Code/Interactions/mitkDisplayVectorInteractorScroll.h
index 9a4010bccf..abce7e8a35 100644
--- a/Core/Code/Interactions/mitkDisplayVectorInteractorScroll.h
+++ b/Core/Code/Interactions/mitkDisplayVectorInteractorScroll.h
@@ -1,120 +1,124 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date: 2009-05-28 17:19:30 +0200 (Thu, 28 May 2009) $
Version: $Revision: 17495 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef MITKDISPLAYVECTORINTERACTORSCROLL_H_HEADER_INCLUDED_C10DC4EB
#define MITKDISPLAYVECTORINTERACTORSCROLL_H_HEADER_INCLUDED_C10DC4EB
#include <MitkExports.h>
#include "mitkBaseRenderer.h"
#include "mitkStateMachine.h"
namespace mitk {
class Operation;
class OperationActor;
/**
* @brief Interactor for scrolling through the slices of an image
*
* This class implements an Interactor for slice-scrolling. It is defined by the 'Scroll'-statemachine which maps 'initmove' to left mousebutton pressed,
* 'scroll' to left mousebutton and move and 'finishmove' to left mousebutton released.
*
* Thus it is possible to scroll through the slices of an image rapidly, without using the mousewheel.
*
* @ingroup MITK_CORE_EXPORT
**/
class MITK_CORE_EXPORT DisplayVectorInteractorScroll : public StateMachine
{
public:
mitkClassMacro(DisplayVectorInteractorScroll, StateMachine);
mitkNewMacro2Param(Self, const char*, OperationActor*);
#pragma GCC visibility push(default)
itkEventMacro( InteractionEvent, itk::AnyEvent );
- itkEventMacro( StartInteractionEvent, InteractionEvent );
- itkEventMacro( EndInteractionEvent, InteractionEvent );
+ itkEventMacro( StartScrollInteractionEvent, InteractionEvent );
+ itkEventMacro( EndScrollInteractionEvent, InteractionEvent );
#pragma GCC visibility pop
/**
* @brief Method derived from OperationActor to recieve and execute operations
**/
virtual void ExecuteOperation(Operation* operation);
/**
* \brief Defines how many slices are scrolled per pixel that the mouse cursor has moved
*/
void SetIndexToSliceModifier( int modifier );
void SetAutoRepeat( bool autoRepeat );
void SetInvertScrollingDirection( bool );
+ bool IsAltModifierActive() const;
+
protected:
/**
* @brief Default Constructor
**/
DisplayVectorInteractorScroll(const char * type, mitk::OperationActor* destination=NULL);
/**
* @brief Default Destructor
**/
virtual ~DisplayVectorInteractorScroll();
/**
* @brief Method derived from StateMachine to implement the own actions
**/
virtual bool ExecuteAction(Action* action, mitk::StateEvent const* stateEvent);
private:
BaseRenderer::Pointer m_Sender;
mitk::Point2D m_StartDisplayCoordinate;
mitk::Point2D m_LastDisplayCoordinate;
mitk::Point2D m_CurrentDisplayCoordinate;
OperationActor* m_Destination;
/**
* \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;
/**
* \brief Defines if it is possible to scroll endlessly
*
* If AutoRepeat is on, scrolling further than the last slice will restart at the first slice and vice versa
*/
bool m_AutoRepeat;
bool m_InvertScrollingDirection;
+ bool m_IsAltModifierActive;
+
};
} // namespace mitk
#endif /* MITKDISPLAYVECTORINTERACTOR_H_HEADER_INCLUDED_C10DC4EB */
diff --git a/Core/Code/Interactions/mitkInteractionConst.h b/Core/Code/Interactions/mitkInteractionConst.h
index b12336b962..43be353356 100644
--- a/Core/Code/Interactions/mitkInteractionConst.h
+++ b/Core/Code/Interactions/mitkInteractionConst.h
@@ -1,743 +1,753 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef MITKINTERACTCONST_H
#define MITKINTERACTCONST_H
//##Documentation
//## @file mitkInteractionConst.h
//## @brief Constants for most interaction classes, due to the generic StateMachines.
//##
//## Changes in Type, ButtonState or Key has to be don in mitkEventMapper.cpp, too.
//## @ingroup Interaction
/*Prefixes for Constants:
E = Enumeration
EID = EventId's
Op = Operations
Ac = Action
Type_ = Type of Event
BS_ = ButtonStates and Buttons
Key_ = Keys like in QT
*/
namespace mitk{
//Constants for EventIds; use the according constant to through an event in the code
enum EEventIds
{
EIDNULLEVENT = 0,
EIDLEFTMOUSEBTN = 1,
EIDRIGHTMOUSEBTN = 2,
EIDLEFTMOUSEBTNANDSHIFT = 3,
EIDMIDDLEMOUSEBTN = 4,
EIDLEFTMOUSEBTNANDCTRL = 5,
EIDMIDDLEMOUSEBTNANDCTRL = 6,
EIDRIGHTMOUSEBTNANDCTRL = 7,
EIDLEFTMOUSEBTNDOUBLECLICK = 8,
EIDMOUSEWHEEL = 9,
EIDLEFTMOUSERELEASE = 505,
EIDMIDDLEMOUSERELEASE = 506,
EIDRIGHTMOUSERELEASE = 507,
EIDLEFTMOUSERELEASEANDSHIFT = 508,
EIDMOUSEMOVE = 520,
EIDLEFTMOUSEBTNANDMOUSEWHEEL = 521,
EIDRIGHTMOUSEBTNANDMOUSEWHEEL = 522,
EIDMIDDLEMOUSEBTNANDMOUSEWHEEL = 523,
EIDLEFTMOUSEBTNANDMOUSEMOVE = 530,
EIDRIGHTMOUSEBTNANDMOUSEMOVE = 531,
EIDMIDDLEMOUSEBTNANDMOUSEMOVE = 533,
EIDCTRLANDLEFTMOUSEBTNANDMOUSEMOVE = 534,
EIDCTRLANDRIGHTMOUSEBTNANDMOUSEMOVE = 535,
EIDCTRLANDMIDDLEMOUSEBTNANDMOUSEMOVE = 536,
EIDCTRLANDLEFTMOUSEBTNRELEASE = 537,
EIDCTRLANDRIGHTMOUSEBTNRELEASE = 538,
EIDCTRLANDMIDDLEMOUSEBTNRELEASE = 539,
EIDSHIFTANDCTRLANDMIDDLEMOUSEBTN = 540,
EIDSHIFTANDLEFTMOUSEBTNANDMOUSEMOVE = 541,
EIDSHIFTANDCTRLANDMOUSEMOVE = 542,
EIDSHIFTANDCTRLANDMOUSERELEASE = 543,
EIDALTANDLEFTMOUSEBTN = 600,
EIDALTANDLEFTMOUSEBTNANDMOUSEMOVE = 610,
EIDALTANDLEFTMOUSERELEASE = 620,
+ EIDCTRLANDLEFTMOUSEWHEEL = 630,
+ EIDALTANDMOUSEWHEEL = 640,
+ EIDALTANDMIDDLEMOUSEBTN = 641,
+ EIDALTANDMIDDLEMOUSEBTNANDMOVE = 642,
+ EIDALTANDMIDDLEMOUSEBTNRELEASE = 643,
+ EIDALTANDSHIFTANDRIGHTMOUSEBTN = 644,
+ EIDALTANDSHIFTANDRIGHTMOUSEBTNANDMOUSEMOVE = 645,
+ EIDALTANDSHIFTANDRIGHTMOUSEBTNRELEASE = 646,
EIDSHIFTANDRIGHTMOUSEPRESS = 2000,
EIDSHIFTANDRIGHTMOUSEMOVE = 2001,
EIDSHIFTANDRIGHTMOUSERELEASE = 2002,
EIDSHIFTANDMIDDLEMOUSEPRESS = 2003,
EIDSHIFTANDMIDDLEMOUSEMOVE = 2004,
EIDSHIFTANDMIDDLEMOUSERELEASE = 2005,
EIDSPACENAVIGATORINPUT = 4001, // 3d Mouse, SpaceNavigator input
EIDSPACENAVIGATORKEYDOWN = 4002, // 3d Mouse, KeyDown
EIDWIIMOTEINPUT = 4003, // WiiMote input
EIDWIIMOTEBUTTON = 4004, // WiiMote home button
EIDWIIMOTEBUTTONB = 4005, // WiiMote b button
EIDSTRGANDN = 10,
EIDSTRGANDE = 11,
EIDDELETE = 12,
EIDN = 13,
EIDESCAPE = 14,
EIDP = 15,
EIDR = 16,
EIDT = 17,
EIDS = 18,
EIDE = 19,
EIDSTRGANDALTANDA = 20,
EIDSTRGANDALTANDB = 21,
EIDH = 22,
EIDRETURN = 23,
EIDENTER = 24,
EIDSPACE = 25,
EIDPLUS = 26,
EIDMINUS = 27,
EIDSTRGANDALTANDH = 30,
EIDSTRGANDALTANDI = 31,
EIDSTRGANDALTANDS = 40,
EIDALT = 90,
EIDSTRGANDB = 91,
EIDNEW = 1000,
EIDOLD = 1001,
EIDFINISHED = 1002,
EIDNO = 1003,
EIDYES = 1004,
EIDSAME = 1005,
EIDNOANDLASTOBJECT = 1006,
EIDNOANDNOTLASTOBJECT = 1007,
EIDLAST = 1008,
EIDNOTLAST = 1009,
EIDSTSMALERNMINUS1 = 1010,
EIDSTLARGERNMINUS1 = 1011,
EIDPOSITIONEVENT = 1012,
EIDEDIT = 1013,
EIDSMALLERN = 1014,
EIDEQUALSN = 1015,
EIDLARGERN = 1016,
EIDEMPTY = 1017,
EIDSUBDESELECT = 1020,
EIDSMTOSELECTED = 1030,
EIDSMTODESELECTED = 1031,
EIDTIP = 1050,
EIDHEAD = 1051,
EIDBODY = 1052,
EIDCLEAR = 1100,
EIDACTIVATETOOL = 1300,
EIDPRINT = 3001,
EV_INIT = 5551001,
EV_PREVIOUS = 5551002,
EV_PATH_COLLECTION_SELECTED = 5551003,
EV_NAVIGATION_SELECTED = 5551004,
EV_LESS_THEN_MIN_COUNT = 5551005,
EV_READY = 5551006,
EV_NEXT = 5551007,
EV_DONE = 5551008,
EV_NEW_LANDMARK = 5551009,
EV_REMOVE_LANDMARK = 5551010,
EIDINSIDE = 2500,
EIDFIGUREHOVER = 12340,
EIDNOFIGUREHOVER = 12341
};
//##Constants for Operations
//## xomments are always examples of the usage
enum EOperations
{
OpNOTHING = 0,
OpTEST = 1,
OpNEWCELL = 10, //add a new cell
OpADD = 100, //add a point or a vessel
OpUNDOADD = 101,
OpADDLINE = 1001, //add a line
OpINSERT = 200, //insert a point at position
OpINSERTLINE = 201, //insert a line at position
OpINSERTPOINT = 202,
OpCLOSECELL = 250, //close a cell (to a polygon)
OpOPENCELL = 251, //close a cell (to a polygon)
OpMOVE = 300, //move a point
OpMOVELINE = 301, //move a line
OpMOVECELL = 302, //move a line
OpUNDOMOVE = 303,
OpMOVEPOINTUP = 304,
OpMOVEPOINTDOWN = 305,
OpREMOVE = 400, //remove a point at position
OpREMOVELINE = 401, //remove a line at position
OpREMOVECELL = 402, //remove a cell
OpREMOVEPOINT = 403,
OpDELETE = 500, //delete
OpDELETELINE = 501, //delete the last line in a cell
OpUNDELETE = 502,
OpDELETECELL = 505,
OpSTATECHANGE = 600, //change a state
OpTIMECHANGE = 601, //change a state
OpTERMINATE = 666, //change a state
OpSELECTPOINT = 700,
OpSELECTLINE = 701,
OpSELECTCELL = 702,
OpSELECTSUBOBJECT = 703, //for VesselGraphInteractor
//OpSELECTNEWSUBOBJECT = 704, //for VesselGraphInteractor
OpSELECT = 705,
OpDESELECTPOINT = 800,
OpDESELECTLINE = 801,
OpDESELECTCELL = 802,
OpDESELECTSUBOBJECT = 803, //for VesselGraphInteractor
OpDESELECTALL = 804, //for VesselGraphInteractor
OpDESELECT = 805,
OpNAVIGATE = 900,
OpZOOM = 1000,
OpSCALE = 1100,
OpROTATE = 1200,
OpORIENT = 1201,
OpSETPOINTTYPE = 1210,
OpMODECHANGE = 1500,
OpSENDCOORDINATES = 1600,
OpPERIPHERYSEARCH = 2000, //used in VesselGraphInteractor
OpROOTSEARCH = 2001, //used in VesselGraphInteractor
OpTHICKSTVESSELSEARCH = 2002, //used in VesselGraphInteractor
OpSHORTESTPATHSEARCH = 2003, //used in VesselGraphInteractor
OpATTRIBUTATION = 2004, //used in VesselGraphInteractor
OpDEFAULT = 2006, //used in VesselGraphInteractor
OpSURFACECHANGED = 3000, // used for changing polydata in surfaces
};
//##Constants for EventMapping...
//##connects the statemachine.xml-File with the implemented conditions.
//##within one statemachine the choice of the actionconstants is freely
//##
//## ActionId
enum EActions
{
AcDONOTHING = 0,
AcINITNEWOBJECT = 5,
AcINITEDITOBJECT = 6,
AcINITEDITGROUP = 7,
AcINITMOVEMENT = 8,
AcINITMOVE = 9,
AcINITFOREGROUND = 45, // used in SeedsInteractor for setting the foreground seeds
AcINITBACKGROUND = 46, // used in SeedsInteractor for setting the background seeds
AcINITNEUTRAL = 47, // used in SeedsInteractor for setting the neutral seeds (rubber)
AcINITUPDATE = 1235, // For shape model deformation
AcADDPOINT = 10,
AcADD = 11,
AcADDLINE = 12,
AcADDANDFINISH = 13,
AcADDSELECTEDTOGROUP = 64,
AcCHECKPOINT = 21,
AcCHECKLINE = 22,
AcCHECKCELL = 23,
AcCHECKELEMENT = 30, // check if there is a element close enough (picking)
AcCHECKOBJECT = 31, // check if an object is hit
AcCHECKNMINUS1 = 32, // check if the number of elements is equal to N-1
AcCHECKEQUALS1 = 33, // check if the number of elements in the data is equal to 1
AcCHECKNUMBEROFPOINTS = 330, //check the number of elements in the data
AcCHECKSELECTED = 34, // check if the given element is selected or not
AcCHECKONESELECTED = 340, //check if there is an element that is selected
AcCHECKHOVERING = 341, //check if there is an element that is selected
AcCHECKGREATERZERO = 35, // check if the current number of elements is greater than 0
AcCHECKGREATERTWO = 36, // check if the current number of elements is greater than two
AcCHECKOPERATION = 37, // check if the operation is of one spectial type
AcCHECKONESUBINTERACTOR = 38,
AcCHECKSUBINTERACTORS = 39,
AcFINISHOBJECT = 40,
AcFINISHGROUP = 41,
AcFINISHMOVEMENT = 42,
AcFINISHMOVE = 43,
AcFINISH = 44,
AcSEARCHOBJECT = 50,
AcSEARCHGROUP = 51,
AcSEARCHANOTHEROBJECT = 52, // one object is selected and another object is to be added to selection
AcSELECTPICKEDOBJECT = 60, // select the picked object and deselect others
AcSELECTANOTHEROBJECT = 61,
AcSELECTGROUP = 62,
AcSELECTALL = 63,
AcSELECT = 65,
AcSELECTPOINT = 66,
AcSELECTLINE = 68,
AcSELECTCELL = 67,
AcSELECTSUBOBJECT = 69, // used in VesselGraphInteractor
AcDESELECTOBJECT = 70, // deselect picked from group
AcDESELECTALL = 72,
AcDESELECT = 75,
AcDESELECTPOINT = 76,
AcDESELECTLINE = 78,
AcDESELECTCELL = 77,
AcNEWPOINT = 80,
AcNEWSUBOBJECT = 81,
AcMOVEPOINT = 90,
AcMOVESELECTED = 91,
AcMOVE = 92,
AcMOVEPOINTUP = 93,
AcMOVEPOINTDOWN = 94,
AcREMOVEPOINT = 100,
AcREMOVE = 101,
AcREMOVELINE = 102,
AcREMOVEALL = 103,
AcREMOVESELECTEDSUBOBJECT = 104, // used in VesselGraphInteractor
AcWHEEL = 105,
AcPLUS = 106,
AcMINUS = 107,
AcDELETEPOINT = 120,
AcCLEAR = 130, // clear all elements from a list
AcINSERTPOINT = 110,
AcINSERTLINE = 111,
AC_SET_NEXT_BUTTON_VISIBLE = 5550001,
AC_SET_NEXT_BUTTON_INVISIBLE = 5550002,
AC_SET_PREVIOUS_BUTTON_VISIBLE = 5550003,
AC_SET_PREVIOUS_BUTTON_INVISIBLE = 5550004,
AC_SET_ASSISTAND_WIDGET_STECK = 5550005,
AC_SETMAX_COUNT_REF_POINTS = 5550006,
AC_SET_NEXT_BUTTON_TEXT = 5550007,
AC_CHECK_LANDMARK_COUNT = 5550008,
AC_SET_DONE_FALSE = 5550009,
AC_INIT = 55500010,
AC_SET_APPLICATION_SELECTED_FALSE = 55500011,
AC_SENSOR_ATTACHED = 55500012,
AC_CLOSE_ASSISTENT = 55500013,
AC_START_APPLICATION_TEXT = 55500014,
AC_START_NAVIGATION = 55500015,
AC_START_PATHCOLLECTION = 55500016,
AC_LOAD_LANDMARKS = 55500017,
AC_CALCULATE_LANDMARK_TRANSFORM = 55500018,
AcTERMINATE_INTERACTION = 666,
AcTRANSLATESTART = 1000,
AcTRANSLATE = 1001,
AcSCALESTART = 1002,
AcSCALE = 1003,
AcROTATESTART = 1004,
AcROTATE = 1005,
AcINITAFFINEINTERACTIONS = 1006,
AcFINISHAFFINEINTERACTIONS = 1007,
AcTRANSLATEEND = 1008,
AcSCALEEND = 1009,
AcROTATEEND = 1010,
AcINITZOOM = 1011,
AcZOOM = 1012,
AcSCROLL = 1013,
AcLEVELWINDOW = 1014,
+ AcSCROLLMOUSEWHEEL = 1015,
AcSETSTARTPOINT = 1050,
AcMODEDESELECT = 1100, // set interactor in not selected mode
AcMODESELECT = 1101, // set interactor in selected mode
AcMODESUBSELECT = 1102, // set interacor in sub selected mode
AcINFORMLISTENERS = 1200, // GlobalInteraction
AcASKINTERACTORS = 1201, // GlobalInteraction
AcCHECKGREATERONE = 1500,
AcCHECKBOUNDINGBOX = 1510,
AcFORCESUBINTERACTORS = 1550,
AcSENDCOORDINATES = 1600,
AcTRANSMITEVENT = 2000, // to transmit an event to a lower Interactor/Statemachine
AcPERIPHERYSEARCH = 3000, // used in VesselGraphInteractor
AcROOTSEARCH = 3001, // used in VesselGraphInteractor
AcTHICKSTVESSELSEARCH = 3002, // used in VesselGraphInteractor
AcSHORTESTPATHSEARCH = 3003, // used in VesselGraphInteractor
AcSINGLE = 3004, // used in VesselGraphInteractor
AcATTRIBUTATION = 3005, // used in VesselGraphInteractor
AcDEFAULT = 3007, // used in VesselGraphInteractor
AcSETVESSELELEMENT = 3008, // used in VesselGraphInteractor
AcCHECKBARRIERSTATUS = 3010, // used in VesselGraphInteractor
AcUPDATEMESH = 1234, // For Shape Model Interaction
AcINCREASE = 49012,
AcDECREASE = 49013,
AcMODIFY = 49014,
AcUNDOUPDATE = 1236, // For restoring a mesh after an update
AcENTEROBJECT = 48000,
AcLEAVEOBJECT = 48001,
AcSWITCHOBJECT = 48002,
AcUPDATELINE = 48003,
AcINITLINE = 48004,
AcTERMINATELINE = 48005,
AcCREATEBOX = 48006,
AcCREATEOBJECTFROMLINE = 48007,
AcCANCEL = 48008,
AcACTIVATETOOL = 48009,
AcROTATEAROUNDPOINT1 = 49002,
AcROTATEAROUNDPOINT2 = 49003,
AcMOVEPOINT1 = 49004,
AcMOVEPOINT2 = 49005,
AcUPDATEPOINT = 49006,
+ AcUPDATERADIUSMOUSEWHEEL = 49007,
AcDISPLAYOPTIONS = 49009,
AcCYCLE = 49010,
AcACCEPT = 49011,
AcONSPACENAVIGATORMOUSEINPUT = 4001, // On input of 3D Mouse
AcONPACENAVIGATORKEYDOWN = 4002, // On input of 3D Mouse
AcONWIIMOTEINPUT = 4003, // used for wiimote to signal IR input
AcRESETVIEW = 4004, // used for wiimote to reset view
AcONWIIMOTEBUTTONRELEASED = 4005, // stops the surface interaction
AcCHECKPOSITION = 5000,
AcINITIALIZECONTOUR = 5001,
AcCALCULATENEWSEGMENTATION_SP= 5002,
AcINTERACTOR = 5003,
AcCALCULATENEWSEGMENTATION_BB= 5004
};
/*
//!!!!!!!!!!!!!!!!!!!!!!!!
//!!!!!!!!!!!!!!!!!!!!!!!!
//EventMechanism:
//If you change anything from here on, then change in mitkEventMapper.cpp (Array of constants) as well.
//!!!!!!!!!!!!!!!!!!!!!!!!
//!!!!!!!!!!!!!!!!!!!!!!!!
*/
//Type of an Event;
enum EEventType
{
Type_None = 0, // invalid event
Type_Timer = 1, // timer event
Type_MouseButtonPress = 2, // mouse button pressed
Type_MouseButtonRelease = 3, // mouse button released
Type_MouseButtonDblClick = 4, // mouse button double click
Type_MouseMove = 5, // mouse move
Type_KeyPress = 6, // key pressed
Type_KeyRelease = 7, // key released
Type_FocusIn = 8, // keyboard focus received
Type_FocusOut = 9, // keyboard focus lost
Type_Enter = 10, // mouse enters widget
Type_Leave = 11, // mouse leaves widget
Type_Paint = 12, // paint widget
Type_Move = 13, // move widget
Type_Resize = 14, // resize widget
Type_Create = 15, // after object creation
Type_Destroy = 16, // during object destruction
Type_Show = 17, // widget is shown
Type_Hide = 18, // widget is hidden
Type_Close = 19, // request to close widget
Type_Quit = 20, // request to quit application
Type_Reparent = 21, // widget has been reparented
Type_ShowMinimized = 22, // widget is shown minimized
Type_ShowNormal = 23, // widget is shown normal
Type_WindowActivate = 24, // window was activated
Type_WindowDeactivate = 25, // window was deactivated
Type_ShowToParent = 26, // widget is shown to parent
Type_HideToParent = 27, // widget is hidden to parent
Type_ShowMaximized = 28, // widget is shown maximized
Type_ShowFullScreen = 29, // widget is shown full-screen
Type_Accel = 30, // accelerator event
Type_Wheel = 31, // wheel event
Type_AccelAvailable = 32, // accelerator available event
Type_CaptionChange = 33, // caption changed
Type_IconChange = 34, // icon changed
Type_ParentFontChange = 35, // parent font changed
Type_ApplicationFontChange = 36, // application font changed
Type_ParentPaletteChange = 37, // parent palette changed
Type_ApplicationPaletteChange = 38, // application palette changed
Type_PaletteChange = 39, // widget palette changed
Type_Clipboard = 40, // internal clipboard event
Type_Speech = 42, // reserved for speech input
Type_SockAct = 50, // socket activation
Type_AccelOverride = 51, // accelerator override event
Type_DeferredDelete = 52, // deferred delete event
Type_DragEnter = 60, // drag moves into widget
Type_DragMove = 61, // drag moves in widget
Type_DragLeave = 62, // drag leaves or is cancelled
Type_Drop = 63, // actual drop
Type_DragResponse = 64, // drag accepted/rejected
Type_ChildInserted = 70, // new child widget
Type_ChildRemoved = 71, // deleted child widget
Type_LayoutHint = 72, // child min/max size changed
Type_ShowWindowRequest = 73, // widget's window should be mapped
Type_ActivateControl = 80, // ActiveX activation
Type_DeactivateControl = 81, // ActiveX deactivation
Type_ContextMenu = 82, // context popup menu
Type_IMStart = 83, // input method composition start
Type_IMCompose = 84, // input method composition
Type_IMEnd = 85, // input method composition end
Type_Accessibility = 86, // accessibility information is requested
Type_TabletMove = 87, // Wacom tablet event
Type_LocaleChange = 88, // the system locale changed
Type_LanguageChange = 89, // the application language changed
Type_LayoutDirectionChange = 90, // the layout direction changed
Type_Style = 91, // internal style event
Type_TabletPress = 92, // tablet press
Type_TabletRelease = 93, // tablet release
Type_User = 1000, // first user event id
Type_SpaceNavigatorInput = 1094, // 3D mouse input occured
Type_SpaceNavigatorKeyDown = 1095, // 3D mouse input occured
Type_WiiMoteInput = 1096, // WiiMote input occured
Type_WiiMoteButton= 1097, // WiiMote button pressed
Type_MaxUser = 65535
};
//##ButtonState
// mouse/keyboard state values
//QT combinations if MOUSEBUTTONRelease: left MouseButton + ControlButton: 0x201
enum EButtonStates
{
BS_NoButton = 0x0000,
BS_LeftButton = 0x0001,
BS_RightButton = 0x0002,
BS_MidButton = 0x0004,
BS_MouseButtonMask = 0x0007,
BS_ShiftButton = 0x0100,
BS_ControlButton = 0x0200,
BS_AltButton = 0x0400,
BS_MetaButton = 0x0800,
BS_KeyButtonMask = 0x0f00,
BS_Keypad = 0x4000
};
//##Key
enum EKeys
{
Key_Escape = 0x1000, // misc keys
Key_Tab = 0x1001,
Key_Backtab = 0x1002,
Key_BackTab = 0x1002, //= Key_Backtab
Key_Backspace = 0x1003,
Key_BackSpace = 0x1003, //= Key_Backspace
Key_Return = 0x1004,
Key_Enter = 0x1005,
Key_Insert = 0x1006,
Key_Delete = 0x1007,
Key_Pause = 0x1008,
Key_Print = 0x1009,
Key_SysReq = 0x100a,
Key_Home = 0x1010, // cursor movement
Key_End = 0x1011,
Key_Left = 0x1012,
Key_Up = 0x1013,
Key_Right = 0x1014,
Key_Down = 0x1015,
Key_Prior = 0x1016,
Key_PageUp = 0x1016, //=Key_Prior
Key_Next = 0x1017,
Key_PageDown = 0x1017, //=Key_Next
Key_Shift = 0x1020, // modifiers
Key_Control = 0x1021,
Key_Meta = 0x1022,
Key_Alt = 0x1023,
Key_CapsLock = 0x1024,
Key_NumLock = 0x1025,
Key_ScrollLock = 0x1026,
Key_F1 = 0x1030, // function keys
Key_F2 = 0x1031,
Key_F3 = 0x1032,
Key_F4 = 0x1033,
Key_F5 = 0x1034,
Key_F6 = 0x1035,
Key_F7 = 0x1036,
Key_F8 = 0x1037,
Key_F9 = 0x1038,
Key_F10 = 0x1039,
Key_F11 = 0x103a,
Key_F12 = 0x103b,
Key_F13 = 0x103c,
Key_F14 = 0x103d,
Key_F15 = 0x103e,
Key_F16 = 0x103f,
Key_F17 = 0x1040,
Key_F18 = 0x1041,
Key_F19 = 0x1042,
Key_F20 = 0x1043,
Key_F21 = 0x1044,
Key_F22 = 0x1045,
Key_F23 = 0x1046,
Key_F24 = 0x1047,
Key_F25 = 0x1048, // F25 .. F35 only on X11
Key_F26 = 0x1049,
Key_F27 = 0x104a,
Key_F28 = 0x104b,
Key_F29 = 0x104c,
Key_F30 = 0x104d,
Key_F31 = 0x104e,
Key_F32 = 0x104f,
Key_F33 = 0x1050,
Key_F34 = 0x1051,
Key_F35 = 0x1052,
Key_Super_L = 0x1053, // extra keys
Key_Super_R = 0x1054,
Key_Menu = 0x1055,
Key_Hyper_L = 0x1056,
Key_Hyper_R = 0x1057,
Key_Help = 0x1058,
// International input method support (X keycode - = 0xEE00)
// Only interesting if you are writing your own input method
Key_Muhenkan = 0x1122, // Cancel Conversion
Key_Henkan = 0x1123, // Start/Stop Conversion
Key_Hiragana_Katakana = 0x1127, // Hiragana/Katakana toggle
Key_Zenkaku_Hankaku = 0x112A, // Zenkaku/Hankaku toggle
Key_Space = 0x20, // 7 bit printable ASCII
Key_Any = 0x20, //= Key_Space
Key_Exclam = 0x21,
Key_QuoteDbl = 0x22,
Key_NumberSign = 0x23,
Key_Dollar = 0x24,
Key_Percent = 0x25,
Key_Ampersand = 0x26,
Key_Apostrophe = 0x27,
Key_ParenLeft = 0x28,
Key_ParenRight = 0x29,
Key_Asterisk = 0x2a,
Key_Plus = 0x2b,
Key_Comma = 0x2c,
Key_Minus = 0x2d,
Key_Period = 0x2e,
Key_Slash = 0x2f,
Key_0 = 0x30,
Key_1 = 0x31,
Key_2 = 0x32,
Key_3 = 0x33,
Key_4 = 0x34,
Key_5 = 0x35,
Key_6 = 0x36,
Key_7 = 0x37,
Key_8 = 0x38,
Key_9 = 0x39,
Key_Colon = 0x3a,
Key_Semicolon = 0x3b,
Key_Less = 0x3c,
Key_Equal = 0x3d,
Key_Greater = 0x3e,
Key_Question = 0x3f,
Key_At = 0x40,
Key_A = 0x41,
Key_B = 0x42,
Key_C = 0x43,
Key_D = 0x44,
Key_E = 0x45,
Key_F = 0x46,
Key_G = 0x47,
Key_H = 0x48,
Key_I = 0x49,
Key_J = 0x4a,
Key_K = 0x4b,
Key_L = 0x4c,
Key_M = 0x4d,
Key_N = 0x4e,
Key_O = 0x4f,
Key_P = 0x50,
Key_Q = 0x51,
Key_R = 0x52,
Key_S = 0x53,
Key_T = 0x54,
Key_U = 0x55,
Key_V = 0x56,
Key_W = 0x57,
Key_X = 0x58,
Key_Y = 0x59,
Key_Z = 0x5a,
Key_BracketLeft = 0x5b,
Key_Backslash = 0x5c,
Key_BracketRight = 0x5d,
Key_AsciiCircum = 0x5e,
Key_Underscore = 0x5f,
Key_QuoteLeft = 0x60,
Key_BraceLeft = 0x7b,
Key_Bar = 0x7c,
Key_BraceRight = 0x7d,
Key_AsciiTilde = 0x7e,
Key_nobreakspace = 0x0a0,
Key_exclamdown = 0x0a1,
Key_cent = 0x0a2,
Key_sterling = 0x0a3,
Key_currency = 0x0a4,
Key_yen = 0x0a5,
Key_brokenbar = 0x0a6,
Key_section = 0x0a7,
Key_diaeresis = 0x0a8,
Key_copyright = 0x0a9,
Key_ordfeminine = 0x0aa,
Key_guillemotleft = 0x0ab, // left angle quotation mark
Key_notsign = 0x0ac,
Key_hyphen = 0x0ad,
Key_registered = 0x0ae,
Key_macron = 0x0af,
Key_degree = 0x0b0,
Key_plusminus = 0x0b1,
Key_twosuperior = 0x0b2,
Key_threesuperior = 0x0b3,
Key_acute = 0x0b4,
Key_mu = 0x0b5,
Key_paragraph = 0x0b6,
Key_periodcentered = 0x0b7,
Key_cedilla = 0x0b8,
Key_onesuperior = 0x0b9,
Key_masculine = 0x0ba,
Key_guillemotright = 0x0bb, // right angle quotation mark
Key_onequarter = 0x0bc,
Key_onehalf = 0x0bd,
Key_threequarters = 0x0be,
Key_questiondown = 0x0bf,
Key_Agrave = 0x0c0,
Key_Aacute = 0x0c1,
Key_Acircumflex = 0x0c2,
Key_Atilde = 0x0c3,
Key_Adiaeresis = 0x0c4,
Key_Aring = 0x0c5,
Key_AE = 0x0c6,
Key_Ccedilla = 0x0c7,
Key_Egrave = 0x0c8,
Key_Eacute = 0x0c9,
Key_Ecircumflex = 0x0ca,
Key_Ediaeresis = 0x0cb,
Key_Igrave = 0x0cc,
Key_Iacute = 0x0cd,
Key_Icircumflex = 0x0ce,
Key_Idiaeresis = 0x0cf,
Key_ETH = 0x0d0,
Key_Ntilde = 0x0d1,
Key_Ograve = 0x0d2,
Key_Oacute = 0x0d3,
Key_Ocircumflex = 0x0d4,
Key_Otilde = 0x0d5,
Key_Odiaeresis = 0x0d6,
Key_multiply = 0x0d7,
Key_Ooblique = 0x0d8,
Key_Ugrave = 0x0d9,
Key_Uacute = 0x0da,
Key_Ucircumflex = 0x0db,
Key_Udiaeresis = 0x0dc,
Key_Yacute = 0x0dd,
Key_THORN = 0x0de,
Key_ssharp = 0x0df,
Key_agrave = 0x0e0,
Key_aacute = 0x0e1,
Key_acircumflex = 0x0e2,
Key_atilde = 0x0e3,
Key_adiaeresis = 0x0e4,
Key_aring = 0x0e5,
Key_ae = 0x0e6,
Key_ccedilla = 0x0e7,
Key_egrave = 0x0e8,
Key_eacute = 0x0e9,
Key_ecircumflex = 0x0ea,
Key_ediaeresis = 0x0eb,
Key_igrave = 0x0ec,
Key_iacute = 0x0ed,
Key_icircumflex = 0x0ee,
Key_idiaeresis = 0x0ef,
Key_eth = 0x0f0,
Key_ntilde = 0x0f1,
Key_ograve = 0x0f2,
Key_oacute = 0x0f3,
Key_ocircumflex = 0x0f4,
Key_otilde = 0x0f5,
Key_odiaeresis = 0x0f6,
Key_division = 0x0f7,
Key_oslash = 0x0f8,
Key_ugrave = 0x0f9,
Key_uacute = 0x0fa,
Key_ucircumflex = 0x0fb,
Key_udiaeresis = 0x0fc,
Key_yacute = 0x0fd,
Key_thorn = 0x0fe,
Key_ydiaeresis = 0x0ff,
Key_unknown = 0xffff,
Key_none = 0xffff//= Key_unknown
};
}//namespace mitk
#endif //ifndef MITKINTERACTCONST_H
diff --git a/Core/Code/Rendering/mitkBaseRenderer.cpp b/Core/Code/Rendering/mitkBaseRenderer.cpp
index f2f5816a07..ac3d54ad04 100644
--- a/Core/Code/Rendering/mitkBaseRenderer.cpp
+++ b/Core/Code/Rendering/mitkBaseRenderer.cpp
@@ -1,828 +1,829 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#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
#include "mitkEventMapper.h"
#include "mitkGlobalInteraction.h"
#include "mitkPositionEvent.h"
#include "mitkDisplayPositionEvent.h"
#include "mitkProperties.h"
#include "mitkWeakPointerProperty.h"
#include "mitkInteractionConst.h"
// VTK
#include <vtkLinearTransform.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkCamera.h>
#include <vtkProperty.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
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
m_RenderingManager->GetGlobalInteraction()->AddFocusElement(this);
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_RenderWindow!=NULL)
{
m_RenderWindow->Delete();
m_RenderWindow = NULL;
}
}
void mitk::BaseRenderer::RemoveAllLocalStorages()
{
this->InvokeEvent(mitk::BaseRenderer::RendererResetEvent());
std::list<mitk::BaseLocalStorageHandler*>::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);
}
void mitk::BaseRenderer::UnregisterLocalStorageHandler( mitk::BaseLocalStorageHandler *lsh )
{
m_RegisteredLocalStorageHandlers.remove(lsh);
}
void mitk::BaseRenderer::SetDataStorage(DataStorage* storage)
{
if ( storage != NULL )
{
m_DataStorage = storage;
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<SlicedGeometry3D*>(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<SlicedGeometry3D*>(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<TimeSlicedGeometry*>(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<SlicedGeometry3D*>(m_TimeSlicedWorldGeometry->GetGeometry3D(m_TimeStep));
}
else
{
slicedWorldGeometry=dynamic_cast<SlicedGeometry3D*>(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<Geometry2D*>(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<const SliceNavigationController::GeometrySendEvent *>(&geometrySendEvent);
assert(sendEvent!=NULL);
SetWorldGeometry(sendEvent ->GetTimeSlicedGeometry());
}
void mitk::BaseRenderer::UpdateGeometry(const itk::EventObject & geometryUpdateEvent)
{
const SliceNavigationController::GeometryUpdateEvent* updateEvent =
dynamic_cast<const SliceNavigationController::GeometryUpdateEvent*>(&geometryUpdateEvent);
if (updateEvent==NULL) return;
if (m_CurrentWorldGeometry.IsNotNull())
{
SlicedGeometry3D* slicedWorldGeometry=dynamic_cast<SlicedGeometry3D*>(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<const SliceNavigationController::GeometrySliceEvent *>(&geometrySliceEvent);
assert(sliceEvent!=NULL);
SetSlice(sliceEvent->GetPos());
}
void mitk::BaseRenderer::SetGeometryTime(const itk::EventObject & geometryTimeEvent)
{
const SliceNavigationController::GeometryTimeEvent * timeEvent =
dynamic_cast<const SliceNavigationController::GeometryTimeEvent *>(&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."<<std::endl;
}
void mitk::BaseRenderer::RequestUpdate()
{
m_RenderingManager->RequestUpdate(this->m_RenderWindow);
}
void mitk::BaseRenderer::ForceImmediateUpdate()
{
m_RenderingManager->ForceImmediateUpdate(this->m_RenderWindow);
}
unsigned int mitk::BaseRenderer::GetNumberOfVisibleLODEnabledMappers() const
{
return m_NumberOfVisibleLODEnabledMappers;
}
mitk::RenderingManager* mitk::BaseRenderer::GetRenderingManager() const
{
return m_RenderingManager.GetPointer();
}
/*!
Sets the new Navigation controller
*/
void mitk::BaseRenderer::SetSliceNavigationController(mitk::SliceNavigationController *SlicenavigationController)
{
if (SlicenavigationController == 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<mitk::VtkInteractorCameraController*>(cameraController);
if (vtkInteractorCameraController.IsNotNull())
MITK_INFO<<"!!!WARNING!!!: RenderWindow interaction events are no longer handled via CameraController (See Bug #954)."<<std::endl;
m_CameraController->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/mitkImageVtkMapper2D.cpp b/Core/Code/Rendering/mitkImageVtkMapper2D.cpp
index a2e2bcada2..ce40d1702b 100644
--- a/Core/Code/Rendering/mitkImageVtkMapper2D.cpp
+++ b/Core/Code/Rendering/mitkImageVtkMapper2D.cpp
@@ -1,1081 +1,1082 @@
/*=========================================================================
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
//MITK
#include <mitkAbstractTransformGeometry.h>
#include <mitkDataNode.h>
#include <mitkDataNodeFactory.h>
#include <mitkImageSliceSelector.h>
#include <mitkLevelWindowProperty.h>
#include <mitkLookupTableProperty.h>
#include <mitkPlaneGeometry.h>
#include <mitkProperties.h>
#include <mitkResliceMethodProperty.h>
#include <mitkTimeSlicedGeometry.h>
#include <mitkVtkResliceInterpolationProperty.h>
#include <mitkPixelType.h>
//MITK Rendering
#include "mitkImageVtkMapper2D.h"
#include "vtkMitkThickSlicesFilter.h"
#include "vtkMitkApplyLevelWindowToRGBFilter.h"
//VTK
#include <vtkProperty.h>
#include <vtkTransform.h>
#include <vtkMatrix4x4.h>
#include <vtkLookupTable.h>
#include <vtkImageData.h>
#include <vtkPoints.h>
#include <vtkGeneralTransform.h>
#include <vtkImageReslice.h>
#include <vtkImageChangeInformation.h>
#include <vtkPlaneSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkTexture.h>
#include <vtkCellArray.h>
#include <vtkCamera.h>
//ITK
#include <itkRGBAPixel.h>
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);
//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.
float depth = this->CalculateLayerDepth(renderer);
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 (transversal, 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() );
}
vtkProp* mitk::ImageVtkMapper2D::GetVtkProp(mitk::BaseRenderer* renderer)
{
// this->Update(renderer);
//return the actor corresponding to the renderer
return m_LSH.GetLocalStorage(renderer)->m_Actor;
}
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() );
if ( input == NULL )
{
return;
}
//check if there is a valid worldGeometry
const Geometry2D *worldGeometry = renderer->GetCurrentWorldGeometry2D();
if( ( worldGeometry == NULL ) || ( !worldGeometry->IsValid() ) || ( !worldGeometry->HasReferenceGeometry() ))
{
return;
}
// check if there is something to display
if ( !input->IsVolumeSet( this->GetTimestep() ) ) return;
input->Update();
vtkImageData* inputData = input->GetVtkImageData( this->GetTimestep() );
if ( inputData == NULL )
{
return;
}
// how big the area is in physical coordinates: widthInMM x heightInMM pixels
mitk::ScalarType widthInMM, heightInMM;
// where we want to sample
Point3D origin;
Vector3D right, bottom, normal;
// take transform of input image into account
const TimeSlicedGeometry *inputTimeGeometry = input->GetTimeSlicedGeometry();
const Geometry3D* inputGeometry = inputTimeGeometry->GetGeometry3D( this->GetTimestep() );
//World spacing
ScalarType mmPerPixel[2];
// Bounds information for reslicing (only reuqired if reference geometry
// is present)
vtkFloatingPointType sliceBounds[6];
bool boundsInitialized = false;
for ( int i = 0; i < 6; ++i )
{
sliceBounds[i] = 0.0;
}
//Extent (in pixels) of the image
Vector2D extent;
// Do we have a simple PlaneGeometry?
// This is the "regular" case (e.g. slicing through an image axis-parallel or even oblique)
const PlaneGeometry *planeGeometry = dynamic_cast< const PlaneGeometry * >( worldGeometry );
if ( planeGeometry != NULL )
{
origin = planeGeometry->GetOrigin();
right = planeGeometry->GetAxisVector( 0 ); // right = Extent of Image in mm (worldspace)
bottom = planeGeometry->GetAxisVector( 1 );
normal = planeGeometry->GetNormal();
bool inPlaneResampleExtentByGeometry = false;
GetDataNode()->GetBoolProperty("in plane resample extent by geometry", inPlaneResampleExtentByGeometry, renderer);
if ( inPlaneResampleExtentByGeometry )
{
// Resampling grid corresponds to the current world geometry. This
// means that the spacing of the output 2D image depends on the
// currently selected world geometry, and *not* on the image itself.
extent[0] = worldGeometry->GetExtent( 0 );
extent[1] = worldGeometry->GetExtent( 1 );
}
else
{
// Resampling grid corresponds to the input geometry. This means that
// the spacing of the output 2D image is directly derived from the
// associated input image, regardless of the currently selected world
// geometry.
Vector3D rightInIndex, bottomInIndex;
inputGeometry->WorldToIndex( right, rightInIndex );
inputGeometry->WorldToIndex( bottom, bottomInIndex );
extent[0] = rightInIndex.GetNorm();
extent[1] = bottomInIndex.GetNorm();
}
// Get the extent of the current world geometry and calculate resampling
// spacing therefrom.
widthInMM = worldGeometry->GetExtentInMM( 0 );
heightInMM = worldGeometry->GetExtentInMM( 1 );
mmPerPixel[0] = widthInMM / extent[0];
mmPerPixel[1] = heightInMM / extent[1];
right.Normalize();
bottom.Normalize();
normal.Normalize();
//transform the origin to corner based coordinates, because VTK is corner based.
origin += right * ( mmPerPixel[0] * 0.5 );
origin += bottom * ( mmPerPixel[1] * 0.5 );
// Use inverse transform of the input geometry for reslicing the 3D image
localStorage->m_Reslicer->SetResliceTransform(
inputGeometry->GetVtkTransform()->GetLinearInverse() );
// Set background level to TRANSLUCENT (see Geometry2DDataVtkMapper3D)
localStorage->m_Reslicer->SetBackgroundLevel( -32768 );
// 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.
boundsInitialized = this->CalculateClippedPlaneBounds(
worldGeometry->GetReferenceGeometry(), planeGeometry, sliceBounds );
}
else
{
// Do we have an AbstractTransformGeometry?
// This is the case for AbstractTransformGeometry's (e.g. a thin-plate-spline transform)
const mitk::AbstractTransformGeometry* abstractGeometry =
dynamic_cast< const AbstractTransformGeometry * >(worldGeometry);
if(abstractGeometry != NULL)
{
extent[0] = abstractGeometry->GetParametricExtent(0);
extent[1] = abstractGeometry->GetParametricExtent(1);
widthInMM = abstractGeometry->GetParametricExtentInMM(0);
heightInMM = abstractGeometry->GetParametricExtentInMM(1);
mmPerPixel[0] = widthInMM / extent[0];
mmPerPixel[1] = heightInMM / extent[1];
origin = abstractGeometry->GetPlane()->GetOrigin();
right = abstractGeometry->GetPlane()->GetAxisVector(0);
right.Normalize();
bottom = abstractGeometry->GetPlane()->GetAxisVector(1);
bottom.Normalize();
normal = abstractGeometry->GetPlane()->GetNormal();
normal.Normalize();
// Use a combination of the InputGeometry *and* the possible non-rigid
// AbstractTransformGeometry for reslicing the 3D Image
vtkGeneralTransform *composedResliceTransform = vtkGeneralTransform::New();
composedResliceTransform->Identity();
composedResliceTransform->Concatenate(
inputGeometry->GetVtkTransform()->GetLinearInverse() );
composedResliceTransform->Concatenate(
abstractGeometry->GetVtkAbstractTransform()
);
localStorage->m_Reslicer->SetResliceTransform( composedResliceTransform );
composedResliceTransform->UnRegister( NULL ); // decrease RC
// Set background level to BLACK instead of translucent, to avoid
// boundary artifacts (see Geometry2DDataVtkMapper3D)
localStorage->m_Reslicer->SetBackgroundLevel( -1023 );
}
else
{
//no geometry => we can't reslice
return;
}
}
// Make sure that the image to display has a certain minimum size.
if ( (extent[0] <= 2) && (extent[1] <= 2) )
{
return;
}
//### begin set reslice interpolation
// 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;
this->GetDataNode()->GetProperty(
resliceInterpolationProperty, "reslice interpolation" );
int interpolationMode = VTK_RESLICE_NEAREST;
if ( resliceInterpolationProperty != NULL )
{
interpolationMode = resliceInterpolationProperty->GetInterpolation();
}
switch ( interpolationMode )
{
case VTK_RESLICE_NEAREST:
localStorage->m_Reslicer->SetInterpolationModeToNearestNeighbor();
break;
case VTK_RESLICE_LINEAR:
localStorage->m_Reslicer->SetInterpolationModeToLinear();
break;
case VTK_RESLICE_CUBIC:
localStorage->m_Reslicer->SetInterpolationModeToCubic();
break;
}
}
else
{
localStorage->m_Reslicer->SetInterpolationModeToNearestNeighbor();
}
//### end set reslice interpolation
//Thickslicing
int thickSlicesMode = 0;
int thickSlicesNum = 1;
// Thick slices parameters
if( inputData->GetNumberOfScalarComponents() == 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";
}
}
localStorage->m_UnitSpacingImageFilter->SetInput( inputData );
localStorage->m_Reslicer->SetInput( localStorage->m_UnitSpacingImageFilter->GetOutput() );
//number of pixels per mm in x- and y-direction of the resampled
Vector2D pixelsPerMM;
pixelsPerMM[0] = 1.0 / mmPerPixel[0];
pixelsPerMM[1] = 1.0 / mmPerPixel[1];
//calulate the originArray and the orientations for the reslice-filter
double originArray[3];
itk2vtk( origin, originArray );
localStorage->m_Reslicer->SetResliceAxesOrigin( originArray );
double cosines[9];
// direction of the X-axis of the sampled result
vnl2vtk( right.Get_vnl_vector(), cosines );
// direction of the Y-axis of the sampled result
vnl2vtk( bottom.Get_vnl_vector(), cosines + 3 );//fill next 3 elements
// normal of the plane
vnl2vtk( normal.Get_vnl_vector(), cosines + 6 );//fill the last 3 elements
localStorage->m_Reslicer->SetResliceAxesDirectionCosines( cosines );
int xMin, xMax, yMin, yMax;
if ( boundsInitialized )
{
// Calculate output extent (integer values)
xMin = static_cast< int >( sliceBounds[0] / mmPerPixel[0] + 0.5 );
xMax = static_cast< int >( sliceBounds[1] / mmPerPixel[0] + 0.5 );
yMin = static_cast< int >( sliceBounds[2] / mmPerPixel[1] + 0.5 );
yMax = static_cast< int >( sliceBounds[3] / mmPerPixel[1] + 0.5 );
}
else
{
// If no reference geometry is available, we also don't know about the
// maximum plane size;
xMin = yMin = 0;
xMax = static_cast< int >( extent[0]
- pixelsPerMM[0] + 0.5);
yMax = static_cast< int >( extent[1]
- pixelsPerMM[1] + 0.5);
}
// Disallow huge dimensions
if ( (xMax-xMin) * (yMax-yMin) > 4096*4096 )
{
return;
}
// Calculate dataset spacing in plane z direction (NOT spacing of current
// world geometry)
double dataZSpacing = 1.0;
Vector3D normInIndex;
inputGeometry->WorldToIndex( normal, normInIndex );
if(thickSlicesMode > 0)
{
dataZSpacing = 1.0 / normInIndex.GetNorm();
localStorage->m_Reslicer->SetOutputDimensionality( 3 );
localStorage->m_Reslicer->SetOutputExtent( xMin, xMax-1, yMin, yMax-1, -thickSlicesNum, 0+thickSlicesNum );
}
else
{
localStorage->m_Reslicer->SetOutputDimensionality( 2 );
localStorage->m_Reslicer->SetOutputExtent( xMin, xMax-1, yMin, yMax-1, 0, 0 );
}
localStorage->m_Reslicer->SetOutputOrigin( 0.0, 0.0, 0.0 );
localStorage->m_Reslicer->SetOutputSpacing( mmPerPixel[0], mmPerPixel[1], dataZSpacing );
// xMax and yMax are meant exclusive until now, whereas
// SetOutputExtent wants an inclusive bound. Thus, we need
// to subtract 1.
vtkImageData* reslicedImage = 0;
// 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.
if(thickSlicesMode>0)
{
localStorage->m_TSFilter->SetThickSliceMode( thickSlicesMode-1 );
localStorage->m_TSFilter->SetInput( localStorage->m_Reslicer->GetOutput() );
localStorage->m_TSFilter->Modified();
localStorage->m_TSFilter->Update();
reslicedImage = localStorage->m_TSFilter->GetOutput();
}
else
{
localStorage->m_Reslicer->Modified();
localStorage->m_Reslicer->Update();
reslicedImage = localStorage->m_Reslicer->GetOutput();
}
if((reslicedImage == NULL) || (reslicedImage->GetDataDimension() < 1))
{
MITK_WARN << "reslicer returned empty image";
return;
}
//set the current slice for the localStorage
// localStorage->m_ReslicedImage = reslicedImage;
localStorage->m_ReslicedImage->DeepCopy( reslicedImage );
//set the current slice as texture for the plane
localStorage->m_Texture->SetInput(localStorage->m_ReslicedImage);
//setup the textured plane
this->GeneratePlane( renderer, sliceBounds );
//apply the properties after the slice was set
this->ApplyProperties( renderer, mmPerPixel );
//get the transformation matrix of the reslicer in order to render the slice as transversal, coronal or saggital
vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
vtkSmartPointer<vtkMatrix4x4> matrix = localStorage->m_Reslicer->GetResliceAxes();
//transform the origin to center based coordinates, because MITK is center based.
Point3D originCenterBased = origin;
originCenterBased -= right * ( mmPerPixel[0] * 0.5 );
originCenterBased -= bottom * ( mmPerPixel[1] * 0.5 );
matrix->SetElement(0, 3, originCenterBased[0]);
matrix->SetElement(1, 3, originCenterBased[1]);
matrix->SetElement(2, 3, originCenterBased[2]);
trans->SetMatrix(matrix);
//transform the plane/contour (the actual actor) to the corresponding view (transversal, coronal or saggital)
localStorage->m_Actor->SetUserTransform(trans);
// We have been modified => save this for next Update()
localStorage->m_LastUpdateTime.Modified();
}
bool mitk::ImageVtkMapper2D::LineIntersectZero( vtkPoints *points, int p1, int p2,
vtkFloatingPointType *bounds )
{
vtkFloatingPointType point1[3];
vtkFloatingPointType point2[3];
points->GetPoint( p1, point1 );
points->GetPoint( p2, point2 );
if ( (point1[2] * point2[2] <= 0.0) && (point1[2] != point2[2]) )
{
double x, y;
x = ( point1[0] * point2[2] - point1[2] * point2[0] ) / ( point2[2] - point1[2] );
y = ( point1[1] * point2[2] - point1[2] * point2[1] ) / ( point2[2] - point1[2] );
if ( x < bounds[0] ) { bounds[0] = x; }
if ( x > bounds[1] ) { bounds[1] = x; }
if ( y < bounds[2] ) { bounds[2] = y; }
if ( y > bounds[3] ) { bounds[3] = y; }
bounds[4] = bounds[5] = 0.0;
return true;
}
return false;
}
bool mitk::ImageVtkMapper2D::CalculateClippedPlaneBounds( const Geometry3D *boundingGeometry,
const PlaneGeometry *planeGeometry, vtkFloatingPointType *bounds )
{
// Clip the plane with the bounding geometry. To do so, the corner points
// of the bounding box are transformed by the inverse transformation
// matrix, and the transformed bounding box edges derived therefrom are
// clipped with the plane z=0. The resulting min/max values are taken as
// bounds for the image reslicer.
const mitk::BoundingBox *boundingBox = boundingGeometry->GetBoundingBox();
mitk::BoundingBox::PointType bbMin = boundingBox->GetMinimum();
mitk::BoundingBox::PointType bbMax = boundingBox->GetMaximum();
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
if(boundingGeometry->GetImageGeometry())
{
points->InsertPoint( 0, bbMin[0]-0.5, bbMin[1]-0.5, bbMin[2]-0.5 );
points->InsertPoint( 1, bbMin[0]-0.5, bbMin[1]-0.5, bbMax[2]-0.5 );
points->InsertPoint( 2, bbMin[0]-0.5, bbMax[1]-0.5, bbMax[2]-0.5 );
points->InsertPoint( 3, bbMin[0]-0.5, bbMax[1]-0.5, bbMin[2]-0.5 );
points->InsertPoint( 4, bbMax[0]-0.5, bbMin[1]-0.5, bbMin[2]-0.5 );
points->InsertPoint( 5, bbMax[0]-0.5, bbMin[1]-0.5, bbMax[2]-0.5 );
points->InsertPoint( 6, bbMax[0]-0.5, bbMax[1]-0.5, bbMax[2]-0.5 );
points->InsertPoint( 7, bbMax[0]-0.5, bbMax[1]-0.5, bbMin[2]-0.5 );
}
else
{
points->InsertPoint( 0, bbMin[0], bbMin[1], bbMin[2] );
points->InsertPoint( 1, bbMin[0], bbMin[1], bbMax[2] );
points->InsertPoint( 2, bbMin[0], bbMax[1], bbMax[2] );
points->InsertPoint( 3, bbMin[0], bbMax[1], bbMin[2] );
points->InsertPoint( 4, bbMax[0], bbMin[1], bbMin[2] );
points->InsertPoint( 5, bbMax[0], bbMin[1], bbMax[2] );
points->InsertPoint( 6, bbMax[0], bbMax[1], bbMax[2] );
points->InsertPoint( 7, bbMax[0], bbMax[1], bbMin[2] );
}
vtkSmartPointer<vtkPoints> newPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
transform->Identity();
transform->Concatenate( planeGeometry->GetVtkTransform()->GetLinearInverse() );
transform->Concatenate( boundingGeometry->GetVtkTransform() );
transform->TransformPoints( points, newPoints );
bounds[0] = bounds[2] = 10000000.0;
bounds[1] = bounds[3] = -10000000.0;
bounds[4] = bounds[5] = 0.0;
this->LineIntersectZero( newPoints, 0, 1, bounds );
this->LineIntersectZero( newPoints, 1, 2, bounds );
this->LineIntersectZero( newPoints, 2, 3, bounds );
this->LineIntersectZero( newPoints, 3, 0, bounds );
this->LineIntersectZero( newPoints, 0, 4, bounds );
this->LineIntersectZero( newPoints, 1, 5, bounds );
this->LineIntersectZero( newPoints, 2, 6, bounds );
this->LineIntersectZero( newPoints, 3, 7, bounds );
this->LineIntersectZero( newPoints, 4, 5, bounds );
this->LineIntersectZero( newPoints, 5, 6, bounds );
this->LineIntersectZero( newPoints, 6, 7, bounds );
this->LineIntersectZero( newPoints, 7, 4, bounds );
if ( (bounds[0] > 9999999.0) || (bounds[2] > 9999999.0)
|| (bounds[1] < -9999999.0) || (bounds[3] < -9999999.0) )
{
return false;
}
else
{
// The resulting bounds must be adjusted by the plane spacing, since we
// we have so far dealt with index coordinates
const float *planeSpacing = planeGeometry->GetFloatSpacing();
bounds[0] *= planeSpacing[0];
bounds[1] *= planeSpacing[0];
bounds[2] *= planeSpacing[1];
bounds[3] *= planeSpacing[1];
bounds[4] *= planeSpacing[2];
bounds[5] *= planeSpacing[2];
return true;
}
}
void mitk::ImageVtkMapper2D::ApplyProperties(mitk::BaseRenderer* renderer, mitk::ScalarType mmPerPixel[2])
{
//get the current localStorage for the corresponding renderer
LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
// check for interpolation properties
bool textureInterpolation = false;
GetDataNode()->GetBoolProperty( "texture interpolation", textureInterpolation, renderer );
//set the interpolation modus according to the property
localStorage->m_Texture->SetInterpolate(textureInterpolation);
//do not repeat the texture (the image)
localStorage->m_Texture->RepeatOff();
float rgb[3]= { 1.0f, 1.0f, 1.0f };
float opacity = 1.0f;
// check for opacity prop and use it for rendering if it exists
GetOpacity( opacity, renderer );
//set the opacity according to the properties
localStorage->m_Actor->GetProperty()->SetOpacity(opacity);
// 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<mitk::ColorProperty*>(GetDataNode()->GetProperty
("binaryimage.hoveringcolor", renderer));
if(colorprop.IsNotNull())
{
memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float));
}
else
{
GetColor( rgb, renderer );
}
}
if(selected)
{
mitk::ColorProperty::Pointer colorprop = dynamic_cast<mitk::ColorProperty*>(GetDataNode()->GetProperty
("binaryimage.selectedcolor", renderer));
if(colorprop.IsNotNull()) {
memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float));
}
else
{
GetColor( rgb, renderer );
}
}
if(!hover && !selected)
{
GetColor( rgb, renderer );
}
//get the binary property
bool binary = false;
this->GetDataNode()->GetBoolProperty( "binary", binary, renderer );
+ localStorage->m_Texture->SetMapColorScalarsThroughLookupTable(binary);
//use color means that we want to use the color from the property list and not a lookuptable
bool useColor = true;
this->GetDataNode()->GetBoolProperty( "use color", useColor, renderer );
//the finalLookuptable will be used for the rendering and can either be a user-defined table or the default lut
vtkSmartPointer<vtkLookupTable> finalLookuptable = localStorage->m_LookupTable;
//BEGIN PROPERTY user-defined lut
//currently we do not allow a lookuptable if it is a binary image
bool useDefaultLut = true;
if((!useColor) && (!binary))
{
// If lookup table use is requested...
mitk::LookupTableProperty::Pointer LookupTableProp;
LookupTableProp = dynamic_cast<mitk::LookupTableProperty*>
(this->GetDataNode()->GetProperty("LookupTable"));
//...check if there is a lookuptable provided by the user
if ( LookupTableProp.IsNull() )
{
MITK_WARN << "The use of a lookuptable is requested, but there is no lookuptable supplied by the user! The default lookuptable will be used instead.";
}
else
{
// If lookup table use is requested and supplied by the user:
// only update the lut, when the properties have changed...
if( LookupTableProp->GetLookupTable()->GetMTime()
<= this->GetDataNode()->GetPropertyList()->GetMTime() )
{
LookupTableProp->GetLookupTable()->ChangeOpacityForAll( opacity );
LookupTableProp->GetLookupTable()->ChangeOpacity(0, 0.0);
}
//we use the user-defined lookuptable
finalLookuptable = LookupTableProp->GetLookupTable()->GetVtkLookupTable();
//we obtained a user-defined lut and dont have to use the default table
useDefaultLut = false;
}
}//END PROPERTY user-defined lut
//use the finalLookuptable for mapping the colors
localStorage->m_Texture->SetLookupTable( finalLookuptable );
//check if we need the default table
if( useDefaultLut )
{
double rgbConv[3] = {(double)rgb[0], (double)rgb[1], (double)rgb[2]}; //conversion to double for VTK
localStorage->m_Actor->GetProperty()->SetColor(rgbConv);
}
else
{
//If the user defines a lut, we dont want to use the color and take white instead.
localStorage->m_Actor->GetProperty()->SetColor(1.0, 1.0, 1.0);
}
bool binaryOutline = false;
this->GetDataNode()->GetBoolProperty( "outline binary", binaryOutline, renderer );
if ( binary )
{
finalLookuptable->SetRange(0.0, 1.0);
//0 is already mapped to transparent.
//1 is now mapped to the current color and alpha
if ( this->GetInput()->GetPixelType().GetBpe() <= 8 )
{
if (binaryOutline)
{
//generate ontours/outlines TODO: not always necessary
localStorage->m_OutlinePolyData = CreateOutlinePolyData(renderer ,localStorage->m_ReslicedImage, mmPerPixel);
float binaryOutlineWidth(1.0);
if (this->GetDataNode()->GetFloatProperty( "outline width", binaryOutlineWidth, renderer ))
{
localStorage->m_Actor->GetProperty()->SetLineWidth(binaryOutlineWidth);
}
}
}
else
{
MITK_WARN << "Type of all binary images should be (un)signed char. Outline does not work on other pixel types!";
}
} //END binary image handling
else
{
LevelWindow levelWindow;
this->GetLevelWindow( levelWindow, renderer );
//set up the lookuptable with the level window range
finalLookuptable->SetRange( levelWindow.GetLowerWindowBound(), levelWindow.GetUpperWindowBound() );
mitk::PixelType pixelType = this->GetInput()->GetPixelType();
if( pixelType.GetBitsPerComponent() == pixelType.GetBpe() ) //gray images with just one component
{
localStorage->m_Texture->MapColorScalarsThroughLookupTableOn();
}
else //RGB, RBGA or other images tpyes with more components
{
// obtain and apply opacity level window if possible
localStorage->m_Texture->MapColorScalarsThroughLookupTableOff();
localStorage->m_LevelWindowToRGBFilterObject->SetLookupTable(localStorage->m_Texture->GetLookupTable());
mitk::LevelWindow opacLevelWindow;
if( this->GetLevelWindow( opacLevelWindow, renderer, "opaclevelwindow" ) )
{
localStorage->m_LevelWindowToRGBFilterObject->SetMinOpacity(opacLevelWindow.GetLowerWindowBound());
localStorage->m_LevelWindowToRGBFilterObject->SetMaxOpacity(opacLevelWindow.GetUpperWindowBound());
}
else
{
localStorage->m_LevelWindowToRGBFilterObject->SetMinOpacity(0.0);
localStorage->m_LevelWindowToRGBFilterObject->SetMaxOpacity(255.0);
}
localStorage->m_LevelWindowToRGBFilterObject->SetInput(localStorage->m_ReslicedImage);
localStorage->m_Texture->SetInputConnection(localStorage->m_LevelWindowToRGBFilterObject->GetOutputPort());
}
}
if(binaryOutline && binary)
{
//We need the contour for the binary oultine property as actor
localStorage->m_Mapper->SetInput(localStorage->m_OutlinePolyData);
localStorage->m_Actor->SetTexture(NULL); //no texture for contours
}
else
{
//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);
}
}
void mitk::ImageVtkMapper2D::Update(mitk::BaseRenderer* renderer)
{
if ( !this->IsVisible( renderer ) )
{
return;
}
mitk::Image* data = const_cast<mitk::Image *>( 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<mitk::Image*>(node->GetData());
// Properties common for both images and segmentations
node->AddProperty( "use color", mitk::BoolProperty::New( true ), renderer, overwrite );
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 );
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 ) );
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->GetScalarValueMin();
maxValue = centralSliceImage->GetScalarValueMax();
min2ndValue = centralSliceImage->GetScalarValue2ndMin();
max2ndValue = centralSliceImage->GetScalarValue2ndMax();
}
if ( minValue == maxValue )
{
// centralSlice is strange, lets look at all data
minValue = image->GetScalarValueMin();
maxValue = image->GetScalarValueMaxNoRecompute();
min2ndValue = image->GetScalarValue2ndMinNoRecompute();
max2ndValue = image->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( "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))
{
mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New();
mitk::LevelWindow levelwindow;
levelwindow.SetAuto( image, true, true );
levWinProp->SetLevelWindow( levelwindow );
node->SetProperty( "levelwindow", levWinProp, renderer );
}
if(((overwrite) || (node->GetProperty("opaclevelwindow", renderer)==NULL))
&& (image->GetPixelType().GetItkTypeId() && *(image->GetPixelType().GetItkTypeId()) == typeid(itk::RGBAPixel<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 );
}
if((overwrite) || (node->GetProperty("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( "LookupTable", mitkLutProp );
}
}
Superclass::SetDefaultProperties(node, renderer, overwrite);
}
vtkSmartPointer<vtkPolyData> mitk::ImageVtkMapper2D::CreateOutlinePolyData(mitk::BaseRenderer* renderer, vtkSmartPointer<vtkImageData> binarySlice, mitk::ScalarType mmPerPixel[2]){
int* dims = binarySlice->GetDimensions(); //dimensions of the image
int line = dims[0]; //how many pixels per line?
int x = 0; //pixel index x
int y = 0; //pixel index y
char* currentPixel;
int nn = dims[0]*dims[1]; //max pixel(n,n)
//get the depth for each contour
float depth = CalculateLayerDepth(renderer);
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New(); //the points to draw
vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New(); //the lines to connect the points
for (int ii = 0; ii<nn; ii++) { //current pixel(i,i)
currentPixel = static_cast<char*>(binarySlice->GetScalarPointer(x, y, 0));
//if the current pixel value is set to something
if ((currentPixel) && (*currentPixel != 0)) {
//check in which direction a line is necessary
if (ii >= line && *(currentPixel-line) == 0) { //x direction - bottom edge of the pixel
//add the 2 points
vtkIdType p1 = points->InsertNextPoint(x*mmPerPixel[0], y*mmPerPixel[1], depth);
vtkIdType p2 = points->InsertNextPoint((x+1)*mmPerPixel[0], y*mmPerPixel[1], depth);
//add the line between both points
lines->InsertNextCell(2);
lines->InsertCellPoint(p1);
lines->InsertCellPoint(p2);
}
if (ii <= nn-line && *(currentPixel+line) == 0) { //x direction - top edge of the pixel
vtkIdType p1 = points->InsertNextPoint(x*mmPerPixel[0], (y+1)*mmPerPixel[1], depth);
vtkIdType p2 = points->InsertNextPoint((x+1)*mmPerPixel[0], (y+1)*mmPerPixel[1], depth);
lines->InsertNextCell(2);
lines->InsertCellPoint(p1);
lines->InsertCellPoint(p2);
}
if (ii > 1 && *(currentPixel-1) == 0) { //y direction - left edge of the pixel
vtkIdType p1 = points->InsertNextPoint(x*mmPerPixel[0], y*mmPerPixel[1], depth);
vtkIdType p2 = points->InsertNextPoint(x*mmPerPixel[0], (y+1)*mmPerPixel[1], depth);
lines->InsertNextCell(2);
lines->InsertCellPoint(p1);
lines->InsertCellPoint(p2);
}
if (ii < nn-1 && *(currentPixel+1) == 0) { //y direction - right edge of the pixel
vtkIdType p1 = points->InsertNextPoint((x+1)*mmPerPixel[0], y*mmPerPixel[1], depth);
vtkIdType p2 = points->InsertNextPoint((x+1)*mmPerPixel[0], (y+1)*mmPerPixel[1], depth);
lines->InsertNextCell(2);
lines->InsertCellPoint(p1);
lines->InsertCellPoint(p2);
}
}
//reached end of line
x++;
if (x >= line) {
x = 0;
y++;
}
}
// Create a polydata to store everything in
vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
// Add the points to the dataset
polyData->SetPoints(points);
// Add the lines to the dataset
polyData->SetLines(lines);
return polyData;
}
mitk::ImageVtkMapper2D::LocalStorage::LocalStorage()
{
//Do as much actions as possible in here to avoid double executions.
m_Plane = vtkSmartPointer<vtkPlaneSource>::New();
m_Texture = vtkSmartPointer<vtkTexture>::New();
m_LookupTable = vtkSmartPointer<vtkLookupTable>::New();
m_Mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
m_Actor = vtkSmartPointer<vtkActor>::New();
m_Reslicer = vtkSmartPointer<vtkImageReslice>::New();
m_TSFilter = vtkSmartPointer<vtkMitkThickSlicesFilter>::New();
m_UnitSpacingImageFilter = vtkSmartPointer<vtkImageChangeInformation>::New();
m_OutlinePolyData = vtkSmartPointer<vtkPolyData>::New();
m_ReslicedImage = vtkSmartPointer<vtkImageData>::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();
m_Reslicer->ReleaseDataFlagOn();
m_UnitSpacingImageFilter->SetOutputSpacing( 1.0, 1.0, 1.0 );
//built a default lookuptable
m_LookupTable->SetRampToLinear();
m_LookupTable->SetSaturationRange( 0.0, 0.0 );
m_LookupTable->SetHueRange( 0.0, 0.0 );
m_LookupTable->SetValueRange( 0.0, 1.0 );
m_LookupTable->Build();
//map all black values to transparent
m_LookupTable->SetTableValue(0, 0.0, 0.0, 0.0, 0.0);
//set the mapper for the actor
m_Actor->SetMapper(m_Mapper);
//filter for RGB(A) images
m_LevelWindowToRGBFilterObject = new vtkMitkApplyLevelWindowToRGBFilter();
}
diff --git a/Core/Code/Rendering/mitkRenderWindowBase.cpp b/Core/Code/Rendering/mitkRenderWindowBase.cpp
index cc000d23c6..99c2ce1dc4 100644
--- a/Core/Code/Rendering/mitkRenderWindowBase.cpp
+++ b/Core/Code/Rendering/mitkRenderWindowBase.cpp
@@ -1,205 +1,209 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date: 2010-07-05 09:49:37 +0200 (Mo, 05 Jul 2010) $
Version: $Revision: 24298 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "mitkRenderWindowBase.h"
#include "mitkDisplayPositionEvent.h"
#include "mitkVtkLayerController.h"
#include "mitkRenderingManager.h"
#include "vtkRenderer.h"
mitk::RenderWindowBase::RenderWindowBase( )
: m_ProcessWheelEvents(true),
m_InvertScrollingDirection(false)
{
}
/*
* "Member functions, including virtual functions (10.3), can be called during construction or destruction (12.6.2). When a
* virtual function is called directly or indirectly from a constructor (including from the mem-initializer for a data member) or from
* a destructor, and the object to which the call applies is the object under construction or destruction, the function called is
* the one defined in the constructor or destructor’s own class or in one of its bases, but not a function overriding it in a class
* derived from the constructor or destructor’s class, or overriding it in one of the other base classes of the most derived object[..]"
* or short: within constructors and destructors classes are not polymorph.
*/
void mitk::RenderWindowBase::Initialize( mitk::RenderingManager* renderingManager, const char* name )
{
if ( renderingManager == NULL )
{
renderingManager = mitk::RenderingManager::GetInstance();
}
if(m_Renderer.IsNull())
{
m_Renderer = mitk::VtkPropRenderer::New( name , GetVtkRenderWindow(), renderingManager );
}
m_Renderer->InitRenderer(this->GetVtkRenderWindow());
mitk::BaseRenderer::AddInstance(GetVtkRenderWindow(),m_Renderer);
renderingManager->AddRenderWindow(GetVtkRenderWindow());
m_RenderProp = vtkMitkRenderProp::New();
m_RenderProp->SetPropRenderer(m_Renderer);
m_Renderer->GetVtkRenderer()->AddViewProp(m_RenderProp);
if((this->GetVtkRenderWindow()->GetSize()[0] > 10)
&& (this->GetVtkRenderWindow()->GetSize()[1] > 10))
m_Renderer->InitSize(this->GetVtkRenderWindow()->GetSize()[0], this->GetVtkRenderWindow()->GetSize()[1]);
m_InResize = false;
}
void mitk::RenderWindowBase::Destroy()
{
m_Renderer->GetRenderingManager()->RemoveRenderWindow(GetVtkRenderWindow());
mitk::BaseRenderer::RemoveInstance(GetVtkRenderWindow());
m_Renderer->GetVtkRenderer()->RemoveViewProp(m_RenderProp);
m_RenderProp->Delete();
}
mitk::RenderWindowBase::~RenderWindowBase()
{
}
void mitk::RenderWindowBase::mousePressMitkEvent(mitk::MouseEvent *me)
{
if (m_Renderer.IsNotNull())
m_Renderer->MousePressEvent(me);
}
void mitk::RenderWindowBase::mouseReleaseMitkEvent(mitk::MouseEvent *me)
{
if(m_Renderer.IsNotNull())
m_Renderer->MouseReleaseEvent(me);
}
void mitk::RenderWindowBase::mouseMoveMitkEvent(mitk::MouseEvent *me)
{
if (m_Renderer.IsNotNull())
m_Renderer->MouseMoveEvent(me);
}
void mitk::RenderWindowBase::wheelMitkEvent(mitk::WheelEvent *we)
{
if ( !m_ProcessWheelEvents )
+ {
+ if(m_Renderer.IsNotNull())
+ m_Renderer->WheelEvent(we);
return;
+ }
if ( !GetSliceNavigationController()->GetSliceLocked() )
{
mitk::Stepper* stepper = GetSliceNavigationController()->GetSlice();
if (stepper->GetSteps() <= 1)
{
stepper = GetSliceNavigationController()->GetTime();
}
// get the desired delta
int delta = we->GetDelta();
if ( m_InvertScrollingDirection )
delta *= -1; // If we want to invert the scrolling direction -> delta * -1
if ( delta < 0 )
{
stepper->Next();
}
else
{
stepper->Previous();
}
//also send to Renderer to send if to MITK interaction mechanism
if(m_Renderer.IsNotNull())
m_Renderer->WheelEvent(we);
}
}
void mitk::RenderWindowBase::keyPressMitkEvent(mitk::KeyEvent* mke)
{
if (m_Renderer.IsNotNull())
m_Renderer->KeyPressEvent(mke);
}
void mitk::RenderWindowBase::resizeMitkEvent(int width, int height)
{
if(m_InResize) //@FIXME CRITICAL probably related to VtkSizeBug
return;
m_InResize = true;
if(m_Renderer.IsNotNull())
{
m_Renderer->Resize(width, height);
}
m_InResize = false;
}
mitk::SliceNavigationController * mitk::RenderWindowBase::GetSliceNavigationController()
{
return mitk::BaseRenderer::GetInstance(this->GetVtkRenderWindow())->GetSliceNavigationController();
}
mitk::CameraRotationController * mitk::RenderWindowBase::GetCameraRotationController()
{
return mitk::BaseRenderer::GetInstance(this->GetVtkRenderWindow())->GetCameraRotationController();
}
mitk::BaseController * mitk::RenderWindowBase::GetController()
{
mitk::BaseRenderer * renderer = mitk::BaseRenderer::GetInstance(GetVtkRenderWindow());
switch ( renderer->GetMapperID() )
{
case mitk::BaseRenderer::Standard2D:
return GetSliceNavigationController();
case mitk::BaseRenderer::Standard3D:
return GetCameraRotationController();
default:
return GetSliceNavigationController();
}
}
mitk::VtkPropRenderer* mitk::RenderWindowBase::GetRenderer()
{
return m_Renderer;
}
void mitk::RenderWindowBase::SetProcessWheelEvents( bool state )
{
m_ProcessWheelEvents = state;
}
bool mitk::RenderWindowBase::GetProcessWheelEvents()
{
return m_ProcessWheelEvents;
}
void mitk::RenderWindowBase::SetInvertScrollingDirection( bool invert )
{
m_InvertScrollingDirection = invert;
-}
\ No newline at end of file
+}
diff --git a/Core/Code/Service/mitkModule.cpp b/Core/Code/Service/mitkModule.cpp
index b209b240a1..a0087a3407 100644
--- a/Core/Code/Service/mitkModule.cpp
+++ b/Core/Code/Service/mitkModule.cpp
@@ -1,225 +1,235 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "mitkModule.h"
#include "mitkModuleContext.h"
#include "mitkModuleActivator.h"
#include "mitkModulePrivate.h"
#include "mitkCoreModuleContext_p.h"
#include <mitkLogMacros.h>
namespace mitk {
const std::string& Module::PROP_ID()
{
static const std::string s("module.id");
return s;
}
const std::string& Module::PROP_NAME()
{
static const std::string s("module.name");
return s;
}
const std::string& Module::PROP_LOCATION()
{
static const std::string s("module.location");
return s;
}
const std::string& Module::PROP_MODULE_DEPENDS()
{
static const std::string s("module.module_depends");
return s;
}
const std::string& Module::PROP_LIB_DEPENDS()
{
static const std::string s("module.lib_depends");
return s;
}
const std::string& Module::PROP_PACKAGE_DEPENDS()
{
static const std::string s("module.package_depends");
return s;
}
const std::string& Module::PROP_VERSION()
{
static const std::string s("module.version");
return s;
}
const std::string& Module::PROP_QT()
{
static const std::string s("module.qt");
return s;
}
Module::Module()
: d(0)
{
}
Module::~Module()
{
delete d;
}
void Module::Init(CoreModuleContext* coreCtx,
ModuleInfo* info)
{
ModulePrivate* mp = new ModulePrivate(this, coreCtx, info);
std::swap(mp, d);
delete mp;
}
+void Module::Uninit()
+{
+ if (d->moduleContext)
+ {
+ delete d->moduleContext;
+ d->moduleContext = 0;
+ }
+ d->moduleActivator = 0;
+}
+
bool Module::IsLoaded() const
{
return d->moduleContext != 0;
}
void Module::Start()
{
if (d->moduleContext)
{
MITK_WARN << "Module " << d->info.name << " already started.";
return;
}
d->moduleContext = new ModuleContext(this->d);
// try
// {
d->coreCtx->listeners.ModuleChanged(ModuleEvent(ModuleEvent::LOADING, this));
// try to get a ModuleActivator instance
if (d->info.activatorHook)
{
try
{
d->moduleActivator = d->info.activatorHook();
}
catch (...)
{
MITK_ERROR << "Creating the module activator of " << d->info.name << " failed";
throw;
}
d->moduleActivator->Load(d->moduleContext);
}
d->coreCtx->listeners.ModuleChanged(ModuleEvent(ModuleEvent::LOADED, this));
// }
// catch (...)
// {
// d->coreCtx->listeners.ModuleChanged(ModuleEvent(ModuleEvent::UNLOADING, this));
// d->RemoveModuleResources();
// delete d->moduleContext;
// d->moduleContext = 0;
// d->coreCtx->listeners.ModuleChanged(ModuleEvent(ModuleEvent::UNLOADED, this));
// MITK_ERROR << "Calling the module activator Load() method of " << d->info.name << " failed!";
// throw;
// }
}
void Module::Stop()
{
if (d->moduleContext == 0)
{
MITK_WARN << "Module " << d->info.name << " already stopped.";
return;
}
try
{
d->coreCtx->listeners.ModuleChanged(ModuleEvent(ModuleEvent::UNLOADING, this));
if (d->moduleActivator)
{
d->moduleActivator->Unload(d->moduleContext);
}
}
catch (...)
{
MITK_ERROR << "Calling the module activator Unload() method of " << d->info.name << " failed!";
try
{
d->RemoveModuleResources();
}
catch (...) {}
delete d->moduleContext;
d->moduleContext = 0;
d->coreCtx->listeners.ModuleChanged(ModuleEvent(ModuleEvent::UNLOADED, this));
throw;
}
d->RemoveModuleResources();
delete d->moduleContext;
d->moduleContext = 0;
d->coreCtx->listeners.ModuleChanged(ModuleEvent(ModuleEvent::UNLOADED, this));
}
ModuleContext* Module::GetModuleContext() const
{
return d->moduleContext;
}
long Module::GetModuleId() const
{
return d->info.id;
}
std::string Module::GetLocation() const
{
return d->info.location;
}
std::string Module::GetName() const
{
return d->info.name;
}
ModuleVersion Module::GetVersion() const
{
return d->version;
}
std::string Module::GetProperty(const std::string& key) const
{
if (d->properties.count(key) == 0) return "";
return d->properties[key];
}
} // end namespace mitk
std::ostream& operator<<(std::ostream& os, const mitk::Module& module)
{
os << "Module[" << "id=" << module.GetModuleId() <<
", loc=" << module.GetLocation() <<
", name=" << module.GetName() << "]";
return os;
}
std::ostream& operator<<(std::ostream& os, mitk::Module const * module)
{
return operator<<(os, *module);
}
diff --git a/Core/Code/Service/mitkModule.h b/Core/Code/Service/mitkModule.h
index a793299260..dbbe618451 100644
--- a/Core/Code/Service/mitkModule.h
+++ b/Core/Code/Service/mitkModule.h
@@ -1,241 +1,242 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef MITKMODULE_H
#define MITKMODULE_H
#include "mitkModuleVersion.h"
namespace mitk {
class CoreModuleContext;
class ModuleInfo;
class ModuleContext;
class ModulePrivate;
/**
* \ingroup MicroServices
*
* Represents a MITK module.
*
* <p>
* A <code>%Module</code> object is the access point to a MITK module.
* Each MITK module has an associated <code>%Module</code> object.
*
* <p>
* A module has unique identity, a <code>long</code>, chosen by the
* framework. This identity does not change during the lifecycle of a module.
*
* <p>
* A module can be in one of two states:
* <ul>
* <li>LOADED
* <li>UNLOADED
* </ul>
* <p>
* You can determine the current state by using IsLoaded().
*
* <p>
* A module can only execute code when its state is <code>LOADED</code>.
* An <code>UNLOADED</code> module is a
* zombie and can only be reached because it was loaded before. However,
* unloaded modules can be loaded again.
*
* <p>
* The framework is the only entity that is allowed to create
* <code>%Module</code> objects.
*
* @remarks This class is thread safe.
*/
class MITK_CORE_EXPORT Module
{
public:
static const std::string& PROP_ID();
static const std::string& PROP_NAME();
static const std::string& PROP_LOCATION();
static const std::string& PROP_MODULE_DEPENDS();
static const std::string& PROP_PACKAGE_DEPENDS();
static const std::string& PROP_LIB_DEPENDS();
static const std::string& PROP_VERSION();
static const std::string& PROP_QT();
~Module();
/**
* Returns this module's current state.
*
* <p>
* A module can be in only one state at any time.
*
* @return <code>true</code> if the module is <code>LOADED</code>
* <code>false</code> if it is <code>UNLOADED</code>
*/
bool IsLoaded() const;
/**
* Returns this module's {@link ModuleContext}. The returned
* <code>ModuleContext</code> can be used by the caller to act on behalf
* of this module.
*
* <p>
* If this module is not in the <code>LOADED</code> state, then this
* module has no valid <code>ModuleContext</code>. This method will
* return <code>0</code> if this module has no valid
* <code>ModuleContext</code>.
*
* @return A <code>ModuleContext</code> for this module or
* <code>0</code> if this module has no valid
* <code>ModuleContext</code>.
*/
ModuleContext* GetModuleContext() const;
/**
* Returns this module's unique identifier. This module is assigned a unique
* identifier by the framework when it was loaded.
*
* <p>
* A module's unique identifier has the following attributes:
* <ul>
* <li>Is unique and persistent.
* <li>Is a <code>long</code>.
* <li>Its value is not reused for another module, even after a module is
* unloaded.
* <li>Does not change while a module remains loaded.
* <li>Does not change when a module is reloaded.
* </ul>
*
* <p>
* This method continues to return this module's unique identifier while
* this module is in the <code>UNLOADED</code> state.
*
* @return The unique identifier of this module.
*/
long GetModuleId() const;
/**
* Returns this module's location.
*
* <p>
* The location is the full path to the module's shared library.
* This method continues to return this module's location
* while this module is in the <code>UNLOADED</code> state.
*
* @return The string representation of this module's location.
*/
std::string GetLocation() const;
/**
* Returns the name of this module as specified by the
* MITK_CREATE_MODULE CMake macro. The module
* name together with a version must identify a unique module.
*
* <p>
* This method continues to return this module's name while
* this module is in the <code>UNLOADED</code> state.
*
* @return The name of this module.
*/
std::string GetName() const;
/**
* Returns the version of this module as specified by the
* MITK_CREATE_MODULE CMake macro. If this module does not have a
* specified version then {@link ModuleVersion#EmptyVersion} is returned.
*
* <p>
* This method continues to return this module's version while
* this module is in the <code>UNLOADED</code> state.
*
* @return The version of this module.
*/
ModuleVersion GetVersion() const;
/**
* Returns the value of the specified property for this module. The
* method returns an empty string if the property is not found.
*
* @param key The name of the requested property.
* @return The value of the requested property, or an empty string
* if the property is undefined.
*/
std::string GetProperty(const std::string& key) const;
private:
friend class ModuleRegistry;
friend class ServiceReferencePrivate;
ModulePrivate* d;
Module();
Module(const Module&);
void Init(CoreModuleContext* coreCtx, ModuleInfo* info);
+ void Uninit();
void Start();
void Stop();
};
}
#ifdef MITK_HAS_UNORDERED_MAP_H
namespace std {
#elif defined(__GNUC__)
namespace __gnu_cxx {
#else
namespace itk {
#endif
template<typename _Key> class hash;
template<> class hash<mitk::Module*>
{
public:
std::size_t operator()(const mitk::Module* module) const
{
#ifdef MITK_HAS_HASH_SIZE_T
return hash<std::size_t>()(reinterpret_cast<std::size_t>(module));
#else
std::size_t key = reinterpret_cast<std::size_t>(module);
return std::size_t(key & (~0U));
#endif
}
};
/**
* \ingroup MicroServices
*/
namespace ModuleConstants {
}
}
/**
* \ingroup MicroServices
*/
MITK_CORE_EXPORT std::ostream& operator<<(std::ostream& os, const mitk::Module& module);
/**
* \ingroup MicroServices
*/
MITK_CORE_EXPORT std::ostream& operator<<(std::ostream& os, mitk::Module const * module);
#endif // MITKMODULE_H
diff --git a/Core/Code/Service/mitkModulePrivate.cpp b/Core/Code/Service/mitkModulePrivate.cpp
index edc5ccbd7b..672b9c660e 100644
--- a/Core/Code/Service/mitkModulePrivate.cpp
+++ b/Core/Code/Service/mitkModulePrivate.cpp
@@ -1,143 +1,144 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "mitkModulePrivate.h"
#include "mitkModule.h"
#include "mitkCoreModuleContext_p.h"
#include "mitkServiceRegistration.h"
#include "mitkServiceReferencePrivate.h"
namespace mitk {
AtomicInt ModulePrivate::idCounter;
ModulePrivate::ModulePrivate(Module* qq, CoreModuleContext* coreCtx,
ModuleInfo* info)
: coreCtx(coreCtx), info(*info), moduleContext(0), moduleActivator(0), q(qq)
{
std::stringstream propId;
propId << this->info.id;
properties[Module::PROP_ID()] = propId.str();
std::stringstream propModuleDepends;
std::stringstream propLibDepends;
std::stringstream propPackageDepends;
int counter = 0;
int counter2 = 0;
std::stringstream ss(this->info.moduleDeps);
while (ss)
{
std::string moduleDep;
ss >> moduleDep;
if (!moduleDep.empty())
{
Module* dep = ModuleRegistry::GetModule(moduleDep);
if (dep)
{
requiresIds.push_back(dep->GetModuleId());
if (counter > 0) propModuleDepends << ", ";
propModuleDepends << moduleDep;
++counter;
}
else
{
requiresLibs.push_back(moduleDep);
if (counter2 > 0) propLibDepends << ", ";
propLibDepends << moduleDep;
++counter2;
}
}
}
properties[Module::PROP_MODULE_DEPENDS()] = propModuleDepends.str();
properties[Module::PROP_LIB_DEPENDS()] = propLibDepends.str();
counter = 0;
ss.clear();
ss.str(this->info.packageDeps);
while (ss)
{
std::string packageDep;
ss >> packageDep;
if (!packageDep.empty())
{
requiresPackages.push_back(packageDep);
if (counter > 0) propPackageDepends << ", ";
propPackageDepends << packageDep;
++counter;
}
}
properties[Module::PROP_PACKAGE_DEPENDS()] = propPackageDepends.str();
if (!this->info.version.empty())
{
try
{
version = mitk::ModuleVersion(this->info.version);
properties[Module::PROP_VERSION()] = this->info.version;
}
catch (const std::exception& e)
{
throw std::invalid_argument(std::string("MITK module does not specify a valid version identifier. Got exception: ") + e.what());
}
}
properties[Module::PROP_LOCATION()] = this->info.location;
properties[Module::PROP_NAME()] = this->info.name;
properties[Module::PROP_QT()] = this->info.qtModule ? "true" : "false";
}
ModulePrivate::~ModulePrivate()
{
+ delete moduleContext;
}
void ModulePrivate::RemoveModuleResources()
{
coreCtx->listeners.RemoveAllListeners(moduleContext);
std::list<ServiceRegistration> srs;
coreCtx->services.GetRegisteredByModule(this, srs);
for (std::list<ServiceRegistration>::iterator i = srs.begin();
i != srs.end(); ++i)
{
try
{
i->Unregister();
}
catch (const std::logic_error& /*ignore*/)
{
// Someone has unregistered the service after stop completed.
// This should not occur, but we don't want get stuck in
// an illegal state so we catch it.
}
}
srs.clear();
coreCtx->services.GetUsedByModule(q, srs);
for (std::list<ServiceRegistration>::const_iterator i = srs.begin();
i != srs.end(); ++i)
{
i->GetReference().d->UngetService(q, false);
}
}
}
diff --git a/Core/Code/Service/mitkModuleRegistry.cpp b/Core/Code/Service/mitkModuleRegistry.cpp
index 6d00646ed2..9e09d842cb 100644
--- a/Core/Code/Service/mitkModuleRegistry.cpp
+++ b/Core/Code/Service/mitkModuleRegistry.cpp
@@ -1,179 +1,195 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "mitkModuleRegistry.h"
#include "mitkModule.h"
#include "mitkModuleInfo.h"
#include "mitkModuleContext.h"
#include "mitkCoreModuleContext_p.h"
#include "mitkStaticInit.h"
#include <itkSimpleFastMutexLock.h>
#include <itkMutexLockHolder.h>
namespace mitk {
#ifdef MITK_HAS_UNORDERED_MAP_H
typedef std::unordered_map<long, Module*> ModuleMap;
#else
typedef itk::hash_map<long, Module*> ModuleMap;
#endif
MITK_GLOBAL_STATIC(CoreModuleContext, coreModuleContext)
+template<typename T>
+struct ModuleDeleter
+{
+ void operator()(GlobalStatic<T>& globalStatic) const
+ {
+ ModuleMap* moduleMap = globalStatic.pointer;
+ for (ModuleMap::const_iterator i = moduleMap->begin();
+ i != moduleMap->end(); ++i)
+ {
+ delete i->second;
+ }
+ DefaultGlobalStaticDeleter<T> defaultDeleter;
+ defaultDeleter(globalStatic);
+ }
+};
+
/**
* Table of all installed modules in this framework.
- * Key is the module location.
+ * Key is the module id.
*/
-MITK_GLOBAL_STATIC(ModuleMap, modules)
+MITK_GLOBAL_STATIC_WITH_DELETER(ModuleMap, modules, ModuleDeleter)
typedef itk::SimpleFastMutexLock MutexType;
typedef itk::MutexLockHolder<MutexType> MutexLocker;
/**
* Lock for protecting the modules object
*/
MITK_GLOBAL_STATIC(MutexType, modulesLock)
/**
* Lock for protecting the register count
*/
MITK_GLOBAL_STATIC(MutexType, countLock)
void ModuleRegistry::Register(ModuleInfo* info)
{
static long regCount = 0;
if (info->id > 0)
{
// The module was already registered
MutexLocker lock(*modulesLock());
Module* module = modules()->operator[](info->id);
module->Start();
}
else
{
Module* module = 0;
// check if the module is reloaded
{
MutexLocker lock(*modulesLock());
ModuleMap* map = modules();
for (ModuleMap::const_iterator i = map->begin();
i != map->end(); ++i)
{
if (i->second->GetLocation() == info->location)
{
module = i->second;
info->id = module->GetModuleId();
}
}
}
if (!module)
{
module = new Module();
countLock()->Lock();
info->id = ++regCount;
countLock()->Unlock();
module->Init(coreModuleContext(), info);
MutexLocker lock(*modulesLock());
ModuleMap* map = modules();
map->insert(std::make_pair(info->id, module));
}
else
{
module->Init(coreModuleContext(), info);
}
module->Start();
}
}
void ModuleRegistry::UnRegister(const ModuleInfo* info)
{
// If we are unregistering the mitkCore module, there is
// nothing to do.
if (info->id == 1) return;
MutexLocker lock(*modulesLock());
Module* curr = modules()->operator[](info->id);
curr->Stop();
- delete curr->GetModuleContext();
+ curr->Uninit();
}
Module* ModuleRegistry::GetModule(long id)
{
MutexLocker lock(*modulesLock());
ModuleMap::const_iterator iter = modules()->find(id);
if (iter != modules()->end())
{
return iter->second;
}
return 0;
}
Module* ModuleRegistry::GetModule(const std::string& name)
{
MutexLocker lock(*modulesLock());
ModuleMap::const_iterator iter = modules()->begin();
ModuleMap::const_iterator iterEnd = modules()->end();
for (; iter != iterEnd; ++iter)
{
if (iter->second->GetName() == name)
{
return iter->second;
}
}
return 0;
}
void ModuleRegistry::GetModules(std::vector<Module*>& m)
{
MutexLocker lock(*modulesLock());
ModuleMap* map = modules();
ModuleMap::const_iterator iter = map->begin();
ModuleMap::const_iterator iterEnd = map->end();
for (; iter != iterEnd; ++iter)
{
m.push_back(iter->second);
}
}
void ModuleRegistry::GetLoadedModules(std::vector<Module*>& m)
{
MutexLocker lock(*modulesLock());
ModuleMap::const_iterator iter = modules()->begin();
ModuleMap::const_iterator iterEnd = modules()->end();
for (; iter != iterEnd; ++iter)
{
if (iter->second->IsLoaded())
{
m.push_back(iter->second);
}
}
}
}
diff --git a/Core/Code/Service/mitkStaticInit.h b/Core/Code/Service/mitkStaticInit.h
index 86b1634786..7c8e8cc989 100644
--- a/Core/Code/Service/mitkStaticInit.h
+++ b/Core/Code/Service/mitkStaticInit.h
@@ -1,123 +1,158 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
Extracted from qglobal.h from Qt 4.7.3 and adapted for MITK.
Original copyright (c) Nokia Corporation. Usage covered by the
GNU Lesser General Public License version 2.1
(http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html) and the Nokia Qt
LGPL Exception version 1.1 (file LGPL_EXCEPTION.txt in Qt 4.7.3 package).
=========================================================================*/
#ifndef MITK_STATIC_INIT_H
#define MITK_STATIC_INIT_H
#include <itkSimpleFastMutexLock.h>
namespace mitk {
// POD for MITK_GLOBAL_STATIC
template <typename T>
class GlobalStatic
{
public:
T* pointer;
bool destroyed;
// Guards acces to "pointer". If a "atomic pointer" class is available,
// this should be used instead of an explicit mutex.
itk::SimpleFastMutexLock mutex;
};
+template<typename T>
+struct DefaultGlobalStaticDeleter
+{
+ void operator()(GlobalStatic<T>& globalStatic) const
+ {
+ delete globalStatic.pointer;
+ globalStatic.pointer = 0;
+ globalStatic.destroyed = true;
+ }
+};
+
// Created as a function-local static to delete a GlobalStatic<T>
-template <typename T>
+template <typename T, template<typename T_> class Deleter = DefaultGlobalStaticDeleter>
class GlobalStaticDeleter
{
public:
GlobalStatic<T> &globalStatic;
GlobalStaticDeleter(GlobalStatic<T> &_globalStatic)
: globalStatic(_globalStatic)
{ }
inline ~GlobalStaticDeleter()
{
- delete globalStatic.pointer;
- globalStatic.pointer = 0;
- globalStatic.destroyed = true;
+ Deleter<T> deleter;
+ deleter(globalStatic);
}
};
} // namespace mitk
#define MITK_GLOBAL_STATIC_INIT(TYPE, NAME) \
static ::mitk::GlobalStatic<TYPE>& this_##NAME() \
{ \
static ::mitk::GlobalStatic<TYPE> l = \
{ 0, false, itk::SimpleFastMutexLock() }; \
return l; \
}
#define MITK_GLOBAL_STATIC(TYPE, NAME) \
MITK_GLOBAL_STATIC_INIT(TYPE, NAME) \
static TYPE *NAME() \
{ \
if (!this_##NAME().pointer && !this_##NAME().destroyed) \
{ \
TYPE *x = new TYPE; \
bool ok = false; \
{ \
this_##NAME().mutex.Lock(); \
if (!this_##NAME().pointer) \
{ \
this_##NAME().pointer = x; \
ok = true; \
} \
this_##NAME().mutex.Unlock(); \
} \
if (!ok) \
delete x; \
else \
static ::mitk::GlobalStaticDeleter<TYPE > cleanup(this_##NAME());\
} \
return this_##NAME().pointer; \
}
+#define MITK_GLOBAL_STATIC_WITH_DELETER(TYPE, NAME, DELETER) \
+ MITK_GLOBAL_STATIC_INIT(TYPE, NAME) \
+ static TYPE *NAME() \
+ { \
+ if (!this_##NAME().pointer && !this_##NAME().destroyed) \
+ { \
+ TYPE *x = new TYPE; \
+ bool ok = false; \
+ { \
+ this_##NAME().mutex.Lock(); \
+ if (!this_##NAME().pointer) \
+ { \
+ this_##NAME().pointer = x; \
+ ok = true; \
+ } \
+ this_##NAME().mutex.Unlock(); \
+ } \
+ if (!ok) \
+ delete x; \
+ else \
+ static ::mitk::GlobalStaticDeleter<TYPE, DELETER > cleanup(this_##NAME());\
+ } \
+ return this_##NAME().pointer; \
+ }
+
#define MITK_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS) \
MITK_GLOBAL_STATIC_INIT(TYPE, NAME) \
static TYPE *NAME() \
{ \
if (!this_##NAME().pointer && !this_##NAME().destroyed) \
{ \
TYPE *x = new TYPE ARGS; \
bool ok = false; \
{ \
this_##NAME().mutex.Lock(); \
if (!this_##NAME().pointer) \
{ \
this_##NAME().pointer = x; \
ok = true; \
} \
this_##NAME().mutex.Unlock(); \
} \
if (!ok) \
delete x; \
else \
static ::mitk::GlobalStaticDeleter<TYPE > cleanup(this_##NAME());\
} \
return this_##NAME().pointer; \
}
#endif // MITK_STATIC_INIT_H
diff --git a/Documentation/Doxygen/Applications.dox b/Documentation/Doxygen/Applications.dox
new file mode 100644
index 0000000000..727ff09deb
--- /dev/null
+++ b/Documentation/Doxygen/Applications.dox
@@ -0,0 +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 the \ref ApplicationsPageApplicationsList , whereas if you are interested in a certain view more information can be found in \ref ModuleListPage .
+
+The basic usage information on MITK can be found in \subpage MITKManualMainPage .
+
+\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 MITKManualMainPage . Further information on any application can be found here:
+<ul>
+ <li> \subpage org_extapplication
+ <li> \subpage org_dti_atlas_application
+ <li> \subpage org_diffusionapplication
+</ul>
+
+*/
\ No newline at end of file
diff --git a/Documentation/Doxygen/Development.dox b/Documentation/Doxygen/Development.dox
index c20b65c530..c1ddcadaec 100644
--- a/Documentation/Doxygen/Development.dox
+++ b/Documentation/Doxygen/Development.dox
@@ -1,30 +1,31 @@
/**
\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 BuildInstructionsPage
\li \subpage thirdpartylibs
\section DevelopmentGettingToKnow Getting To Know MITK
\li \subpage DirectoryStructurePage
\li \subpage TutorialPage
\section DevelopmentWith Developing With MITK
\li \subpage DICOMTesting
\li \subpage NewPluginPage
\li \subpage StatemachineEditor
\li \subpage mitkExtPointsIndex
\li \subpage KnownProblemsPage
\section DevelopmentContributing Contributing To MITK
+\li \subpage DocumentationGuide
\li \subpage StylesAndNotesPage
*/
diff --git a/Documentation/Doxygen/DocumentationGuide.dox b/Documentation/Doxygen/DocumentationGuide.dox
new file mode 100644
index 0000000000..df0a3fa479
--- /dev/null
+++ b/Documentation/Doxygen/DocumentationGuide.dox
@@ -0,0 +1,47 @@
+/**
+\page DocumentationGuide Writing Documentation
+
+\section DocumentationGuideCodeGeneral General remarks
+
+MITK uses <a href="http://www.stack.nl/~dimitri/doxygen/">Doxygen</a> for the generation of our user manual pages as well as for the generation of the on- and offline reference manuals. So on the technical side many questions can be answered by the <a href="http://www.stack.nl/~dimitri/doxygen/manual.html">doxygen documentation</a>, such as the list of commands or a few basic doxygen tutorials.
+
+Therefore this document is not primarily intended as a guide to using doxygen, the doxygen manual does a much better job of that, but as a guide to use doxygen in MITK and a collection of helpful hints and advise about pittfalls.
+
+Also, of course you need to have doxygen installed to generate documentation.
+
+\section DocumentationGuideCode Documenting the source code
+
+MITK is a substantial project and encompasses many different source files by many different developers over quite a considerable timeframe. Many of them have written excellent code which can do a lot of things and is very helpful to people who might apply it in wholly unlooked for ways for completely different problems. To facilitate this sharing and reusing of ressources one first and foremost has to know what kind of ressources are already available.
+
+Few people write code in the intention for it to be difficult to be used by others, but unfortunately what might seem a very efficient and easily understandable piece of code to the author might be nigh unreadable for someone else. Very often it does not in fact matter whether the code itself is understandable, as long as it one can get the information what a function is supposed to do. While comments in the source file help a lot to gain this knowledge in can get quite tedious go through every file looking for the right tool.
+
+This is were using doxygen pays of, by giving a short comment in the header file a reference manual is automatically generated.
+
+\subsection DocumentationGuideCodeHints Helpful hints:
+<ul>
+ <li> Always put comments intended for doxygen in the header files.
+ <li> Use the /// or //! style, to be able to comment out the entire file quickly
+</ul>
+
+\section DocumentationGuideManual Writing user manuals
+
+While the usage of your view/perspective/application might seem obvious and accessible to you, to most people it is not. Writing a good manual is key for this. It is very difficult to write a manual which is too comprehensive, most often if something can be done in a wrong way, somebody will see this as the only one.
+
+It is advisable to use a dedicated .dox file for a manual, helps keeping things clean and tidy. For MITK purposes you should put your documentation in BUNDLEPATH/documentation/UserManual/ .
+
+The nightly generated HTML documentation and the QtAssistant documentation can contain different content using the isHTML command.
+
+\subsection DocumentationGuideManualHints Helpful hints:
+<ul>
+ <li> Do not use . in identifiern, it throws doxygen off
+ <li> Think were your page should go in the MITK help page structure and declare it as a subpage accordingly
+ <li> Use structuring elements, such as sections and subsections
+ <li> Use references to allow for fast navigation
+ <li> Images, pictures and sketches are great, use them
+ <li> Use visual help like remark, paragraph and warning
+ <li> Use the /** or /*! style, so as not to be forced to comment out every line
+ <li> BLUEBERRY_USE_QT_HELP should be set to ON
+</ul>
+
+*/
+
diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/Crosshair_Modes.png b/Documentation/Doxygen/UserManual/Crosshair_Modes.png
similarity index 100%
rename from Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/Crosshair_Modes.png
rename to Documentation/Doxygen/UserManual/Crosshair_Modes.png
diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/GUI.png b/Documentation/Doxygen/UserManual/GUI.png
similarity index 100%
rename from Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/GUI.png
rename to Documentation/Doxygen/UserManual/GUI.png
diff --git a/Modules/Bundles/org.mitk.gui.qt.extapplication/documentation/UserManual/GUI_Commented.png b/Documentation/Doxygen/UserManual/GUI_Commented.png
similarity index 100%
rename from Modules/Bundles/org.mitk.gui.qt.extapplication/documentation/UserManual/GUI_Commented.png
rename to Documentation/Doxygen/UserManual/GUI_Commented.png
diff --git a/Modules/Bundles/org.mitk.gui.qt.extapplication/documentation/UserManual/QmitkExtapplicationUserManual.dox b/Documentation/Doxygen/UserManual/MITKUserManual.dox
similarity index 62%
copy from Modules/Bundles/org.mitk.gui.qt.extapplication/documentation/UserManual/QmitkExtapplicationUserManual.dox
copy to Documentation/Doxygen/UserManual/MITKUserManual.dox
index 63dccc44fe..8b60bcc1d6 100644
--- a/Modules/Bundles/org.mitk.gui.qt.extapplication/documentation/UserManual/QmitkExtapplicationUserManual.dox
+++ b/Documentation/Doxygen/UserManual/MITKUserManual.dox
@@ -1,120 +1,118 @@
/**
-\bundlemainpage{org_extapplication} The Main Application
+\page MITKManualMainPage The MITK User Manual
-Welcome to the MITK ExtApplication, build with the <B>M</B>edical <B>I</B>maging <B>T</B>ool<B>k</B>it ( http://mitk.org/ ).
+Welcome to the basic MITK user manual. This document tries to give a concise overview of the basic functions of MITK and be an comprehensible guide on using them.
Available sections:
- - \ref QmitkExtApplicationUserManualOverview
- - \ref QmitkExtApplicationUserManualUserInterface
- - \ref QmitkExtApplicationUserManualPerspectives
+ - \ref MITKManualMainPageOverview
+ - \ref MITKManualMainPageUserInterface
+ - \ref MITKManualMainPagePerspectives
-\section QmitkExtApplicationUserManualOverview About MITK and MITK ExtApplication
+\section MITKManualMainPageOverview About MITK
MITK is an open-source framework that was originally developed as a common framework for Ph.D. students in the Division of Medical and Biological Informatics (MBI) at the German Cancer Research Center. MITK aims at supporting the development of leading-edge medical imaging software with a high degree of interaction.
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 features not supported by VTK or ITK.
Research institutes, medical professionals and companies alike can use MITK as a basic framework for their research and even commercial (thorough code research needed) software due to the BSD-like software license.
Research institutes will profit from the high level of integration of ITK and VTK enhanced with data management, advanced visualization and interaction functionality in a single framework that is supported by a wide variety of researchers and developers. You will not have to reinvent the wheel over and over and can concentrate on your work.
-Medical Professionals will profit from MITK and the MITK ExtApplication by using its basic functionalities for research projects. But nonetheless they will be better off, unless they are programmers themselves, to cooperate with a research institute developing with MITK to get the functionalitiy they need. MITK and the presented MITK ExtApplication are not certified medical products and may be used in a research setting only. They must not be used in patient care.
+Medical Professionals will profit from MITK and the MITK applications by using its basic functionalities for research projects. But nonetheless they will be better off, unless they are programmers themselves, to cooperate with a research institute developing with MITK to get the functionalitiy they need. MITK and the MITK applications are not certified medical products and may be used in a research setting only. They must not be used in patient care.
-MITK ExtApplication is a demonstration of the capabilites of the MITK framework and has been created by the Division of Medical and Biological Informatics (MBI) at the German Cancer Research Center.
+\section MITKManualMainPageUserInterface The User Interface
-\section QmitkExtApplicationUserManualUserInterface The User Interface
+The layout of the MITK applications is designed to give a clear distinction between the different work areas. The following figure gives an overview of the main sections of the user interface.
-The layout of the MITK ExtApplication is designed to give a clear distinction between the different work areas. The following figure gives an overview of the main sections of the user interface.
+\image html GUI_Commented.png "The Common MITK Application Graphical User Interface"
-\image html GUI_Commented.png "The MITK ExtApplication User Interface"
+The datamanager and the \ref MITKManualMainPagePerspectives have their own help sections. This document explains the use of:
+ - The \ref MITKManualMainPageMultiWidget
+ - The \ref MITKManualMainPageMenu
+ - The \ref MITKManualMainPageLevelWindow
+ - The \ref MITKManualMainPageMemoryUsage
+ - The \ref MITKManualMainPageViews
-The datamanager and the \ref QmitkExtApplicationUserManualPerspectives have their own help sections. This document explains the use of:
- - The \ref QmitkExtApplicationUserManualMultiWidget
- - The \ref QmitkExtApplicationUserManualMenu
- - The \ref QmitkExtApplicationUserManualLevelWindow
- - The \ref QmitkExtApplicationUserManualMemoryUsage
- - The \ref QmitkExtApplicationUserManualViews
-
-\section QmitkExtApplicationUserManualMultiWidget Four Window View
+\section MITKManualMainPageMultiWidget Four Window View
-\subsection QmitkExtApplicationUserManualMultiWidgetOverview Overview
+\subsection MITKManualMainPageMultiWidgetOverview Overview
-The four window view is the heart of the MITK ExtApplication image viewing. The standard layout is three 2D windows and one 3D window, with the transversal window in the top left quarter, the sagittal window in the top right quarter, the coronal window in the lower left quarter and the 3D window in the lower right quarter. The different planes form a crosshair that can be seen in the 3D window.
+The four window view is the heart of the MITK image viewing. The standard layout is three 2D windows and one 3D window, with the transversal window in the top left quarter, the sagittal window in the top right quarter, the coronal window in the lower left quarter and the 3D window in the lower right quarter. The different planes form a crosshair that can be seen in the 3D window.
Once you select a point within the picture, informations about it are displayed at the bottom of the screen.
-\subsection QmitkExtApplicationUserManualMultiWidgetNavigation Navigation
+\subsection MITKManualMainPageMultiWidgetNavigation Navigation
Left click in any of the 2D windows centers the crosshair on that point. Pressing the right mouse button and moving the mouse <B>zooms</B> in and out. By scrolling with the mouse wheel you can <B>navigate through</B> the slices of the active window and pressing the mouse wheel while moving the mouse <B>pans</B> the image section.
In the 3D window you can <B>rotate</B> the object by pressing the left mouse button and moving the mouse, <B>zoom</B> either with the right mouse button as in 2D or with the mouse wheel, and <B>pan</B> the object by moving the mouse while the mouse wheel is pressed. Placing the cursor within the 3D window and holding the "F" key allows <B>free flight</B> into the 3D view.
-\subsection QmitkExtApplicationUserManualMultiWidgetCustomizingViews Customizing
+\subsection MITKManualMainPageMultiWidgetCustomizingViews Customizing
By moving the cursor to the upper right corner of any window you can activate the window menu. It consists of three buttons.
\image html Crosshair_Modes.png "Crosshair"
The crosshair button allows you toggle the crosshair, reset the view and change the behaviour of the planes.
Activating either of the rotation modes allows you to rotate the planes visible in a 2D window by moving the mouse cursor close to them and click and dragging once it changes to indicate that rotation can be done.
The swivel mode is recommended only for advanced users as the planes can be moved freely by clicking and dragging anywhere within a 2D window.
The middle button expands the corresponding window to fullscreen within the four window view.
\image html Views_Choices.png "Layout Choices"
The right button allows you to choose between many different layouts of the four window view to use the one most suited to your task.
-\section QmitkExtApplicationUserManualMenu Menu
+\section MITKManualMainPageMenu Menu
-\subsection QmitkExtApplicationUserManualFile File
+\subsection MITKManualMainPageFile File
This dialog allows you to save, load and clear entire projects, this includes any nodes in the data manager.
-\subsection QmitkExtApplicationUserManualEdit Edit
+\subsection MITKManualMainPageEdit Edit
This dialog supports undo and redo operations as well as the image navigator, which gives you sliders to navigate through the data quickly.
-\subsection QmitkExtApplicationUserManualWindow Window
+\subsection MITKManualMainPageWindow Window
This dialog allows you to open a new window, change between perspectives and reset your current one to default settings.
If you want to use an operation of a certain perspective within another perspective the "Show View" menu allows to select a specific function that is opened and can be moved within the working areas according to your wishes. Be aware that not every function works with every perspective in a meaningful way.
The Preferences dialog allows you to adjust and save your custom settings.
\image html Window_Dropdown.png "Preferences"
-\subsection QmitkExtApplicationUserManualHelp Help
+\subsection MITKManualMainPageHelp Help
This dialog contains this help, the welcome screen and information about MITK 3M3.
-\section QmitkExtApplicationUserManualLevelWindow Levelwindow
+\section MITKManualMainPageLevelWindow Levelwindow
Once an image is loaded the levelwindow appears to the right hand side of the four window view. With this tool you can adjust the range of grey values displayed and the gradient between them. Moving the lower boundary up results in any pixels having a value lower than that boundary to be displayed as black. Lowering the upper boundary causes all pixels having a value higher than it to be displayed as white.
The pixels with a value between the lower and upper boundary are displayed in different shades of grey. This way a smaller levelwindow results in higher contrasts while cutting of the information outside its range whereas a larger levelwindow displays more information at the cost of contrast and detail.
You can pick the levelwindow with the mouse to move it up and down, while moving the mouse cursor to the left or right to change its size. Picking one of the boundaries with a left click allows you to change the size symmetrically. Holding CTRL and clicking a boundary adjusts only that value.
-\section QmitkExtApplicationUserManualMemoryUsage System Load Indicator
+\section MITKManualMainPageMemoryUsage System Load Indicator
-The System Load Indicator in the lower right hand corner of the screen gives information about the memory currently required by the MITK ExtApplication. Keep in mind that image processing is a highly memory intensive task and monitor the indicator to avoid your system freezing while constantly swapping to the hard drive.
+The System Load Indicator in the lower right hand corner of the screen gives information about the memory currently required by the MITK application. Keep in mind that image processing is a highly memory intensive task and monitor the indicator to avoid your system freezing while constantly swapping to the hard drive.
-\section QmitkExtApplicationUserManualViews Views
+\section MITKManualMainPageViews Views
Each solution for a specific problem that is self contained is realized as a single view. Thus you can create a workflow for your problem by combining the capabilities of different views to suit your needs.
-One elegant way to do this is by combining views in \ref QmitkExtApplicationUserManualPerspectives.
+One elegant way to do this is by combining views in \ref MITKManualMainPagePerspectives.
By pressing and holding the left mouse button on a views tab you can move it around to suit your needs, even out of the application window.
-\section QmitkExtApplicationUserManualPerspectives Perspectives
+\section MITKManualMainPagePerspectives Perspectives
The different tasks that arise in medical imaging need very different approaches. To acknowledge this circumstance MITK supplies a framework that can be build uppon by very different solutions to those tasks. These solutions are called perspectives, each of them works independently of others although they might be used in sequence to achieve the solution of more difficult problems.
It is possible to switch between the perspectives using the "Window"->"Open Perspective" dialog.
-See \ref QmitkExtApplicationUserManualMenu for more information about switching perspectives.
+See \ref MITKManualMainPageMenu for more information about switching perspectives.
*/
diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/Top_Right_Corner_Menu.png b/Documentation/Doxygen/UserManual/Top_Right_Corner_Menu.png
similarity index 100%
rename from Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/Top_Right_Corner_Menu.png
rename to Documentation/Doxygen/UserManual/Top_Right_Corner_Menu.png
diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/Views_Choices.png b/Documentation/Doxygen/UserManual/Views_Choices.png
similarity index 100%
rename from Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/Views_Choices.png
rename to Documentation/Doxygen/UserManual/Views_Choices.png
diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/Window_Dropdown.png b/Documentation/Doxygen/UserManual/Window_Dropdown.png
similarity index 100%
rename from Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/Window_Dropdown.png
rename to Documentation/Doxygen/UserManual/Window_Dropdown.png
diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperView.cpp b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperView.cpp
index 5faefe9e69..b6dc8c13b4 100644
--- a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperView.cpp
+++ b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperView.cpp
@@ -1,857 +1,1239 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date: 2010-03-31 16:40:27 +0200 (Mi, 31 Mrz 2010) $
Version: $Revision: 21975 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
//=========FOR TESTING==========
//random generation, number of points equal requested points
// Blueberry application and interaction service
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
// Qmitk
#include "QmitkFiberBundleDeveloperView.h"
#include <QmitkStdMultiWidget.h>
// Qt
#include <QTimer>
// MITK
-//#include <mitkFiberBundleX.h> //for fiberStructure
-#include <mitkFiberBundleXThreadMonitor.h>
+
//===needed when timeSlicedGeometry is null to invoke rendering mechansims ====
#include <mitkNodePredicateNot.h>
#include <mitkNodePredicateProperty.h>
// VTK
#include <vtkPointSource.h> //for randomized FiberStructure
#include <vtkPolyLine.h> //for fiberStructure
#include <vtkCellArray.h> //for fiberStructure
#include <vtkMatrix4x4.h> //for geometry
//ITK
#include <itkTimeProbe.h>
//==============================================
//======== W O R K E R S ____ S T A R T ========
//==============================================
/*===================================================================================
* THIS METHOD IMPLEMENTS THE ACTIONS WHICH SHALL BE EXECUTED by the according THREAD
* --generate FiberIDs--*/
QmitkFiberIDWorker::QmitkFiberIDWorker(QThread* hostingThread, Package4WorkingThread itemPackage)
: m_itemPackage(itemPackage),
m_hostingThread(hostingThread)
{
}
void QmitkFiberIDWorker::run()
{
+ if(m_itemPackage.st_Controls->checkBoxMonitorFiberThreads->isChecked())
+ m_itemPackage.st_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_RUNNING);
/* MEASUREMENTS AND FANCY GUI EFFECTS
* accurate time measurement using ITK timeProbe*/
itk::TimeProbe clock;
clock.Start();
//set GUI representation of timer to 0, is essential for correct timer incrementation
m_itemPackage.st_Controls->infoTimerGenerateFiberIds->setText(QString::number(0));
m_itemPackage.st_FancyGUITimer1->start();
//do processing
m_itemPackage.st_FBX->DoGenerateFiberIds();
/* MEASUREMENTS AND FANCY GUI EFFECTS CLEANUP */
clock.Stop();
m_itemPackage.st_FancyGUITimer1->stop();
m_itemPackage.st_Controls->infoTimerGenerateFiberIds->setText( QString::number(clock.GetTotal()) );
delete m_itemPackage.st_FancyGUITimer1; // fancy timer is not needed anymore
m_hostingThread->quit();
}
/*===================================================================================
* THIS METHOD IMPLEMENTS THE ACTIONS WHICH SHALL BE EXECUTED by the according THREAD
* --generate random fibers--*/
QmitkFiberGenerateRandomWorker::QmitkFiberGenerateRandomWorker(QThread* hostingThread, Package4WorkingThread itemPackage)
: m_itemPackage(itemPackage),
m_hostingThread(hostingThread)
{
}
void QmitkFiberGenerateRandomWorker::run()
{
-
+ if(m_itemPackage.st_Controls->checkBoxMonitorFiberThreads->isChecked())
+ m_itemPackage.st_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_RUNNING);
+
/* MEASUREMENTS AND FANCY GUI EFFECTS */
m_itemPackage.st_Controls->infoTimerGenerateFiberBundle->setText(QString::number(0));
m_itemPackage.st_FancyGUITimer1->start();
//do processing, generateRandomFibers
int numOfFibers = m_itemPackage.st_Controls->boxFiberNumbers->value();
int distrRadius = m_itemPackage.st_Controls->boxDistributionRadius->value();
int numOfPoints = numOfFibers * distrRadius;
std::vector< std::vector<int> > fiberStorage;
for (int i=0; i<numOfFibers; ++i) {
std::vector<int> a;
fiberStorage.push_back( a );
}
/* Generate Point Cloud */
vtkSmartPointer<vtkPointSource> randomPoints = vtkSmartPointer<vtkPointSource>::New();
randomPoints->SetCenter(0.0, 0.0, 0.0);
randomPoints->SetNumberOfPoints(numOfPoints);
randomPoints->SetRadius(distrRadius);
randomPoints->Update();
vtkPoints* pnts = randomPoints->GetOutput()->GetPoints();
/* ASSIGN EACH POINT TO A RANDOM FIBER */
srand((unsigned)time(0)); // init randomizer
for (int i=0; i<pnts->GetNumberOfPoints(); ++i) {
//generate random number between 0 and numOfFibers-1
int random_integer;
random_integer = (rand()%numOfFibers);
//add current point to random fiber
fiberStorage.at(random_integer).push_back(i);
// MITK_INFO << "point" << i << " |" << pnts->GetPoint(random_integer)[0] << "|" << pnts->GetPoint(random_integer)[1]<< "|" << pnts->GetPoint(random_integer)[2] << "| into fiber" << random_integer;
}
// initialize accurate time measurement
itk::TimeProbe clock;
clock.Start();
/* GENERATE VTK POLYLINES OUT OF FIBERSTORAGE */
vtkSmartPointer<vtkCellArray> linesCell = vtkSmartPointer<vtkCellArray>::New(); // Host vtkPolyLines
linesCell->Allocate(pnts->GetNumberOfPoints()*2); //allocate for each cellindex also space for the pointId, e.g. [idx | pntID]
for (unsigned long i=0; i<fiberStorage.size(); ++i)
{
std::vector<int> singleFiber = fiberStorage.at(i);
vtkSmartPointer<vtkPolyLine> fiber = vtkSmartPointer<vtkPolyLine>::New();
fiber->GetPointIds()->SetNumberOfIds((int)singleFiber.size());
for (unsigned long si=0; si<singleFiber.size(); ++si)
{ //hopefully unsigned long to double works fine in VTK ;-)
fiber->GetPointIds()->SetId( si, singleFiber.at(si) );
}
linesCell->InsertNextCell(fiber);
}
/* checkpoint for cellarray allocation */
if ( (linesCell->GetSize()/pnts->GetNumberOfPoints()) != 2 ) //e.g. size: 12, number of points:6 .... each cell hosts point ids (6 ids) + cell index for each idPoint. 6 * 2 = 12
{
MITK_INFO << "RANDOM FIBER ALLOCATION CAN NOT BE TRUSTED ANYMORE! Correct leak or remove command: linesCell->Allocate(pnts->GetNumberOfPoints()*2) but be aware of possible loss in performance.";
}
/* HOSTING POLYDATA FOR RANDOM FIBERSTRUCTURE */
vtkPolyData* PDRandom = vtkPolyData::New(); //no need to delete because data is needed in datastorage.
PDRandom->SetPoints(pnts);
PDRandom->SetLines(linesCell);
// accurate timer measurement stop
clock.Stop();
//MITK_INFO << "=====Assambling random Fibers to Polydata======\nMean: " << clock.GetMean() << " Total: " << clock.GetTotal() << std::endl;
// call function to convert fiberstructure into fiberbundleX and pass it to datastorage
(m_itemPackage.st_host->*m_itemPackage.st_pntr_to_Method_PutFibersToDataStorage)(PDRandom);
/* MEASUREMENTS AND FANCY GUI EFFECTS CLEANUP */
m_itemPackage.st_FancyGUITimer1->stop();
m_itemPackage.st_Controls->infoTimerGenerateFiberBundle->setText( QString::number(clock.GetTotal()) );
delete m_itemPackage.st_FancyGUITimer1; // fancy timer is not needed anymore
m_hostingThread->quit();
}
+
+/*===================================================================================
+ * THIS METHOD IMPLEMENTS THE ACTIONS WHICH SHALL BE EXECUTED by the according THREAD
+ * --update GUI elements of thread monitor--
+ * implementation not thread safe, not needed so far because
+ * there exists only 1 thread for fiberprocessing
+ * for threadsafety, you need to implement checking mechanisms in methods "::threadFor...." */
+QmitkFiberThreadMonitorWorker::QmitkFiberThreadMonitorWorker( QThread* hostingThread, Package4WorkingThread itemPackage )
+: m_itemPackage(itemPackage)
+, m_hostingThread(hostingThread)
+, m_pixelstepper(10) //for next rendering call, move object 10px
+, m_steppingDistance(220) //use only a multiple value of pixelstepper, x-axis border for fancy stuff
+{
+
+
+ //set timers
+ m_thtimer_initMonitor = new QTimer;
+ m_thtimer_initMonitor->setInterval(10);
+
+ m_thtimer_initMonitorSetFinalPosition = new QTimer;
+ m_thtimer_initMonitorSetFinalPosition->setInterval(10);
+
+ m_thtimer_initMonitorSetMasks = new QTimer;
+ m_thtimer_initMonitorSetFinalPosition->setInterval(10);
+
+
+ m_thtimer_threadStarted = new QTimer;
+ m_thtimer_threadStarted->setInterval(50);
+
+ m_thtimer_threadFinished = new QTimer;
+ m_thtimer_threadFinished->setInterval(50);
+
+ m_thtimer_threadTerminated = new QTimer;
+ m_thtimer_threadTerminated->setInterval(50);
+
+
+
+ connect (m_thtimer_initMonitor, SIGNAL( timeout()), this, SLOT( fancyMonitorInitialization() ) );
+ connect ( m_thtimer_initMonitorSetFinalPosition, SIGNAL( timeout() ), this, SLOT( fancyMonitorInitializationFinalPos() ) );
+ connect ( m_thtimer_initMonitorSetMasks, SIGNAL( timeout() ), this, SLOT( fancyMonitorInitializationMask() ) );
+
+ connect (m_thtimer_threadStarted, SIGNAL( timeout()), this, SLOT( fancyTextFading_threadStarted() ) );
+ connect (m_thtimer_threadFinished, SIGNAL( timeout()), this, SLOT( fancyTextFading_threadFinished() ) );
+ connect (m_thtimer_threadTerminated, SIGNAL( timeout()), this, SLOT( fancyTextFading_threadTerminated() ) );
+
+ //first, the current text shall turn transparent
+ m_decreaseOpacity_threadStarted = true;
+ m_decreaseOpacity_threadFinished = true;
+ m_decreaseOpacity_threadTerminated = true;
+
+
+
+
+}
+void QmitkFiberThreadMonitorWorker::run()
+{
+
+}
+
+void QmitkFiberThreadMonitorWorker::initializeMonitor()
+{
+ //fancy configuration of animation start
+ mitk::Point2D pntOpen;
+ pntOpen[0] = 118;
+ pntOpen[1] = 10;
+
+ mitk::Point2D headPos;
+ headPos[0] = 19;
+ headPos[1] = 10;
+
+ mitk::Point2D statusPos;
+ statusPos[0] = 105;
+ statusPos[1] = 23;
+
+ mitk::Point2D startedPos;
+ startedPos[0] = 68;
+ startedPos[1] = 10;
+
+ mitk::Point2D finishedPos;
+ finishedPos[0] = 143;
+ finishedPos[1] = 10;
+
+ mitk::Point2D terminatedPos;
+ terminatedPos[0] = 240;
+ terminatedPos[1] = 10;
+
+ m_itemPackage.st_FBX_Monitor->setBracketClosePosition(pntOpen);
+ m_itemPackage.st_FBX_Monitor->setBracketOpenPosition(pntOpen);
+ m_itemPackage.st_FBX_Monitor->setHeadingPosition(headPos);
+ m_itemPackage.st_FBX_Monitor->setMaskPosition(headPos);
+ m_itemPackage.st_FBX_Monitor->setStatusPosition(statusPos);
+ m_itemPackage.st_FBX_Monitor->setStartedPosition(startedPos);
+ m_itemPackage.st_FBX_Monitor->setFinishedPosition(finishedPos);
+ m_itemPackage.st_FBX_Monitor->setTerminatedPosition(terminatedPos);
+
+
+ m_thtimer_initMonitor->start();
+}
+
+void QmitkFiberThreadMonitorWorker::setThreadStatus(QString status)
+{
+ m_itemPackage.st_FBX_Monitor->setStatus(status);
+ m_itemPackage.st_ThreadMonitorDataNode->Modified();
+ m_itemPackage.st_MultiWidget->RequestUpdate();
+}
+
+void QmitkFiberThreadMonitorWorker::threadForFiberProcessingStarted()
+{
+ if(!m_thtimer_threadStarted->isActive()) {
+ m_thtimer_threadStarted->start();
+ } else {
+ //fast change without fancy stuff
+ int counter = m_itemPackage.st_FBX_Monitor->getStarted();
+ m_itemPackage.st_FBX_Monitor->setStarted(++counter);
+
+ }
+
+
+}
+
+void QmitkFiberThreadMonitorWorker::threadForFiberProcessingFinished()
+{
+ if(!m_thtimer_threadFinished->isActive()) {
+ m_thtimer_threadFinished->start();
+ } else {
+ //fast change without fancy stuff
+ int counter = m_itemPackage.st_FBX_Monitor->getFinished();
+ m_itemPackage.st_FBX_Monitor->setFinished(++counter);
+
+ }
+
+}
+
+void QmitkFiberThreadMonitorWorker::threadForFiberProcessingTerminated()
+{
+ if(!m_thtimer_threadTerminated->isActive()) {
+ m_thtimer_threadTerminated->start();
+ } else {
+ //fast change without fancy stuff
+ int counter = m_itemPackage.st_FBX_Monitor->getTerminated();
+ m_itemPackage.st_FBX_Monitor->setTerminated(++counter);
+
+ }
+
+}
+
+
+
+void QmitkFiberThreadMonitorWorker::fancyTextFading_threadStarted()
+{
+
+ if (m_decreaseOpacity_threadStarted) {
+ int startedOpacity = m_itemPackage.st_FBX_Monitor->getStartedOpacity();
+ m_itemPackage.st_FBX_Monitor->setStartedOpacity( --startedOpacity );
+
+ if (startedOpacity == 0) {
+ int counter = m_itemPackage.st_FBX_Monitor->getStarted();
+ m_itemPackage.st_FBX_Monitor->setStarted(++counter);
+ m_decreaseOpacity_threadStarted = false;
+ }
+ m_itemPackage.st_ThreadMonitorDataNode->Modified();
+ m_itemPackage.st_MultiWidget->RequestUpdate();
+
+ } else {
+
+ int startedOpacity = m_itemPackage.st_FBX_Monitor->getStartedOpacity();
+ m_itemPackage.st_FBX_Monitor->setStartedOpacity( ++startedOpacity );
+
+ if (startedOpacity >= 10) {
+ m_thtimer_threadStarted->stop();
+ m_decreaseOpacity_threadStarted = true; //set back to true, cuz next iteration shall decrease opacity as well
+ }
+
+ m_itemPackage.st_ThreadMonitorDataNode->Modified();
+ m_itemPackage.st_MultiWidget->RequestUpdate();
+
+ }
+
+
+}
+
+void QmitkFiberThreadMonitorWorker::fancyTextFading_threadFinished()
+{
+ if (m_decreaseOpacity_threadFinished) {
+ int finishedOpacity = m_itemPackage.st_FBX_Monitor->getFinishedOpacity();
+ m_itemPackage.st_FBX_Monitor->setFinishedOpacity( --finishedOpacity );
+
+ if (finishedOpacity == 0) {
+ int counter = m_itemPackage.st_FBX_Monitor->getFinished();
+ m_itemPackage.st_FBX_Monitor->setFinished(++counter);
+ m_decreaseOpacity_threadFinished = false;
+ }
+ m_itemPackage.st_ThreadMonitorDataNode->Modified();
+ m_itemPackage.st_MultiWidget->RequestUpdate();
+
+ } else {
+
+ int finishedOpacity = m_itemPackage.st_FBX_Monitor->getFinishedOpacity();
+ m_itemPackage.st_FBX_Monitor->setFinishedOpacity( ++finishedOpacity );
+
+ if (finishedOpacity >= 10) {
+ m_thtimer_threadFinished->stop();
+ m_decreaseOpacity_threadFinished = true; //set back to true, cuz next iteration shall decrease opacity as well
+ }
+
+ m_itemPackage.st_ThreadMonitorDataNode->Modified();
+ m_itemPackage.st_MultiWidget->RequestUpdate();
+
+ }
+
+}
+
+void QmitkFiberThreadMonitorWorker::fancyTextFading_threadTerminated()
+{
+ if (m_decreaseOpacity_threadTerminated) {
+ int terminatedOpacity = m_itemPackage.st_FBX_Monitor->getTerminatedOpacity();
+ m_itemPackage.st_FBX_Monitor->setTerminatedOpacity( --terminatedOpacity );
+
+ if (terminatedOpacity == 0) {
+ int counter = m_itemPackage.st_FBX_Monitor->getTerminated();
+ m_itemPackage.st_FBX_Monitor->setTerminated(++counter);
+ m_decreaseOpacity_threadTerminated = false;
+ }
+ m_itemPackage.st_ThreadMonitorDataNode->Modified();
+ m_itemPackage.st_MultiWidget->RequestUpdate();
+
+ } else {
+
+ int terminatedOpacity = m_itemPackage.st_FBX_Monitor->getTerminatedOpacity();
+ m_itemPackage.st_FBX_Monitor->setTerminatedOpacity( ++terminatedOpacity );
+
+ if (terminatedOpacity >= 10) {
+ m_thtimer_threadTerminated->stop();
+ m_decreaseOpacity_threadTerminated = true; //set back to true, cuz next iteration shall decrease opacity as well
+ }
+
+ m_itemPackage.st_ThreadMonitorDataNode->Modified();
+ m_itemPackage.st_MultiWidget->RequestUpdate();
+
+ }
+
+
+
+}
+
+void QmitkFiberThreadMonitorWorker::fancyMonitorInitialization()
+{
+
+ mitk::Point2D pntClose = m_itemPackage.st_FBX_Monitor->getBracketClosePosition(); //possible bottleneck, set pntClose to member
+ mitk::Point2D pntOpen = m_itemPackage.st_FBX_Monitor->getBracketOpenPosition(); //possible bottleneck, set pntClose to member
+
+ pntClose[0] += m_pixelstepper;
+ pntOpen[0] -= m_pixelstepper;
+ //MITK_INFO << pntClose[0] << " " << pntOpen[0];
+
+ m_itemPackage.st_FBX_Monitor->setBracketClosePosition(pntClose);
+ m_itemPackage.st_FBX_Monitor->setBracketOpenPosition(pntOpen);
+
+ int opacity = m_itemPackage.st_FBX_Monitor->getHeadingOpacity() + 1;
+ if (opacity > 10)
+ opacity = 10;
+ m_itemPackage.st_FBX_Monitor->setHeadingOpacity(opacity);
+
+
+ if (pntClose[0] >= m_steppingDistance)
+ {
+ if (m_itemPackage.st_FBX_Monitor->getHeadingOpacity() != 10 )
+ {
+ m_itemPackage.st_FBX_Monitor->setHeadingOpacity(10);
+ m_itemPackage.st_ThreadMonitorDataNode->Modified();
+ m_itemPackage.st_MultiWidget->RequestUpdate();
+ }
+
+ m_thtimer_initMonitor->stop();
+
+ //position them to obt y=25
+ m_thtimer_initMonitorSetFinalPosition->start();
+ }
+
+ m_itemPackage.st_ThreadMonitorDataNode->Modified();
+ m_itemPackage.st_MultiWidget->RequestUpdate();
+
+
+}
+
+void QmitkFiberThreadMonitorWorker::fancyMonitorInitializationFinalPos()
+{
+ //get y pos of
+ mitk::Point2D pntClose = m_itemPackage.st_FBX_Monitor->getBracketClosePosition();
+ mitk::Point2D pntOpen = m_itemPackage.st_FBX_Monitor->getBracketOpenPosition();
+ mitk::Point2D pntHead = m_itemPackage.st_FBX_Monitor->getHeadingPosition();
+
+ pntClose[1] += 5;
+ pntOpen[1] += 5;
+ pntHead[1] += 5;
+
+ m_itemPackage.st_FBX_Monitor->setBracketClosePosition(pntClose);
+ m_itemPackage.st_FBX_Monitor->setBracketOpenPosition(pntOpen);
+ m_itemPackage.st_FBX_Monitor->setHeadingPosition(pntHead);
+
+
+ if (pntClose[1] >= 35) { //35 = y position
+ m_thtimer_initMonitorSetFinalPosition->stop();
+ //now init mask of labels
+ m_thtimer_initMonitorSetMasks->start();
+ }
+
+ m_itemPackage.st_ThreadMonitorDataNode->Modified();
+ m_itemPackage.st_MultiWidget->RequestUpdate();
+
+}
+
+void QmitkFiberThreadMonitorWorker::fancyMonitorInitializationMask()
+{
+ //increase opacity
+ int opacity = m_itemPackage.st_FBX_Monitor->getMaskOpacity();
+ opacity++;
+ m_itemPackage.st_FBX_Monitor->setMaskOpacity(opacity);
+ m_itemPackage.st_FBX_Monitor->setStartedOpacity(opacity);
+ m_itemPackage.st_FBX_Monitor->setFinishedOpacity(opacity);
+ m_itemPackage.st_FBX_Monitor->setTerminatedOpacity(opacity);
+ m_itemPackage.st_FBX_Monitor->setStatusOpacity(opacity);
+
+ if (opacity >=10) {
+ m_thtimer_initMonitorSetMasks->stop();
+ }
+
+ m_itemPackage.st_ThreadMonitorDataNode->Modified();
+ m_itemPackage.st_MultiWidget->RequestUpdate();
+
+}
//==============================================
//======== W O R K E R S ________ E N D ========
//==============================================
-// ========= HERE STARTS THE ACTUAL FIBERBUNDLE DEVELOPER VIEW IMPLEMENTATION ======
+// ========= HERE STARTS THE ACTUAL FIBERB2UNDLE DEVELOPER VIEW IMPLEMENTATION ======
const std::string QmitkFiberBundleDeveloperView::VIEW_ID = "org.mitk.views.fiberbundledeveloper";
const std::string id_DataManager = "org.mitk.views.datamanager";
using namespace berry;
QmitkFiberBundleDeveloperView::QmitkFiberBundleDeveloperView()
: QmitkFunctionality()
, m_Controls( 0 )
, m_MultiWidget( NULL )
+, m_FiberIDGenerator( NULL)
+, m_GeneratorFibersRandom( NULL )
+, m_fiberMonitorIsOn( false )
{
m_hostThread = new QThread;
m_threadInProgress = false;
}
// Destructor
QmitkFiberBundleDeveloperView::~QmitkFiberBundleDeveloperView()
{
//m_FiberBundleX->Delete(); using weakPointer, therefore no delete necessary
delete m_hostThread;
if (m_FiberIDGenerator != NULL)
delete m_FiberIDGenerator;
if (m_GeneratorFibersRandom != NULL)
delete m_GeneratorFibersRandom;
}
void QmitkFiberBundleDeveloperView::CreateQtPartControl( QWidget *parent )
{
// build up qt view, unless already done in QtDesigner, etc.
if ( !m_Controls )
{
// create GUI widgets from the Qt Designer's .ui file
m_Controls = new Ui::QmitkFiberBundleDeveloperViewControls;
m_Controls->setupUi( parent );
/*=========INITIALIZE BUTTON CONFIGURATION ================*/
m_Controls->radioButton_directionX->setEnabled(false);
m_Controls->radioButton_directionY->setEnabled(false);
m_Controls->radioButton_directionZ->setEnabled(false);
m_Controls->buttonGenerateFiberIds->setEnabled(false);
m_Controls->buttonGenerateFibers->setEnabled(true);
m_Controls->buttonColorFibers->setEnabled(false);//not yet implemented
m_Controls->buttonSMFibers->setEnabled(false);//not yet implemented
m_Controls->buttonVtkDecimatePro->setEnabled(false);//not yet implemented
m_Controls->buttonVtkSmoothPD->setEnabled(false);//not yet implemented
m_Controls->buttonGenerateTubes->setEnabled(false);//not yet implemented
-
+
connect( m_Controls->buttonGenerateFibers, SIGNAL(clicked()), this, SLOT(DoGenerateFibers()) );
connect( m_Controls->buttonGenerateFiberIds, SIGNAL(pressed()), this, SLOT(DoGenerateFiberIDs()) );
connect( m_Controls->radioButton_directionRandom, SIGNAL(clicked()), this, SLOT(DoUpdateGenerateFibersWidget()) );
connect( m_Controls->radioButton_directionX, SIGNAL(clicked()), this, SLOT(DoUpdateGenerateFibersWidget()) );
connect( m_Controls->radioButton_directionY, SIGNAL(clicked()), this, SLOT(DoUpdateGenerateFibersWidget()) );
connect( m_Controls->radioButton_directionZ, SIGNAL(clicked()), this, SLOT(DoUpdateGenerateFibersWidget()) );
connect( m_Controls->toolBox, SIGNAL(currentChanged ( int ) ), this, SLOT(SelectionChangedToolBox(int)) );
connect( m_Controls->checkBoxMonitorFiberThreads, SIGNAL(stateChanged(int)), this, SLOT(DoMonitorFiberThreads(int)) );
}
// Checkpoint for fiber ORIENTATION
if ( m_DirectionRadios.empty() )
{
m_DirectionRadios.insert(0, m_Controls->radioButton_directionRandom);
m_DirectionRadios.insert(1, m_Controls->radioButton_directionX);
m_DirectionRadios.insert(2, m_Controls->radioButton_directionY);
m_DirectionRadios.insert(3, m_Controls->radioButton_directionZ);
}
// set GUI elements of FiberGenerator to according configuration
DoUpdateGenerateFibersWidget();
}
/* THIS METHOD UPDATES ALL GUI ELEMENTS OF QGroupBox DEPENDING ON CURRENTLY SELECTED
* RADIO BUTTONS
*/
void QmitkFiberBundleDeveloperView::DoUpdateGenerateFibersWidget()
{
//get selected radioButton
QString fibDirection; //stores the object_name of selected radiobutton
QVector<QRadioButton*>::const_iterator i;
for (i = m_DirectionRadios.begin(); i != m_DirectionRadios.end(); ++i)
{
QRadioButton* rdbtn = *i;
if (rdbtn->isChecked())
fibDirection = rdbtn->objectName();
}
if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_RANDOM ) {
// disable radiobuttons
if (m_Controls->boxFiberMinLength->isEnabled())
m_Controls->boxFiberMinLength->setEnabled(false);
if (m_Controls->labelFiberMinLength->isEnabled())
m_Controls->labelFiberMinLength->setEnabled(false);
if (m_Controls->boxFiberMaxLength->isEnabled())
m_Controls->boxFiberMaxLength->setEnabled(false);
if (m_Controls->labelFiberMaxLength->isEnabled())
m_Controls->labelFiberMaxLength->setEnabled(false);
//enable radiobuttons
if (!m_Controls->labelFibersTotal->isEnabled())
m_Controls->labelFibersTotal->setEnabled(true);
if (!m_Controls->boxFiberNumbers->isEnabled())
m_Controls->boxFiberNumbers->setEnabled(true);
if (!m_Controls->labelDistrRadius->isEnabled())
m_Controls->labelDistrRadius->setEnabled(true);
if (!m_Controls->boxDistributionRadius->isEnabled())
m_Controls->boxDistributionRadius->setEnabled(true);
} else {
// disable radiobuttons
if (m_Controls->labelDistrRadius->isEnabled())
m_Controls->labelDistrRadius->setEnabled(false);
if (m_Controls->boxDistributionRadius->isEnabled())
m_Controls->boxDistributionRadius->setEnabled(false);
//enable radiobuttons
if (!m_Controls->labelFibersTotal->isEnabled())
m_Controls->labelFibersTotal->setEnabled(true);
if (!m_Controls->boxFiberNumbers->isEnabled())
m_Controls->boxFiberNumbers->setEnabled(true);
if (!m_Controls->boxFiberMinLength->isEnabled())
m_Controls->boxFiberMinLength->setEnabled(true);
if (!m_Controls->labelFiberMinLength->isEnabled())
m_Controls->labelFiberMinLength->setEnabled(true);
if (!m_Controls->boxFiberMaxLength->isEnabled())
m_Controls->boxFiberMaxLength->setEnabled(true);
if (!m_Controls->labelFiberMaxLength->isEnabled())
m_Controls->labelFiberMaxLength->setEnabled(true);
}
}
void QmitkFiberBundleDeveloperView::DoGenerateFibers()
{
// GET SELECTED FIBER DIRECTION
QString fibDirection; //stores the object_name of selected radiobutton
QVector<QRadioButton*>::const_iterator i;
for (i = m_DirectionRadios.begin(); i != m_DirectionRadios.end(); ++i)
{
QRadioButton* rdbtn = *i;
if (rdbtn->isChecked())
fibDirection = rdbtn->objectName();
}
// vtkPolyData* output; // FiberPD stores the generated PolyData... going to be generated in thread
if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_RANDOM ) {
// build polydata with random lines and fibers
// output =
GenerateVtkFibersRandom();
} else if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_X ) {
// build polydata with XDirection fibers
//output = GenerateVtkFibersDirectionX();
} else if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_Y ) {
// build polydata with YDirection fibers
// output = GenerateVtkFibersDirectionY();
} else if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_Z ) {
// build polydata with ZDirection fibers
// output = GenerateVtkFibersDirectionZ();
}
}
void QmitkFiberBundleDeveloperView::PutFibersToDataStorage( vtkPolyData* threadOutput)
{
- MITK_INFO << "YEHAAAAAAAAA WHAT A GREAT DAY!!!!!!";
MITK_INFO << "lines: " << threadOutput->GetNumberOfLines() << "pnts: " << threadOutput->GetNumberOfPoints();
//qthread mutex lock
mitk::FiberBundleX::Pointer FB = mitk::FiberBundleX::New();
FB->SetFibers(threadOutput);
FB->SetGeometry(this->GenerateStandardGeometryForMITK());
mitk::DataNode::Pointer FBNode;
FBNode = mitk::DataNode::New();
FBNode->SetName("FiberBundleX");
FBNode->SetData(FB);
FBNode->SetVisibility(true);
GetDataStorage()->Add(FBNode);
//output->Delete();
const mitk::PlaneGeometry * tsgeo = m_MultiWidget->GetTimeNavigationController()->GetCurrentPlaneGeometry();
if (tsgeo == NULL) {
/* GetDataStorage()->Modified etc. have no effect, therefore proceed as followed below */
// get all nodes that have not set "includeInBoundingBox" to false
mitk::NodePredicateNot::Pointer pred = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("includeInBoundingBox"
, mitk::BoolProperty::New(false)));
mitk::DataStorage::SetOfObjects::ConstPointer rs = GetDataStorage()->GetSubset(pred);
// calculate bounding geometry of these nodes
mitk::TimeSlicedGeometry::Pointer bounds = GetDataStorage()->ComputeBoundingGeometry3D(rs);
// initialize the views to the bounding geometry
mitk::RenderingManager::GetInstance()->InitializeViews(bounds);
} else {
GetDataStorage()->Modified();
m_MultiWidget->RequestUpdate(); //necessary??
}
//qthread mutex unlock
}
/*
* Generate polydata of random fibers
*/
void QmitkFiberBundleDeveloperView::GenerateVtkFibersRandom()
{
/* ===== TIMER CONFIGURATIONS for visual effect ======
* start and stop is called in Thread */
QTimer *localTimer = new QTimer; // timer must be initialized here, otherwise timer is not fancy enough
localTimer->setInterval( 10 );
connect( localTimer, SIGNAL(timeout()), this, SLOT(UpdateGenerateRandomFibersTimer()) );
struct Package4WorkingThread ItemPackageForRandomGenerator;
ItemPackageForRandomGenerator.st_FBX = m_FiberBundleX;
ItemPackageForRandomGenerator.st_Controls = m_Controls;
ItemPackageForRandomGenerator.st_FancyGUITimer1 = localTimer;
ItemPackageForRandomGenerator.st_host = this;
ItemPackageForRandomGenerator.st_pntr_to_Method_PutFibersToDataStorage = &QmitkFiberBundleDeveloperView::PutFibersToDataStorage;
+ //set element for thread monitoring
+ if (m_fiberMonitorIsOn)
+ ItemPackageForRandomGenerator.st_fiberThreadMonitorWorker = m_fiberThreadMonitorWorker;
+
+
if (m_threadInProgress)
return; //maybe popup window saying, working thread still in progress...pls wait
m_GeneratorFibersRandom = new QmitkFiberGenerateRandomWorker(m_hostThread, ItemPackageForRandomGenerator);
m_GeneratorFibersRandom->moveToThread(m_hostThread);
connect(m_hostThread, SIGNAL(started()), this, SLOT( BeforeThread_GenerateFibersRandom()) );
connect(m_hostThread, SIGNAL(started()), m_GeneratorFibersRandom, SLOT(run()) );
connect(m_hostThread, SIGNAL(finished()), this, SLOT(AfterThread_GenerateFibersRandom()) );
connect(m_hostThread, SIGNAL(terminated()), this, SLOT(AfterThread_GenerateFibersRandom()) );
m_hostThread->start(QThread::LowestPriority);
}
void QmitkFiberBundleDeveloperView::UpdateGenerateRandomFibersTimer()
{
//MAKE SURE by yourself THAT NOTHING ELSE THAN A NUMBER IS SET IN THAT LABEL
QString crntValue = m_Controls->infoTimerGenerateFiberBundle->text();
int tmpVal = crntValue.toInt();
m_Controls->infoTimerGenerateFiberBundle->setText(QString::number(++tmpVal));
m_Controls->infoTimerGenerateFiberBundle->update();
-
+
}
void QmitkFiberBundleDeveloperView::BeforeThread_GenerateFibersRandom()
{
- m_threadInProgress = true;
+ m_threadInProgress = true;
+ if (m_fiberMonitorIsOn){
+ m_fiberThreadMonitorWorker->threadForFiberProcessingStarted();
+ //m_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_STARTED);
+ }
}
void QmitkFiberBundleDeveloperView::AfterThread_GenerateFibersRandom()
{
m_threadInProgress = false;
+ if (m_fiberMonitorIsOn){
+ m_fiberThreadMonitorWorker->threadForFiberProcessingFinished();
+ m_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_IDLE);
+ }
disconnect(m_hostThread, 0, 0, 0);
m_hostThread->disconnect();
+
+
}
vtkSmartPointer<vtkPolyData> QmitkFiberBundleDeveloperView::GenerateVtkFibersDirectionX()
{
int numOfFibers = m_Controls->boxFiberNumbers->value();
vtkSmartPointer<vtkCellArray> linesCell = vtkSmartPointer<vtkCellArray>::New();
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
//insert Origin point, this point has index 0 in point array
double originX = 0.0;
double originY = 0.0;
double originZ = 0.0;
//after each iteration the origin of the new fiber increases
//here you set which direction is affected.
double increaseX = 0.0;
double increaseY = 1.0;
double increaseZ = 0.0;
//walk along X axis
//length of fibers increases in each iteration
for (int i=0; i<numOfFibers; ++i) {
vtkSmartPointer<vtkPolyLine> newFiber = vtkSmartPointer<vtkPolyLine>::New();
newFiber->GetPointIds()->SetNumberOfIds(i+2);
//create starting point and add it to pointset
points->InsertNextPoint(originX + (double)i * increaseX , originY + (double)i * increaseY, originZ + (double)i * increaseZ);
//add starting point to fiber
newFiber->GetPointIds()->SetId(0,points->GetNumberOfPoints()-1);
//insert remaining points for fiber
for (int pj=0; pj<=i ; ++pj)
{ //generate next point on X axis
points->InsertNextPoint( originX + (double)pj+1 , originY + (double)i * increaseY, originZ + (double)i * increaseZ );
newFiber->GetPointIds()->SetId(pj+1,points->GetNumberOfPoints()-1);
}
linesCell->InsertNextCell(newFiber);
}
vtkSmartPointer<vtkPolyData> PDX = vtkSmartPointer<vtkPolyData>::New();
PDX->SetPoints(points);
PDX->SetLines(linesCell);
return PDX;
}
vtkSmartPointer<vtkPolyData> QmitkFiberBundleDeveloperView::GenerateVtkFibersDirectionY()
{
vtkSmartPointer<vtkPolyData> PDY = vtkSmartPointer<vtkPolyData>::New();
//todo
return PDY;
}
vtkSmartPointer<vtkPolyData> QmitkFiberBundleDeveloperView::GenerateVtkFibersDirectionZ()
{
vtkSmartPointer<vtkPolyData> PDZ = vtkSmartPointer<vtkPolyData>::New();
//todo
return PDZ;
}
/* === OutSourcedMethod: THIS METHOD GENERATES ESSENTIAL GEOMETRY PARAMETERS FOR THE MITK FRAMEWORK ===
* WITHOUT, the rendering mechanism will ignore objects without valid Geometry
* for each object, MITK requires: ORIGIN, SPACING, TRANSFORM MATRIX, BOUNDING-BOX */
mitk::Geometry3D::Pointer QmitkFiberBundleDeveloperView::GenerateStandardGeometryForMITK()
{
mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New();
// generate origin
mitk::Point3D origin;
origin[0] = 0;
origin[1] = 0;
origin[2] = 0;
geometry->SetOrigin(origin);
// generate spacing
float spacing[3] = {1,1,1};
geometry->SetSpacing(spacing);
// generate identity transform-matrix
vtkMatrix4x4* m = vtkMatrix4x4::New();
geometry->SetIndexToWorldTransformByVtkMatrix(m);
// generate boundingbox
// for an usable bounding-box use gui parameters to estimate the boundingbox
float bounds[] = {500, 500, 500, -500, -500, -500};
// GET SELECTED FIBER DIRECTION
QString fibDirection; //stores the object_name of selected radiobutton
QVector<QRadioButton*>::const_iterator i;
for (i = m_DirectionRadios.begin(); i != m_DirectionRadios.end(); ++i)
{
QRadioButton* rdbtn = *i;
if (rdbtn->isChecked())
fibDirection = rdbtn->objectName();
}
if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_RANDOM ) {
// use information about distribution parameter to calculate bounding box
int distrRadius = m_Controls->boxDistributionRadius->value();
bounds[0] = distrRadius;
bounds[1] = distrRadius;
bounds[2] = distrRadius;
bounds[3] = -distrRadius;
bounds[4] = -distrRadius;
bounds[5] = -distrRadius;
} else {
// so far only X,Y,Z directions are available
MITK_INFO << "_______GEOMETRY ISSUE_____\n***BoundingBox for X, Y, Z fiber directions are not optimized yet!***";
int maxFibLength = m_Controls->boxFiberMaxLength->value();
bounds[0] = maxFibLength;
bounds[1] = maxFibLength;
bounds[2] = maxFibLength;
bounds[3] = -maxFibLength;
bounds[4] = -maxFibLength;
bounds[5] = -maxFibLength;
}
geometry->SetFloatBounds(bounds);
geometry->SetImageGeometry(true); //??
return geometry;
}
void QmitkFiberBundleDeveloperView::UpdateFiberIDTimer()
{
//MAKE SURE by yourself THAT NOTHING ELSE THAN A NUMBER IS SET IN THAT LABEL
QString crntValue = m_Controls->infoTimerGenerateFiberIds->text();
int tmpVal = crntValue.toInt();
m_Controls->infoTimerGenerateFiberIds->setText(QString::number(++tmpVal));
m_Controls->infoTimerGenerateFiberIds->update();
}
/* Initialie ID dataset in FiberBundleX */
void QmitkFiberBundleDeveloperView::DoGenerateFiberIDs()
{
/* ===== TIMER CONFIGURATIONS for visual effect ======
* start and stop is called in Thread */
QTimer *localTimer = new QTimer; // timer must be initialized here, otherwise timer is not fancy enough
localTimer->setInterval( 10 );
connect( localTimer, SIGNAL(timeout()), this, SLOT(UpdateFiberIDTimer()) );
// pack items which are needed by thread processing
struct Package4WorkingThread FiberIdPackage;
FiberIdPackage.st_FBX = m_FiberBundleX;
FiberIdPackage.st_FancyGUITimer1 = localTimer;
FiberIdPackage.st_Controls = m_Controls;
+ //set element for thread monitoring
+ if (m_fiberMonitorIsOn)
+ FiberIdPackage.st_fiberThreadMonitorWorker = m_fiberThreadMonitorWorker;
+
if (m_threadInProgress)
return; //maybe popup window saying, working thread still in progress...pls wait
// THREAD CONFIGURATION
m_FiberIDGenerator = new QmitkFiberIDWorker(m_hostThread, FiberIdPackage);
m_FiberIDGenerator->moveToThread(m_hostThread);
connect(m_hostThread, SIGNAL(started()), this, SLOT( BeforeThread_IdGenerate()) );
connect(m_hostThread, SIGNAL(started()), m_FiberIDGenerator, SLOT(run()));
connect(m_hostThread, SIGNAL(finished()), this, SLOT(AfterThread_IdGenerate()));
connect(m_hostThread, SIGNAL(terminated()), this, SLOT(AfterThread_IdGenerate()));
m_hostThread->start(QThread::LowestPriority);
// m_Controls->infoTimerGenerateFiberIds->setText(QString::number(clock.GetTotal()));
}
void QmitkFiberBundleDeveloperView::BeforeThread_IdGenerate()
{
m_threadInProgress = true;
-
+ if (m_fiberMonitorIsOn){
+ m_fiberThreadMonitorWorker->threadForFiberProcessingStarted();
+ m_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_STARTED);
+ }
}
void QmitkFiberBundleDeveloperView::AfterThread_IdGenerate()
{
-
-
m_threadInProgress = false;
+ if (m_fiberMonitorIsOn){
+ m_fiberThreadMonitorWorker->threadForFiberProcessingFinished();
+ m_fiberThreadMonitorWorker->setThreadStatus(FBX_STATUS_IDLE);
+ }
disconnect(m_hostThread, 0, 0, 0);
m_hostThread->disconnect();
}
-/* THE WORKER ACCESS THIS METHOD TO PASS GENERATED FIBERBUNDLE
- * TO DATASTORAGE */
-void QmitkFiberBundleDeveloperView::SetGeneratedFBX()
-{
-
-
-
-}
void QmitkFiberBundleDeveloperView::ResetFiberInfoWidget()
{
if (m_Controls->infoAnalyseNumOfFibers->isEnabled()) {
m_Controls->infoAnalyseNumOfFibers->setText("-");
m_Controls->infoAnalyseNumOfPoints->setText("-");
m_Controls->infoAnalyseNumOfFibers->setEnabled(false);
}
}
void QmitkFiberBundleDeveloperView::FeedFiberInfoWidget()
{
if (!m_Controls->infoAnalyseNumOfFibers->isEnabled())
m_Controls->infoAnalyseNumOfFibers->setEnabled(true);
QString numOfFibers;
numOfFibers.setNum( m_FiberBundleX->GetFibers()->GetNumberOfLines() );
QString numOfPoints;
numOfPoints.setNum( m_FiberBundleX->GetFibers()->GetNumberOfPoints() );
m_Controls->infoAnalyseNumOfFibers->setText( numOfFibers );
m_Controls->infoAnalyseNumOfPoints->setText( numOfPoints );
}
void QmitkFiberBundleDeveloperView::SelectionChangedToolBox(int idx)
{
MITK_INFO << "printtoolbox: " << idx;
if (m_Controls->page_FiberInfo->isVisible() && m_FiberBundleX != NULL)
{
FeedFiberInfoWidget();
} else {
//if infolables are disabled: return
//else set info back to - and set label and info to disabled
if (!m_Controls->page_FiberInfo->isVisible()) {
return;
} else {
ResetFiberInfoWidget();
}
}
}
void QmitkFiberBundleDeveloperView::FBXDependendGUIElementsConfigurator(bool isVisible)
{
// ==== FIBER PROCESSING ELEMENTS ======
m_Controls->buttonGenerateFiberIds->setEnabled(isVisible);
}
void QmitkFiberBundleDeveloperView::DoMonitorFiberThreads(int checkStatus)
{
//check if in datanode exists already a node of type mitkFiberBundleXThreadMonitor
//if not then put node to datastorage
//if checkStatus is 1 then start qtimer using fading in starting text in datanode
//if checkStatus is 0 then fade out dataNode using qtimer
if (checkStatus)
{
- mitk::FiberBundleXThreadMonitor::Pointer FBXThreadMonitor = mitk::FiberBundleXThreadMonitor::New();
+ m_fiberMonitorIsOn = true;
+ // Generate Node hosting thread information
+ mitk::FiberBundleXThreadMonitor::Pointer FBXThreadMonitor = mitk::FiberBundleXThreadMonitor::New();
FBXThreadMonitor->SetGeometry(this->GenerateStandardGeometryForMITK());
- m_MonitorNode = mitk::DataNode::New();
- m_MonitorNode->SetName("FBX_threadMonitor");
- m_MonitorNode->SetData(FBXThreadMonitor);
- m_MonitorNode->SetVisibility(true);
- m_MonitorNode->SetOpacity(1.0);
-
- GetDataStorage()->Add(m_MonitorNode);
-
- const mitk::PlaneGeometry * tsgeo = m_MultiWidget->GetTimeNavigationController()->GetCurrentPlaneGeometry();
- if (tsgeo == NULL) {
- /* GetDataStorage()->Modified etc. have no effect, therefore proceed as followed below */
- // get all nodes that have not set "includeInBoundingBox" to false
- mitk::NodePredicateNot::Pointer pred = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New( "includeInBoundingBox"
- , mitk::BoolProperty::New(false)));
- mitk::DataStorage::SetOfObjects::ConstPointer rs = GetDataStorage()->GetSubset(pred);
- // calculate bounding geometry of these nodes
- mitk::TimeSlicedGeometry::Pointer bounds = GetDataStorage()->ComputeBoundingGeometry3D(rs);
- // initialize the views to the bounding geometry
- mitk::RenderingManager::GetInstance()->InitializeViews(bounds);
- } else {
- GetDataStorage()->Modified();
- m_MultiWidget->RequestUpdate(); //necessary??
- }
-
-
+ m_MonitorNode = mitk::DataNode::New();
+ m_MonitorNode->SetName("FBX_threadMonitor");
+ m_MonitorNode->SetData(FBXThreadMonitor);
+ m_MonitorNode->SetVisibility(true);
+ m_MonitorNode->SetOpacity(1.0);
+
+ GetDataStorage()->Add(m_MonitorNode);
+
+ //following code is needed for rendering text in mitk! without geometry nothing is rendered
+ const mitk::PlaneGeometry * tsgeo = m_MultiWidget->GetTimeNavigationController()->GetCurrentPlaneGeometry();
+ if (tsgeo == NULL) {
+ /* GetDataStorage()->Modified etc. have no effect, therefore proceed as followed below */
+ // get all nodes that have not set "includeInBoundingBox" to false
+ mitk::NodePredicateNot::Pointer pred = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New( "includeInBoundingBox"
+ , mitk::BoolProperty::New(false)));
+ mitk::DataStorage::SetOfObjects::ConstPointer rs = GetDataStorage()->GetSubset(pred);
+ // calculate bounding geometry of these nodes
+ mitk::TimeSlicedGeometry::Pointer bounds = GetDataStorage()->ComputeBoundingGeometry3D(rs);
+ // initialize the views to the bounding geometry
+ mitk::RenderingManager::GetInstance()->InitializeViews(bounds);
+ } else {
+
+ GetDataStorage()->Modified();
+ m_MultiWidget->RequestUpdate(); //necessary??
+ }
+ //__GEOMETRY FOR THREADMONITOR GENERATED
+
+ /* ====== initialize thread for managing fiberThread information ========= */
+ m_monitorThread = new QThread;
+ // the package needs datastorage, MonitorDatanode, standardmultiwidget,
+ struct Package4WorkingThread ItemPackageForThreadMonitor;
+ ItemPackageForThreadMonitor.st_DataStorage = GetDataStorage();
+ ItemPackageForThreadMonitor.st_ThreadMonitorDataNode = m_MonitorNode;
+ ItemPackageForThreadMonitor.st_MultiWidget = m_MultiWidget;
+ ItemPackageForThreadMonitor.st_FBX_Monitor = FBXThreadMonitor;
+
+ m_fiberThreadMonitorWorker = new QmitkFiberThreadMonitorWorker(m_monitorThread, ItemPackageForThreadMonitor);
+
+ m_fiberThreadMonitorWorker->moveToThread(m_monitorThread);
+ connect ( m_monitorThread, SIGNAL( started() ), m_fiberThreadMonitorWorker, SLOT( run() ) );
+ m_monitorThread->start(QThread::LowestPriority);
+ m_fiberThreadMonitorWorker->initializeMonitor();//do some init animation ;-)
+
+
} else {
+ m_fiberMonitorIsOn = false;
+
+ m_monitorThread->quit();
+ //think about outsourcing following lines to quit / terminate slot of thread
GetDataStorage()->Remove(m_MonitorNode);
GetDataStorage()->Modified();
m_MultiWidget->RequestUpdate(); //necessary??
}
+
}
void QmitkFiberBundleDeveloperView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget)
{
m_MultiWidget = &stdMultiWidget;
}
void QmitkFiberBundleDeveloperView::StdMultiWidgetNotAvailable()
{
m_MultiWidget = NULL;
}
/* OnSelectionChanged is registered to SelectionService, therefore no need to
implement SelectionService Listener explicitly */
void QmitkFiberBundleDeveloperView::OnSelectionChanged( std::vector<mitk::DataNode*> nodes )
{
/* ==== reset everyhing related to FiberBundleX ======
* - variable m_FiberBundleX
* - visualization of analysed fiberbundle
*/
m_FiberBundleX = NULL; //reset pointer, so that member does not point to depricated locations
ResetFiberInfoWidget();
- FBXDependendGUIElementsConfigurator(false);
- m_Controls->infoTimerGenerateFiberIds->setText("-"); //set GUI representation of timer to -
- m_Controls->infoTimerGenerateFiberBundle->setText( "-" );
+ FBXDependendGUIElementsConfigurator(false); //every gui element which needs a FBX for processing is disabled
+
+ //timer reset only when no thread is in progress
+ if (!m_threadInProgress) {
+ m_Controls->infoTimerGenerateFiberIds->setText("-"); //set GUI representation of timer to -
+ m_Controls->infoTimerGenerateFiberBundle->setText( "-" );
+ }
//====================================================
if (nodes.empty())
return;
for( std::vector<mitk::DataNode*>::iterator it = nodes.begin(); it != nodes.end(); ++it )
{
mitk::DataNode::Pointer node = *it;
/* CHECKPOINT: FIBERBUNDLE*/
if( node.IsNotNull() && dynamic_cast<mitk::FiberBundleX*>(node->GetData()) )
{
m_FiberBundleX = dynamic_cast<mitk::FiberBundleX*>(node->GetData());
if (m_FiberBundleX == NULL)
MITK_INFO << "========ATTENTION=========\n unable to load selected FiberBundleX to FiberBundleDeveloper-plugin \n";
// ==== FIBERBUNDLE_INFO ELEMENTS ====
if ( m_Controls->page_FiberInfo->isVisible() )
FeedFiberInfoWidget();
// enable FiberBundleX related Gui Elements, such as buttons etc.
FBXDependendGUIElementsConfigurator(true);
}
}
}
void QmitkFiberBundleDeveloperView::Activated()
{
MITK_INFO << "FB DevelopersV ACTIVATED()";
}
diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperView.h b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperView.h
index 956a72ba70..989d530d0d 100644
--- a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperView.h
+++ b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperView.h
@@ -1,233 +1,289 @@
/*=========================================================================
-
-Program: Medical Imaging & Interaction Toolkit
-Language: C++
-Date: $Date: 2010-03-31 16:40:27 +0200 (Mi, 31 Mrz 2010) $
-Version: $Revision: 21975 $
-
-Copyright (c) German Cancer Research Center, Division of Medical and
-Biological Informatics. All rights reserved.
-See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
-
-This software is distributed WITHOUT ANY WARRANTY; without even
-the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-PURPOSE. See the above copyright notices for more information.
-
-=========================================================================*/
+
+ Program: Medical Imaging & Interaction Toolkit
+ Language: C++
+ Date: $Date: 2010-03-31 16:40:27 +0200 (Mi, 31 Mrz 2010) $
+ Version: $Revision: 21975 $
+
+ Copyright (c) German Cancer Research Center, Division of Medical and
+ Biological Informatics. All rights reserved.
+ See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the above copyright notices for more information.
+
+ =========================================================================*/
#ifndef QmitkFiberBundleDeveloperView_h
#define QmitkFiberBundleDeveloperView_h
#include <berryISelectionListener.h>
#include <berryIStructuredSelection.h>
#include <QmitkFunctionality.h>
#include "ui_QmitkFiberBundleDeveloperViewControls.h"
#include <mitkDataStorage.h>
#include <mitkDataStorageSelection.h>
#include <mitkWeakPointer.h>
+#include <mitkFiberBundleXThreadMonitor.h>
// Qt
#include <QVector>
#include <QRadioButton>
#include <QString>
// VTK
#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <mitkFiberBundleX.h>
#include <mitkFiberBundleX.h>
#include <QTimer>
#include <QThread>
+class QmitkFiberThreadMonitorWorker; //include needed for struct element
class QmitkFiberBundleDeveloperView; //this include is needed for the struct element, especially for functors to QmitkFiberBundleDeveloperView
/* ==== THIS STRUCT CONTAINS ALL NECESSARY VARIABLES
* TO EXECUTE AND UPDATE GUI ELEMENTS DURING PROCESSING OF A THREAD
* why? either you add tons of friendclasses (e.g. FiberWorker objects), or you create a package containing all items needed. Otherwise you have to set all members etc. to public!
*/
struct Package4WorkingThread
{
mitk::FiberBundleX* st_FBX;
QTimer* st_FancyGUITimer1;
Ui::QmitkFiberBundleDeveloperViewControls* st_Controls;
+
+
//functors to outdoor methods
QmitkFiberBundleDeveloperView* st_host;
void (QmitkFiberBundleDeveloperView::*st_pntr_to_Method_PutFibersToDataStorage) (vtkPolyData*);
+ //==DO NOT TOUCH THIS SECTION===
+ //host MITK I/O elements, especially needed for thread monitoring
+ QmitkFiberThreadMonitorWorker *st_fiberThreadMonitorWorker;
+ mitk::FiberBundleXThreadMonitor::Pointer st_FBX_Monitor; //needed for direct access do animation/fancy methods
+ mitk::DataNode::Pointer st_ThreadMonitorDataNode; //needed for renderer to recognize node modifications
+ mitk::DataStorage::Pointer st_DataStorage; //well that is discussable if needed ;-) probably not
+ QmitkStdMultiWidget* st_MultiWidget; //needed for rendering update
+
};
// ====================================================================
// ============= WORKER WHICH IS PASSED TO THREAD =====================
// ====================================================================
//## Documentation
//## This class does the actual work for generating fiber ids.
class QmitkFiberIDWorker : public QObject
{
Q_OBJECT
public:
-
QmitkFiberIDWorker( QThread*, Package4WorkingThread );
public slots:
-
void run();
private:
- //mitk::FiberBundleX* m_FBX;
-
Package4WorkingThread m_itemPackage;
QThread* m_hostingThread;
};
// ====================================================================
// ============= WORKER WHICH IS PASSED TO THREAD =====================
// ====================================================================
class QmitkFiberGenerateRandomWorker : public QObject
{
Q_OBJECT
public:
-
QmitkFiberGenerateRandomWorker( QThread*, Package4WorkingThread );
public slots:
-
void run();
private:
- //mitk::FiberBundleX* m_FBX;
-
Package4WorkingThread m_itemPackage;
QThread* m_hostingThread;
};
+class QmitkFiberThreadMonitorWorker : public QObject
+{
+ Q_OBJECT
+
+public:
+
+
+ QmitkFiberThreadMonitorWorker( QThread*, Package4WorkingThread );
+
+ void initializeMonitor();
+ void threadForFiberProcessingStarted();
+ void threadForFiberProcessingFinished();
+ void threadForFiberProcessingTerminated();
+ void setThreadStatus(QString);
+
+
+ public slots:
+ void run();
+ void fancyMonitorInitialization();
+ void fancyMonitorInitializationFinalPos();
+ void fancyMonitorInitializationMask();
+ void fancyTextFading_threadStarted();
+ void fancyTextFading_threadFinished();
+ void fancyTextFading_threadTerminated();
+
+private:
+ Package4WorkingThread m_itemPackage;
+ QThread* m_hostingThread;
+ QTimer* m_thtimer_initMonitor;
+ QTimer* m_thtimer_initMonitorSetFinalPosition;
+ QTimer* m_thtimer_initMonitorSetMasks;
+ QTimer* m_thtimer_threadStarted;
+ QTimer* m_thtimer_threadFinished;
+ QTimer* m_thtimer_threadTerminated;
+
+ // flags for fancy fading
+ bool m_decreaseOpacity_threadStarted;
+ bool m_decreaseOpacity_threadFinished;
+ bool m_decreaseOpacity_threadTerminated;
+
+ // members for fancy animation
+ int m_pixelstepper;
+ int m_steppingDistance;
+
+
+};
+// strings to display fiber_thread monitor
+const QString FBX_STATUS_IDLE = "idle";
+const QString FBX_STATUS_STARTED = "starting";
+const QString FBX_STATUS_RUNNING = "running";
// ========= HERE STARTS THE ACTUAL FIBERBUNDLE DEVELOPER VIEW =======
const QString FIB_RADIOBUTTON_DIRECTION_RANDOM = "radioButton_directionRandom";
const QString FIB_RADIOBUTTON_DIRECTION_X = "radioButton_directionX";
const QString FIB_RADIOBUTTON_DIRECTION_Y = "radioButton_directionY";
const QString FIB_RADIOBUTTON_DIRECTION_Z = "radioButton_directionZ";
/*!
-\brief QmitkFiberBundleView
-
-\warning This application module is not yet documented. Use "svn blame/praise/annotate" and ask the author to provide basic documentation.
-
-\sa QmitkFunctionality
-\ingroup Functionalities
-*/
+ \brief QmitkFiberBundleView
+
+ \warning This application module is not yet documented. Use "svn blame/praise/annotate" and ask the author to provide basic documentation.
+
+ \sa QmitkFunctionality
+ \ingroup Functionalities
+ */
class QmitkFiberBundleDeveloperView : 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;
-
+
QmitkFiberBundleDeveloperView();
virtual ~QmitkFiberBundleDeveloperView();
-
+
virtual void CreateQtPartControl(QWidget *parent);
-
+
virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget);
virtual void StdMultiWidgetNotAvailable();
virtual void Activated();
-
+
protected slots:
void DoGenerateFibers();
void DoGenerateFiberIDs();
void DoUpdateGenerateFibersWidget();
void SelectionChangedToolBox(int);
void DoMonitorFiberThreads(int);
//SLOTS FOR THREADS
void BeforeThread_IdGenerate();
void AfterThread_IdGenerate();
void BeforeThread_GenerateFibersRandom();
void AfterThread_GenerateFibersRandom();
//SLOTS FOR TIMERS
void UpdateFiberIDTimer();
void UpdateGenerateRandomFibersTimer();
-
+
protected:
-
+
/// \brief called by QmitkFunctionality when DataManager's selection has changed
virtual void OnSelectionChanged( std::vector<mitk::DataNode*> nodes );
-
+
Ui::QmitkFiberBundleDeveloperViewControls* m_Controls;
-
+
QmitkStdMultiWidget* m_MultiWidget;
-
-
-
- private:
+
+
+
+private:
/* METHODS GENERATING FIBERSTRUCTURES */
void GenerateVtkFibersRandom();
vtkSmartPointer<vtkPolyData> GenerateVtkFibersDirectionX();
vtkSmartPointer<vtkPolyData> GenerateVtkFibersDirectionY();
vtkSmartPointer<vtkPolyData> GenerateVtkFibersDirectionZ();
-
+
void PutFibersToDataStorage( vtkPolyData* );
/* METHODS FOR FIBER PROCESSING OR PREPROCESSING */
-
+
/* HELPERMETHODS */
mitk::Geometry3D::Pointer GenerateStandardGeometryForMITK();
void ResetFiberInfoWidget();
void FeedFiberInfoWidget();
void FBXDependendGUIElementsConfigurator(bool);
void SetGeneratedFBX();
//contains the selected FiberBundle
//mitk::FiberBundleX* m_FiberBundleX;
mitk::WeakPointer<mitk::FiberBundleX> m_FiberBundleX;
-// radiobutton groups
+ // radiobutton groups
QVector< QRadioButton* > m_DirectionRadios;
QVector< QRadioButton* > m_FARadios;
QVector< QRadioButton* > m_GARadios;
// Thread based Workers which do some processing of fibers
QmitkFiberIDWorker * m_FiberIDGenerator;
QmitkFiberGenerateRandomWorker * m_GeneratorFibersRandom;
QThread * m_hostThread;
+ QThread * m_monitorThread;
bool m_threadInProgress;
mitk::DataNode::Pointer m_MonitorNode;
+ QmitkFiberThreadMonitorWorker *m_fiberThreadMonitorWorker;
+ bool m_fiberMonitorIsOn;
-
};
#endif // _QMITKFIBERTRACKINGVIEW_H_INCLUDED
diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperViewControls.ui b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperViewControls.ui
index a060497d1d..63db98fc7d 100644
--- a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperViewControls.ui
+++ b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleDeveloperViewControls.ui
@@ -1,843 +1,846 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QmitkFiberBundleDeveloperViewControls</class>
<widget class="QWidget" name="QmitkFiberBundleDeveloperViewControls">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>405</width>
<height>753</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QToolBox" name="toolBox">
<property name="font">
<font>
<pointsize>12</pointsize>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="page_FiberGenerator">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>366</width>
<height>449</height>
</rect>
</property>
<attribute name="label">
<string>Fiber Generator</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_8">
<item row="2" column="0">
<widget class="QTabWidget" name="tabWidget_2">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Fiber Bundles</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_12">
<item row="3" column="0">
<widget class="QCommandLinkButton" name="buttonGenerateFibers">
<property name="text">
<string>Generate Fiberbundle</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QGroupBox" name="groupBox_5">
<property name="title">
<string>Fiber Parameters</string>
</property>
<layout class="QGridLayout" name="gridLayout_11">
<item row="2" column="0">
<widget class="QLabel" name="labelFibersTotal">
<property name="font">
<font>
<pointsize>11</pointsize>
</font>
</property>
<property name="text">
<string>Total number of Fibers</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="boxFiberNumbers">
<property name="font">
<font>
<pointsize>10</pointsize>
</font>
</property>
<property name="maximum">
<number>999999999</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
<item row="2" column="4">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="4" column="0">
<widget class="QLabel" name="labelDistrRadius">
<property name="font">
<font>
<pointsize>11</pointsize>
</font>
</property>
<property name="text">
<string>Distribution Radius</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSpinBox" name="boxDistributionRadius">
<property name="font">
<font>
<pointsize>10</pointsize>
</font>
</property>
+ <property name="maximum">
+ <number>9999</number>
+ </property>
<property name="value">
- <number>99</number>
+ <number>100</number>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="labelFiberMaxLength">
<property name="font">
<font>
<pointsize>11</pointsize>
</font>
</property>
<property name="text">
<string>Fiber Length Max (points)</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QSpinBox" name="boxFiberMaxLength">
<property name="font">
<font>
<pointsize>10</pointsize>
</font>
</property>
<property name="value">
<number>50</number>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="labelFiberMinLength">
<property name="font">
<font>
<pointsize>11</pointsize>
</font>
</property>
<property name="text">
<string>Fiber Length Min (points)</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QSpinBox" name="boxFiberMinLength">
<property name="font">
<font>
<pointsize>10</pointsize>
</font>
</property>
<property name="value">
<number>10</number>
</property>
</widget>
</item>
</layout>
<zorder>labelFibersTotal</zorder>
<zorder>boxFiberNumbers</zorder>
<zorder>horizontalSpacer_3</zorder>
<zorder>labelDistrRadius</zorder>
<zorder>boxDistributionRadius</zorder>
<zorder>labelFiberMaxLength</zorder>
<zorder>boxFiberMaxLength</zorder>
<zorder>labelFiberMinLength</zorder>
<zorder>boxFiberMinLength</zorder>
</widget>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="font">
<font>
<pointsize>11</pointsize>
</font>
</property>
<property name="title">
<string>Fiber Orientation</string>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<item row="3" column="1">
<widget class="QRadioButton" name="radioButton_directionZ">
<property name="text">
<string>along Z Axis</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QRadioButton" name="radioButton_directionX">
<property name="text">
<string>along X Axis</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QRadioButton" name="radioButton_directionRandom">
<property name="text">
<string>random</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QRadioButton" name="radioButton_directionY">
<property name="text">
<string>along Y Axis</string>
</property>
</widget>
</item>
<item row="2" column="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="6" column="0">
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="0">
<widget class="QFrame" name="frame_3">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QFormLayout" name="formLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="labelTimerGenerateFiberBundle">
<property name="font">
<font>
<pointsize>10</pointsize>
</font>
</property>
<property name="text">
<string>Time:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="infoTimerGenerateFiberBundle">
<property name="font">
<font>
<pointsize>10</pointsize>
</font>
</property>
<property name="text">
<string>-</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_3">
<attribute name="title">
<string>DWI Values</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_13">
<item row="1" column="0">
<widget class="QGroupBox" name="groupBox_6">
<property name="title">
<string>GA Values</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QRadioButton" name="radioButton_2">
<property name="text">
<string>no values</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="GAlabel">
<property name="text">
<string>nothing yet implemented</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox_4">
<property name="font">
<font>
<pointsize>11</pointsize>
</font>
</property>
<property name="title">
<string>FA Values</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="1">
<widget class="QRadioButton" name="radioButton_FAconst">
<property name="text">
<string>const value</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QDoubleSpinBox" name="boxFAupper">
<property name="enabled">
<bool>false</bool>
</property>
<property name="font">
<font>
<pointsize>10</pointsize>
</font>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QRadioButton" name="radioButton_6">
<property name="text">
<string>random range</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QDoubleSpinBox" name="boxFAlower">
<property name="enabled">
<bool>false</bool>
</property>
<property name="font">
<font>
<pointsize>10</pointsize>
</font>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="radioButton_FAnoValue">
<property name="text">
<string>no values</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QDoubleSpinBox" name="boxFAconst">
<property name="enabled">
<bool>false</bool>
</property>
<property name="font">
<font>
<pointsize>10</pointsize>
</font>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_4">
<attribute name="title">
<string>Page</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Select a FiberBundle in Datamanager</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item row="3" column="0">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_FiberProcessing">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
- <width>366</width>
+ <width>307</width>
<height>403</height>
</rect>
</property>
<attribute name="label">
<string>Fiber Processor</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_9">
<item row="0" column="1">
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>2</number>
</property>
<widget class="QWidget" name="tabColoring">
<attribute name="title">
<string>Colors</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_6">
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox_8">
<property name="title">
<string>Fiber Coloring</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QCommandLinkButton" name="buttonColorFibers">
<property name="text">
<string>Color Fibers</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabSmoothing">
<attribute name="title">
<string>Shape</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_7">
<item row="3" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox_7">
<property name="title">
<string>Fiber Smoothing</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="4" column="0">
<widget class="QCommandLinkButton" name="buttonSMFibers">
<property name="text">
<string>Smooth Fibers</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QRadioButton" name="radioButton_SMstatic_2">
<property name="text">
<string>static value</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="radioButton_SMrelative">
<property name="text">
<string>relative in%</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="boxSMrelativeValue">
<property name="enabled">
<bool>false</bool>
</property>
<property name="font">
<font>
<pointsize>10</pointsize>
</font>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QRadioButton" name="radioButton">
<property name="text">
<string>none</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="boxSMstaticValue">
<property name="enabled">
<bool>false</bool>
</property>
<property name="font">
<font>
<pointsize>10</pointsize>
</font>
</property>
<property name="maximum">
<number>9999</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="1">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>vtkFilters</string>
</property>
<layout class="QGridLayout" name="gridLayout_10">
<item row="3" column="0">
<widget class="QCommandLinkButton" name="buttonGenerateTubes">
<property name="text">
<string>Tubes</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCommandLinkButton" name="buttonVtkDecimatePro">
<property name="text">
<string>vtkDecimatePro</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCommandLinkButton" name="buttonVtkSmoothPD">
<property name="text">
<string>vtkSmoothPolyDataFilter</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Cutting</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_15">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Step1: Generate Fibers IDs in FBX</string>
</property>
</widget>
</item>
<item row="5" column="0">
<spacer name="verticalSpacer_8">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0">
<widget class="QFrame" name="frame_2">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QFormLayout" name="formLayout_2">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::FieldsStayAtSizeHint</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="labelTimerGenerateFiberIds">
<property name="font">
<font>
<pointsize>10</pointsize>
</font>
</property>
<property name="text">
<string>Timer:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="infoTimerGenerateFiberIds">
<property name="font">
<font>
<pointsize>10</pointsize>
</font>
</property>
<property name="text">
<string>-</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QCommandLinkButton" name="buttonGenerateFiberIds">
<property name="text">
<string>Execute Step1</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_FiberInfo">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
- <width>381</width>
- <height>249</height>
+ <width>185</width>
+ <height>116</height>
</rect>
</property>
<attribute name="label">
<string>FiberInfo</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_14">
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox_9">
<property name="title">
<string>General Information</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="labelAnalyseNumOfFibers">
<property name="text">
<string>Number of Fibers:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="infoAnalyseNumOfFibers">
<property name="text">
<string>-</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelAnalyseNumOfPoints">
<property name="text">
<string>Number of Points:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="infoAnalyseNumOfPoints">
<property name="text">
<string>-</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<spacer name="verticalSpacer_7">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxMonitorFiberThreads">
<property name="text">
<string>Monitor Fiber Threading in mitkRenderWindow4</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_6">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources>
<include location="../../resources/QmitkDiffusionImaging.qrc"/>
</resources>
<connections/>
</ui>
diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleOperationsView.cpp b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleOperationsView.cpp
index 569b06eb18..e360eaf64d 100644
--- a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleOperationsView.cpp
+++ b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleOperationsView.cpp
@@ -1,1904 +1,1875 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date: 2010-03-31 16:40:27 +0200 (Mi, 31 Mrz 2010) $
Version: $Revision: 21975 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
// Qmitk
#include "QmitkFiberBundleOperationsView.h"
#include "QmitkStdMultiWidget.h"
// Qt
#include <QMessageBox>
//MITK
#include "mitkNodePredicateProperty.h"
//#include "mitkNodePredicateAND.h"
#include "mitkImageCast.h"
#include "mitkPointSet.h"
#include "mitkPlanarCircle.h"
#include "mitkPlanarPolygon.h"
#include <mitkPlanarRectangle.h>
#include "mitkPlanarFigureInteractor.h"
#include "mitkGlobalInteraction.h"
#include <mitkImageAccessByItk.h>
#include <itkResampleImageFilter.h>
#include <itkGaussianInterpolateImageFunction.h>
#include <itkImageRegionIteratorWithIndex.h>
#include <itkTractsToDWIImageFilter.h>
#include <itkTractsToFiberEndingsImageFilter.h>
#include <itkTractsToProbabilityImageFilter.h>
#include <mitkDiffusionImage.h>
#include <mitkDataNodeObject.h>
+#include <itkImageRegion.h>
const std::string QmitkFiberBundleOperationsView::VIEW_ID = "org.mitk.views.fiberbundleoperations";
const std::string id_DataManager = "org.mitk.views.datamanager";
using namespace berry;
using namespace mitk;
struct FboSelListener : ISelectionListener
{
berryObjectMacro(FboSelListener);
FboSelListener(QmitkFiberBundleOperationsView* view)
{
m_View = view;
}
void DoSelectionChanged(ISelection::ConstPointer selection)
{
// save current selection in member variable
m_View->m_CurrentSelection = selection.Cast<const IStructuredSelection>();
// do something with the selected items
if(m_View->m_CurrentSelection)
{
bool foundFiberBundle = false;
std::string classname = "FiberBundle";
// iterate selection
for (IStructuredSelection::iterator i = m_View->m_CurrentSelection->Begin();
i != m_View->m_CurrentSelection->End(); ++i)
{
// extract datatree node
if (mitk::DataNodeObject::Pointer nodeObj = i->Cast<mitk::DataNodeObject>())
{
mitk::DataNode::Pointer node = nodeObj->GetDataNode();
std::string fname = node->GetData()->GetNameOfClass();
if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
{
foundFiberBundle = true;
}
}
}
if(foundFiberBundle)
{
m_View->m_Controls->m_CircleButton->setEnabled(true);
m_View->m_Controls->m_PolygonButton->setEnabled(true);
m_View->m_Controls->m_RectangleButton->setEnabled(true);
}
else{
m_View->m_Controls->m_CircleButton->setEnabled(false);
m_View->m_Controls->m_PolygonButton->setEnabled(false);
m_View->m_Controls->m_RectangleButton->setEnabled(false);
}
}
}
void SelectionChanged(IWorkbenchPart::Pointer part, ISelection::ConstPointer selection)
{
// check, if selection comes from datamanager
if (part)
{
QString partname(part->GetPartName().c_str());
if(partname.compare("Datamanager")==0)
{
// apply selection
DoSelectionChanged(selection);
}
}
}
QmitkFiberBundleOperationsView* m_View;
};
QmitkFiberBundleOperationsView::QmitkFiberBundleOperationsView()
: QmitkFunctionality()
, m_Controls( 0 )
, m_MultiWidget( NULL )
, m_EllipseCounter(0)
, m_PolygonCounter(0)
//, m_SelectedFBNodes( NULL )
//, m_SelectedPFNodes(0)
, m_UpsamplingFactor(5)
{
}
// Destructor
QmitkFiberBundleOperationsView::~QmitkFiberBundleOperationsView()
{
}
void QmitkFiberBundleOperationsView::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::QmitkFiberBundleOperationsViewControls;
m_Controls->setupUi( parent );
m_Controls->doExtractFibersButton->setDisabled(true);
m_Controls->PFCompoANDButton->setDisabled(true);
m_Controls->PFCompoORButton->setDisabled(true);
m_Controls->PFCompoNOTButton->setDisabled(true);
m_Controls->PFCompoDELButton->setDisabled(true);
m_Controls->m_CircleButton->setEnabled(false);
m_Controls->m_PolygonButton->setEnabled(false);
m_Controls->m_RectangleButton->setEnabled(false);
connect( m_Controls->doExtractFibersButton, SIGNAL(clicked()), this, SLOT(DoFiberExtraction()) );
//connect( m_Controls->comboBox_fiberAlgo, SIGNAL(selected()), this, SLOT(handleAlgoSelection() );
connect( m_Controls->m_CircleButton, SIGNAL( clicked() ), this, SLOT( ActionDrawEllipseTriggered() ) );
connect( m_Controls->m_PolygonButton, SIGNAL( clicked() ), this, SLOT( ActionDrawPolygonTriggered() ) );
connect(m_Controls->PFCompoANDButton, SIGNAL(clicked()), this, SLOT(generatePFCompo_AND()) );
connect(m_Controls->PFCompoORButton, SIGNAL(clicked()), this, SLOT(generatePFCompo_OR()) );
connect(m_Controls->PFCompoNOTButton, SIGNAL(clicked()), this, SLOT(generatePFCompo_NOT()) );
connect(m_Controls->PFCompoDELButton, SIGNAL(clicked()), this, SLOT(deletePFCompo()) );
connect(m_Controls->m_JoinBundles, SIGNAL(clicked()), this, SLOT(JoinBundles()) );
connect(m_Controls->m_SubstractBundles, SIGNAL(clicked()), this, SLOT(SubstractBundles()) );
connect(m_Controls->m_GenerateROIImage, SIGNAL(clicked()), this, SLOT(GenerateROIImage()) );
connect( m_Controls->m_GenerationStartButton, SIGNAL(clicked()), this, SLOT(GenerationStart()) );
}
m_SelListener = berry::ISelectionListener::Pointer(new FboSelListener(this));
this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->AddPostSelectionListener(/*"org.mitk.views.datamanager",*/ m_SelListener);
berry::ISelection::ConstPointer sel(
this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager"));
m_CurrentSelection = sel.Cast<const IStructuredSelection>();
m_SelListener.Cast<FboSelListener>()->DoSelectionChanged(sel);
}
void QmitkFiberBundleOperationsView::GenerateROIImage(){
if (m_Image.IsNull() || m_SelectedPF.empty())
return;
mitk::Image* image = const_cast<mitk::Image*>(m_Image.GetPointer());
MaskImage3DType::Pointer temp = MaskImage3DType::New();
mitk::CastToItkImage<MaskImage3DType>(m_Image, temp);
m_PlanarFigureImage = MaskImage3DType::New();
m_PlanarFigureImage->SetSpacing( temp->GetSpacing() ); // Set the image spacing
m_PlanarFigureImage->SetOrigin( temp->GetOrigin() ); // Set the image origin
m_PlanarFigureImage->SetDirection( temp->GetDirection() ); // Set the image direction
m_PlanarFigureImage->SetRegions( temp->GetLargestPossibleRegion() );
m_PlanarFigureImage->Allocate();
m_PlanarFigureImage->FillBuffer( 0 );
for (int i=0; i<m_SelectedPF.size(); i++)
- CompositeExtraction(dynamic_cast<mitk::PlanarFigure*>(m_SelectedPF.at(i)->GetData()), image);
+ CompositeExtraction(m_SelectedPF.at(i), image);
DataNode::Pointer node = DataNode::New();
Image::Pointer tmpImage = Image::New();
tmpImage->InitializeByItk(m_PlanarFigureImage.GetPointer());
tmpImage->SetVolume(m_PlanarFigureImage->GetBufferPointer());
node->SetData(tmpImage);
node->SetName("planarFigureImage");
this->GetDefaultDataStorage()->Add(node);
}
-void QmitkFiberBundleOperationsView::CompositeExtraction(mitk::PlanarFigure::Pointer planarFigure, mitk::Image* image)
+void QmitkFiberBundleOperationsView::CompositeExtraction(mitk::DataNode::Pointer node, mitk::Image* image)
{
- if (dynamic_cast<mitk::PlanarFigureComposite*>(planarFigure.GetPointer())){
- mitk::PlanarFigureComposite::Pointer pfcomp = dynamic_cast<mitk::PlanarFigureComposite*>(planarFigure.GetPointer());
-
- for (int i=0; i<pfcomp->getNumberOfChildren(); ++i)
- {
- CompositeExtraction(pfcomp->getChildAt(i), image);
- }
- }
- else
+ if (dynamic_cast<mitk::PlanarFigure*>(node.GetPointer()->GetData()) && !dynamic_cast<mitk::PlanarFigureComposite*>(node.GetPointer()->GetData()))
{
- m_PlanarFigure = planarFigure;
- AccessFixedDimensionByItk_3(
+ m_PlanarFigure = dynamic_cast<mitk::PlanarFigure*>(node.GetPointer()->GetData());
+ AccessFixedDimensionByItk_2(
image,
InternalReorientImagePlane, 3,
- image->GetGeometry(),
m_PlanarFigure->GetGeometry(), -1);
- AccessFixedDimensionByItk_1(
+// itk::Image< unsigned char, 3 >::Pointer outimage = itk::Image< unsigned char, 3 >::New();
+
+// outimage->SetSpacing( m_PlanarFigure->GetGeometry()->GetSpacing()/m_UpsamplingFactor ); // Set the image spacing
+
+// mitk::Point3D origin = m_PlanarFigure->GetGeometry()->GetOrigin();
+// mitk::Point3D indexOrigin;
+// m_PlanarFigure->GetGeometry()->WorldToIndex(origin, indexOrigin);
+// indexOrigin[0] = indexOrigin[0] - .5 * (1.0-1.0/m_UpsamplingFactor);
+// indexOrigin[1] = indexOrigin[1] - .5 * (1.0-1.0/m_UpsamplingFactor);
+// indexOrigin[2] = indexOrigin[2] - .5 * (1.0-1.0/m_UpsamplingFactor);
+// mitk::Point3D newOrigin;
+// m_PlanarFigure->GetGeometry()->IndexToWorld(indexOrigin, newOrigin);
+
+// outimage->SetOrigin( newOrigin ); // Set the image origin
+// itk::Matrix<double, 3, 3> matrix;
+// for (int i=0; i<3; i++)
+// for (int j=0; j<3; j++)
+// matrix[j][i] = m_PlanarFigure->GetGeometry()->GetMatrixColumn(i)[j]/m_PlanarFigure->GetGeometry()->GetSpacing().GetElement(i);
+// outimage->SetDirection( matrix ); // Set the image direction
+
+// itk::ImageRegion<3> upsampledRegion;
+// upsampledRegion.SetSize(0, m_PlanarFigure->GetGeometry()->GetParametricExtentInMM(0)/m_PlanarFigure->GetGeometry()->GetSpacing()[0]);
+// upsampledRegion.SetSize(1, m_PlanarFigure->GetGeometry()->GetParametricExtentInMM(1)/m_PlanarFigure->GetGeometry()->GetSpacing()[1]);
+// upsampledRegion.SetSize(2, 1);
+
+// typename itk::Image< unsigned char, 3 >::RegionType::SizeType upsampledSize = upsampledRegion.GetSize();
+// for (unsigned int n = 0; n < 2; n++)
+// {
+// upsampledSize[n] = upsampledSize[n] * m_UpsamplingFactor;
+// }
+// upsampledRegion.SetSize( upsampledSize );
+// outimage->SetRegions( upsampledRegion );
+
+// outimage->Allocate();
+
+// this->m_InternalImage = mitk::Image::New();
+// this->m_InternalImage->InitializeByItk( outimage.GetPointer() );
+// this->m_InternalImage->SetVolume( outimage->GetBufferPointer() );
+
+ AccessFixedDimensionByItk_2(
m_InternalImage,
InternalCalculateMaskFromPlanarFigure,
- 3, 2 );
+ 3, 2, node->GetName() );
}
}
template < typename TPixel, unsigned int VImageDimension >
void QmitkFiberBundleOperationsView::InternalReorientImagePlane(
- const itk::Image< TPixel, VImageDimension > *image,
- mitk::Geometry3D* imggeo, mitk::Geometry3D* planegeo3D, int additionalIndex )
+ const itk::Image< TPixel, VImageDimension > *image, mitk::Geometry3D* planegeo3D, int additionalIndex )
{
MITK_INFO << "InternalReorientImagePlane() start";
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::Image< float, VImageDimension > FloatImageType;
typedef itk::ResampleImageFilter<ImageType, FloatImageType, double> ResamplerType;
typename ResamplerType::Pointer resampler = ResamplerType::New();
mitk::PlaneGeometry* planegeo = dynamic_cast<mitk::PlaneGeometry*>(planegeo3D);
float upsamp = m_UpsamplingFactor;
float gausssigma = 0.5;
// Spacing
typename ResamplerType::SpacingType spacing = planegeo->GetSpacing();
spacing[0] = image->GetSpacing()[0] / upsamp;
spacing[1] = image->GetSpacing()[1] / upsamp;
spacing[2] = image->GetSpacing()[2];
resampler->SetOutputSpacing( spacing );
// Size
typename ResamplerType::SizeType size;
size[0] = planegeo->GetParametricExtentInMM(0) / spacing[0];
size[1] = planegeo->GetParametricExtentInMM(1) / spacing[1];
size[2] = 1;
resampler->SetSize( size );
// Origin
typename mitk::Point3D orig = planegeo->GetOrigin();
typename mitk::Point3D corrorig;
planegeo3D->WorldToIndex(orig,corrorig);
corrorig[0] += 0.5/upsamp;
corrorig[1] += 0.5/upsamp;
corrorig[2] += 0;
planegeo3D->IndexToWorld(corrorig,corrorig);
resampler->SetOutputOrigin(corrorig );
// Direction
typename ResamplerType::DirectionType direction;
typename mitk::AffineTransform3D::MatrixType matrix = planegeo->GetIndexToWorldTransform()->GetMatrix();
for(int c=0; c<matrix.ColumnDimensions; c++)
{
double sum = 0;
for(int r=0; r<matrix.RowDimensions; r++)
{
sum += matrix(r,c)*matrix(r,c);
}
for(int r=0; r<matrix.RowDimensions; r++)
{
direction(r,c) = matrix(r,c)/sqrt(sum);
}
}
resampler->SetOutputDirection( direction );
// Gaussian interpolation
if(gausssigma != 0)
{
double sigma[3];
for( unsigned int d = 0; d < 3; d++ )
{
sigma[d] = gausssigma * image->GetSpacing()[d];
}
double alpha = 2.0;
typedef itk::GaussianInterpolateImageFunction<ImageType, double>
GaussianInterpolatorType;
typename GaussianInterpolatorType::Pointer interpolator
= GaussianInterpolatorType::New();
interpolator->SetInputImage( image );
interpolator->SetParameters( sigma, alpha );
resampler->SetInterpolator( interpolator );
}
else
{
// typedef typename itk::BSplineInterpolateImageFunction<ImageType, double>
// InterpolatorType;
typedef typename itk::LinearInterpolateImageFunction<ImageType, double> InterpolatorType;
typename InterpolatorType::Pointer interpolator
= InterpolatorType::New();
interpolator->SetInputImage( image );
resampler->SetInterpolator( interpolator );
}
// Other resampling options
resampler->SetInput( image );
resampler->SetDefaultPixelValue(0);
MITK_INFO << "Resampling requested image plane ... ";
resampler->Update();
MITK_INFO << " ... done";
if(additionalIndex < 0)
{
this->m_InternalImage = mitk::Image::New();
this->m_InternalImage->InitializeByItk( resampler->GetOutput() );
this->m_InternalImage->SetVolume( resampler->GetOutput()->GetBufferPointer() );
}
}
template < typename TPixel, unsigned int VImageDimension >
void QmitkFiberBundleOperationsView::InternalCalculateMaskFromPlanarFigure(
- itk::Image< TPixel, VImageDimension > *image, unsigned int axis )
+ itk::Image< TPixel, VImageDimension > *image, unsigned int axis, std::string nodeName )
{
MITK_INFO << "InternalCalculateMaskFromPlanarFigure() start";
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::CastImageFilter< ImageType, MaskImage3DType > CastFilterType;
// Generate mask image as new image with same header as input image and
// initialize with "1".
MaskImage3DType::Pointer newMaskImage = MaskImage3DType::New();
newMaskImage->SetSpacing( image->GetSpacing() ); // Set the image spacing
newMaskImage->SetOrigin( image->GetOrigin() ); // Set the image origin
newMaskImage->SetDirection( image->GetDirection() ); // Set the image direction
newMaskImage->SetRegions( image->GetLargestPossibleRegion() );
newMaskImage->Allocate();
newMaskImage->FillBuffer( 1 );
// Generate VTK polygon from (closed) PlanarFigure polyline
// (The polyline points are shifted by -0.5 in z-direction to make sure
// that the extrusion filter, which afterwards elevates all points by +0.5
// in z-direction, creates a 3D object which is cut by the the plane z=0)
const Geometry2D *planarFigureGeometry2D = m_PlanarFigure->GetGeometry2D();
const PlanarFigure::PolyLineType planarFigurePolyline = m_PlanarFigure->GetPolyLine( 0 );
const Geometry3D *imageGeometry3D = m_InternalImage->GetGeometry( 0 );
vtkPolyData *polyline = vtkPolyData::New();
polyline->Allocate( 1, 1 );
// Determine x- and y-dimensions depending on principal axis
int i0, i1;
switch ( axis )
{
case 0:
i0 = 1;
i1 = 2;
break;
case 1:
i0 = 0;
i1 = 2;
break;
case 2:
default:
i0 = 0;
i1 = 1;
break;
}
// Create VTK polydata object of polyline contour
vtkPoints *points = vtkPoints::New();
PlanarFigure::PolyLineType::const_iterator it;
std::vector<vtkIdType> indices;
unsigned int numberOfPoints = 0;
for ( it = planarFigurePolyline.begin();
it != planarFigurePolyline.end();
++it )
{
Point3D point3D;
// Convert 2D point back to the local index coordinates of the selected
// image
Point2D point2D = it->Point;
planarFigureGeometry2D->WorldToIndex(point2D, point2D);
point2D[0] -= 0.5/m_UpsamplingFactor;
point2D[1] -= 0.5/m_UpsamplingFactor;
planarFigureGeometry2D->IndexToWorld(point2D, point2D);
planarFigureGeometry2D->Map( point2D, point3D );
// Polygons (partially) outside of the image bounds can not be processed
// further due to a bug in vtkPolyDataToImageStencil
if ( !imageGeometry3D->IsInside( point3D ) )
{
float bounds[2] = {0,0};
bounds[0] =
this->m_InternalImage->GetLargestPossibleRegion().GetSize().GetElement(i0);
bounds[1] =
this->m_InternalImage->GetLargestPossibleRegion().GetSize().GetElement(i1);
imageGeometry3D->WorldToIndex( point3D, point3D );
if (point3D[i0]<0)
point3D[i0] = 0.5;
else if (point3D[i0]>bounds[0])
point3D[i0] = bounds[0]-0.5;
if (point3D[i1]<0)
point3D[i1] = 0.5;
else if (point3D[i1]>bounds[1])
point3D[i1] = bounds[1]-0.5;
points->InsertNextPoint( point3D[i0], point3D[i1], -0.5 );
numberOfPoints++;
}
else
{
imageGeometry3D->WorldToIndex( point3D, point3D );
point3D[i0] += 0.5;
point3D[i1] += 0.5;
// Add point to polyline array
points->InsertNextPoint( point3D[i0], point3D[i1], -0.5 );
numberOfPoints++;
}
}
polyline->SetPoints( points );
points->Delete();
vtkIdType *ptIds = new vtkIdType[numberOfPoints];
for ( vtkIdType i = 0; i < numberOfPoints; ++i )
{
ptIds[i] = i;
}
polyline->InsertNextCell( VTK_POLY_LINE, numberOfPoints, ptIds );
// Extrude the generated contour polygon
vtkLinearExtrusionFilter *extrudeFilter = vtkLinearExtrusionFilter::New();
extrudeFilter->SetInput( polyline );
extrudeFilter->SetScaleFactor( 1 );
extrudeFilter->SetExtrusionTypeToNormalExtrusion();
extrudeFilter->SetVector( 0.0, 0.0, 1.0 );
// Make a stencil from the extruded polygon
vtkPolyDataToImageStencil *polyDataToImageStencil = vtkPolyDataToImageStencil::New();
polyDataToImageStencil->SetInput( extrudeFilter->GetOutput() );
// Export from ITK to VTK (to use a VTK filter)
typedef itk::VTKImageImport< MaskImage3DType > ImageImportType;
typedef itk::VTKImageExport< MaskImage3DType > ImageExportType;
typename ImageExportType::Pointer itkExporter = ImageExportType::New();
itkExporter->SetInput( newMaskImage );
vtkImageImport *vtkImporter = vtkImageImport::New();
this->ConnectPipelines( itkExporter, vtkImporter );
vtkImporter->Update();
// Apply the generated image stencil to the input image
vtkImageStencil *imageStencilFilter = vtkImageStencil::New();
imageStencilFilter->SetInputConnection( vtkImporter->GetOutputPort() );
imageStencilFilter->SetStencil( polyDataToImageStencil->GetOutput() );
imageStencilFilter->ReverseStencilOff();
imageStencilFilter->SetBackgroundValue( 0 );
imageStencilFilter->Update();
// Export from VTK back to ITK
vtkImageExport *vtkExporter = vtkImageExport::New();
vtkExporter->SetInputConnection( imageStencilFilter->GetOutputPort() );
vtkExporter->Update();
typename ImageImportType::Pointer itkImporter = ImageImportType::New();
this->ConnectPipelines( vtkExporter, itkImporter );
itkImporter->Update();
// calculate cropping bounding box
m_InternalImageMask3D = itkImporter->GetOutput();
m_InternalImageMask3D->SetDirection(image->GetDirection());
itk::ImageRegionConstIterator<MaskImage3DType>
itmask(m_InternalImageMask3D, m_InternalImageMask3D->GetLargestPossibleRegion());
itk::ImageRegionIterator<ImageType>
itimage(image, image->GetLargestPossibleRegion());
itmask = itmask.Begin();
itimage = itimage.Begin();
typename ImageType::SizeType lowersize = {{9999999999,9999999999,9999999999}};
typename ImageType::SizeType uppersize = {{0,0,0}};
while( !itmask.IsAtEnd() )
{
if(itmask.Get() == 0)
{
itimage.Set(0);
}
else
{
typename ImageType::IndexType index = itimage.GetIndex();
typename ImageType::SizeType signedindex;
signedindex[0] = index[0];
signedindex[1] = index[1];
signedindex[2] = index[2];
lowersize[0] = signedindex[0] < lowersize[0] ? signedindex[0] : lowersize[0];
lowersize[1] = signedindex[1] < lowersize[1] ? signedindex[1] : lowersize[1];
lowersize[2] = signedindex[2] < lowersize[2] ? signedindex[2] : lowersize[2];
uppersize[0] = signedindex[0] > uppersize[0] ? signedindex[0] : uppersize[0];
uppersize[1] = signedindex[1] > uppersize[1] ? signedindex[1] : uppersize[1];
uppersize[2] = signedindex[2] > uppersize[2] ? signedindex[2] : uppersize[2];
}
++itmask;
++itimage;
}
typename ImageType::IndexType index;
index[0] = lowersize[0];
index[1] = lowersize[1];
index[2] = lowersize[2];
typename ImageType::SizeType size;
size[0] = uppersize[0] - lowersize[0] + 1;
size[1] = uppersize[1] - lowersize[1] + 1;
size[2] = uppersize[2] - lowersize[2] + 1;
itk::ImageRegion<3> cropRegion = itk::ImageRegion<3>(index, size);
// // crop internal image
// typedef itk::RegionOfInterestImageFilter< ImageType, ImageType > ROIFilterType;
// typename ROIFilterType::Pointer roi = ROIFilterType::New();
// roi->SetRegionOfInterest(cropRegion);
// roi->SetInput(image);
// roi->Update();
// m_InternalImage = mitk::Image::New();
// m_InternalImage->InitializeByItk(roi->GetOutput());
// m_InternalImage->SetVolume(roi->GetOutput()->GetBufferPointer());
// crop internal mask
typedef itk::RegionOfInterestImageFilter< MaskImage3DType, MaskImage3DType > ROIMaskFilterType;
typename ROIMaskFilterType::Pointer roi2 = ROIMaskFilterType::New();
roi2->SetRegionOfInterest(cropRegion);
roi2->SetInput(m_InternalImageMask3D);
roi2->Update();
m_InternalImageMask3D = roi2->GetOutput();
- DataNode::Pointer node = DataNode::New();
+// DataNode::Pointer node = DataNode::New();
Image::Pointer tmpImage = Image::New();
tmpImage->InitializeByItk(m_InternalImageMask3D.GetPointer());
tmpImage->SetVolume(m_InternalImageMask3D->GetBufferPointer());
- node->SetData(tmpImage);
- this->GetDefaultDataStorage()->Add(node);
+// node->SetData(tmpImage);
+// node->SetName(nodeName);
+// GetDefaultDataStorage()->Add(node);
Image::Pointer tmpImage2 = Image::New();
tmpImage2->InitializeByItk(m_PlanarFigureImage.GetPointer());
const Geometry3D *pfImageGeometry3D = tmpImage2->GetGeometry( 0 );
const Geometry3D *intImageGeometry3D = tmpImage->GetGeometry( 0 );
typedef itk::ImageRegionIteratorWithIndex<MaskImage3DType> IteratorType;
IteratorType imageIterator (m_InternalImageMask3D, m_InternalImageMask3D->GetRequestedRegion());
imageIterator.GoToBegin();
while ( !imageIterator.IsAtEnd() )
{
unsigned char val = imageIterator.Value();
if (val>0)
{
itk::Index<3> index = imageIterator.GetIndex();
Point3D point;
point[0] = index[0];
point[1] = index[1];
point[2] = index[2];
intImageGeometry3D->IndexToWorld(point, point);
pfImageGeometry3D->WorldToIndex(point, point);
index[0] = point[0];
index[1] = point[1];
index[2] = point[2];
m_PlanarFigureImage->SetPixel(index, 1);
}
++imageIterator;
}
// Clean up VTK objects
polyline->Delete();
extrudeFilter->Delete();
polyDataToImageStencil->Delete();
vtkImporter->Delete();
imageStencilFilter->Delete();
//vtkExporter->Delete(); // TODO: crashes when outcommented; memory leak??
delete[] ptIds;
}
void QmitkFiberBundleOperationsView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget)
{
m_MultiWidget = &stdMultiWidget;
}
void QmitkFiberBundleOperationsView::StdMultiWidgetNotAvailable()
{
m_MultiWidget = NULL;
}
/* OnSelectionChanged is registered to SelectionService, therefore no need to
implement SelectionService Listener explicitly */
void QmitkFiberBundleOperationsView::OnSelectionChanged( std::vector<mitk::DataNode*> nodes )
{
-
if ( !this->IsVisible() )
- {
- // do nothing if nobody wants to see me :-(
return;
- }
+ if (nodes.empty())
+ {
+ m_Controls->doExtractFibersButton->setDisabled(true);
+ m_Controls->PFCompoANDButton->setDisabled(true);
+ m_Controls->PFCompoORButton->setDisabled(true);
+ m_Controls->PFCompoNOTButton->setDisabled(true);
+ m_Controls->m_JoinBundles->setEnabled(false);
+ m_Controls->m_SubstractBundles->setEnabled(false);
+ m_Controls->PFCompoDELButton->setDisabled(true);
+ }
//reset existing Vectors containing FiberBundles and PlanarFigures from a previous selection
m_SelectedFB.clear();
m_SelectedPF.clear();
m_Image = NULL;
-
- //differ between 2 scenarios...
- // 1) add PF to an existing Spaghetti
- // 2) BOOLEAN OPERATORS HANDLING ... selection of multiple PF, and or multiple Spaghetti
-
-
- //scenario 1
-
- for( std::vector<mitk::DataNode*>::iterator it = nodes.begin();
- it != nodes.end(); ++it )
+ for( std::vector<mitk::DataNode*>::iterator it = nodes.begin(); it != nodes.end(); ++it )
{
-
mitk::DataNode::Pointer node = *it;
if ( dynamic_cast<mitk::FiberBundle*>(node->GetData()) )
{
- // MITK_INFO << "onselectionchg(): " << node->GetData()->GetNameOfClass();
m_SelectedFB.push_back(node);
mitk::FiberBundle::Pointer bundle = dynamic_cast<mitk::FiberBundle*>(node->GetData());
QString numFibers;
this->m_Controls->m_NumFibersLabel->setText(numFibers.setNum(bundle->GetNumTracts()));
-
- } else if (dynamic_cast<mitk::PlanarFigure*>(node->GetData())){
-
- // MITK_INFO << "onselectionchg(): " << node->GetData()->GetNameOfClass();
+ }
+ else if (dynamic_cast<mitk::PlanarFigure*>(node->GetData()))
m_SelectedPF.push_back(node);
-
- } else if (dynamic_cast<mitk::Image*>(node->GetData())){
+ else if (dynamic_cast<mitk::Image*>(node->GetData()))
m_Image = dynamic_cast<mitk::Image*>(node->GetData());
- }
-
}
if (m_SelectedPF.size() >= 1 && m_Image.IsNotNull())
m_Controls->m_GenerateROIImage->setEnabled(true);
else
m_Controls->m_GenerateROIImage->setEnabled(false);
- //quick and dirty control structure for extraction ATM
- if (m_SelectedPF.size() == 1) {
-
-
- //#############################################
- //### PLANAR FIGURE COMPOSIT SelectionLOGIC ###
- //#############################################
-
+ if (m_SelectedPF.size() == 1)
+ {
m_Controls->PFCompoANDButton->setDisabled(true);
m_Controls->PFCompoORButton->setDisabled(true);
m_Controls->PFCompoNOTButton->setEnabled(true);
m_Controls->PFCompoDELButton->setDisabled(true);
- //if planarFigureComposite selected, activate DEL button
if ( dynamic_cast<mitk::PlanarFigureComposite*>(m_SelectedPF.at(0)->GetData()) )
- {
m_Controls->PFCompoDELButton->setEnabled(true);
- }
-
-
- } else if (m_SelectedPF.size() > 1) {
-
- //#############################################
- //### PLANAR FIGURE COMPOSIT SelectionLOGIC ###
- //#############################################
- // if 2 PlanarFigure objects (PFCircle, PFPoly, ..., PFComposite) selected,
- //then activate AND OR NOT PF Composite Buttons
-
+ }
+ else if (m_SelectedPF.size() > 1)
+ {
m_Controls->PFCompoANDButton->setEnabled(true);
m_Controls->PFCompoORButton->setEnabled(true);
m_Controls->PFCompoNOTButton->setDisabled(true);
m_Controls->PFCompoDELButton->setDisabled(true);
}
-
-
if (m_SelectedFB.size() == 1 && m_SelectedPF.size() == 1)
- {
-
- //#############################################
- //##### EXTRACT FIBERBUNDLE SelectionLOGIC ####
- //#############################################
-
m_Controls->doExtractFibersButton->setEnabled(true);
-
-
- } else if (nodes.size() > 1 ) {
- //scenario 2
-
-
- } else if (nodes.empty()) {
-
- //#############################################
- //##### EXTRACT FIBERBUNDLE SelectionLOGIC ####
- //#############################################
-
- m_Controls->doExtractFibersButton->setDisabled(true);
-
-
- //#############################################
- //### PLANAR FIGURE COMPOSIT SelectionLOGIC ###
- //#############################################
-
- m_Controls->PFCompoANDButton->setDisabled(true);
- m_Controls->PFCompoORButton->setDisabled(true);
- m_Controls->PFCompoNOTButton->setDisabled(true);
-
- }
-
if (m_SelectedFB.size() == 2)
{
-
- //#############################################
- //##### JOIN/SUBSTRACT FIBERBUNDLES ####
- //#############################################
-
m_Controls->m_JoinBundles->setEnabled(true);
m_Controls->m_SubstractBundles->setEnabled(true);
-
}
else
{
-
m_Controls->m_JoinBundles->setEnabled(false);
m_Controls->m_SubstractBundles->setEnabled(false);
-
}
-
}
void QmitkFiberBundleOperationsView::ActionDrawPolygonTriggered()
{
// bool checked = m_Controls->m_PolygonButton->isChecked();
// if(!this->AssertDrawingIsPossible(checked))
// return;
mitk::PlanarPolygon::Pointer figure = mitk::PlanarPolygon::New();
figure->ClosedOn();
this->AddFigureToDataStorage(figure, QString("Polygon%1").arg(++m_PolygonCounter));
MITK_INFO << "PlanarPolygon created ...";
mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet = this->GetDefaultDataStorage()->GetAll();
mitk::DataNode* node = 0;
mitk::PlanarFigureInteractor::Pointer figureInteractor = 0;
mitk::PlanarFigure* figureP = 0;
for(mitk::DataStorage::SetOfObjects::ConstIterator it=_NodeSet->Begin(); it!=_NodeSet->End()
; it++)
{
node = const_cast<mitk::DataNode*>(it->Value().GetPointer());
figureP = dynamic_cast<mitk::PlanarFigure*>(node->GetData());
if(figureP)
{
figureInteractor = dynamic_cast<mitk::PlanarFigureInteractor*>(node->GetInteractor());
if(figureInteractor.IsNull())
figureInteractor = mitk::PlanarFigureInteractor::New("PlanarFigureInteractor", node);
mitk::GlobalInteraction::GetInstance()->AddInteractor(figureInteractor);
}
}
}
void QmitkFiberBundleOperationsView::ActionDrawEllipseTriggered()
{
//bool checked = m_Controls->m_CircleButton->isChecked();
//if(!this->AssertDrawingIsPossible(checked))
// return;
mitk::PlanarCircle::Pointer figure = mitk::PlanarCircle::New();
this->AddFigureToDataStorage(figure, QString("Circle%1").arg(++m_EllipseCounter));
this->GetDataStorage()->Modified();
MITK_INFO << "PlanarCircle created ...";
//call
mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet = this->GetDefaultDataStorage()->GetAll();
mitk::DataNode* node = 0;
mitk::PlanarFigureInteractor::Pointer figureInteractor = 0;
mitk::PlanarFigure* figureP = 0;
for(mitk::DataStorage::SetOfObjects::ConstIterator it=_NodeSet->Begin(); it!=_NodeSet->End()
; it++)
{
node = const_cast<mitk::DataNode*>(it->Value().GetPointer());
figureP = dynamic_cast<mitk::PlanarFigure*>(node->GetData());
if(figureP)
{
figureInteractor = dynamic_cast<mitk::PlanarFigureInteractor*>(node->GetInteractor());
if(figureInteractor.IsNull())
figureInteractor = mitk::PlanarFigureInteractor::New("PlanarFigureInteractor", node);
mitk::GlobalInteraction::GetInstance()->AddInteractor(figureInteractor);
}
}
}
void QmitkFiberBundleOperationsView::Activated()
{
MITK_INFO << "FB OPerations ACTIVATED()";
/*
mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet = this->GetDefaultDataStorage()->GetAll();
mitk::DataNode* node = 0;
mitk::PlanarFigureInteractor::Pointer figureInteractor = 0;
mitk::PlanarFigure* figure = 0;
for(mitk::DataStorage::SetOfObjects::ConstIterator it=_NodeSet->Begin(); it!=_NodeSet->End()
; it++)
{
node = const_cast<mitk::DataNode*>(it->Value().GetPointer());
figure = dynamic_cast<mitk::PlanarFigure*>(node->GetData());
if(figure)
{
figureInteractor = dynamic_cast<mitk::PlanarFigureInteractor*>(node->GetInteractor());
if(figureInteractor.IsNull())
figureInteractor = mitk::PlanarFigureInteractor::New("PlanarFigureInteractor", node);
mitk::GlobalInteraction::GetInstance()->AddInteractor(figureInteractor);
}
}
*/
}
void QmitkFiberBundleOperationsView::AddFigureToDataStorage(mitk::PlanarFigure* figure, const QString& name,
const char *propertyKey, mitk::BaseProperty *property )
{
//set desired data to DataNode where Planarfigure is stored
mitk::DataNode::Pointer newNode = mitk::DataNode::New();
newNode->SetName(name.toStdString());
newNode->SetData(figure);
newNode->AddProperty( "planarfigure.default.line.color", mitk::ColorProperty::New(1.0,0.0,0.0));
newNode->AddProperty( "planarfigure.line.width", mitk::FloatProperty::New(2.0));
newNode->AddProperty( "planarfigure.drawshadow", mitk::BoolProperty::New(true));
newNode->AddProperty( "selected", mitk::BoolProperty::New(true) );
newNode->AddProperty( "planarfigure.ishovering", mitk::BoolProperty::New(true) );
newNode->AddProperty( "planarfigure.drawoutline", mitk::BoolProperty::New(true) );
newNode->AddProperty( "planarfigure.drawquantities", mitk::BoolProperty::New(false) );
newNode->AddProperty( "planarfigure.drawshadow", mitk::BoolProperty::New(true) );
newNode->AddProperty( "planarfigure.line.width", mitk::FloatProperty::New(3.0) );
newNode->AddProperty( "planarfigure.shadow.widthmodifier", mitk::FloatProperty::New(2.0) );
newNode->AddProperty( "planarfigure.outline.width", mitk::FloatProperty::New(2.0) );
newNode->AddProperty( "planarfigure.helperline.width", mitk::FloatProperty::New(2.0) );
// PlanarFigureControlPointStyleProperty::Pointer styleProperty =
// dynamic_cast< PlanarFigureControlPointStyleProperty* >( node->GetProperty( "planarfigure.controlpointshape" ) );
// if ( styleProperty.IsNotNull() )
// {
// m_ControlPointShape = styleProperty->GetShape();
// }
newNode->AddProperty( "planarfigure.default.line.color", mitk::ColorProperty::New(1.0,1.0,1.0) );
newNode->AddProperty( "planarfigure.default.line.opacity", mitk::FloatProperty::New(2.0) );
newNode->AddProperty( "planarfigure.default.outline.color", mitk::ColorProperty::New(1.0,0.0,0.0) );
newNode->AddProperty( "planarfigure.default.outline.opacity", mitk::FloatProperty::New(2.0) );
newNode->AddProperty( "planarfigure.default.helperline.color", mitk::ColorProperty::New(1.0,0.0,0.0) );
newNode->AddProperty( "planarfigure.default.helperline.opacity", mitk::FloatProperty::New(2.0) );
newNode->AddProperty( "planarfigure.default.markerline.color", mitk::ColorProperty::New(0.0,0.0,0.0) );
newNode->AddProperty( "planarfigure.default.markerline.opacity", mitk::FloatProperty::New(2.0) );
newNode->AddProperty( "planarfigure.default.marker.color", mitk::ColorProperty::New(1.0,1.0,1.0) );
newNode->AddProperty( "planarfigure.default.marker.opacity",mitk::FloatProperty::New(2.0) );
newNode->AddProperty( "planarfigure.hover.line.color", mitk::ColorProperty::New(1.0,0.0,0.0) );
newNode->AddProperty( "planarfigure.hover.line.opacity", mitk::FloatProperty::New(2.0) );
newNode->AddProperty( "planarfigure.hover.outline.color", mitk::ColorProperty::New(1.0,0.0,0.0) );
newNode->AddProperty( "planarfigure.hover.outline.opacity", mitk::FloatProperty::New(2.0) );
newNode->AddProperty( "planarfigure.hover.helperline.color", mitk::ColorProperty::New(1.0,0.0,0.0) );
newNode->AddProperty( "planarfigure.hover.helperline.opacity", mitk::FloatProperty::New(2.0) );
newNode->AddProperty( "planarfigure.hover.markerline.color", mitk::ColorProperty::New(1.0,0.0,0.0) );
newNode->AddProperty( "planarfigure.hover.markerline.opacity", mitk::FloatProperty::New(2.0) );
newNode->AddProperty( "planarfigure.hover.marker.color", mitk::ColorProperty::New(1.0,0.0,0.0) );
newNode->AddProperty( "planarfigure.hover.marker.opacity", mitk::FloatProperty::New(2.0) );
newNode->AddProperty( "planarfigure.selected.line.color", mitk::ColorProperty::New(1.0,0.0,0.0) );
newNode->AddProperty( "planarfigure.selected.line.opacity",mitk::FloatProperty::New(2.0) );
newNode->AddProperty( "planarfigure.selected.outline.color", mitk::ColorProperty::New(1.0,0.0,0.0) );
newNode->AddProperty( "planarfigure.selected.outline.opacity", mitk::FloatProperty::New(2.0));
newNode->AddProperty( "planarfigure.selected.helperline.color", mitk::ColorProperty::New(1.0,0.0,0.0) );
newNode->AddProperty( "planarfigure.selected.helperline.opacity",mitk::FloatProperty::New(2.0) );
newNode->AddProperty( "planarfigure.selected.markerline.color", mitk::ColorProperty::New(1.0,0.0,0.0) );
newNode->AddProperty( "planarfigure.selected.markerline.opacity", mitk::FloatProperty::New(2.0) );
newNode->AddProperty( "planarfigure.selected.marker.color", mitk::ColorProperty::New(1.0,0.0,0.0) );
newNode->AddProperty( "planarfigure.selected.marker.opacity",mitk::FloatProperty::New(2.0));
// Add custom property, if available
//if ( (propertyKey != NULL) && (property != NULL) )
//{
// newNode->AddProperty( propertyKey, property );
//}
//get current selected DataNode -which should be a FiberBundle- and set PlanarFigure as child
//this->GetDataStorage()->GetNodes()
// mitk::FiberBundle::Pointer selectedFBNode = m_SelectedFBNodes.at(0);
// figure drawn on the topmost layer / image
this->GetDataStorage()->Add(newNode );
std::vector<mitk::DataNode*> selectedNodes = GetDataManagerSelection();
for(unsigned int i = 0; i < selectedNodes.size(); i++)
{
selectedNodes[i]->SetSelected(false);
}
//selectedNodes = m_SelectedPlanarFigureNodes->GetNodes();
/*for(unsigned int i = 0; i < selectedNodes.size(); i++)
{
selectedNodes[i]->SetSelected(false);
}
*/
newNode->SetSelected(true);
//Select(newNode);
}
void QmitkFiberBundleOperationsView::DoFiberExtraction()
{
mitk::FiberBundle::Pointer selFB = dynamic_cast<mitk::FiberBundle*>(m_SelectedFB.at(0)->GetData());
mitk::PlanarFigure::Pointer selPF = dynamic_cast<mitk::PlanarFigure*> (m_SelectedPF.at(0)->GetData());
std::vector<int> extFBset = selFB->extractFibersByPF(selPF);
//MITK_INFO << "returned vector in FBOperationsView: " << extFBset.size();
// for(std::vector<int>::iterator dispIt = extFBset.begin(); dispIt != extFBset.end(); dispIt++)
// {
// MITK_INFO << "vector DTI ID: " << *dispIt;
//
// }
mitk::FiberBundle::Pointer extFB = selFB->extractFibersById(extFBset);
MITK_INFO << " Number Of Tracts in sourceFiberBundle: " << selFB->GetNumTracts();
MITK_INFO << " Number Of Tracts in extractedFiberBundle: " << extFB->GetNumTracts();
mitk::DataNode::Pointer fbNode;
fbNode = mitk::DataNode::New();
fbNode->SetData(extFB);
fbNode->SetName("extGroupFinberBundle");
fbNode->SetVisibility(true);
GetDataStorage()->Add(fbNode);
}
void QmitkFiberBundleOperationsView::generatePFCompo_AND()
{
mitk::PlanarFigureComposite::Pointer PFCAnd = mitk::PlanarFigureComposite::New();
+
+ mitk::PlaneGeometry* currentGeometry2D = dynamic_cast<mitk::PlaneGeometry*>( const_cast<mitk::Geometry2D*>(GetActiveStdMultiWidget()->GetRenderWindow1()->GetRenderer()->GetCurrentWorldGeometry2D()));
+ PFCAnd->SetGeometry2D(currentGeometry2D);
+
PFCAnd->setOperationType(mitk::PFCOMPOSITION_AND_OPERATION);
for( std::vector<mitk::DataNode::Pointer>::iterator it = m_SelectedPF.begin();
it != m_SelectedPF.end(); ++it )
{
mitk::DataNode::Pointer nodePF = *it;
mitk::PlanarFigure::Pointer tmpPF = dynamic_cast<mitk::PlanarFigure*>( nodePF->GetData() );
PFCAnd->addPlanarFigure( tmpPF );
PFCAnd->addDataNode( nodePF );
PFCAnd->setDisplayName("AND_COMPO");
// MITK_INFO << "PFCAND(): added to AND PF" << nodePF->GetName();
}
debugPFComposition(PFCAnd, 0);
this->addPFCompositionToDataStorage(PFCAnd, NULL /*parent*/);
}
void QmitkFiberBundleOperationsView::debugPFComposition(mitk::PlanarFigureComposite::Pointer pfc, int itLevelStatus)
{
int myLevel = itLevelStatus;
if (myLevel == 0)
{
MITK_INFO << "############################################## " ;
MITK_INFO << "######### DEBUG START ############## " ;
MITK_INFO << "############################################## " ;
}
MITK_INFO << "############################################## " ;
MITK_INFO << "Name: " << pfc->getDisplayName();
MITK_INFO << "iterationLevel: " << myLevel;
MITK_INFO << "CompositionType: " << pfc->getOperationType();
MITK_INFO << "Number of children: " << pfc->getNumberOfChildren();
//iterate through pfcs children
for(int i=0; i<pfc->getNumberOfChildren(); ++i)
{
mitk::PlanarFigure::Pointer tmpPFchild = pfc->getChildAt(i);
mitk::DataNode::Pointer savedPFchildNode = pfc->getDataNodeAt(i);
if (tmpPFchild == savedPFchildNode->GetData())
{
MITK_INFO << "[OK] Pointers point to same Data...";
}else{
MITK_INFO << "Pointers differ in equation";
}
MITK_INFO << "Level: " << myLevel << " ChildNr.: " << i ;
mitk::PlanarFigureComposite::Pointer pfcompcastNode= dynamic_cast<mitk::PlanarFigureComposite*>(savedPFchildNode->GetData());
mitk::PlanarFigureComposite::Pointer pfcompcast= dynamic_cast<mitk::PlanarFigureComposite*>(tmpPFchild.GetPointer());
if( !pfcompcast.IsNull() )
{ // we have a composite as child
if ( pfcompcastNode.IsNull() )
{
MITK_INFO << "************** NODE DIFFER FROM PFC...ERROR! ***************";
} else {
MITK_INFO << "[OK]...node contains right type ";
}
itLevelStatus++;
MITK_INFO << "child is PFC...debug this PFC";
debugPFComposition(pfcompcast, itLevelStatus);
} else {
// we have a planarFigure as child
// figure out which type
mitk::PlanarCircle::Pointer circleName = mitk::PlanarCircle::New();
mitk::PlanarRectangle::Pointer rectName = mitk::PlanarRectangle::New();
mitk::PlanarPolygon::Pointer polyName = mitk::PlanarPolygon::New();
if (tmpPFchild->GetNameOfClass() == circleName->GetNameOfClass() )
{
MITK_INFO << "a circle child of " << pfc->getDisplayName() ;
} else if (tmpPFchild->GetNameOfClass() == rectName->GetNameOfClass() ){
MITK_INFO << "a rectangle child of " << pfc->getDisplayName() ;
} else if (tmpPFchild->GetNameOfClass() == polyName->GetNameOfClass() ) {
MITK_INFO << "a polygon child of " << pfc->getDisplayName() ;
}
MITK_INFO << "....................................................... " ;
}
} //end for
if (myLevel == 0)
{
MITK_INFO << "############################################## " ;
MITK_INFO << "######### DEBUG END ############## " ;
MITK_INFO << "############################################## " ;
}
}
void QmitkFiberBundleOperationsView::generatePFCompo_OR()
{
mitk::PlanarFigureComposite::Pointer PFCOr = mitk::PlanarFigureComposite::New();
+ mitk::PlaneGeometry* currentGeometry2D = dynamic_cast<mitk::PlaneGeometry*>( const_cast<mitk::Geometry2D*>(GetActiveStdMultiWidget()->GetRenderWindow1()->GetRenderer()->GetCurrentWorldGeometry2D()));
+ PFCOr->SetGeometry2D(currentGeometry2D);
PFCOr->setOperationType(mitk::PFCOMPOSITION_OR_OPERATION);
for( std::vector<mitk::DataNode::Pointer>::iterator it = m_SelectedPF.begin();
it != m_SelectedPF.end(); ++it )
{
mitk::DataNode::Pointer nodePF = *it;
mitk::PlanarFigure::Pointer tmpPF = dynamic_cast<mitk::PlanarFigure*>( nodePF->GetData() );
PFCOr->addPlanarFigure( tmpPF );
PFCOr->addDataNode( nodePF );
PFCOr->setDisplayName("OR_COMPO");
// MITK_INFO << "PFCAND(): added to AND PF" << nodePF->GetName();
}
debugPFComposition(PFCOr, 0);
this->addPFCompositionToDataStorage(PFCOr, NULL /*parent*/);
}
void QmitkFiberBundleOperationsView::generatePFCompo_NOT()
{
mitk::PlanarFigureComposite::Pointer PFCNot = mitk::PlanarFigureComposite::New();
+ mitk::PlaneGeometry* currentGeometry2D = dynamic_cast<mitk::PlaneGeometry*>( const_cast<mitk::Geometry2D*>(GetActiveStdMultiWidget()->GetRenderWindow1()->GetRenderer()->GetCurrentWorldGeometry2D()));
+ PFCNot->SetGeometry2D(currentGeometry2D);
PFCNot->setOperationType(mitk::PFCOMPOSITION_NOT_OPERATION);
for( std::vector<mitk::DataNode::Pointer>::iterator it = m_SelectedPF.begin();
it != m_SelectedPF.end(); ++it )
{
mitk::DataNode::Pointer nodePF = *it;
mitk::PlanarFigure::Pointer tmpPF = dynamic_cast<mitk::PlanarFigure*>( nodePF->GetData() );
PFCNot->addPlanarFigure( tmpPF );
PFCNot->addDataNode( nodePF );
PFCNot->setDisplayName("NOT_COMPO");
// MITK_INFO << "PFCAND(): added to AND PF" << nodePF->GetName();
}
debugPFComposition(PFCNot, 0);
this->addPFCompositionToDataStorage(PFCNot, NULL /*parent*/);
}
void QmitkFiberBundleOperationsView::deletePFCompo()
{
}
void QmitkFiberBundleOperationsView::addPFCompositionToDataStorage(mitk::PlanarFigureComposite::Pointer pfcomp, mitk::DataNode::Pointer parentDataNode )
{
//a new planarFigureComposition arrived
//convert it into a dataNode
mitk::DataNode::Pointer newPFCNode;
newPFCNode = mitk::DataNode::New();
newPFCNode->SetName( pfcomp->getDisplayName() );
//MITK_INFO << "PFComp Name: " << pfcomp->getDisplayName() << " newPFCNodeName: " << newPFCNode->GetName();
newPFCNode->SetData(pfcomp);
newPFCNode->SetVisibility(true);
switch (pfcomp->getOperationType()) {
case 0:
{
// AND PLANARFIGURECOMPOSITE
// newPFCNode->SetName("AND_PFCombo");
if (!parentDataNode.IsNull()) {
MITK_INFO << "adding " << newPFCNode->GetName() << " to " << parentDataNode->GetName() ;
GetDataStorage()->Add(newPFCNode, parentDataNode);
} else {
MITK_INFO << "adding " << newPFCNode->GetName();
GetDataStorage()->Add(newPFCNode);
}
//iterate through its childs
for(int i=0; i<pfcomp->getNumberOfChildren(); ++i)
{
mitk::PlanarFigure::Pointer tmpPFchild = pfcomp->getChildAt(i);
mitk::DataNode::Pointer savedPFchildNode = pfcomp->getDataNodeAt(i);
mitk::PlanarFigureComposite::Pointer pfcompcast= dynamic_cast<mitk::PlanarFigureComposite*>(tmpPFchild.GetPointer());
if ( !pfcompcast.IsNull() )
{ // child is of type planar Figure composite
// make new node of the child, cuz later the child has to be removed of its old position in datamanager
// feed new dataNode with information of the savedDataNode, which is gonna be removed soon
mitk::DataNode::Pointer newChildPFCNode;
newChildPFCNode = mitk::DataNode::New();
newChildPFCNode->SetData(tmpPFchild);
newChildPFCNode->SetName( savedPFchildNode->GetName() );
pfcompcast->setDisplayName( savedPFchildNode->GetName() ); //name might be changed in DataManager by user
//update inside vector the dataNodePointer
pfcomp->replaceDataNodeAt(i, newChildPFCNode);
addPFCompositionToDataStorage(pfcompcast, newPFCNode); //the current PFCNode becomes the childs parent
// remove savedNode here, cuz otherwise its children will change their position in the dataNodeManager
// without having its parent anymore
//GetDataStorage()->Remove(savedPFchildNode);
if ( GetDataStorage()->Exists(savedPFchildNode)) {
MITK_INFO << savedPFchildNode->GetName() << " exists in DS...trying to remove it";
}else{
MITK_INFO << "[ERROR] does NOT exist, but can I read its Name? " << savedPFchildNode->GetName();
}
// remove old child position in dataStorage
GetDataStorage()->Remove(savedPFchildNode);
if ( GetDataStorage()->Exists(savedPFchildNode)) {
MITK_INFO << savedPFchildNode->GetName() << " still exists";
}
} else {
// child is not of type PlanarFigureComposite, so its one of the planarFigures
// create new dataNode containing the data of the old dataNode, but position in dataManager will be
// modified cuz we re setting a (new) parent.
mitk::DataNode::Pointer newPFchildNode = mitk::DataNode::New();
newPFchildNode->SetName(savedPFchildNode->GetName() );
newPFchildNode->SetData(tmpPFchild);
newPFchildNode->SetVisibility(true);
// replace the dataNode in PFComp DataNodeVector
pfcomp->replaceDataNodeAt(i, newPFchildNode);
if ( GetDataStorage()->Exists(savedPFchildNode)) {
MITK_INFO << savedPFchildNode->GetName() << " exists in DS...trying to remove it";
}else{
MITK_INFO << "[ERROR] does NOT exist, but can I read its Name? " << savedPFchildNode->GetName();
}
// remove old child position in dataStorage
GetDataStorage()->Remove(savedPFchildNode);
if ( GetDataStorage()->Exists(savedPFchildNode)) {
MITK_INFO << savedPFchildNode->GetName() << " still exists";
}
MITK_INFO << "adding " << newPFchildNode->GetName() << " to " << newPFCNode->GetName();
//add new child to datamanager with its new position as child of newPFCNode parent
GetDataStorage()->Add(newPFchildNode, newPFCNode);
}
}
GetDataStorage()->Modified();
break;
}
case 1:
{
// AND PLANARFIGURECOMPOSITE
// newPFCNode->SetName("AND_PFCombo");
if (!parentDataNode.IsNull()) {
MITK_INFO << "adding " << newPFCNode->GetName() << " to " << parentDataNode->GetName() ;
GetDataStorage()->Add(newPFCNode, parentDataNode);
} else {
MITK_INFO << "adding " << newPFCNode->GetName();
GetDataStorage()->Add(newPFCNode);
}
//iterate through its childs
for(int i=0; i<pfcomp->getNumberOfChildren(); ++i)
{
mitk::PlanarFigure::Pointer tmpPFchild = pfcomp->getChildAt(i);
mitk::DataNode::Pointer savedPFchildNode = pfcomp->getDataNodeAt(i);
mitk::PlanarFigureComposite::Pointer pfcompcast= dynamic_cast<mitk::PlanarFigureComposite*>(tmpPFchild.GetPointer());
if ( !pfcompcast.IsNull() )
{ // child is of type planar Figure composite
// make new node of the child, cuz later the child has to be removed of its old position in datamanager
// feed new dataNode with information of the savedDataNode, which is gonna be removed soon
mitk::DataNode::Pointer newChildPFCNode;
newChildPFCNode = mitk::DataNode::New();
newChildPFCNode->SetData(tmpPFchild);
newChildPFCNode->SetName( savedPFchildNode->GetName() );
pfcompcast->setDisplayName( savedPFchildNode->GetName() ); //name might be changed in DataManager by user
//update inside vector the dataNodePointer
pfcomp->replaceDataNodeAt(i, newChildPFCNode);
addPFCompositionToDataStorage(pfcompcast, newPFCNode); //the current PFCNode becomes the childs parent
// remove savedNode here, cuz otherwise its children will change their position in the dataNodeManager
// without having its parent anymore
//GetDataStorage()->Remove(savedPFchildNode);
if ( GetDataStorage()->Exists(savedPFchildNode)) {
MITK_INFO << savedPFchildNode->GetName() << " exists in DS...trying to remove it";
}else{
MITK_INFO << "[ERROR] does NOT exist, but can I read its Name? " << savedPFchildNode->GetName();
}
// remove old child position in dataStorage
GetDataStorage()->Remove(savedPFchildNode);
if ( GetDataStorage()->Exists(savedPFchildNode)) {
MITK_INFO << savedPFchildNode->GetName() << " still exists";
}
} else {
// child is not of type PlanarFigureComposite, so its one of the planarFigures
// create new dataNode containing the data of the old dataNode, but position in dataManager will be
// modified cuz we re setting a (new) parent.
mitk::DataNode::Pointer newPFchildNode = mitk::DataNode::New();
newPFchildNode->SetName(savedPFchildNode->GetName() );
newPFchildNode->SetData(tmpPFchild);
newPFchildNode->SetVisibility(true);
// replace the dataNode in PFComp DataNodeVector
pfcomp->replaceDataNodeAt(i, newPFchildNode);
if ( GetDataStorage()->Exists(savedPFchildNode)) {
MITK_INFO << savedPFchildNode->GetName() << " exists in DS...trying to remove it";
}else{
MITK_INFO << "[ERROR] does NOT exist, but can I read its Name? " << savedPFchildNode->GetName();
}
// remove old child position in dataStorage
GetDataStorage()->Remove(savedPFchildNode);
if ( GetDataStorage()->Exists(savedPFchildNode)) {
MITK_INFO << savedPFchildNode->GetName() << " still exists";
}
MITK_INFO << "adding " << newPFchildNode->GetName() << " to " << newPFCNode->GetName();
//add new child to datamanager with its new position as child of newPFCNode parent
GetDataStorage()->Add(newPFchildNode, newPFCNode);
}
}
GetDataStorage()->Modified();
break;
}
case 2:
{
// AND PLANARFIGURECOMPOSITE
// newPFCNode->SetName("AND_PFCombo");
if (!parentDataNode.IsNull()) {
MITK_INFO << "adding " << newPFCNode->GetName() << " to " << parentDataNode->GetName() ;
GetDataStorage()->Add(newPFCNode, parentDataNode);
} else {
MITK_INFO << "adding " << newPFCNode->GetName();
GetDataStorage()->Add(newPFCNode);
}
//iterate through its childs
for(int i=0; i<pfcomp->getNumberOfChildren(); ++i)
{
mitk::PlanarFigure::Pointer tmpPFchild = pfcomp->getChildAt(i);
mitk::DataNode::Pointer savedPFchildNode = pfcomp->getDataNodeAt(i);
mitk::PlanarFigureComposite::Pointer pfcompcast= dynamic_cast<mitk::PlanarFigureComposite*>(tmpPFchild.GetPointer());
if ( !pfcompcast.IsNull() )
{ // child is of type planar Figure composite
// makeRemoveBundle new node of the child, cuz later the child has to be removed of its old position in datamanager
// feed new dataNode with information of the savedDataNode, which is gonna be removed soon
mitk::DataNode::Pointer newChildPFCNode;
newChildPFCNode = mitk::DataNode::New();
newChildPFCNode->SetData(tmpPFchild);
newChildPFCNode->SetName( savedPFchildNode->GetName() );
pfcompcast->setDisplayName( savedPFchildNode->GetName() ); //name might be changed in DataManager by user
//update inside vector the dataNodePointer
pfcomp->replaceDataNodeAt(i, newChildPFCNode);
addPFCompositionToDataStorage(pfcompcast, newPFCNode); //the current PFCNode becomes the childs parent
// remove savedNode here, cuz otherwise its children will change their position in the dataNodeManager
// without having its parent anymore
//GetDataStorage()->Remove(savedPFchildNode);
if ( GetDataStorage()->Exists(savedPFchildNode)) {
MITK_INFO << savedPFchildNode->GetName() << " exists in DS...trying to remove it";
}else{
MITK_INFO << "[ERROR] does NOT exist, but can I read its Name? " << savedPFchildNode->GetName();
}
// remove old child position in dataStorage
GetDataStorage()->Remove(savedPFchildNode);
if ( GetDataStorage()->Exists(savedPFchildNode)) {
MITK_INFO << savedPFchildNode->GetName() << " still exists";
}
} else {
// child is not of type PlanarFigureComposite, so its one of the planarFigures
// create new dataNode containing the data of the old dataNode, but position in dataManager will be
// modified cuz we re setting a (new) parent.
mitk::DataNode::Pointer newPFchildNode = mitk::DataNode::New();
newPFchildNode->SetName(savedPFchildNode->GetName() );
newPFchildNode->SetData(tmpPFchild);
newPFchildNode->SetVisibility(true);
// replace the dataNode in PFComp DataNodeVector
pfcomp->replaceDataNodeAt(i, newPFchildNode);
if ( GetDataStorage()->Exists(savedPFchildNode)) {
MITK_INFO << savedPFchildNode->GetName() << " exists in DS...trying to remove it";
}else{
MITK_INFO << "[ERROR] does NOT exist, but can I read its Name? " << savedPFchildNode->GetName();
}
// remove old child position in dataStorage
GetDataStorage()->Remove(savedPFchildNode);
if ( GetDataStorage()->Exists(savedPFchildNode)) {
MITK_INFO << savedPFchildNode->GetName() << " still exists";
}
MITK_INFO << "adding " << newPFchildNode->GetName() << " to " << newPFCNode->GetName();
//add new child to datamanager with its new position as child of newPFCNode parent
GetDataStorage()->Add(newPFchildNode, newPFCNode);
}
}
GetDataStorage()->Modified();
break;
}
default:
MITK_INFO << "we have an UNDEFINED composition... ERROR" ;
break;
}
}
void QmitkFiberBundleOperationsView::JoinBundles()
{
mitk::FiberBundle::Pointer bundle1 = dynamic_cast<mitk::FiberBundle*>(m_SelectedFB.at(0)->GetData());
mitk::FiberBundle::Pointer bundle2 = dynamic_cast<mitk::FiberBundle*>(m_SelectedFB.at(1)->GetData());
mitk::FiberBundle::Pointer newBundle = bundle1->JoinBundle(bundle2);
mitk::DataNode::Pointer fbNode = mitk::DataNode::New();
fbNode->SetData(newBundle);
fbNode->SetName(m_SelectedFB.at(0)->GetName()+"+"+m_SelectedFB.at(1)->GetName());
fbNode->SetVisibility(true);
GetDataStorage()->Add(fbNode);
}
void QmitkFiberBundleOperationsView::SubstractBundles()
{
mitk::FiberBundle::Pointer bundle1 = dynamic_cast<mitk::FiberBundle*>(m_SelectedFB.at(0)->GetData());
mitk::FiberBundle::Pointer bundle2 = dynamic_cast<mitk::FiberBundle*>(m_SelectedFB.at(1)->GetData());
mitk::FiberBundle::Pointer newBundle = bundle1->SubstractBundle(bundle2);
mitk::DataNode::Pointer fbNode = mitk::DataNode::New();
fbNode->SetData(newBundle);
fbNode->SetName(m_SelectedFB.at(0)->GetName()+"-"+m_SelectedFB.at(1)->GetName());
fbNode->SetVisibility(true);
GetDataStorage()->Add(fbNode);
}
void QmitkFiberBundleOperationsView::GenerationStart()
{
int generationMethod = m_Controls->m_GenerationBox->currentIndex();
std::vector<mitk::DataNode*> nodes = GetDataManagerSelection();
if (nodes.empty()){
QMessageBox::information( NULL, "Warning", "No data object selected!");
MITK_WARN("QmitkFiberBundleOperationsView") << "no data object selected";
return;
}
for( std::vector<mitk::DataNode*>::iterator it = nodes.begin(); it != nodes.end(); ++it )
{
mitk::DataNode::Pointer node = *it;
if (node.IsNotNull() && dynamic_cast<mitk::FiberBundle*>(node->GetData()))
{
m_FiberBundle = dynamic_cast<mitk::FiberBundle*>(node->GetData());
m_FiberBundleNode = node;
switch(generationMethod){
case 0:
GenerateGreyscaleHeatmap(true);
break;
case 1:
GenerateGreyscaleHeatmap(false);
break;
case 2:
GenerateColorHeatmap();
break;
case 3:
GenerateFiberEndingsImage();
break;
case 4:
GenerateFiberEndingsPointSet();
break;
case 5:
DWIGenerationStart();
break;
}
}
}
}
// generate pointset displaying the fiber endings
void QmitkFiberBundleOperationsView::GenerateFiberEndingsPointSet()
{
if(m_FiberBundle.IsNull()){
QMessageBox::information( NULL, "Warning", "No fiber bundle selected!");
MITK_WARN("QmitkGlobalFiberTrackingView") << "no fiber bundle selected";
return;
}
mitk::Geometry3D::Pointer geometry = m_FiberBundle->GetGeometry();
mitk::PointSet::Pointer pointSet = mitk::PointSet::New();
int numTracts = m_FiberBundle->GetNumTracts();
int count = 0;
for( int i=0; i<numTracts; i++ )
{
// get fiber start point
int numVertices = m_FiberBundle->GetNumPoints(i);
itk::Point<float, 3> start = m_FiberBundle->GetPoint(i,0);
itk::Point<float, 3> world1;
geometry->IndexToWorld(start, world1);
pointSet->InsertPoint(count, world1);
count++;
// get fiber end point
if(numVertices>1)
{
itk::Point<float, 3> end = m_FiberBundle->GetPoint(i,numVertices-1);
itk::Point<float, 3> world;
geometry->IndexToWorld(end, world);
pointSet->InsertPoint(count, world);
count++;
}
}
mitk::DataNode::Pointer pointSetNode = mitk::DataNode::New();
pointSetNode->SetData( pointSet );
QString name(m_FiberBundleNode->GetName().c_str());
name += "_fiber_endings";
pointSetNode->SetName(name.toStdString());
pointSetNode->SetProperty( "opacity", mitk::FloatProperty::New( 1 ) );
pointSetNode->SetProperty( "pointsize", mitk::FloatProperty::New( 0.3) );
pointSetNode->SetColor( 1.0, 1.0, 1.0 );
GetDefaultDataStorage()->Add(pointSetNode);
}
// generate image displaying the fiber endings
void QmitkFiberBundleOperationsView::GenerateFiberEndingsImage()
{
if(m_FiberBundle.IsNull()){
QMessageBox::information( NULL, "Warning", "No fiber bundle selected!");
MITK_WARN("QmitkGlobalFiberTrackingView") << "no fiber bundle selected";
return;
}
typedef unsigned char OutPixType;
// run generator
typedef itk::TractsToFiberEndingsImageFilter<FloatImageType,
OutPixType> ImageGeneratorType;
ImageGeneratorType::Pointer generator = ImageGeneratorType::New();
generator->SetFiberBundle(m_FiberBundle);
generator->SetUpsamplingFactor(m_Controls->m_UpsamplingSpinBox->value());
generator->Update();
// get result
typedef itk::Image<OutPixType,3> OutType;
OutType::Pointer outImg = generator->GetOutput();
mitk::Image::Pointer img = mitk::Image::New();
img->InitializeByItk(outImg.GetPointer());
img->SetVolume(outImg->GetBufferPointer());
// to datastorage
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData(img);
QString name(m_FiberBundleNode->GetName().c_str());
name += "_fiber_endings";
node->SetName(name.toStdString());
node->SetVisibility(true);
GetDataStorage()->Add(node);
}
// generate rgba heatmap from fiber bundle
void QmitkFiberBundleOperationsView::GenerateColorHeatmap()
{
if(m_FiberBundle.IsNull() || m_FiberBundleNode.IsNull())
{
QMessageBox::information( NULL, "Warning", "No fiber bundle selected!");
MITK_WARN("QmitkGlobalFiberTrackingView") << "no fiber bundle selected";
return;
}
typedef itk::RGBAPixel<unsigned char> OutPixType;
// run generator
typedef itk::TractsToProbabilityImageFilter<FloatImageType, OutPixType>
ImageGeneratorType;
ImageGeneratorType::Pointer generator = ImageGeneratorType::New();
//generator->SetInput(NULL);
generator->SetFiberBundle(m_FiberBundle);
generator->SetUpsamplingFactor(m_Controls->m_UpsamplingSpinBox->value());
generator->Update();
// get result
typedef itk::Image<OutPixType,3> OutType;
OutType::Pointer outImg = generator->GetOutput();
mitk::Image::Pointer img = mitk::Image::New();
img->InitializeByItk(outImg.GetPointer());
img->SetVolume(outImg->GetBufferPointer());
// to datastorage
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData(img);
QString name(m_FiberBundleNode->GetName().c_str());
name += "_rgba_heatmap";
node->SetName(name.toStdString());
node->SetVisibility(true);
mitk::LevelWindow opaclevwin;
opaclevwin.SetRangeMinMax(0,255);
opaclevwin.SetWindowBounds(0,0);
mitk::LevelWindowProperty::Pointer prop =
mitk::LevelWindowProperty::New(opaclevwin);
node->AddProperty( "opaclevelwindow", prop );
GetDataStorage()->Add(node);
}
// generate greyscale heatmap from fiber bundle
void QmitkFiberBundleOperationsView::GenerateGreyscaleHeatmap(bool binary)
{
if(m_FiberBundle.IsNull() || m_FiberBundleNode.IsNull())
{
QMessageBox::information( NULL, "Warning", "No fiber bundle selected!");
MITK_WARN("QmitkGlobalFiberTrackingView") << "no fiber bundle selected";
return;
}
typedef unsigned char OutPixType;
// run generator
typedef itk::TractsToProbabilityImageFilter<FloatImageType, OutPixType> ImageGeneratorType;
ImageGeneratorType::Pointer generator = ImageGeneratorType::New();
generator->SetFiberBundle(m_FiberBundle);
generator->SetInvertImage(m_Controls->m_InvertCheckbox->isChecked());
generator->SetUpsamplingFactor(m_Controls->m_UpsamplingSpinBox->value());
if (binary)
generator->SetBinaryEnvelope(true);
else
generator->SetBinaryEnvelope(false);
generator->Update();
// get result
typedef itk::Image<OutPixType,3> OutType;
OutType::Pointer outImg = generator->GetOutput();
mitk::Image::Pointer img = mitk::Image::New();
img->InitializeByItk(outImg.GetPointer());
img->SetVolume(outImg->GetBufferPointer());
// to datastorage
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData(img);
QString name(m_FiberBundleNode->GetName().c_str());
if(binary)
name += "_enveloppe";
else
name += "_heatmap";
node->SetName(name.toStdString());
node->SetVisibility(true);
mitk::LevelWindow opaclevwin2;
opaclevwin2.SetRangeMinMax(0,255);
opaclevwin2.SetWindowBounds(0,0);
mitk::LevelWindowProperty::Pointer prop2 =
mitk::LevelWindowProperty::New(opaclevwin2);
node->AddProperty( "opaclevelwindow", prop2 );
GetDataStorage()->Add(node);
}
// generate dwi from fiber bundle (experimental)
void QmitkFiberBundleOperationsView::DWIGenerationStart()
{
// get fiber bundle and dwi image from data manager
typedef mitk::DiffusionImage<short> DiffVolumesType;
std::vector<mitk::DataNode*> nodes = GetDataManagerSelection();
DiffVolumesType::Pointer originalDWI = NULL;
mitk::FiberBundle::Pointer fiberBundle = NULL;
for( std::vector<mitk::DataNode*>::iterator it = nodes.begin(); it != nodes.end(); ++it )
{
mitk::DataNode::Pointer node = *it;
if (node.IsNotNull() &&
dynamic_cast<DiffVolumesType*>(node->GetData()))
{
originalDWI = dynamic_cast<DiffVolumesType*>(node->GetData());
continue;
}
if (node.IsNotNull() &&
dynamic_cast<mitk::FiberBundle*>(node->GetData()))
{
fiberBundle = dynamic_cast<mitk::FiberBundle*>(node->GetData());
}
}
if(fiberBundle.IsNull() || originalDWI.IsNull()){
QMessageBox::information( NULL, "Warning", "Please load and select a dwi image and a fiber bundle.");
MITK_WARN("QmitkGlobalFiberTrackingView") << "please select a fiber bundle and a diffusion image";
return;
}
// CONSTRUCT CONTAINER WITH DIRECTIONS
typedef vnl_vector_fixed< double, 3 > GradientDirectionType;
typedef itk::VectorContainer< unsigned int, GradientDirectionType > GradientDirectionContainerType;
GradientDirectionContainerType::Pointer directions = originalDWI->GetDirections();
float bVal = originalDWI->GetB_Value();
typedef itk::VectorImage< short, 3 > DWIImageType;
DWIImageType::Pointer vectorImage = DWIImageType::New();
itk::TractsToDWIImageFilter::Pointer filter = itk::TractsToDWIImageFilter::New();
filter->SetInput(originalDWI->GetVectorImage());
filter->SetFiberBundle(fiberBundle);
filter->SetbD(m_Controls->m_UpsamplingSpinBox->value());
filter->SetGradientDirections(directions);
filter->SetParticleWidth(0.2);
filter->GenerateData();
vectorImage = filter->GetOutput();
DiffVolumesType::Pointer diffImage = DiffVolumesType::New();
diffImage->SetDirections(directions);
diffImage->SetOriginalDirections(directions);
diffImage->SetVectorImage(vectorImage);
diffImage->SetB_Value(bVal);
diffImage->InitializeFromVectorImage();
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData( diffImage );
QString name(m_FiberBundleNode->GetName().c_str());
name += "_dwi";
GetDefaultDataStorage()->Add(node);
}
diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleOperationsView.h b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleOperationsView.h
index b63a768740..7b48845074 100644
--- a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleOperationsView.h
+++ b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberBundleOperationsView.h
@@ -1,199 +1,199 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date: 2010-03-31 16:40:27 +0200 (Mi, 31 Mrz 2010) $
Version: $Revision: 21975 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef QmitkFiberBundleOperationsView_h
#define QmitkFiberBundleOperationsView_h
#include <berryISelectionListener.h>
#include <berryIStructuredSelection.h>
#include <QmitkFunctionality.h>
#include "ui_QmitkFiberBundleOperationsViewControls.h"
#include "mitkDataStorage.h"
#include "mitkDataStorageSelection.h"
#include "mitkPlanarFigure.h"
#include "mitkFiberBundle.h"
#include "mitkPlanarFigureComposite.h"
#include <itkImage.h>
#include <itkCastImageFilter.h>
#include <vtkLinearExtrusionFilter.h>
#include <vtkPolyDataToImageStencil.h>
#include <vtkImageImport.h>
#include <vtkImageExport.h>
#include <itkVTKImageImport.h>
#include <itkVTKImageExport.h>
#include <vtkImageStencil.h>
#include <itkRegionOfInterestImageFilter.h>
#include <vtkSmartPointer.h>
#include <berryISelectionListener.h>
#include <berryIStructuredSelection.h>
struct FboSelListener;
/*!
\brief QmitkFiberBundleView
\warning This application module is not yet documented. Use "svn blame/praise/annotate" and ask the author to provide basic documentation.
\sa QmitkFunctionality
\ingroup Functionalities
*/
class QmitkFiberBundleOperationsView : public QmitkFunctionality
{
friend struct FboSelListener;
// 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:
typedef itk::Image< unsigned char, 3 > MaskImage3DType;
typedef itk::Image< float, 3 > FloatImageType;
static const std::string VIEW_ID;
QmitkFiberBundleOperationsView();
virtual ~QmitkFiberBundleOperationsView();
virtual void CreateQtPartControl(QWidget *parent);
virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget);
virtual void StdMultiWidgetNotAvailable();
virtual void Activated();
protected slots:
/// \brief Called when the user clicks the GUI button
void ActionDrawEllipseTriggered();
void ActionDrawPolygonTriggered();
void DoFiberExtraction();
void generatePFCompo_AND();
void generatePFCompo_OR();
void generatePFCompo_NOT();
void deletePFCompo();
void JoinBundles();
void SubstractBundles();
void GenerateROIImage();
void GenerationStart();
virtual void AddFigureToDataStorage(mitk::PlanarFigure* figure, const QString& name,
const char *propertyKey = NULL, mitk::BaseProperty *property = NULL );
protected:
/// \brief called by QmitkFunctionality when DataManager's selection has changed
virtual void OnSelectionChanged( std::vector<mitk::DataNode*> nodes );
Ui::QmitkFiberBundleOperationsViewControls* m_Controls;
QmitkStdMultiWidget* m_MultiWidget;
//void Select( mitk::DataNode::Pointer node, bool clearMaskOnFirstArgNULL=false, bool clearImageOnFirstArgNULL=false );
/** Connection from VTK to ITK */
template <typename VTK_Exporter, typename ITK_Importer>
void ConnectPipelines(VTK_Exporter* exporter, ITK_Importer importer)
{
importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback());
importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback());
importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback());
importer->SetSpacingCallback(exporter->GetSpacingCallback());
importer->SetOriginCallback(exporter->GetOriginCallback());
importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback());
importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback());
importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback());
importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback());
importer->SetDataExtentCallback(exporter->GetDataExtentCallback());
importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback());
importer->SetCallbackUserData(exporter->GetCallbackUserData());
}
template <typename ITK_Exporter, typename VTK_Importer>
void ConnectPipelines(ITK_Exporter exporter, VTK_Importer* importer)
{
importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback());
importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback());
importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback());
importer->SetSpacingCallback(exporter->GetSpacingCallback());
importer->SetOriginCallback(exporter->GetOriginCallback());
importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback());
importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback());
importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback());
importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback());
importer->SetDataExtentCallback(exporter->GetDataExtentCallback());
importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback());
importer->SetCallbackUserData(exporter->GetCallbackUserData());
}
template < typename TPixel, unsigned int VImageDimension >
void InternalCalculateMaskFromPlanarFigure(
- itk::Image< TPixel, VImageDimension > *image, unsigned int axis );
+ itk::Image< TPixel, VImageDimension > *image, unsigned int axis, std::string nodeName );
template < typename TPixel, unsigned int VImageDimension >
void InternalReorientImagePlane(
- const itk::Image< TPixel, VImageDimension > *image, mitk::Geometry3D* imggeo, mitk::Geometry3D* planegeo3D, int additionalIndex );
+ const itk::Image< TPixel, VImageDimension > *image, mitk::Geometry3D* planegeo3D, int additionalIndex );
berry::ISelectionListener::Pointer m_SelListener;
berry::IStructuredSelection::ConstPointer m_CurrentSelection;
private:
int m_EllipseCounter;
int m_PolygonCounter;
//contains the selected FiberBundles
std::vector<mitk::DataNode::Pointer> m_SelectedFB;
//contains the selected PlanarFigures
std::vector<mitk::DataNode::Pointer> m_SelectedPF;
mitk::Image::ConstPointer m_Image;
mitk::Image::Pointer m_InternalImage;
mitk::PlanarFigure::Pointer m_PlanarFigure;
float m_UpsamplingFactor;
MaskImage3DType::Pointer m_InternalImageMask3D;
MaskImage3DType::Pointer m_PlanarFigureImage;
mitk::FiberBundle::Pointer m_FiberBundle;
mitk::DataNode::Pointer m_FiberBundleNode;
void addPFCompositionToDataStorage(mitk::PlanarFigureComposite::Pointer, mitk::DataNode::Pointer);
void debugPFComposition(mitk::PlanarFigureComposite::Pointer , int );
- void CompositeExtraction(mitk::PlanarFigure::Pointer planarFigure, mitk::Image* image);
+ void CompositeExtraction(mitk::DataNode::Pointer node, mitk::Image* image);
void GenerateGreyscaleHeatmap(bool binary);
void GenerateColorHeatmap();
void GenerateFiberEndingsImage();
void GenerateFiberEndingsPointSet();
void DWIGenerationStart();
};
#endif // _QMITKFIBERTRACKINGVIEW_H_INCLUDED
diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPartialVolumeAnalysisView.cpp b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPartialVolumeAnalysisView.cpp
index baef555424..cff754a5c3 100644
--- a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPartialVolumeAnalysisView.cpp
+++ b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPartialVolumeAnalysisView.cpp
@@ -1,2075 +1,2076 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date: 2009-05-22 11:00:35 +0200 (Fr, 22 Mai 2009) $
Version: $Revision: 10185 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "QmitkPartialVolumeAnalysisView.h"
#include <limits>
#include <qlabel.h>
#include <qspinbox.h>
#include <qpushbutton.h>
#include <qcheckbox.h>
#include <qgroupbox.h>
#include <qradiobutton.h>
#include <qlineedit.h>
#include <qclipboard.h>
#include <qfiledialog.h>
#include <berryIEditorPart.h>
#include <berryIWorkbenchPage.h>
#include <berryPlatform.h>
#include "QmitkStdMultiWidget.h"
#include "QmitkSliderNavigatorWidget.h"
#include "mitkNodePredicateDataType.h"
#include "mitkNodePredicateOr.h"
#include "mitkImageTimeSelector.h"
#include "mitkProperties.h"
#include "mitkProgressBar.h"
// Includes for image processing
#include "mitkImageCast.h"
#include "mitkImageToItk.h"
#include "mitkITKImageImport.h"
#include "mitkDataNodeObject.h"
#include "mitkNodePredicateData.h"
#include "mitkPlanarFigureInteractor.h"
#include "mitkGlobalInteraction.h"
#include "mitkTensorImage.h"
#include "mitkPlanarCircle.h"
#include "mitkPlanarRectangle.h"
#include "mitkPlanarPolygon.h"
#include "mitkPartialVolumeAnalysisClusteringCalculator.h"
#include <itkVectorImage.h>
#include "itkTensorDerivedMeasurementsFilter.h"
#include "itkDiffusionTensor3D.h"
#include "itkCartesianToPolarVectorImageFilter.h"
#include "itkPolarToCartesianVectorImageFilter.h"
#include "itkBinaryThresholdImageFilter.h"
#include "itkMaskImageFilter.h"
#include "itkCastImageFilter.h"
#include "itkImageMomentsCalculator.h"
#include <vnl/vnl_vector.h>
#define PVA_PI 3.141592653589793238462643383
const std::string QmitkPartialVolumeAnalysisView::VIEW_ID =
"org.mitk.views.partialvolumeanalysisview";
class QmitkRequestStatisticsUpdateEvent : public QEvent
{
public:
enum Type
{
StatisticsUpdateRequest = QEvent::MaxUser - 1025
};
QmitkRequestStatisticsUpdateEvent()
: QEvent( (QEvent::Type) StatisticsUpdateRequest ) {};
};
typedef itk::Image<short, 3> ImageType;
typedef itk::Image<float, 3> FloatImageType;
typedef itk::Image<itk::Vector<float,3>, 3> VectorImageType;
inline bool my_isnan(float x)
{
volatile float d = x;
if(d!=d)
return true;
if(d==d)
return false;
return d != d;
}
QmitkPartialVolumeAnalysisView::QmitkPartialVolumeAnalysisView(QObject */*parent*/, const char */*name*/)
: QmitkFunctionality(),
m_Controls( NULL ),
m_TimeStepperAdapter( NULL ),
m_MeasurementInfoRenderer(0),
m_MeasurementInfoAnnotation(0),
m_SelectedImageNodes( ),
m_SelectedImage( NULL ),
m_SelectedMaskNode( NULL ),
m_SelectedImageMask( NULL ),
m_SelectedPlanarFigureNodes(0),
m_SelectedPlanarFigure( NULL ),
m_IsTensorImage(false),
m_FAImage(0),
m_RDImage(0),
m_ADImage(0),
m_MDImage(0),
m_CAImage(0),
// m_DirectionImage(0),
m_DirectionComp1Image(0),
m_DirectionComp2Image(0),
m_AngularErrorImage(0),
m_SelectedRenderWindow(NULL),
m_LastRenderWindow(NULL),
m_ImageObserverTag( -1 ),
m_ImageMaskObserverTag( -1 ),
m_PlanarFigureObserverTag( -1 ),
m_CurrentStatisticsValid( false ),
m_StatisticsUpdatePending( false ),
m_GaussianSigmaChangedSliding(false),
m_NumberBinsSliding(false),
m_UpsamplingChangedSliding(false),
m_ClusteringResult(NULL),
m_EllipseCounter(0),
m_RectangleCounter(0),
m_PolygonCounter(0),
m_CurrentFigureNodeInitialized(false),
m_QuantifyClass(2),
m_IconTexOFF(new QIcon(":/QmitkPartialVolumeAnalysisView/texIntOFFIcon.png")),
m_IconTexON(new QIcon(":/QmitkPartialVolumeAnalysisView/texIntONIcon.png")),
m_TexIsOn(true)
{
}
QmitkPartialVolumeAnalysisView::~QmitkPartialVolumeAnalysisView()
{
if ( m_SelectedImage.IsNotNull() )
m_SelectedImage->RemoveObserver( m_ImageObserverTag );
if ( m_SelectedImageMask.IsNotNull() )
m_SelectedImageMask->RemoveObserver( m_ImageMaskObserverTag );
if ( m_SelectedPlanarFigure.IsNotNull() )
{
m_SelectedPlanarFigure->RemoveObserver( m_PlanarFigureObserverTag );
m_SelectedPlanarFigure->RemoveObserver( m_InitializedObserverTag );
}
this->GetDefaultDataStorage()->AddNodeEvent -= mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeAddedInDataStorage );
m_SelectedPlanarFigureNodes->NodeChanged.RemoveListener( mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeChanged ) );
m_SelectedPlanarFigureNodes->NodeRemoved.RemoveListener( mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeRemoved ) );
m_SelectedPlanarFigureNodes->PropertyChanged.RemoveListener( mitk::MessageDelegate2<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*, const mitk::BaseProperty*>( this, &QmitkPartialVolumeAnalysisView::PropertyChanged ) );
m_SelectedImageNodes->NodeChanged.RemoveListener( mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeChanged ) );
m_SelectedImageNodes->NodeRemoved.RemoveListener( mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeRemoved ) );
m_SelectedImageNodes->PropertyChanged.RemoveListener( mitk::MessageDelegate2<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*, const mitk::BaseProperty*>( this, &QmitkPartialVolumeAnalysisView::PropertyChanged ) );
}
void QmitkPartialVolumeAnalysisView::CreateQtPartControl(QWidget *parent)
{
if (m_Controls == NULL)
{
m_Controls = new Ui::QmitkPartialVolumeAnalysisViewControls;
m_Controls->setupUi(parent);
this->CreateConnections();
m_Controls->m_ErrorMessageLabel->hide();
}
SetHistogramVisibility();
m_Controls->m_TextureIntON->setIcon(*m_IconTexON);
m_Controls->m_SimilarAnglesFrame->setVisible(false);
m_Controls->m_SimilarAnglesLabel->setVisible(false);
vtkTextProperty *textProp = vtkTextProperty::New();
textProp->SetColor(1.0, 1.0, 1.0);
m_MeasurementInfoAnnotation = vtkCornerAnnotation::New();
m_MeasurementInfoAnnotation->SetMaximumFontSize(12);
m_MeasurementInfoAnnotation->SetTextProperty(textProp);
m_MeasurementInfoRenderer = vtkRenderer::New();
m_MeasurementInfoRenderer->AddActor(m_MeasurementInfoAnnotation);
m_SelectedPlanarFigureNodes = mitk::DataStorageSelection::New(this->GetDefaultDataStorage(), false);
m_SelectedPlanarFigureNodes->NodeChanged.AddListener( mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeChanged ) );
m_SelectedPlanarFigureNodes->NodeRemoved.AddListener( mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeRemoved ) );
m_SelectedPlanarFigureNodes->PropertyChanged.AddListener( mitk::MessageDelegate2<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*, const mitk::BaseProperty*>( this, &QmitkPartialVolumeAnalysisView::PropertyChanged ) );
m_SelectedImageNodes = mitk::DataStorageSelection::New(this->GetDefaultDataStorage(), false);
m_SelectedImageNodes->PropertyChanged.AddListener( mitk::MessageDelegate2<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*, const mitk::BaseProperty*>( this, &QmitkPartialVolumeAnalysisView::PropertyChanged ) );
m_SelectedImageNodes->NodeChanged.AddListener( mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeChanged ) );
m_SelectedImageNodes->NodeRemoved.AddListener( mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeRemoved ) );
this->GetDefaultDataStorage()->AddNodeEvent.AddListener( mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeAddedInDataStorage ) );
Select(NULL,true,true);
SetAdvancedVisibility();
}
void QmitkPartialVolumeAnalysisView::SetHistogramVisibility()
{
m_Controls->m_HistogramWidget->setVisible(m_Controls->m_DisplayHistogramCheckbox->isChecked());
}
void QmitkPartialVolumeAnalysisView::SetAdvancedVisibility()
{
m_Controls->frame_7->setVisible(m_Controls->m_AdvancedCheckbox->isChecked());
}
void QmitkPartialVolumeAnalysisView::CreateConnections()
{
if ( m_Controls )
{
connect( m_Controls->m_DisplayHistogramCheckbox, SIGNAL( clicked() )
, this, SLOT( SetHistogramVisibility() ) );
connect( m_Controls->m_AdvancedCheckbox, SIGNAL( clicked() )
, this, SLOT( SetAdvancedVisibility() ) );
connect( m_Controls->m_NumberBinsSlider, SIGNAL( sliderReleased () ),
this, SLOT( NumberBinsReleasedSlider( ) ) );
connect( m_Controls->m_UpsamplingSlider, SIGNAL( sliderReleased( ) ),
this, SLOT( UpsamplingReleasedSlider( ) ) );
connect( m_Controls->m_GaussianSigmaSlider, SIGNAL( sliderReleased( ) ),
this, SLOT( GaussianSigmaReleasedSlider( ) ) );
connect( m_Controls->m_SimilarAnglesSlider, SIGNAL( sliderReleased( ) ),
this, SLOT( SimilarAnglesReleasedSlider( ) ) );
connect( m_Controls->m_NumberBinsSlider, SIGNAL( valueChanged (int) ),
this, SLOT( NumberBinsChangedSlider( int ) ) );
connect( m_Controls->m_UpsamplingSlider, SIGNAL( valueChanged( int ) ),
this, SLOT( UpsamplingChangedSlider( int ) ) );
connect( m_Controls->m_GaussianSigmaSlider, SIGNAL( valueChanged( int ) ),
this, SLOT( GaussianSigmaChangedSlider( int ) ) );
connect( m_Controls->m_SimilarAnglesSlider, SIGNAL( valueChanged( int ) ),
this, SLOT( SimilarAnglesChangedSlider(int) ) );
connect( m_Controls->m_OpacitySlider, SIGNAL( valueChanged( int ) ),
this, SLOT( OpacityChangedSlider(int) ) );
connect( (QObject*)(m_Controls->m_ButtonCopyHistogramToClipboard), SIGNAL(clicked()),(QObject*) this, SLOT(ToClipBoard()));
connect( m_Controls->m_CircleButton, SIGNAL( clicked() )
, this, SLOT( ActionDrawEllipseTriggered() ) );
connect( m_Controls->m_RectangleButton, SIGNAL( clicked() )
, this, SLOT( ActionDrawRectangleTriggered() ) );
connect( m_Controls->m_PolygonButton, SIGNAL( clicked() )
, this, SLOT( ActionDrawPolygonTriggered() ) );
connect( m_Controls->m_GreenRadio, SIGNAL( clicked(bool) )
, this, SLOT( GreenRadio(bool) ) );
connect( m_Controls->m_PartialVolumeRadio, SIGNAL( clicked(bool) )
, this, SLOT( PartialVolumeRadio(bool) ) );
connect( m_Controls->m_BlueRadio, SIGNAL( clicked(bool) )
, this, SLOT( BlueRadio(bool) ) );
connect( m_Controls->m_AllRadio, SIGNAL( clicked(bool) )
, this, SLOT( AllRadio(bool) ) );
connect( m_Controls->m_EstimateCircle, SIGNAL( clicked() )
, this, SLOT( EstimateCircle() ) );
connect( (QObject*)(m_Controls->m_TextureIntON), SIGNAL(clicked()), this, SLOT(TextIntON()) );
}
}
void QmitkPartialVolumeAnalysisView::EstimateCircle()
{
typedef itk::Image<unsigned char, 3> SegImageType;
SegImageType::Pointer mask_itk = SegImageType::New();
typedef mitk::ImageToItk<SegImageType> CastType;
CastType::Pointer caster = CastType::New();
caster->SetInput(m_SelectedImageMask);
caster->Update();
typedef itk::ImageMomentsCalculator< SegImageType > MomentsType;
MomentsType::Pointer momentsCalc = MomentsType::New();
momentsCalc->SetImage(caster->GetOutput());
momentsCalc->Compute();
MomentsType::VectorType cog = momentsCalc->GetCenterOfGravity();
MomentsType::MatrixType axes = momentsCalc->GetPrincipalAxes();
MomentsType::VectorType moments = momentsCalc->GetPrincipalMoments();
// moments-coord conversion
// third coordinate min oder max?
// max-min = extent
MomentsType::AffineTransformPointer trafo = momentsCalc->GetPhysicalAxesToPrincipalAxesTransform();
itk::ImageRegionIterator<SegImageType>
itimage(caster->GetOutput(), caster->GetOutput()->GetLargestPossibleRegion());
itimage = itimage.Begin();
double max = -9999999999.0;
double min = 9999999999.0;
while( !itimage.IsAtEnd() )
{
if(itimage.Get())
{
ImageType::IndexType index = itimage.GetIndex();
itk::Point<float,3> point;
caster->GetOutput()->TransformIndexToPhysicalPoint(index,point);
itk::Point<float,3> newPoint;
newPoint = trafo->TransformPoint(point);
if(newPoint[2]<min)
min = newPoint[2];
if(newPoint[2]>max)
max = newPoint[2];
}
++itimage;
}
double extent = max - min;
MITK_INFO << "EXTENT = " << extent;
mitk::Point3D origin;
mitk::Vector3D right, bottom, normal;
double factor = 1000.0;
mitk::FillVector3D(origin, cog[0]-factor*axes[1][0]-factor*axes[2][0],
cog[1]-factor*axes[1][1]-factor*axes[2][1],
cog[2]-factor*axes[1][2]-factor*axes[2][2]);
// mitk::FillVector3D(normal, axis[0][0],axis[0][1],axis[0][2]);
mitk::FillVector3D(bottom, 2*factor*axes[1][0], 2*factor*axes[1][1], 2*factor*axes[1][2]);
mitk::FillVector3D(right, 2*factor*axes[2][0], 2*factor*axes[2][1], 2*factor*axes[2][2]);
mitk::PlaneGeometry::Pointer planegeometry = mitk::PlaneGeometry::New();
planegeometry->InitializeStandardPlane(right.Get_vnl_vector(), bottom.Get_vnl_vector());
planegeometry->SetOrigin(origin);
double len1 = sqrt(axes[1][0]*axes[1][0] + axes[1][1]*axes[1][1] + axes[1][2]*axes[1][2]);
double len2 = sqrt(axes[2][0]*axes[2][0] + axes[2][1]*axes[2][1] + axes[2][2]*axes[2][2]);
mitk::Point2D point1;
point1[0] = factor*len1;
point1[1] = factor*len2;
mitk::Point2D point2;
point2[0] = factor*len1+extent*.5;
point2[1] = factor*len2;
mitk::PlanarCircle::Pointer circle = mitk::PlanarCircle::New();
circle->SetGeometry2D(planegeometry);
circle->PlaceFigure( point1 );
circle->SetControlPoint(0,point1);
circle->SetControlPoint(1,point2);
//circle->SetCurrentControlPoint( point2 );
mitk::PlanarFigure::PolyLineType polyline = circle->GetPolyLine( 0 );
MITK_INFO << "SIZE of planar figure polyline: " << polyline.size();
AddFigureToDataStorage(circle, "Circle");
}
void QmitkPartialVolumeAnalysisView::StdMultiWidgetAvailable( QmitkStdMultiWidget& stdMultiWidget )
{
QmitkFunctionality::StdMultiWidgetAvailable(stdMultiWidget);
}
bool QmitkPartialVolumeAnalysisView::AssertDrawingIsPossible(bool checked)
{
if (m_SelectedImageNodes->GetNode().IsNull())
{
checked = false;
this->HandleException("Please select an image!", this->m_Parent, true);
return false;
}
//this->GetActiveStdMultiWidget()->SetWidgetPlanesVisibility(false);
return checked;
}
void QmitkPartialVolumeAnalysisView::ActionDrawEllipseTriggered()
{
bool checked = m_Controls->m_CircleButton->isChecked();
if(!this->AssertDrawingIsPossible(checked))
return;
mitk::PlanarCircle::Pointer figure = mitk::PlanarCircle::New();
this->AddFigureToDataStorage(figure, QString("Circle%1").arg(++m_EllipseCounter));
MITK_INFO << "PlanarCircle created ...";
}
void QmitkPartialVolumeAnalysisView::ActionDrawRectangleTriggered()
{
bool checked = m_Controls->m_RectangleButton->isChecked();
if(!this->AssertDrawingIsPossible(checked))
return;
mitk::PlanarRectangle::Pointer figure = mitk::PlanarRectangle::New();
this->AddFigureToDataStorage(figure, QString("Rectangle%1").arg(++m_RectangleCounter));
MITK_INFO << "PlanarRectangle created ...";
}
void QmitkPartialVolumeAnalysisView::ActionDrawPolygonTriggered()
{
bool checked = m_Controls->m_PolygonButton->isChecked();
if(!this->AssertDrawingIsPossible(checked))
return;
mitk::PlanarPolygon::Pointer figure = mitk::PlanarPolygon::New();
figure->ClosedOn();
this->AddFigureToDataStorage(figure, QString("Polygon%1").arg(++m_PolygonCounter));
MITK_INFO << "PlanarPolygon created ...";
}
void QmitkPartialVolumeAnalysisView::AddFigureToDataStorage(mitk::PlanarFigure* figure, const QString& name,
const char *propertyKey, mitk::BaseProperty *property )
{
mitk::DataNode::Pointer newNode = mitk::DataNode::New();
newNode->SetName(name.toStdString());
newNode->SetData(figure);
// Add custom property, if available
if ( (propertyKey != NULL) && (property != NULL) )
{
newNode->AddProperty( propertyKey, property );
}
// figure drawn on the topmost layer / image
this->GetDataStorage()->Add(newNode, m_SelectedImageNodes->GetNode() );
std::vector<mitk::DataNode*> selectedNodes = GetDataManagerSelection();
for(unsigned int i = 0; i < selectedNodes.size(); i++)
{
selectedNodes[i]->SetSelected(false);
}
selectedNodes = m_SelectedPlanarFigureNodes->GetNodes();
for(unsigned int i = 0; i < selectedNodes.size(); i++)
{
selectedNodes[i]->SetSelected(false);
}
newNode->SetSelected(true);
Select(newNode);
}
void QmitkPartialVolumeAnalysisView::PlanarFigureInitialized()
{
if(m_SelectedPlanarFigureNodes->GetNode().IsNull())
return;
m_CurrentFigureNodeInitialized = true;
this->Select(m_SelectedPlanarFigureNodes->GetNode());
m_Controls->m_CircleButton->setChecked(false);
m_Controls->m_RectangleButton->setChecked(false);
m_Controls->m_PolygonButton->setChecked(false);
//this->GetActiveStdMultiWidget()->SetWidgetPlanesVisibility(true);
this->RequestStatisticsUpdate();
}
void QmitkPartialVolumeAnalysisView::PlanarFigureFocus(mitk::DataNode* node)
{
mitk::PlanarFigure* _PlanarFigure = 0;
_PlanarFigure = dynamic_cast<mitk::PlanarFigure*> (node->GetData());
if (_PlanarFigure)
{
FindRenderWindow(node);
const mitk::PlaneGeometry
* _PlaneGeometry =
dynamic_cast<const mitk::PlaneGeometry*> (_PlanarFigure->GetGeometry2D());
// make node visible
if (m_SelectedRenderWindow)
{
mitk::Point3D centerP = _PlaneGeometry->GetOrigin();
m_SelectedRenderWindow->GetSliceNavigationController()->ReorientSlices(
centerP, _PlaneGeometry->GetNormal());
m_SelectedRenderWindow->GetSliceNavigationController()->SelectSliceByPoint(
centerP);
}
}
}
void QmitkPartialVolumeAnalysisView::FindRenderWindow(mitk::DataNode* node)
{
if(node)
{
mitk::PlanarFigure* _PlanarFigure = 0;
_PlanarFigure = dynamic_cast<mitk::PlanarFigure*> (node->GetData());
if (_PlanarFigure)
{
m_SelectedRenderWindow = 0;
QmitkRenderWindow* RenderWindow1 =
this->GetActiveStdMultiWidget()->GetRenderWindow1();
QmitkRenderWindow* RenderWindow2 =
this->GetActiveStdMultiWidget()->GetRenderWindow2();
QmitkRenderWindow* RenderWindow3 =
this->GetActiveStdMultiWidget()->GetRenderWindow3();
QmitkRenderWindow* RenderWindow4 =
this->GetActiveStdMultiWidget()->GetRenderWindow4();
bool PlanarFigureInitializedWindow = false;
// find initialized renderwindow
if (node->GetBoolProperty("PlanarFigureInitializedWindow",
PlanarFigureInitializedWindow, RenderWindow1->GetRenderer()))
{
m_SelectedRenderWindow = RenderWindow1;
}
if (!m_SelectedRenderWindow && node->GetBoolProperty(
"PlanarFigureInitializedWindow", PlanarFigureInitializedWindow,
RenderWindow2->GetRenderer()))
{
m_SelectedRenderWindow = RenderWindow2;
}
if (!m_SelectedRenderWindow && node->GetBoolProperty(
"PlanarFigureInitializedWindow", PlanarFigureInitializedWindow,
RenderWindow3->GetRenderer()))
{
m_SelectedRenderWindow = RenderWindow3;
}
if (!m_SelectedRenderWindow && node->GetBoolProperty(
"PlanarFigureInitializedWindow", PlanarFigureInitializedWindow,
RenderWindow4->GetRenderer()))
{
m_SelectedRenderWindow = RenderWindow4;
}
}
}
}
void QmitkPartialVolumeAnalysisView::OnSelectionChanged( std::vector<mitk::DataNode*> nodes )
{
if ( !this->IsVisible() )
{
return;
}
if ( nodes.empty() || nodes.size() > 1 )
{
// Nothing to do: invalidate image, clear statistics, histogram, and GUI
return;
}
Select(nodes.front());
}
void QmitkPartialVolumeAnalysisView::Select( mitk::DataNode::Pointer node, bool clearMaskOnFirstArgNULL, bool clearImageOnFirstArgNULL )
{
// Clear any unreferenced images
this->RemoveOrphanImages();
bool somethingChanged = false;
if(node.IsNull())
{
somethingChanged = true;
if(clearMaskOnFirstArgNULL)
{
if ( (m_SelectedImageMask.IsNotNull()) && (m_ImageMaskObserverTag >= 0) )
{
m_SelectedImageMask->RemoveObserver( m_ImageMaskObserverTag );
m_ImageMaskObserverTag = -1;
}
if ( (m_SelectedPlanarFigure.IsNotNull()) && (m_PlanarFigureObserverTag >= 0) )
{
m_SelectedPlanarFigure->RemoveObserver( m_PlanarFigureObserverTag );
m_PlanarFigureObserverTag = -1;
}
if ( (m_SelectedPlanarFigure.IsNotNull()) && (m_InitializedObserverTag >= 0) )
{
m_SelectedPlanarFigure->RemoveObserver( m_InitializedObserverTag );
m_InitializedObserverTag = -1;
}
m_SelectedPlanarFigure = NULL;
m_SelectedPlanarFigureNodes->RemoveAllNodes();
m_CurrentFigureNodeInitialized = false;
m_SelectedRenderWindow = 0;
m_SelectedMaskNode = NULL;
m_SelectedImageMask = NULL;
}
if(clearImageOnFirstArgNULL)
{
if ( (m_SelectedImage.IsNotNull()) && (m_ImageObserverTag >= 0) )
{
m_SelectedImage->RemoveObserver( m_ImageObserverTag );
m_ImageObserverTag = -1;
}
m_SelectedImageNodes->RemoveAllNodes();
m_SelectedImage = NULL;
m_IsTensorImage = false;
m_FAImage = NULL;
m_RDImage = NULL;
m_ADImage = NULL;
m_MDImage = NULL;
m_CAImage = NULL;
m_DirectionComp1Image = NULL;
m_DirectionComp2Image = NULL;
m_AngularErrorImage = NULL;
m_Controls->m_SimilarAnglesFrame->setVisible(false);
m_Controls->m_SimilarAnglesLabel->setVisible(false);
}
}
else
{
typedef itk::SimpleMemberCommand< QmitkPartialVolumeAnalysisView > ITKCommandType;
ITKCommandType::Pointer changeListener;
changeListener = ITKCommandType::New();
changeListener->SetCallbackFunction( this, &QmitkPartialVolumeAnalysisView::RequestStatisticsUpdate );
// Get selected element
mitk::TensorImage *selectedTensorImage = dynamic_cast< mitk::TensorImage * >( node->GetData() );
mitk::Image *selectedImage = dynamic_cast< mitk::Image * >( node->GetData() );
mitk::PlanarFigure *selectedPlanar = dynamic_cast< mitk::PlanarFigure * >( node->GetData() );
bool isMask = false;
bool isImage = false;
bool isPlanar = false;
bool isTensorImage = false;
if (selectedTensorImage != NULL)
{
isTensorImage = true;
}
else if(selectedImage != NULL)
{
node->GetPropertyValue("binary", isMask);
isImage = !isMask;
}
else if ( (selectedPlanar != NULL) )
{
isPlanar = true;
}
// image
if(isImage && selectedImage->GetDimension()==3)
{
if(selectedImage != m_SelectedImage.GetPointer())
{
somethingChanged = true;
if ( (m_SelectedImage.IsNotNull()) && (m_ImageObserverTag >= 0) )
{
m_SelectedImage->RemoveObserver( m_ImageObserverTag );
m_ImageObserverTag = -1;
}
*m_SelectedImageNodes = node;
m_SelectedImage = selectedImage;
m_IsTensorImage = false;
m_FAImage = NULL;
m_RDImage = NULL;
m_ADImage = NULL;
m_MDImage = NULL;
m_CAImage = NULL;
m_DirectionComp1Image = NULL;
m_DirectionComp2Image = NULL;
m_AngularErrorImage = NULL;
// Add change listeners to selected objects
m_ImageObserverTag = m_SelectedImage->AddObserver(
itk::ModifiedEvent(), changeListener );
m_Controls->m_SimilarAnglesFrame->setVisible(false);
m_Controls->m_SimilarAnglesLabel->setVisible(false);
m_Controls->m_SelectedImageLabel->setText( m_SelectedImageNodes->GetNode()->GetName().c_str() );
}
}
//planar
if(isPlanar)
{
if(selectedPlanar != m_SelectedPlanarFigure.GetPointer())
{
MITK_INFO << "Planar selection changed";
somethingChanged = true;
// Possibly previous change listeners
if ( (m_SelectedPlanarFigure.IsNotNull()) && (m_PlanarFigureObserverTag >= 0) )
{
m_SelectedPlanarFigure->RemoveObserver( m_PlanarFigureObserverTag );
m_PlanarFigureObserverTag = -1;
}
if ( (m_SelectedPlanarFigure.IsNotNull()) && (m_InitializedObserverTag >= 0) )
{
m_SelectedPlanarFigure->RemoveObserver( m_InitializedObserverTag );
m_InitializedObserverTag = -1;
}
m_SelectedPlanarFigure = selectedPlanar;
*m_SelectedPlanarFigureNodes = node;
m_CurrentFigureNodeInitialized = selectedPlanar->IsPlaced();
m_SelectedMaskNode = NULL;
m_SelectedImageMask = NULL;
m_PlanarFigureObserverTag = m_SelectedPlanarFigure->AddObserver(
mitk::EndInteractionPlanarFigureEvent(), changeListener );
if(!m_CurrentFigureNodeInitialized)
{
typedef itk::SimpleMemberCommand< QmitkPartialVolumeAnalysisView > ITKCommandType;
ITKCommandType::Pointer initializationCommand;
initializationCommand = ITKCommandType::New();
// set the callback function of the member command
initializationCommand->SetCallbackFunction( this, &QmitkPartialVolumeAnalysisView::PlanarFigureInitialized );
// add an observer
m_InitializedObserverTag = selectedPlanar->AddObserver( mitk::EndPlacementPlanarFigureEvent(), initializationCommand );
}
m_Controls->m_SelectedMaskLabel->setText( m_SelectedPlanarFigureNodes->GetNode()->GetName().c_str() );
PlanarFigureFocus(node);
}
}
//mask
if(isMask && selectedImage->GetDimension()==3)
{
if(selectedImage != m_SelectedImage.GetPointer())
{
somethingChanged = true;
if ( (m_SelectedImageMask.IsNotNull()) && (m_ImageMaskObserverTag >= 0) )
{
m_SelectedImageMask->RemoveObserver( m_ImageMaskObserverTag );
m_ImageMaskObserverTag = -1;
}
m_SelectedMaskNode = node;
m_SelectedImageMask = selectedImage;
m_SelectedPlanarFigure = NULL;
m_SelectedPlanarFigureNodes->RemoveAllNodes();
m_ImageMaskObserverTag = m_SelectedImageMask->AddObserver(
itk::ModifiedEvent(), changeListener );
m_Controls->m_SelectedMaskLabel->setText( m_SelectedMaskNode->GetName().c_str() );
}
}
//tensor image
if(isTensorImage && selectedTensorImage->GetDimension()==3)
{
if(selectedImage != m_SelectedImage.GetPointer())
{
somethingChanged = true;
if ( (m_SelectedImage.IsNotNull()) && (m_ImageObserverTag >= 0) )
{
m_SelectedImage->RemoveObserver( m_ImageObserverTag );
m_ImageObserverTag = -1;
}
*m_SelectedImageNodes = node;
m_SelectedImage = selectedImage;
m_IsTensorImage = true;
ExtractTensorImages(selectedImage);
// Add change listeners to selected objects
m_ImageObserverTag = m_SelectedImage->AddObserver(
itk::ModifiedEvent(), changeListener );
m_Controls->m_SimilarAnglesFrame->setVisible(true);
m_Controls->m_SimilarAnglesLabel->setVisible(true);
m_Controls->m_SelectedImageLabel->setText( m_SelectedImageNodes->GetNode()->GetName().c_str() );
}
}
}
if(somethingChanged)
{
this->SetMeasurementInfoToRenderWindow("");
if(m_SelectedPlanarFigure.IsNull() && m_SelectedImageMask.IsNull() )
{
m_Controls->m_SelectedMaskLabel->setText( "None" );
m_Controls->m_ResampleOptionsFrame->setEnabled(false);
m_Controls->m_HistogramWidget->setEnabled(false);
m_Controls->m_ClassSelector->setEnabled(false);
m_Controls->m_DisplayHistogramCheckbox->setEnabled(false);
m_Controls->m_AdvancedCheckbox->setEnabled(false);
m_Controls->frame_7->setEnabled(false);
}
else
{
m_Controls->m_ResampleOptionsFrame->setEnabled(true);
m_Controls->m_HistogramWidget->setEnabled(true);
m_Controls->m_ClassSelector->setEnabled(true);
m_Controls->m_DisplayHistogramCheckbox->setEnabled(true);
m_Controls->m_AdvancedCheckbox->setEnabled(true);
m_Controls->frame_7->setEnabled(true);
}
// Clear statistics / histogram GUI if nothing is selected
if ( m_SelectedImage.IsNull() )
{
m_Controls->m_PlanarFigureButtonsFrame->setEnabled(false);
m_Controls->m_OpacityFrame->setEnabled(false);
m_Controls->m_SelectedImageLabel->setText( "None" );
}
else
{
m_Controls->m_PlanarFigureButtonsFrame->setEnabled(true);
m_Controls->m_OpacityFrame->setEnabled(true);
}
if( m_SelectedImage.IsNull()
|| (m_SelectedPlanarFigure.IsNull() && m_SelectedImageMask.IsNull()) )
{
m_Controls->m_HistogramWidget->ClearItemModel();
m_CurrentStatisticsValid = false;
m_Controls->m_ErrorMessageLabel->hide();
}
else
{
this->RequestStatisticsUpdate();
}
}
}
void QmitkPartialVolumeAnalysisView::ShowClusteringResults()
{
typedef itk::Image<unsigned char, 3> MaskImageType;
mitk::Image::Pointer mask = 0;
MaskImageType::Pointer itkmask = 0;
if(m_IsTensorImage && m_Controls->m_SimilarAnglesSlider->value() != 0)
{
typedef itk::Image<float, 3> AngularErrorImageType;
typedef mitk::ImageToItk<AngularErrorImageType> CastType;
CastType::Pointer caster = CastType::New();
caster->SetInput(m_AngularErrorImage);
caster->Update();
typedef itk::BinaryThresholdImageFilter< AngularErrorImageType, MaskImageType > ThreshType;
ThreshType::Pointer thresh = ThreshType::New();
thresh->SetUpperThreshold((90-m_Controls->m_SimilarAnglesSlider->value())*(PVA_PI/180.0));
thresh->SetInsideValue(1.0);
thresh->SetInput(caster->GetOutput());
thresh->Update();
itkmask = thresh->GetOutput();
mask = mitk::Image::New();
mask->InitializeByItk(itkmask.GetPointer());
mask->SetVolume(itkmask->GetBufferPointer());
// GetDefaultDataStorage()->Remove(m_newnode);
// m_newnode = mitk::DataNode::New();
// m_newnode->SetData(mask);
// m_newnode->SetName("masking node");
// m_newnode->SetIntProperty( "layer", 1002 );
// GetDefaultDataStorage()->Add(m_newnode, m_SelectedImageNodes->GetNode());
}
mitk::Image::Pointer clusteredImage;
ClusteringType::Pointer clusterer = ClusteringType::New();
if(m_QuantifyClass==3)
{
if(m_IsTensorImage)
{
double *green_fa, *green_rd, *green_ad, *green_md;
//double *greengray_fa, *greengray_rd, *greengray_ad, *greengray_md;
double *gray_fa, *gray_rd, *gray_ad, *gray_md;
//double *redgray_fa, *redgray_rd, *redgray_ad, *redgray_md;
double *red_fa, *red_rd, *red_ad, *red_md;
mitk::Image* tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(0);
mitk::Image::ConstPointer imgToCluster = tmpImg;
red_fa = clusterer->PerformQuantification(imgToCluster, m_CurrentRGBClusteringResults->rgbChannels->r, mask);
green_fa = clusterer->PerformQuantification(imgToCluster, m_CurrentRGBClusteringResults->rgbChannels->g, mask);
gray_fa = clusterer->PerformQuantification(imgToCluster, m_CurrentRGBClusteringResults->rgbChannels->b, mask);
tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(3);
mitk::Image::ConstPointer imgToCluster3 = tmpImg;
red_rd = clusterer->PerformQuantification(imgToCluster3, m_CurrentRGBClusteringResults->rgbChannels->r, mask);
green_rd = clusterer->PerformQuantification(imgToCluster3, m_CurrentRGBClusteringResults->rgbChannels->g, mask);
gray_rd = clusterer->PerformQuantification(imgToCluster3, m_CurrentRGBClusteringResults->rgbChannels->b, mask);
tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(4);
mitk::Image::ConstPointer imgToCluster4 = tmpImg;
red_ad = clusterer->PerformQuantification(imgToCluster4, m_CurrentRGBClusteringResults->rgbChannels->r, mask);
green_ad = clusterer->PerformQuantification(imgToCluster4, m_CurrentRGBClusteringResults->rgbChannels->g, mask);
gray_ad = clusterer->PerformQuantification(imgToCluster4, m_CurrentRGBClusteringResults->rgbChannels->b, mask);
tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(5);
mitk::Image::ConstPointer imgToCluster5 = tmpImg;
red_md = clusterer->PerformQuantification(imgToCluster5, m_CurrentRGBClusteringResults->rgbChannels->r, mask);
green_md = clusterer->PerformQuantification(imgToCluster5, m_CurrentRGBClusteringResults->rgbChannels->g, mask);
gray_md = clusterer->PerformQuantification(imgToCluster5, m_CurrentRGBClusteringResults->rgbChannels->b, mask);
// clipboard
QString clipboardText("FA\t%1\t%2\t\t%3\t%4\t\t%5\t%6\t");
clipboardText = clipboardText
.arg(red_fa[0]).arg(red_fa[1])
.arg(gray_fa[0]).arg(gray_fa[1])
.arg(green_fa[0]).arg(green_fa[1]);
QString clipboardText3("RD\t%1\t%2\t\t%3\t%4\t\t%5\t%6\t");
clipboardText3 = clipboardText3
.arg(red_rd[0]).arg(red_rd[1])
.arg(gray_rd[0]).arg(gray_rd[1])
.arg(green_rd[0]).arg(green_rd[1]);
QString clipboardText4("AD\t%1\t%2\t\t%3\t%4\t\t%5\t%6\t");
clipboardText4 = clipboardText4
.arg(red_ad[0]).arg(red_ad[1])
.arg(gray_ad[0]).arg(gray_ad[1])
.arg(green_ad[0]).arg(green_ad[1]);
QString clipboardText5("MD\t%1\t%2\t\t%3\t%4\t\t%5\t%6");
clipboardText5 = clipboardText5
.arg(red_md[0]).arg(red_md[1])
.arg(gray_md[0]).arg(gray_md[1])
.arg(green_md[0]).arg(green_md[1]);
QApplication::clipboard()->setText(clipboardText+clipboardText3+clipboardText4+clipboardText5, QClipboard::Clipboard);
// now paint infos also on renderwindow
QString plainInfoText("%1 %2 %3 \n");
plainInfoText = plainInfoText
.arg("Red ", 20)
.arg("Gray ", 20)
.arg("Green", 20);
QString plainInfoText0("FA:%1 ± %2%3 ± %4%5 ± %6\n");
plainInfoText0 = plainInfoText0
.arg(red_fa[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(red_fa[1], -10, 'g', 2, QLatin1Char( ' ' ))
.arg(gray_fa[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(gray_fa[1], -10, 'g', 2, QLatin1Char( ' ' ))
.arg(green_fa[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(green_fa[1], -10, 'g', 2, QLatin1Char( ' ' ));
QString plainInfoText3("RDx10³:%1 ± %2%3 ± %4%5 ± %6\n");
plainInfoText3 = plainInfoText3
.arg(1000.0 * red_rd[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * red_rd[1], -10, 'g', 2, QLatin1Char( ' ' ))
.arg(1000.0 * gray_rd[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * gray_rd[1], -10, 'g', 2, QLatin1Char( ' ' ))
.arg(1000.0 * green_rd[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * green_rd[1], -10, 'g', 2, QLatin1Char( ' ' ));
QString plainInfoText4("ADx10³:%1 ± %2%3 ± %4%5 ± %6\n");
plainInfoText4 = plainInfoText4
.arg(1000.0 * red_ad[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * red_ad[1], -10, 'g', 2, QLatin1Char( ' ' ))
.arg(1000.0 * gray_ad[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * gray_ad[1], -10, 'g', 2, QLatin1Char( ' ' ))
.arg(1000.0 * green_ad[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * green_ad[1], -10, 'g', 2, QLatin1Char( ' ' ));
QString plainInfoText5("MDx10³:%1 ± %2%3 ± %4%5 ± %6");
plainInfoText5 = plainInfoText5
.arg(1000.0 * red_md[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * red_md[1], -10, 'g', 2, QLatin1Char( ' ' ))
.arg(1000.0 * gray_md[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * gray_md[1], -10, 'g', 2, QLatin1Char( ' ' ))
.arg(1000.0 * green_md[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * green_md[1], -10, 'g', 2, QLatin1Char( ' ' ));
this->SetMeasurementInfoToRenderWindow(plainInfoText+plainInfoText0+plainInfoText3+plainInfoText4+plainInfoText5);
}
else
{
double* green;
double* gray;
double* red;
mitk::Image* tmpImg = m_CurrentStatisticsCalculator->GetInternalImage();
mitk::Image::ConstPointer imgToCluster = tmpImg;
red = clusterer->PerformQuantification(imgToCluster, m_CurrentRGBClusteringResults->rgbChannels->r);
green = clusterer->PerformQuantification(imgToCluster, m_CurrentRGBClusteringResults->rgbChannels->g);
gray = clusterer->PerformQuantification(imgToCluster, m_CurrentRGBClusteringResults->rgbChannels->b);
// clipboard
QString clipboardText("%1\t%2\t\t%3\t%4\t\t%5\t%6");
clipboardText = clipboardText.arg(red[0]).arg(red[1])
.arg(gray[0]).arg(gray[1])
.arg(green[0]).arg(green[1]);
QApplication::clipboard()->setText(clipboardText, QClipboard::Clipboard);
// now paint infos also on renderwindow
QString plainInfoText("Red: %1 ± %2\nGray: %3 ± %4\nGreen: %5 ± %6");
plainInfoText = plainInfoText.arg(red[0]).arg(red[1])
.arg(gray[0]).arg(gray[1])
.arg(green[0]).arg(green[1]);
this->SetMeasurementInfoToRenderWindow(plainInfoText);
}
clusteredImage = m_CurrentRGBClusteringResults->rgb;
}
else
{
if(m_IsTensorImage)
{
double *red_fa, *red_rd, *red_ad, *red_md;
mitk::Image* tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(0);
mitk::Image::ConstPointer imgToCluster = tmpImg;
red_fa = clusterer->PerformQuantification(imgToCluster, m_CurrentPerformClusteringResults->clusteredImage, mask);
tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(3);
mitk::Image::ConstPointer imgToCluster3 = tmpImg;
red_rd = clusterer->PerformQuantification(imgToCluster3, m_CurrentPerformClusteringResults->clusteredImage, mask);
tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(4);
mitk::Image::ConstPointer imgToCluster4 = tmpImg;
red_ad = clusterer->PerformQuantification(imgToCluster4, m_CurrentPerformClusteringResults->clusteredImage, mask);
tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(5);
mitk::Image::ConstPointer imgToCluster5 = tmpImg;
red_md = clusterer->PerformQuantification(imgToCluster5, m_CurrentPerformClusteringResults->clusteredImage, mask);
// clipboard
QString clipboardText("FA\t%1\t%2\t");
clipboardText = clipboardText
.arg(red_fa[0]).arg(red_fa[1]);
QString clipboardText3("RD\t%1\t%2\t");
clipboardText3 = clipboardText3
.arg(red_rd[0]).arg(red_rd[1]);
QString clipboardText4("AD\t%1\t%2\t");
clipboardText4 = clipboardText4
.arg(red_ad[0]).arg(red_ad[1]);
QString clipboardText5("MD\t%1\t%2\t");
clipboardText5 = clipboardText5
.arg(red_md[0]).arg(red_md[1]);
QApplication::clipboard()->setText(clipboardText+clipboardText3+clipboardText4+clipboardText5, QClipboard::Clipboard);
// now paint infos also on renderwindow
QString plainInfoText("%1 \n");
plainInfoText = plainInfoText
.arg("Red ", 20);
QString plainInfoText0("FA:%1 ± %2\n");
plainInfoText0 = plainInfoText0
.arg(red_fa[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(red_fa[1], -10, 'g', 2, QLatin1Char( ' ' ));
QString plainInfoText3("RDx10³:%1 ± %2\n");
plainInfoText3 = plainInfoText3
.arg(1000.0 * red_rd[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * red_rd[1], -10, 'g', 2, QLatin1Char( ' ' ));
QString plainInfoText4("ADx10³:%1 ± %2\n");
plainInfoText4 = plainInfoText4
.arg(1000.0 * red_ad[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * red_ad[1], -10, 'g', 2, QLatin1Char( ' ' ));
QString plainInfoText5("MDx10³:%1 ± %2");
plainInfoText5 = plainInfoText5
.arg(1000.0 * red_md[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * red_md[1], -10, 'g', 2, QLatin1Char( ' ' ));
this->SetMeasurementInfoToRenderWindow(plainInfoText+plainInfoText0+plainInfoText3+plainInfoText4+plainInfoText5);
}
else
{
double* quant;
mitk::Image* tmpImg = m_CurrentStatisticsCalculator->GetInternalImage();
mitk::Image::ConstPointer imgToCluster = tmpImg;
quant = clusterer->PerformQuantification(imgToCluster, m_CurrentPerformClusteringResults->clusteredImage);
// clipboard
QString clipboardText("%1\t%2");
clipboardText = clipboardText.arg(quant[0]).arg(quant[1]);
QApplication::clipboard()->setText(clipboardText, QClipboard::Clipboard);
// now paint infos also on renderwindow
QString plainInfoText("Measurement: %1 ± %2");
plainInfoText = plainInfoText.arg(quant[0]).arg(quant[1]);
this->SetMeasurementInfoToRenderWindow(plainInfoText);
}
clusteredImage = m_CurrentPerformClusteringResults->displayImage;
}
if(mask.IsNotNull())
{
typedef itk::Image<itk::RGBAPixel<unsigned char>,3> RGBImageType;
typedef mitk::ImageToItk<RGBImageType> ClusterCasterType;
ClusterCasterType::Pointer clCaster = ClusterCasterType::New();
clCaster->SetInput(clusteredImage);
clCaster->Update();
clCaster->GetOutput();
typedef itk::MaskImageFilter< RGBImageType, MaskImageType, RGBImageType > MaskType;
MaskType::Pointer masker = MaskType::New();
masker->SetInput1(clCaster->GetOutput());
masker->SetInput2(itkmask);
masker->Update();
clusteredImage = mitk::Image::New();
clusteredImage->InitializeByItk(masker->GetOutput());
clusteredImage->SetVolume(masker->GetOutput()->GetBufferPointer());
}
if(m_ClusteringResult.IsNotNull())
{
GetDefaultDataStorage()->Remove(m_ClusteringResult);
}
m_ClusteringResult = mitk::DataNode::New();
m_ClusteringResult->SetBoolProperty("helper object", true);
m_ClusteringResult->SetIntProperty( "layer", 1000 );
m_ClusteringResult->SetBoolProperty("texture interpolation", m_TexIsOn);
m_ClusteringResult->SetData(clusteredImage);
m_ClusteringResult->SetName("Clusterprobs");
GetDefaultDataStorage()->Add(m_ClusteringResult, m_SelectedImageNodes->GetNode());
if(m_SelectedPlanarFigure.IsNotNull() && m_SelectedPlanarFigureNodes->GetNode().IsNotNull())
{
m_SelectedPlanarFigureNodes->GetNode()->SetIntProperty( "layer", 1001 );
}
GetActiveStdMultiWidget()->RequestUpdate();
}
void QmitkPartialVolumeAnalysisView::UpdateStatistics()
{
MITK_INFO << "UpdateStatistics()";
if(!m_CurrentFigureNodeInitialized && m_SelectedPlanarFigure.IsNotNull())
{
MITK_INFO << "Selected planar figure not initialized. No stats calculation performed.";
return;
}
// Remove any cached images that are no longer referenced elsewhere
this->RemoveOrphanImages();
QmitkStdMultiWidget *multiWidget = this->GetActiveStdMultiWidget();
if ( multiWidget == NULL )
{
return;
}
if ( m_SelectedImage.IsNotNull() )
{
// Check if a the selected image is a multi-channel image. If yes, statistics
// cannot be calculated currently.
if ( !m_IsTensorImage && m_SelectedImage->GetPixelType().GetNumberOfComponents() > 1 )
{
std::stringstream message;
message << "<font color='red'>Multi-component images not supported.</font>";
m_Controls->m_ErrorMessageLabel->setText( message.str().c_str() );
m_Controls->m_ErrorMessageLabel->show();
m_Controls->m_HistogramWidget->ClearItemModel();
m_CurrentStatisticsValid = false;
return;
}
// Retrieve HistogramStatisticsCalculator from has map (or create a new one
// for this image if non-existant)
PartialVolumeAnalysisMapType::iterator it =
m_PartialVolumeAnalysisMap.find( m_SelectedImage );
if ( it != m_PartialVolumeAnalysisMap.end() )
{
m_CurrentStatisticsCalculator = it->second;
MITK_INFO << "Retrieving StatisticsCalculator";
}
else
{
m_CurrentStatisticsCalculator = mitk::PartialVolumeAnalysisHistogramCalculator::New();
+// m_CurrentStatisticsCalculator->SetPlanarFigureThickness(1);
if(m_IsTensorImage)
{
m_CurrentStatisticsCalculator->SetImage( m_CAImage );
m_CurrentStatisticsCalculator->AddAdditionalResamplingImage( m_FAImage );
m_CurrentStatisticsCalculator->AddAdditionalResamplingImage( m_DirectionComp1Image );
m_CurrentStatisticsCalculator->AddAdditionalResamplingImage( m_DirectionComp2Image );
m_CurrentStatisticsCalculator->AddAdditionalResamplingImage( m_RDImage );
m_CurrentStatisticsCalculator->AddAdditionalResamplingImage( m_ADImage );
m_CurrentStatisticsCalculator->AddAdditionalResamplingImage( m_MDImage );
}
else
{
m_CurrentStatisticsCalculator->SetImage( m_SelectedImage );
}
m_PartialVolumeAnalysisMap[m_SelectedImage] = m_CurrentStatisticsCalculator;
MITK_INFO << "Creating StatisticsCalculator";
}
std::string maskName;
std::string maskType;
unsigned int maskDimension;
if ( m_SelectedImageMask.IsNotNull() )
{
mitk::PixelType pixelType = m_SelectedImageMask->GetPixelType();
std::cout << pixelType.GetType() << std::endl;
if(pixelType.GetBitsPerComponent() == 16)
{
//convert from short to uchar
typedef itk::Image<short, 3> ShortImageType;
typedef itk::Image<unsigned char, 3> CharImageType;
CharImageType::Pointer charImage;
ShortImageType::Pointer shortImage;
mitk::CastToItkImage(m_SelectedImageMask, shortImage);
typedef itk::CastImageFilter<ShortImageType, CharImageType> ImageCasterType;
ImageCasterType::Pointer caster = ImageCasterType::New();
caster->SetInput( shortImage );
caster->Update();
charImage = caster->GetOutput();
mitk::CastToMitkImage(charImage, m_SelectedImageMask);
}
m_CurrentStatisticsCalculator->SetImageMask( m_SelectedImageMask );
m_CurrentStatisticsCalculator->SetMaskingModeToImage();
maskName = m_SelectedMaskNode->GetName();
maskType = m_SelectedImageMask->GetNameOfClass();
maskDimension = 3;
std::stringstream maskLabel;
maskLabel << maskName;
if ( maskDimension > 0 )
{
maskLabel << " [" << maskDimension << "D " << maskType << "]";
}
m_Controls->m_SelectedMaskLabel->setText( maskLabel.str().c_str() );
}
else if ( m_SelectedPlanarFigure.IsNotNull() && m_SelectedPlanarFigureNodes->GetNode().IsNotNull())
{
m_CurrentStatisticsCalculator->SetPlanarFigure( m_SelectedPlanarFigure );
m_CurrentStatisticsCalculator->SetMaskingModeToPlanarFigure();
maskName = m_SelectedPlanarFigureNodes->GetNode()->GetName();
maskType = m_SelectedPlanarFigure->GetNameOfClass();
maskDimension = 2;
}
else
{
m_CurrentStatisticsCalculator->SetMaskingModeToNone();
maskName = "None";
maskType = "";
maskDimension = 0;
}
bool statisticsChanged = false;
bool statisticsCalculationSuccessful = false;
// Initialize progress bar
mitk::ProgressBar::GetInstance()->AddStepsToDo( 100 );
// Install listener for progress events and initialize progress bar
typedef itk::SimpleMemberCommand< QmitkPartialVolumeAnalysisView > ITKCommandType;
ITKCommandType::Pointer progressListener;
progressListener = ITKCommandType::New();
progressListener->SetCallbackFunction( this, &QmitkPartialVolumeAnalysisView::UpdateProgressBar );
unsigned long progressObserverTag = m_CurrentStatisticsCalculator
->AddObserver( itk::ProgressEvent(), progressListener );
ClusteringType::ParamsType *cparams = 0;
ClusteringType::ClusterResultType *cresult = 0;
ClusteringType::HistType *chist = 0;
try
{
m_CurrentStatisticsCalculator->SetNumberOfBins(m_Controls->m_NumberBins->text().toInt());
m_CurrentStatisticsCalculator->SetUpsamplingFactor(m_Controls->m_Upsampling->text().toDouble());
m_CurrentStatisticsCalculator->SetGaussianSigma(m_Controls->m_GaussianSigma->text().toDouble());
// Compute statistics
statisticsChanged =
m_CurrentStatisticsCalculator->ComputeStatistics( );
mitk::Image* tmpImg = m_CurrentStatisticsCalculator->GetInternalImage();
mitk::Image::ConstPointer imgToCluster = tmpImg;
if(imgToCluster.IsNotNull())
{
// perform clustering
const HistogramType *histogram = m_CurrentStatisticsCalculator->GetHistogram( );
ClusteringType::Pointer clusterer = ClusteringType::New();
clusterer->SetStepsNumIntegration(200);
clusterer->SetMaxIt(1000);
mitk::Image::Pointer pFiberImg;
if(m_QuantifyClass==3)
{
if(m_Controls->m_Quantiles->isChecked())
{
m_CurrentRGBClusteringResults = clusterer->PerformRGBQuantiles(imgToCluster, histogram, m_Controls->m_q1->value(),m_Controls->m_q2->value());
}
else
{
m_CurrentRGBClusteringResults = clusterer->PerformRGBClustering(imgToCluster, histogram);
}
pFiberImg = m_CurrentRGBClusteringResults->rgbChannels->r;
cparams = m_CurrentRGBClusteringResults->params;
cresult = m_CurrentRGBClusteringResults->result;
chist = m_CurrentRGBClusteringResults->hist;
}
else
{
if(m_Controls->m_Quantiles->isChecked())
{
m_CurrentPerformClusteringResults =
clusterer->PerformQuantiles(imgToCluster, histogram, m_Controls->m_q1->value(),m_Controls->m_q2->value());
}
else
{
m_CurrentPerformClusteringResults =
clusterer->PerformClustering(imgToCluster, histogram, m_QuantifyClass);
}
pFiberImg = m_CurrentPerformClusteringResults->clusteredImage;
cparams = m_CurrentPerformClusteringResults->params;
cresult = m_CurrentPerformClusteringResults->result;
chist = m_CurrentPerformClusteringResults->hist;
}
if(m_IsTensorImage)
{
m_AngularErrorImage = clusterer->CaculateAngularErrorImage(
m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(1),
m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(2),
pFiberImg);
// GetDefaultDataStorage()->Remove(m_newnode2);
// m_newnode2 = mitk::DataNode::New();
// m_newnode2->SetData(m_AngularErrorImage);
// m_newnode2->SetName(("AngularError"));
// m_newnode2->SetIntProperty( "layer", 1003 );
// GetDefaultDataStorage()->Add(m_newnode2, m_SelectedImageNodes->GetNode());
// newnode = mitk::DataNode::New();
// newnode->SetData(m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(1));
// newnode->SetName(("Comp1"));
// GetDefaultDataStorage()->Add(newnode, m_SelectedImageNodes->GetNode());
// newnode = mitk::DataNode::New();
// newnode->SetData(m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(2));
// newnode->SetName(("Comp2"));
// GetDefaultDataStorage()->Add(newnode, m_SelectedImageNodes->GetNode());
}
ShowClusteringResults();
}
statisticsCalculationSuccessful = true;
}
catch ( const std::runtime_error &e )
{
// In case of exception, print error message on GUI
std::stringstream message;
message << "<font color='red'>" << e.what() << "</font>";
m_Controls->m_ErrorMessageLabel->setText( message.str().c_str() );
m_Controls->m_ErrorMessageLabel->show();
}
catch ( const std::exception &e )
{
MITK_ERROR << "Caught exception: " << e.what();
// In case of exception, print error message on GUI
std::stringstream message;
message << "<font color='red'>Error in calculating histogram: " << e.what() << "</font>";
m_Controls->m_ErrorMessageLabel->setText( message.str().c_str() );
m_Controls->m_ErrorMessageLabel->show();
}
m_CurrentStatisticsCalculator->RemoveObserver( progressObserverTag );
// Make sure that progress bar closes
mitk::ProgressBar::GetInstance()->Progress( 100 );
if ( statisticsCalculationSuccessful )
{
if ( statisticsChanged )
{
// Do not show any error messages
m_Controls->m_ErrorMessageLabel->hide();
m_CurrentStatisticsValid = true;
}
// m_Controls->m_HistogramWidget->SetHistogramModeToDirectHistogram();
m_Controls->m_HistogramWidget->SetParameters(
cparams, cresult, chist );
// m_Controls->m_HistogramWidget->UpdateItemModelFromHistogram();
}
else
{
m_Controls->m_SelectedMaskLabel->setText( "None" );
// Clear statistics and histogram
m_Controls->m_HistogramWidget->ClearItemModel();
m_CurrentStatisticsValid = false;
// If a (non-closed) PlanarFigure is selected, display a line profile widget
if ( m_SelectedPlanarFigure.IsNotNull() )
{
// TODO: enable line profile widget
//m_Controls->m_StatisticsWidgetStack->setCurrentIndex( 1 );
//m_Controls->m_LineProfileWidget->SetImage( m_SelectedImage );
//m_Controls->m_LineProfileWidget->SetPlanarFigure( m_SelectedPlanarFigure );
//m_Controls->m_LineProfileWidget->UpdateItemModelFromPath();
}
}
}
}
void QmitkPartialVolumeAnalysisView::SetMeasurementInfoToRenderWindow(const QString& text)
{
FindRenderWindow(m_SelectedPlanarFigureNodes->GetNode());
if(m_LastRenderWindow != m_SelectedRenderWindow)
{
if(m_LastRenderWindow)
{
QObject::disconnect( m_LastRenderWindow, SIGNAL( destroyed(QObject*) )
, this, SLOT( OnRenderWindowDelete(QObject*) ) );
}
m_LastRenderWindow = m_SelectedRenderWindow;
if(m_LastRenderWindow)
{
QObject::connect( m_LastRenderWindow, SIGNAL( destroyed(QObject*) )
, this, SLOT( OnRenderWindowDelete(QObject*) ) );
}
}
if(m_LastRenderWindow && m_SelectedPlanarFigureNodes->GetNode().IsNotNull())
{
if (!text.isEmpty())
{
m_MeasurementInfoAnnotation->SetText(1, text.toLatin1().data());
mitk::VtkLayerController::GetInstance(m_LastRenderWindow->GetRenderWindow())->InsertForegroundRenderer(
m_MeasurementInfoRenderer, true);
}
else
{
if (mitk::VtkLayerController::GetInstance(
m_LastRenderWindow->GetRenderWindow()) ->IsRendererInserted(
m_MeasurementInfoRenderer))
mitk::VtkLayerController::GetInstance(m_LastRenderWindow->GetRenderWindow())->RemoveRenderer(
m_MeasurementInfoRenderer);
}
}
else
{
if (!text.isEmpty())
{
m_MeasurementInfoAnnotation->SetText(1, text.toLatin1().data());
mitk::VtkLayerController::GetInstance(this->GetActiveStdMultiWidget()->GetRenderWindow1()->GetRenderWindow())->InsertForegroundRenderer(
m_MeasurementInfoRenderer, true);
}
else
{
if (mitk::VtkLayerController::GetInstance(
this->GetActiveStdMultiWidget()->GetRenderWindow1()->GetRenderWindow()) ->IsRendererInserted(
m_MeasurementInfoRenderer))
mitk::VtkLayerController::GetInstance(this->GetActiveStdMultiWidget()->GetRenderWindow1()->GetRenderWindow())->RemoveRenderer(
m_MeasurementInfoRenderer);
}
}
}
void QmitkPartialVolumeAnalysisView::UpdateProgressBar()
{
mitk::ProgressBar::GetInstance()->Progress();
}
void QmitkPartialVolumeAnalysisView::RequestStatisticsUpdate()
{
if ( !m_StatisticsUpdatePending )
{
QApplication::postEvent( this, new QmitkRequestStatisticsUpdateEvent );
m_StatisticsUpdatePending = true;
}
}
void QmitkPartialVolumeAnalysisView::RemoveOrphanImages()
{
PartialVolumeAnalysisMapType::iterator it = m_PartialVolumeAnalysisMap.begin();
while ( it != m_PartialVolumeAnalysisMap.end() )
{
mitk::Image *image = it->first;
mitk::PartialVolumeAnalysisHistogramCalculator *calculator = it->second;
++it;
mitk::NodePredicateData::Pointer hasImage = mitk::NodePredicateData::New( image );
if ( this->GetDefaultDataStorage()->GetNode( hasImage ) == NULL )
{
if ( m_SelectedImage == image )
{
m_SelectedImage = NULL;
m_SelectedImageNodes->RemoveAllNodes();
}
if ( m_CurrentStatisticsCalculator == calculator )
{
m_CurrentStatisticsCalculator = NULL;
}
m_PartialVolumeAnalysisMap.erase( image );
it = m_PartialVolumeAnalysisMap.begin();
}
}
}
void QmitkPartialVolumeAnalysisView::ExtractTensorImages(
mitk::Image::ConstPointer tensorimage)
{
typedef itk::Image< itk::DiffusionTensor3D<float>, 3> TensorImageType;
typedef mitk::ImageToItk<TensorImageType> CastType;
CastType::Pointer caster = CastType::New();
caster->SetInput(tensorimage);
caster->Update();
TensorImageType::Pointer image = caster->GetOutput();
typedef itk::TensorDerivedMeasurementsFilter<float> MeasurementsType;
MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New();
measurementsCalculator->SetInput(image );
measurementsCalculator->SetMeasure(MeasurementsType::FA);
measurementsCalculator->Update();
MeasurementsType::OutputImageType::Pointer fa = measurementsCalculator->GetOutput();
m_FAImage = mitk::Image::New();
m_FAImage->InitializeByItk(fa.GetPointer());
m_FAImage->SetVolume(fa->GetBufferPointer());
// mitk::DataNode::Pointer node = mitk::DataNode::New();
// node->SetData(m_FAImage);
// GetDefaultDataStorage()->Add(node);
measurementsCalculator = MeasurementsType::New();
measurementsCalculator->SetInput(image );
measurementsCalculator->SetMeasure(MeasurementsType::CA);
measurementsCalculator->Update();
MeasurementsType::OutputImageType::Pointer ca = measurementsCalculator->GetOutput();
m_CAImage = mitk::Image::New();
m_CAImage->InitializeByItk(ca.GetPointer());
m_CAImage->SetVolume(ca->GetBufferPointer());
// node = mitk::DataNode::New();
// node->SetData(m_CAImage);
// GetDefaultDataStorage()->Add(node);
measurementsCalculator = MeasurementsType::New();
measurementsCalculator->SetInput(image );
measurementsCalculator->SetMeasure(MeasurementsType::RD);
measurementsCalculator->Update();
MeasurementsType::OutputImageType::Pointer rd = measurementsCalculator->GetOutput();
m_RDImage = mitk::Image::New();
m_RDImage->InitializeByItk(rd.GetPointer());
m_RDImage->SetVolume(rd->GetBufferPointer());
// node = mitk::DataNode::New();
// node->SetData(m_CAImage);
// GetDefaultDataStorage()->Add(node);
measurementsCalculator = MeasurementsType::New();
measurementsCalculator->SetInput(image );
measurementsCalculator->SetMeasure(MeasurementsType::AD);
measurementsCalculator->Update();
MeasurementsType::OutputImageType::Pointer ad = measurementsCalculator->GetOutput();
m_ADImage = mitk::Image::New();
m_ADImage->InitializeByItk(ad.GetPointer());
m_ADImage->SetVolume(ad->GetBufferPointer());
// node = mitk::DataNode::New();
// node->SetData(m_CAImage);
// GetDefaultDataStorage()->Add(node);
measurementsCalculator = MeasurementsType::New();
measurementsCalculator->SetInput(image );
measurementsCalculator->SetMeasure(MeasurementsType::RA);
measurementsCalculator->Update();
MeasurementsType::OutputImageType::Pointer md = measurementsCalculator->GetOutput();
m_MDImage = mitk::Image::New();
m_MDImage->InitializeByItk(md.GetPointer());
m_MDImage->SetVolume(md->GetBufferPointer());
// node = mitk::DataNode::New();
// node->SetData(m_CAImage);
// GetDefaultDataStorage()->Add(node);
typedef DirectionsFilterType::OutputImageType DirImageType;
DirectionsFilterType::Pointer dirFilter = DirectionsFilterType::New();
dirFilter->SetInput(image );
dirFilter->Update();
itk::ImageRegionIterator<DirImageType>
itd(dirFilter->GetOutput(), dirFilter->GetOutput()->GetLargestPossibleRegion());
itd = itd.Begin();
while( !itd.IsAtEnd() )
{
DirImageType::PixelType direction = itd.Get();
direction[0] = fabs(direction[0]);
direction[1] = fabs(direction[1]);
direction[2] = fabs(direction[2]);
itd.Set(direction);
++itd;
}
typedef itk::CartesianToPolarVectorImageFilter<
DirImageType, DirImageType, true> C2PFilterType;
C2PFilterType::Pointer cpFilter = C2PFilterType::New();
cpFilter->SetInput(dirFilter->GetOutput());
cpFilter->Update();
DirImageType::Pointer dir = cpFilter->GetOutput();
typedef itk::Image<float, 3> CompImageType;
CompImageType::Pointer comp1 = CompImageType::New();
comp1->SetSpacing( dir->GetSpacing() ); // Set the image spacing
comp1->SetOrigin( dir->GetOrigin() ); // Set the image origin
comp1->SetDirection( dir->GetDirection() ); // Set the image direction
comp1->SetRegions( dir->GetLargestPossibleRegion() );
comp1->Allocate();
CompImageType::Pointer comp2 = CompImageType::New();
comp2->SetSpacing( dir->GetSpacing() ); // Set the image spacing
comp2->SetOrigin( dir->GetOrigin() ); // Set the image origin
comp2->SetDirection( dir->GetDirection() ); // Set the image direction
comp2->SetRegions( dir->GetLargestPossibleRegion() );
comp2->Allocate();
itk::ImageRegionConstIterator<DirImageType>
it(dir, dir->GetLargestPossibleRegion());
itk::ImageRegionIterator<CompImageType>
it1(comp1, comp1->GetLargestPossibleRegion());
itk::ImageRegionIterator<CompImageType>
it2(comp2, comp2->GetLargestPossibleRegion());
it = it.Begin();
it1 = it1.Begin();
it2 = it2.Begin();
while( !it.IsAtEnd() )
{
it1.Set(it.Get()[1]);
it2.Set(it.Get()[2]);
++it;
++it1;
++it2;
}
m_DirectionComp1Image = mitk::Image::New();
m_DirectionComp1Image->InitializeByItk(comp1.GetPointer());
m_DirectionComp1Image->SetVolume(comp1->GetBufferPointer());
m_DirectionComp2Image = mitk::Image::New();
m_DirectionComp2Image->InitializeByItk(comp2.GetPointer());
m_DirectionComp2Image->SetVolume(comp2->GetBufferPointer());
}
void QmitkPartialVolumeAnalysisView::OnRenderWindowDelete(QObject * obj)
{
if(obj == m_LastRenderWindow)
m_LastRenderWindow = 0;
}
bool QmitkPartialVolumeAnalysisView::event( QEvent *event )
{
if ( event->type() == (QEvent::Type) QmitkRequestStatisticsUpdateEvent::StatisticsUpdateRequest )
{
// Update statistics
m_StatisticsUpdatePending = false;
this->UpdateStatistics();
return true;
}
return false;
}
void QmitkPartialVolumeAnalysisView::Visible()
{
this->OnSelectionChanged( this->GetDataManagerSelection() );
}
bool QmitkPartialVolumeAnalysisView::IsExclusiveFunctionality() const
{
return true;
}
void QmitkPartialVolumeAnalysisView::Activated()
{
this->GetActiveStdMultiWidget()->SetWidgetPlanesVisibility(false);
//this->GetActiveStdMultiWidget()->GetRenderWindow1()->FullScreenMode(true);
mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet = this->GetDefaultDataStorage()->GetAll();
mitk::DataNode* node = 0;
mitk::PlanarFigure* figure = 0;
mitk::PlanarFigureInteractor::Pointer figureInteractor = 0;
// finally add all nodes to the model
for(mitk::DataStorage::SetOfObjects::ConstIterator it=_NodeSet->Begin(); it!=_NodeSet->End()
; it++)
{
node = const_cast<mitk::DataNode*>(it->Value().GetPointer());
figure = dynamic_cast<mitk::PlanarFigure*>(node->GetData());
if(figure)
{
figureInteractor = dynamic_cast<mitk::PlanarFigureInteractor*>(node->GetInteractor());
if(figureInteractor.IsNull())
figureInteractor = mitk::PlanarFigureInteractor::New("PlanarFigureInteractor", node);
mitk::GlobalInteraction::GetInstance()->AddInteractor(figureInteractor);
}
}
m_Visible = true;
}
void QmitkPartialVolumeAnalysisView::Deactivated()
{
this->GetActiveStdMultiWidget()->SetWidgetPlanesVisibility(true);
//this->GetActiveStdMultiWidget()->GetRenderWindow1()->FullScreenMode(false);
this->SetMeasurementInfoToRenderWindow("");
mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet = this->GetDefaultDataStorage()->GetAll();
mitk::DataNode* node = 0;
mitk::PlanarFigure* figure = 0;
mitk::PlanarFigureInteractor::Pointer figureInteractor = 0;
// finally add all nodes to the model
for(mitk::DataStorage::SetOfObjects::ConstIterator it=_NodeSet->Begin(); it!=_NodeSet->End()
; it++)
{
node = const_cast<mitk::DataNode*>(it->Value().GetPointer());
figure = dynamic_cast<mitk::PlanarFigure*>(node->GetData());
if(figure)
{
figureInteractor = dynamic_cast<mitk::PlanarFigureInteractor*>(node->GetInteractor());
if(figureInteractor)
mitk::GlobalInteraction::GetInstance()->RemoveInteractor(figureInteractor);
}
}
m_Visible = false;
}
void QmitkPartialVolumeAnalysisView::GreenRadio(bool checked)
{
if(checked)
{
m_Controls->m_PartialVolumeRadio->setChecked(false);
m_Controls->m_BlueRadio->setChecked(false);
m_Controls->m_AllRadio->setChecked(false);
}
m_QuantifyClass = 0;
RequestStatisticsUpdate();
}
void QmitkPartialVolumeAnalysisView::PartialVolumeRadio(bool checked)
{
if(checked)
{
m_Controls->m_GreenRadio->setChecked(false);
m_Controls->m_BlueRadio->setChecked(false);
m_Controls->m_AllRadio->setChecked(false);
}
m_QuantifyClass = 1;
RequestStatisticsUpdate();
}
void QmitkPartialVolumeAnalysisView::BlueRadio(bool checked)
{
if(checked)
{
m_Controls->m_PartialVolumeRadio->setChecked(false);
m_Controls->m_GreenRadio->setChecked(false);
m_Controls->m_AllRadio->setChecked(false);
}
m_QuantifyClass = 2;
RequestStatisticsUpdate();
}
void QmitkPartialVolumeAnalysisView::AllRadio(bool checked)
{
if(checked)
{
m_Controls->m_BlueRadio->setChecked(false);
m_Controls->m_PartialVolumeRadio->setChecked(false);
m_Controls->m_GreenRadio->setChecked(false);
}
m_QuantifyClass = 3;
RequestStatisticsUpdate();
}
void QmitkPartialVolumeAnalysisView::NumberBinsChangedSlider(int v )
{
m_Controls->m_NumberBins->setText(QString("%1").arg(m_Controls->m_NumberBinsSlider->value()*5.0));
}
void QmitkPartialVolumeAnalysisView::UpsamplingChangedSlider( int v)
{
m_Controls->m_Upsampling->setText(QString("%1").arg(m_Controls->m_UpsamplingSlider->value()/10.0));
}
void QmitkPartialVolumeAnalysisView::GaussianSigmaChangedSlider(int v )
{
m_Controls->m_GaussianSigma->setText(QString("%1").arg(m_Controls->m_GaussianSigmaSlider->value()/100.0));
}
void QmitkPartialVolumeAnalysisView::SimilarAnglesChangedSlider(int v )
{
m_Controls->m_SimilarAngles->setText(QString("%1°").arg(90-m_Controls->m_SimilarAnglesSlider->value()));
ShowClusteringResults();
}
void QmitkPartialVolumeAnalysisView::OpacityChangedSlider(int v )
{
if(m_SelectedImageNodes->GetNode().IsNotNull())
{
float opacImag = 1.0f-(v-5)/5.0f;
opacImag = opacImag < 0 ? 0 : opacImag;
m_SelectedImageNodes->GetNode()->SetFloatProperty("opacity", opacImag);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
if(m_ClusteringResult.IsNotNull())
{
float opacClust = v/5.0f;
opacClust = opacClust > 1 ? 1 : opacClust;
m_ClusteringResult->SetFloatProperty("opacity", opacClust);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkPartialVolumeAnalysisView::NumberBinsReleasedSlider( )
{
RequestStatisticsUpdate();
}
void QmitkPartialVolumeAnalysisView::UpsamplingReleasedSlider( )
{
RequestStatisticsUpdate();
}
void QmitkPartialVolumeAnalysisView::GaussianSigmaReleasedSlider( )
{
RequestStatisticsUpdate();
}
void QmitkPartialVolumeAnalysisView::SimilarAnglesReleasedSlider( )
{
}
void QmitkPartialVolumeAnalysisView::ToClipBoard()
{
std::vector<std::vector<double>* > vals = m_Controls->m_HistogramWidget->m_Vals;
QString clipboardText;
for (std::vector<std::vector<double>* >::iterator it = vals.begin(); it
!= vals.end(); ++it)
{
for (std::vector<double>::iterator it2 = (**it).begin(); it2 != (**it).end(); ++it2)
{
clipboardText.append(QString("%1 \t").arg(*it2));
}
clipboardText.append(QString("\n"));
}
QApplication::clipboard()->setText(clipboardText, QClipboard::Clipboard);
}
void QmitkPartialVolumeAnalysisView::PropertyChanged(const mitk::DataNode* /*node*/, const mitk::BaseProperty* /*prop*/)
{
}
void QmitkPartialVolumeAnalysisView::NodeChanged(const mitk::DataNode* /*node*/)
{
}
void QmitkPartialVolumeAnalysisView::NodeRemoved(const mitk::DataNode* node)
{
if( node == m_SelectedPlanarFigureNodes->GetNode().GetPointer()
|| node == m_SelectedMaskNode.GetPointer() )
{
this->Select(NULL,true,false);
SetMeasurementInfoToRenderWindow("");
}
if( node == m_SelectedImageNodes->GetNode().GetPointer() )
{
this->Select(NULL,false,true);
SetMeasurementInfoToRenderWindow("");
}
}
void QmitkPartialVolumeAnalysisView::NodeAddedInDataStorage(const mitk::DataNode* node)
{
if(!m_Visible)
return;
mitk::DataNode* nonConstNode = const_cast<mitk::DataNode*>(node);
mitk::PlanarFigure* figure = dynamic_cast<mitk::PlanarFigure*>(nonConstNode->GetData());
if(figure)
{
// set interactor for new node (if not already set)
mitk::PlanarFigureInteractor::Pointer figureInteractor
= dynamic_cast<mitk::PlanarFigureInteractor*>(node->GetInteractor());
if(figureInteractor.IsNull())
figureInteractor = mitk::PlanarFigureInteractor::New("PlanarFigureInteractor", nonConstNode);
mitk::GlobalInteraction::GetInstance()->AddInteractor(figureInteractor);
// remove uninitialized old planars
if( m_SelectedPlanarFigureNodes->GetNode().IsNotNull() && m_CurrentFigureNodeInitialized == false )
{
mitk::Interactor::Pointer oldInteractor = m_SelectedPlanarFigureNodes->GetNode()->GetInteractor();
if(oldInteractor.IsNotNull())
mitk::GlobalInteraction::GetInstance()->RemoveInteractor(oldInteractor);
this->GetDefaultDataStorage()->Remove(m_SelectedPlanarFigureNodes->GetNode());
}
}
}
void QmitkPartialVolumeAnalysisView::TextIntON()
{
if(m_ClusteringResult.IsNotNull())
{
if(m_TexIsOn)
{
m_Controls->m_TextureIntON->setIcon(*m_IconTexOFF);
}
else
{
m_Controls->m_TextureIntON->setIcon(*m_IconTexON);
}
m_ClusteringResult->SetBoolProperty("texture interpolation", !m_TexIsOn);
m_TexIsOn = !m_TexIsOn;
GetActiveStdMultiWidget()->RequestUpdate();
}
}
diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionView.cpp b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionView.cpp
index 5d0974f07b..2a8b7bdc61 100644
--- a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionView.cpp
+++ b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionView.cpp
@@ -1,802 +1,850 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Module: $RCSfile$
Language: C++
Date: $Date: 2009-05-28 17:19:30 +0200 (Do, 28 Mai 2009) $
-Version: $Revision: 17495 $
+Version: $Revision: 17495 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "QmitkTensorReconstructionView.h"
#include "mitkDiffusionImagingConfigure.h"
// qt includes
#include <QMessageBox>
// itk includes
#include "itkTimeProbe.h"
//#include "itkTensor.h"
// mitk includes
#include "mitkProgressBar.h"
#include "mitkStatusBar.h"
#include "mitkNodePredicateDataType.h"
#include "QmitkDataStorageComboBox.h"
#include "QmitkStdMultiWidget.h"
#include "mitkTeemDiffusionTensor3DReconstructionImageFilter.h"
#include "itkDiffusionTensor3DReconstructionImageFilter.h"
#include "itkTensorImageToDiffusionImageFilter.h"
#include "itkPointShell.h"
#include "itkVector.h"
-#include "mitkTensorImage.h"
#include "mitkProperties.h"
#include "mitkDataNodeObject.h"
#include "mitkOdfNormalizationMethodProperty.h"
#include "mitkOdfScaleByProperty.h"
#include "mitkDiffusionImageMapper.h"
#include "berryIStructuredSelection.h"
#include "berryIWorkbenchWindow.h"
#include "berryISelectionService.h"
-const std::string QmitkTensorReconstructionView::VIEW_ID =
+#include <itkTensorImageToQBallImageFilter.h>
+
+const std::string QmitkTensorReconstructionView::VIEW_ID =
"org.mitk.views.tensorreconstruction";
#define DI_INFO MITK_INFO("DiffusionImaging")
typedef float TTensorPixelType;
using namespace berry;
struct TrSelListener : ISelectionListener
{
berryObjectMacro(TrSelListener);
TrSelListener(QmitkTensorReconstructionView* view)
{
m_View = view;
}
void DoSelectionChanged(ISelection::ConstPointer selection)
{
// if(!m_View->IsVisible())
// return;
// save current selection in member variable
m_View->m_CurrentSelection = selection.Cast<const IStructuredSelection>();
// do something with the selected items
if(m_View->m_CurrentSelection)
{
bool foundDwiVolume = false;
bool foundTensorVolume = false;
// iterate selection
- for (IStructuredSelection::iterator i = m_View->m_CurrentSelection->Begin();
+ for (IStructuredSelection::iterator i = m_View->m_CurrentSelection->Begin();
i != m_View->m_CurrentSelection->End(); ++i)
{
// extract datatree node
if (mitk::DataNodeObject::Pointer nodeObj = i->Cast<mitk::DataNodeObject>())
{
mitk::DataNode::Pointer node = nodeObj->GetDataNode();
// only look at interesting types
if(QString("DiffusionImage").compare(node->GetData()->GetNameOfClass())==0)
{
foundDwiVolume = true;
}
// only look at interesting types
if(QString("TensorImage").compare(node->GetData()->GetNameOfClass())==0)
{
foundTensorVolume = true;
}
}
}
m_View->m_Controls->m_ItkReconstruction->setEnabled(foundDwiVolume);
m_View->m_Controls->m_TeemReconstruction->setEnabled(foundDwiVolume);
m_View->m_Controls->m_TensorsToDWIButton->setEnabled(foundTensorVolume);
+ m_View->m_Controls->m_TensorsToQbiButton->setEnabled(foundTensorVolume);
+
}
}
void SelectionChanged(IWorkbenchPart::Pointer part, ISelection::ConstPointer selection)
{
// check, if selection comes from datamanager
if (part)
{
QString partname(part->GetPartName().c_str());
if(partname.compare("Datamanager")==0)
{
// apply selection
DoSelectionChanged(selection);
}
}
}
QmitkTensorReconstructionView* m_View;
};
QmitkTensorReconstructionView::QmitkTensorReconstructionView()
: QmitkFunctionality(),
m_Controls(NULL),
m_MultiWidget(NULL)
{
}
QmitkTensorReconstructionView::QmitkTensorReconstructionView(const QmitkTensorReconstructionView& other)
{
Q_UNUSED(other)
throw std::runtime_error("Copy constructor not implemented");
}
QmitkTensorReconstructionView::~QmitkTensorReconstructionView()
{
this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->RemovePostSelectionListener(/*"org.mitk.views.datamanager",*/ m_SelListener);
}
void QmitkTensorReconstructionView::CreateQtPartControl(QWidget *parent)
{
if (!m_Controls)
{
// create GUI widgets
m_Controls = new Ui::QmitkTensorReconstructionViewControls;
m_Controls->setupUi(parent);
this->CreateConnections();
m_Controls->m_TensorReconstructionNumberThreadsSpinbox->setValue(8);
QStringList items;
items << "LLS (Linear Least Squares)"
<< "MLE (Maximum Likelihood)"
<< "NLS (Nonlinear Least Squares)"
<< "WLS (Weighted Least Squares)";
m_Controls->m_TensorEstimationTeemEstimationMethodCombo->addItems(items);
m_Controls->m_TensorEstimationTeemEstimationMethodCombo->setCurrentIndex(0);
m_Controls->m_TensorEstimationManualThreashold->setChecked(false);
m_Controls->m_TensorEstimationTeemSigmaEdit->setText("NaN");
m_Controls->m_TensorEstimationTeemNumItsSpin->setValue(1);
m_Controls->m_TensorEstimationTeemFuzzyEdit->setText("0.0");
m_Controls->m_TensorEstimationTeemMinValEdit->setText("1.0");
m_Controls->m_TensorEstimationTeemNumItsLabel_2->setEnabled(true);
m_Controls->m_TensorEstimationTeemNumItsSpin->setEnabled(true);
m_Controls->m_TensorsToDWIBValueEdit->setText("1000");
Advanced1CheckboxClicked();
Advanced2CheckboxClicked();
TeemCheckboxClicked();
#ifndef DIFFUSION_IMAGING_EXTENDED
m_Controls->m_TeemToggle->setVisible(false);
#endif
// define data type for combobox
//m_Controls->m_ImageSelector->SetDataStorage( this->GetDefaultDataStorage() );
//m_Controls->m_ImageSelector->SetPredicate( mitk::NodePredicateDataType::New("DiffusionImage") );
}
m_SelListener = berry::ISelectionListener::Pointer(new TrSelListener(this));
this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->AddPostSelectionListener(/*"org.mitk.views.datamanager",*/ m_SelListener);
berry::ISelection::ConstPointer sel(
this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager"));
m_CurrentSelection = sel.Cast<const IStructuredSelection>();
m_SelListener.Cast<TrSelListener>()->DoSelectionChanged(sel);
}
void QmitkTensorReconstructionView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget)
{
berry::ISelection::ConstPointer sel(
this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager"));
m_CurrentSelection = sel.Cast<const IStructuredSelection>();
m_SelListener.Cast<TrSelListener>()->DoSelectionChanged(sel);
m_MultiWidget = &stdMultiWidget;
}
void QmitkTensorReconstructionView::StdMultiWidgetNotAvailable()
{
m_MultiWidget = NULL;
}
void QmitkTensorReconstructionView::CreateConnections()
{
if ( m_Controls )
{
connect( (QObject*)(m_Controls->m_TeemToggle), SIGNAL(clicked()), this, SLOT(TeemCheckboxClicked()) );
connect( (QObject*)(m_Controls->m_ItkReconstruction), SIGNAL(clicked()), this, SLOT(ItkReconstruction()) );
connect( (QObject*)(m_Controls->m_TeemReconstruction), SIGNAL(clicked()), this, SLOT(TeemReconstruction()) );
connect( (QObject*)(m_Controls->m_TensorEstimationTeemEstimationMethodCombo), SIGNAL(currentIndexChanged(int)), this, SLOT(MethodChoosen(int)) );
connect( (QObject*)(m_Controls->m_Advanced1), SIGNAL(clicked()), this, SLOT(Advanced1CheckboxClicked()) );
connect( (QObject*)(m_Controls->m_Advanced2), SIGNAL(clicked()), this, SLOT(Advanced2CheckboxClicked()) );
connect( (QObject*)(m_Controls->m_TensorEstimationManualThreashold), SIGNAL(clicked()), this, SLOT(ManualThresholdClicked()) );
connect( (QObject*)(m_Controls->m_TensorsToDWIButton), SIGNAL(clicked()), this, SLOT(TensorsToDWI()) );
+ connect( (QObject*)(m_Controls->m_TensorsToQbiButton), SIGNAL(clicked()), this, SLOT(TensorsToQbi()) );
}
}
void QmitkTensorReconstructionView::TeemCheckboxClicked()
{
m_Controls->groupBox_3->setVisible(m_Controls->
- m_TeemToggle->isChecked());
+ m_TeemToggle->isChecked());
}
void QmitkTensorReconstructionView::Advanced1CheckboxClicked()
{
bool check = m_Controls->
m_Advanced1->isChecked();
m_Controls->frame->setVisible(check);
}
void QmitkTensorReconstructionView::Advanced2CheckboxClicked()
{
bool check = m_Controls->
m_Advanced2->isChecked();
m_Controls->frame_2->setVisible(check);
}
void QmitkTensorReconstructionView::ManualThresholdClicked()
{
m_Controls->m_TensorReconstructionThreasholdEdit_2->setEnabled(
m_Controls->m_TensorEstimationManualThreashold->isChecked());
}
void QmitkTensorReconstructionView::Activated()
{
QmitkFunctionality::Activated();
}
void QmitkTensorReconstructionView::Deactivated()
{
QmitkFunctionality::Deactivated();
}
void QmitkTensorReconstructionView::MethodChoosen(int method)
{
m_Controls->m_TensorEstimationTeemNumItsLabel_2->setEnabled(method==3);
m_Controls->m_TensorEstimationTeemNumItsSpin->setEnabled(method==3);
}
void QmitkTensorReconstructionView::ItkReconstruction()
{
Reconstruct(0);
}
void QmitkTensorReconstructionView::TeemReconstruction()
{
Reconstruct(1);
}
void QmitkTensorReconstructionView::Reconstruct(int method)
{
if (m_CurrentSelection)
{
mitk::DataStorage::SetOfObjects::Pointer set =
mitk::DataStorage::SetOfObjects::New();
int at = 0;
- for (IStructuredSelection::iterator i = m_CurrentSelection->Begin();
- i != m_CurrentSelection->End();
+ for (IStructuredSelection::iterator i = m_CurrentSelection->Begin();
+ i != m_CurrentSelection->End();
++i)
{
if (mitk::DataNodeObject::Pointer nodeObj = i->Cast<mitk::DataNodeObject>())
{
mitk::DataNode::Pointer node = nodeObj->GetDataNode();
if(QString("DiffusionImage").compare(node->GetData()->GetNameOfClass())==0)
{
set->InsertElement(at++, node);
}
}
}
if(method == 0)
{
ItkTensorReconstruction(set);
}
if(method == 1)
{
TeemTensorReconstruction(set);
}
}
}
void QmitkTensorReconstructionView::ItkTensorReconstruction
-(mitk::DataStorage::SetOfObjects::Pointer inImages)
+(mitk::DataStorage::SetOfObjects::Pointer inImages)
{
try
{
itk::TimeProbe clock;
int nrFiles = inImages->size();
if (!nrFiles) return;
QString status;
mitk::ProgressBar::GetInstance()->AddStepsToDo(nrFiles);
- mitk::DataStorage::SetOfObjects::const_iterator itemiter( inImages->begin() );
- mitk::DataStorage::SetOfObjects::const_iterator itemiterend( inImages->end() );
+ mitk::DataStorage::SetOfObjects::const_iterator itemiter( inImages->begin() );
+ mitk::DataStorage::SetOfObjects::const_iterator itemiterend( inImages->end() );
std::vector<mitk::DataNode::Pointer> nodes;
while ( itemiter != itemiterend ) // for all items
{
- mitk::DiffusionImage<DiffusionPixelType>* vols =
+ mitk::DiffusionImage<DiffusionPixelType>* vols =
static_cast<mitk::DiffusionImage<DiffusionPixelType>*>(
(*itemiter)->GetData());
std::string nodename;
(*itemiter)->GetStringProperty("name", nodename);
++itemiter;
// TENSOR RECONSTRUCTION
clock.Start();
MBI_INFO << "Tensor reconstruction ";
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf(
"Tensor reconstruction for %s", nodename.c_str()).toAscii());
- typedef itk::DiffusionTensor3DReconstructionImageFilter<
+ typedef itk::DiffusionTensor3DReconstructionImageFilter<
DiffusionPixelType, DiffusionPixelType, TTensorPixelType > TensorReconstructionImageFilterType;
- TensorReconstructionImageFilterType::Pointer tensorReconstructionFilter =
+ TensorReconstructionImageFilterType::Pointer tensorReconstructionFilter =
TensorReconstructionImageFilterType::New();
tensorReconstructionFilter->SetGradientImage( vols->GetDirections(), vols->GetVectorImage() );
tensorReconstructionFilter->SetNumberOfThreads( m_Controls->m_TensorReconstructionNumberThreadsSpinbox->value() );
- tensorReconstructionFilter->SetBValue(vols->GetB_Value());
+ tensorReconstructionFilter->SetBValue(vols->GetB_Value());
tensorReconstructionFilter->SetThreshold( m_Controls->m_TensorReconstructionThreasholdEdit->text().toFloat() );
tensorReconstructionFilter->Update();
clock.Stop();
MBI_DEBUG << "took " << clock.GetMeanTime() << "s.";
// TENSORS TO DATATREE
mitk::TensorImage::Pointer image = mitk::TensorImage::New();
-
- typedef itk::Image<itk::DiffusionTensor3D<TTensorPixelType>, 3> TensorImageType;
+
+ typedef itk::Image<itk::DiffusionTensor3D<TTensorPixelType>, 3> TensorImageType;
TensorImageType::Pointer tensorImage;
- tensorImage = tensorReconstructionFilter->GetOutput();
+ tensorImage = tensorReconstructionFilter->GetOutput();
+
-
// Check the tensor for negative eigenvalues
if(m_Controls->m_CheckNegativeEigenvalues->isChecked())
- {
+ {
typedef itk::ImageRegionIterator<TensorImageType> TensorImageIteratorType;
TensorImageIteratorType tensorIt(tensorImage, tensorImage->GetRequestedRegion());
tensorIt.GoToBegin();
while(!tensorIt.IsAtEnd())
{
typedef itk::DiffusionTensor3D<TTensorPixelType> TensorType;
//typedef itk::Tensor<TTensorPixelType, 3> TensorType2;
TensorType tensor = tensorIt.Get();
// TensorType2 tensor2;
/*
for(int i=0; i<tensor.GetNumberOfComponents(); i++)
{
- tensor2.SetNthComponent(i, tensor.GetNthComponent(i));
+ tensor2.SetNthComponent(i, tensor.GetNthComponent(i));
}
-
+
typedef vnl_symmetric_eigensystem< TTensorPixelType > SymEigenSystemType;
- SymEigenSystemType eig (tensor2.GetVnlMatrix());
+ SymEigenSystemType eig (tensor2.GetVnlMatrix());
for(unsigned int i=0; i<eig.D.size(); i++)
{
if (eig.D[i] < 0.0 )
- {
+ {
tensor.Fill(0.0);
- tensorIt.Set(tensor);
- }
+ tensorIt.Set(tensor);
+ }
}*/
-
+
TensorType::EigenValuesArrayType ev;
- tensor.ComputeEigenValues(ev);
+ tensor.ComputeEigenValues(ev);
for(unsigned int i=0; i<ev.Size(); i++)
{
if(ev[i] < 0.0)
{
tensor.Fill(0.0);
- tensorIt.Set(tensor);
+ tensorIt.Set(tensor);
break;
}
- }
-
+ }
+
++tensorIt;
- }
+ }
}
image->InitializeByItk( tensorImage.GetPointer() );
image->SetVolume( tensorReconstructionFilter->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer node=mitk::DataNode::New();
node->SetData( image );
QString newname;
newname = newname.append(nodename.c_str());
newname = newname.append("_dti");
SetDefaultNodeProperties(node, newname.toStdString());
nodes.push_back(node);
mitk::ProgressBar::GetInstance()->Progress();
}
std::vector<mitk::DataNode::Pointer>::iterator nodeIt;
for(nodeIt = nodes.begin(); nodeIt != nodes.end(); ++nodeIt)
GetDefaultDataStorage()->Add(*nodeIt);
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Finished Processing %d Files", nrFiles).toAscii());
m_MultiWidget->RequestUpdate();
}
catch (itk::ExceptionObject &ex)
{
MBI_INFO << ex ;
return ;
}
}
void QmitkTensorReconstructionView::TeemTensorReconstruction
-(mitk::DataStorage::SetOfObjects::Pointer inImages)
+(mitk::DataStorage::SetOfObjects::Pointer inImages)
{
try
{
itk::TimeProbe clock;
int nrFiles = inImages->size();
if (!nrFiles) return;
QString status;
mitk::ProgressBar::GetInstance()->AddStepsToDo(nrFiles);
- mitk::DataStorage::SetOfObjects::const_iterator itemiter( inImages->begin() );
- mitk::DataStorage::SetOfObjects::const_iterator itemiterend( inImages->end() );
+ mitk::DataStorage::SetOfObjects::const_iterator itemiter( inImages->begin() );
+ mitk::DataStorage::SetOfObjects::const_iterator itemiterend( inImages->end() );
std::vector<mitk::DataNode::Pointer> nodes;
while ( itemiter != itemiterend ) // for all items
{
- mitk::DiffusionImage<DiffusionPixelType>* vols =
+ mitk::DiffusionImage<DiffusionPixelType>* vols =
static_cast<mitk::DiffusionImage<DiffusionPixelType>*>(
(*itemiter)->GetData());
std::string nodename;
(*itemiter)->GetStringProperty("name", nodename);
++itemiter;
// TENSOR RECONSTRUCTION
clock.Start();
MBI_INFO << "Teem Tensor reconstruction ";
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf(
"Teem Tensor reconstruction for %s", nodename.c_str()).toAscii());
- typedef mitk::TeemDiffusionTensor3DReconstructionImageFilter<
+ typedef mitk::TeemDiffusionTensor3DReconstructionImageFilter<
DiffusionPixelType, TTensorPixelType > TensorReconstructionImageFilterType;
- TensorReconstructionImageFilterType::Pointer tensorReconstructionFilter =
+ TensorReconstructionImageFilterType::Pointer tensorReconstructionFilter =
TensorReconstructionImageFilterType::New();
tensorReconstructionFilter->SetInput( vols );
if(!m_Controls->m_TensorEstimationTeemSigmaEdit->text().contains(QString("NaN")))
tensorReconstructionFilter->SetSigma( m_Controls->m_TensorEstimationTeemSigmaEdit->text().toFloat() );
switch(m_Controls->m_TensorEstimationTeemEstimationMethodCombo->currentIndex())
{
// items << "LLS (Linear Least Squares)"
//<< "MLE (Maximum Likelihood)"
//<< "NLS (Nonlinear Least Squares)"
//<< "WLS (Weighted Least Squares)";
case 0:
tensorReconstructionFilter->SetEstimationMethod(mitk::TeemTensorEstimationMethodsLLS);
break;
case 1:
tensorReconstructionFilter->SetEstimationMethod(mitk::TeemTensorEstimationMethodsMLE);
break;
case 2:
tensorReconstructionFilter->SetEstimationMethod(mitk::TeemTensorEstimationMethodsNLS);
break;
case 3:
tensorReconstructionFilter->SetEstimationMethod(mitk::TeemTensorEstimationMethodsWLS);
break;
default:
tensorReconstructionFilter->SetEstimationMethod(mitk::TeemTensorEstimationMethodsLLS);
}
tensorReconstructionFilter->SetNumIterations( m_Controls->m_TensorEstimationTeemNumItsSpin->value() );
if(m_Controls->m_TensorEstimationManualThreashold->isChecked())
tensorReconstructionFilter->SetConfidenceThreshold( m_Controls->m_TensorReconstructionThreasholdEdit_2->text().toDouble() );
tensorReconstructionFilter->SetConfidenceFuzzyness( m_Controls->m_TensorEstimationTeemFuzzyEdit->text().toFloat() );
tensorReconstructionFilter->SetMinPlausibleValue( m_Controls->m_TensorEstimationTeemMinValEdit->text().toDouble() );
tensorReconstructionFilter->Update();
clock.Stop();
MBI_DEBUG << "took " << clock.GetMeanTime() << "s." ;
// TENSORS TO DATATREE
mitk::DataNode::Pointer node2=mitk::DataNode::New();
node2->SetData( tensorReconstructionFilter->GetOutputItk() );
QString newname;
newname = newname.append(nodename.c_str());
newname = newname.append("_dtix");
SetDefaultNodeProperties(node2, newname.toStdString());
nodes.push_back(node2);
mitk::ProgressBar::GetInstance()->Progress();
}
std::vector<mitk::DataNode::Pointer>::iterator nodeIt;
for(nodeIt = nodes.begin(); nodeIt != nodes.end(); ++nodeIt)
GetDefaultDataStorage()->Add(*nodeIt);
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Finished Processing %d Files", nrFiles).toAscii());
m_MultiWidget->RequestUpdate();
}
catch (itk::ExceptionObject &ex)
{
MBI_INFO << ex ;
return ;
}
}
void QmitkTensorReconstructionView::SetDefaultNodeProperties(mitk::DataNode::Pointer node, std::string name)
{
node->SetProperty( "ShowMaxNumber", mitk::IntProperty::New( 500 ) );
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", mitk::BoolProperty::New( false ) );
node->SetProperty ("layer", mitk::IntProperty::New(100));
node->SetProperty( "DoRefresh", mitk::BoolProperty::New( true ) );
//node->SetProperty( "opacity", mitk::FloatProperty::New(1.0f) );
node->SetProperty( "name", mitk::StringProperty::New(name) );
}
//node->SetProperty( "volumerendering", mitk::BoolProperty::New( false ) );
//node->SetProperty( "use color", mitk::BoolProperty::New( true ) );
//node->SetProperty( "texture interpolation", mitk::BoolProperty::New( true ) );
//node->SetProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New() );
//node->SetProperty( "layer", mitk::IntProperty::New(0));
//node->SetProperty( "in plane resample extent by geometry", mitk::BoolProperty::New( false ) );
//node->SetOpacity(1.0f);
-//node->SetColor(1.0,1.0,1.0);
+//node->SetColor(1.0,1.0,1.0);
//node->SetVisibility(true);
//node->SetProperty( "IsTensorVolume", mitk::BoolProperty::New( true ) );
//mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New();
//mitk::LevelWindow levelwindow;
//// levelwindow.SetAuto( image );
//levWinProp->SetLevelWindow( levelwindow );
//node->GetPropertyList()->SetProperty( "levelwindow", levWinProp );
//// add a default rainbow lookup table for color mapping
//if(!node->GetProperty("LookupTable"))
//{
// 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( "LookupTable", mitkLutProp );
//}
//if(!node->GetProperty("binary"))
// node->SetProperty( "binary", mitk::BoolProperty::New( false ) );
//// add a default transfer function
//mitk::TransferFunction::Pointer tf = mitk::TransferFunction::New();
//node->SetProperty ( "TransferFunction", mitk::TransferFunctionProperty::New ( tf.GetPointer() ) );
//// set foldername as string property
//mitk::StringProperty::Pointer nameProp = mitk::StringProperty::New( name );
//node->SetProperty( "name", nameProp );
void QmitkTensorReconstructionView::TensorsToDWI()
{
if (m_CurrentSelection)
{
mitk::DataStorage::SetOfObjects::Pointer set =
mitk::DataStorage::SetOfObjects::New();
int at = 0;
- for (IStructuredSelection::iterator i = m_CurrentSelection->Begin();
- i != m_CurrentSelection->End();
+ for (IStructuredSelection::iterator i = m_CurrentSelection->Begin();
+ i != m_CurrentSelection->End();
++i)
{
if (mitk::DataNodeObject::Pointer nodeObj = i->Cast<mitk::DataNodeObject>())
{
mitk::DataNode::Pointer node = nodeObj->GetDataNode();
if(QString("TensorImage").compare(node->GetData()->GetNameOfClass())==0)
{
set->InsertElement(at++, node);
}
}
}
DoTensorsToDWI(set);
}
}
+void QmitkTensorReconstructionView::TensorsToQbi()
+{
+ std::vector<mitk::DataNode*> nodes = this->GetDataManagerSelection();
+ for (int i=0; i<nodes.size(); i++)
+ {
+ mitk::DataNode::Pointer tensorImageNode = nodes.at(i);
+ MITK_INFO << "starting Q-Ball estimation";
+
+ typedef float TTensorPixelType;
+ typedef itk::DiffusionTensor3D< TTensorPixelType > TensorPixelType;
+ typedef itk::Image< TensorPixelType, 3 > TensorImageType;
+
+ TensorImageType::Pointer itkvol = TensorImageType::New();
+ mitk::CastToItkImage<TensorImageType>(dynamic_cast<mitk::TensorImage*>(tensorImageNode->GetData()), itkvol);
+
+ typedef itk::TensorImageToQBallImageFilter< TTensorPixelType, TTensorPixelType > FilterType;
+ FilterType::Pointer filter = FilterType::New();
+ filter->SetInput( itkvol );
+ filter->Update();
+
+ typedef itk::Vector<TTensorPixelType,QBALL_ODFSIZE> OutputPixelType;
+ typedef itk::Image<OutputPixelType,3> OutputImageType;
+
+ mitk::QBallImage::Pointer image = mitk::QBallImage::New();
+ OutputImageType::Pointer outimg = filter->GetOutput();
+ image->InitializeByItk( outimg.GetPointer() );
+ image->SetVolume( outimg->GetBufferPointer() );
+ mitk::DataNode::Pointer node = mitk::DataNode::New();
+ node->SetData( image );
+ QString newname;
+ newname = newname.append(tensorImageNode->GetName().c_str());
+ newname = newname.append("_qbi");
+ node->SetName(newname.toAscii());
+ GetDefaultDataStorage()->Add(node);
+ }
+}
+
+void QmitkTensorReconstructionView::OnSelectionChanged( std::vector<mitk::DataNode*> nodes )
+{
+ if ( !this->IsVisible() )
+ return;
+
+}
+
template<int ndirs>
std::vector<itk::Vector<double,3> > QmitkTensorReconstructionView::MakeGradientList()
{
std::vector<itk::Vector<double,3> > retval;
vnl_matrix_fixed<double, 3, ndirs>* U =
itk::PointShell<ndirs, vnl_matrix_fixed<double, 3, ndirs> >::DistributePointShell();
- for(int i=0; i<ndirs;i++)
+ for(int i=0; i<ndirs;i++)
{
itk::Vector<double,3> 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 QmitkTensorReconstructionView::DoTensorsToDWI
-(mitk::DataStorage::SetOfObjects::Pointer inImages)
+(mitk::DataStorage::SetOfObjects::Pointer inImages)
{
try
{
itk::TimeProbe clock;
int nrFiles = inImages->size();
if (!nrFiles) return;
QString status;
mitk::ProgressBar::GetInstance()->AddStepsToDo(nrFiles);
- mitk::DataStorage::SetOfObjects::const_iterator itemiter( inImages->begin() );
- mitk::DataStorage::SetOfObjects::const_iterator itemiterend( inImages->end() );
+ mitk::DataStorage::SetOfObjects::const_iterator itemiter( inImages->begin() );
+ mitk::DataStorage::SetOfObjects::const_iterator itemiterend( inImages->end() );
std::vector<mitk::DataNode::Pointer> nodes;
while ( itemiter != itemiterend ) // for all items
{
std::string nodename;
(*itemiter)->GetStringProperty("name", nodename);
-
- mitk::TensorImage* vol =
+
+ mitk::TensorImage* vol =
static_cast<mitk::TensorImage*>((*itemiter)->GetData());
-
+
++itemiter;
typedef float TTensorPixelType;
typedef itk::DiffusionTensor3D< TTensorPixelType > TensorPixelType;
typedef itk::Image< TensorPixelType, 3 > TensorImageType;
-
+
TensorImageType::Pointer itkvol = TensorImageType::New();
mitk::CastToItkImage<TensorImageType>(vol, itkvol);
- typedef itk::TensorImageToDiffusionImageFilter<
+ typedef itk::TensorImageToDiffusionImageFilter<
TTensorPixelType, DiffusionPixelType > FilterType;
FilterType::GradientListType gradientList;
switch(m_Controls->m_TensorsToDWINumDirsSelect->currentIndex())
{
case 0:
gradientList = MakeGradientList<12>();
break;
case 1:
gradientList = MakeGradientList<42>();
break;
case 2:
gradientList = MakeGradientList<92>();
break;
case 3:
gradientList = MakeGradientList<162>();
break;
case 4:
gradientList = MakeGradientList<252>();
break;
case 5:
gradientList = MakeGradientList<362>();
break;
case 6:
gradientList = MakeGradientList<492>();
break;
case 7:
gradientList = MakeGradientList<642>();
break;
case 8:
gradientList = MakeGradientList<812>();
break;
case 9:
gradientList = MakeGradientList<1002>();
break;
default:
gradientList = MakeGradientList<92>();
}
double bVal = m_Controls->m_TensorsToDWIBValueEdit->text().toDouble();
// DWI ESTIMATION
clock.Start();
MBI_INFO << "DWI Estimation ";
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf(
"DWI Estimation for %s", nodename.c_str()).toAscii());
FilterType::Pointer filter = FilterType::New();
filter->SetInput( itkvol );
- filter->SetBValue(bVal);
- filter->SetGradientList(gradientList);
- filter->SetNumberOfThreads(1);
+ filter->SetBValue(bVal);
+ filter->SetGradientList(gradientList);
+ //filter->SetNumberOfThreads(1);
filter->Update();
clock.Stop();
MBI_DEBUG << "took " << clock.GetMeanTime() << "s.";
itk::Vector<double,3> v;
v[0] = 0; v[1] = 0; v[2] = 0;
gradientList.push_back(v);
// TENSORS TO DATATREE
mitk::DiffusionImage<DiffusionPixelType>::Pointer image = mitk::DiffusionImage<DiffusionPixelType>::New();
image->SetVectorImage( filter->GetOutput() );
image->SetB_Value(bVal);
image->SetDirections(gradientList);
image->SetOriginalDirections(gradientList);
image->InitializeFromVectorImage();
mitk::DataNode::Pointer node=mitk::DataNode::New();
node->SetData( image );
mitk::DiffusionImageMapper<short>::SetDefaultProperties(node);
QString newname;
newname = newname.append(nodename.c_str());
newname = newname.append("_dwi");
node->SetName(newname.toAscii());
nodes.push_back(node);
mitk::ProgressBar::GetInstance()->Progress();
}
std::vector<mitk::DataNode::Pointer>::iterator nodeIt;
for(nodeIt = nodes.begin(); nodeIt != nodes.end(); ++nodeIt)
GetDefaultDataStorage()->Add(*nodeIt);
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Finished Processing %d Files", nrFiles).toAscii());
m_MultiWidget->RequestUpdate();
}
catch (itk::ExceptionObject &ex)
{
MBI_INFO << ex ;
return ;
}
}
diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionView.h b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionView.h
index c9a8a6bd45..24deb57a32 100644
--- a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionView.h
+++ b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionView.h
@@ -1,120 +1,123 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Module: $RCSfile$
Language: C++
Date: $Date: 2009-05-28 17:19:30 +0200 (Do, 28 Mai 2009) $
-Version: $Revision: 17495 $
-
+Version: $Revision: 17495 $
+
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef _QMITKTENSORRECONSTRUCTIONVIEW_H_INCLUDED
#define _QMITKTENSORRECONSTRUCTIONVIEW_H_INCLUDED
#include <QmitkFunctionality.h>
#include <string>
#include "ui_QmitkTensorReconstructionViewControls.h"
-#include "mitkDiffusionImage.h"
+#include <mitkDiffusionImage.h>
+#include <mitkTensorImage.h>
#include <berryIPartListener.h>
#include <berryISelectionListener.h>
#include <berryIStructuredSelection.h>
typedef short DiffusionPixelType;
struct TrSelListener;
/*!
* \ingroup org_mitk_gui_qt_tensorreconstruction_internal
*
* \brief QmitkTensorReconstructionView
*
* Document your class here.
*
* \sa QmitkFunctionality
*/
class QmitkTensorReconstructionView : public QmitkFunctionality
{
friend struct TrSelListener;
// this is needed for all Qt objects that should have a MOC object (everything that derives from QObject)
Q_OBJECT
public:
static const std::string VIEW_ID;
QmitkTensorReconstructionView();
QmitkTensorReconstructionView(const QmitkTensorReconstructionView& other);
virtual ~QmitkTensorReconstructionView();
virtual void CreateQtPartControl(QWidget *parent);
/// \brief Creation of the connections of main and control widget
virtual void CreateConnections();
/// \brief Called when the functionality is activated
virtual void Activated();
virtual void Deactivated();
virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget);
virtual void StdMultiWidgetNotAvailable();
static const int nrconvkernels;
protected slots:
+ void TensorsToQbi();
void TensorsToDWI();
void DoTensorsToDWI(mitk::DataStorage::SetOfObjects::Pointer inImages);
void TeemCheckboxClicked();
void Advanced1CheckboxClicked();
void Advanced2CheckboxClicked();
void ManualThresholdClicked();
void MethodChoosen(int method);
void Reconstruct(int method);
void TeemReconstruction();
void ItkReconstruction();
void ItkTensorReconstruction
(mitk::DataStorage::SetOfObjects::Pointer inImages);
void TeemTensorReconstruction
(mitk::DataStorage::SetOfObjects::Pointer inImages);
protected:
+ void OnSelectionChanged( std::vector<mitk::DataNode*> nodes );
+
Ui::QmitkTensorReconstructionViewControls* m_Controls;
QmitkStdMultiWidget* m_MultiWidget;
template<int ndirs>
std::vector<itk::Vector<double,3> > MakeGradientList() ;
template<int L>
- void TemplatedAnalyticalTensorReconstruction(mitk::DiffusionImage<DiffusionPixelType>* vols,
+ void TemplatedAnalyticalTensorReconstruction(mitk::DiffusionImage<DiffusionPixelType>* vols,
float lambda, std::string nodename, std::vector<mitk::DataNode::Pointer>* nodes, int normalization);
void SetDefaultNodeProperties(mitk::DataNode::Pointer node, std::string name);
berry::ISelectionListener::Pointer m_SelListener;
berry::IStructuredSelection::ConstPointer m_CurrentSelection;
-
};
#endif // _QMITKTENSORRECONSTRUCTIONVIEW_H_INCLUDED
diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionViewControls.ui b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionViewControls.ui
index 42a1582308..68d661b78e 100644
--- a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionViewControls.ui
+++ b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionViewControls.ui
@@ -1,510 +1,538 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QmitkTensorReconstructionViewControls</class>
<widget class="QWidget" name="QmitkTensorReconstructionViewControls">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
- <width>288</width>
- <height>672</height>
+ <width>345</width>
+ <height>836</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="acceptDrops">
<bool>true</bool>
</property>
<property name="windowTitle">
<string>QmitkTensorReconstructionViewControls</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>ITK Reconstruction</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCheckBox" name="m_Advanced1">
<property name="text">
<string>Advanced Settings</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="m_TensorReconstructionNumberThreadsLabel_2">
<property name="text">
<string>Number of Threads</string>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="m_TensorReconstructionNumberThreadsSpinbox">
<property name="value">
<number>4</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="m_TensorReconstructionThresholdLabel_2">
<property name="text">
<string>B0 Threshold</string>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="m_TensorReconstructionThreasholdEdit">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="m_CheckNegativeEigenvalues">
<property name="text">
<string>Check for negative eigenvalues</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="m_TensorReconstructionNumberThreadsFrame_2">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
</widget>
</item>
<item>
<widget class="QCommandLinkButton" name="m_ItkReconstruction">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string comment="sum of raw signal on equator, normalized to unit mass (Tuch et al. 2004)" extracomment="sum of raw signal on equator, normalized to unit mass (Tuch et al. 2004)">sum of raw signal on equator, normalized to unit mass (Tuch et al. 2004)</string>
</property>
<property name="statusTip">
<string comment="sum of raw signal on equator, normalized to unit mass (Tuch et al. 2004)" extracomment="sum of raw signal on equator, normalized to unit mass (Tuch et al. 2004)">sum of raw signal on equator, normalized to unit mass (Tuch et al. 2004)</string>
</property>
<property name="whatsThis">
<string notr="true" comment="sum of raw signal on equator, normalized to unit mass (Tuch et al. 2004)" extracomment="sum of raw signal on equator, normalized to unit mass (Tuch et al. 2004)">sum of raw signal on equator, normalized to unit mass (Tuch et al. 2004)</string>
</property>
<property name="text">
<string>ITK Tensor Reconstruction</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Estimate Diffusion Image from Tensors</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QFrame" name="m_TensorsToDWIFrame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QFormLayout" name="formLayout_3">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="horizontalSpacing">
<number>6</number>
</property>
<property name="verticalSpacing">
<number>6</number>
</property>
<property name="margin">
<number>9</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="m_TensorsToDWIBValueLabel">
<property name="toolTip">
<string comment="how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;" extracomment="how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;">how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;</string>
</property>
<property name="statusTip">
<string comment="how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;" extracomment="how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;">how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;</string>
</property>
<property name="whatsThis">
<string comment="how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;" extracomment="how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;">how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;</string>
</property>
<property name="text">
<string>B-Value</string>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="m_TensorsToDWIBValueEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string comment="how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;" extracomment="how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;">how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;</string>
</property>
<property name="statusTip">
<string comment="how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;" extracomment="how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;">how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;</string>
</property>
<property name="whatsThis">
<string comment="how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;" extracomment="how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;">how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="m_TensorsToDWINumDirsLabel">
<property name="text">
<string># Gradient Directions</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="m_TensorsToDWINumDirsSelect">
<property name="currentIndex">
<number>3</number>
</property>
<item>
<property name="text">
<string>12</string>
</property>
</item>
<item>
<property name="text">
<string>42</string>
</property>
</item>
<item>
<property name="text">
<string>92</string>
</property>
</item>
<item>
<property name="text">
<string>162</string>
</property>
</item>
<item>
<property name="text">
<string>252</string>
</property>
</item>
<item>
<property name="text">
<string>362</string>
</property>
</item>
<item>
<property name="text">
<string>492</string>
</property>
</item>
<item>
<property name="text">
<string>642</string>
</property>
</item>
<item>
<property name="text">
<string>812</string>
</property>
</item>
<item>
<property name="text">
<string>1002</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QCommandLinkButton" name="m_TensorsToDWIButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string comment="sum of raw signal on equator, normalized to unit mass (Tuch et al. 2004)" extracomment="sum of raw signal on equator, normalized to unit mass (Tuch et al. 2004)">sum of raw signal on equator, normalized to unit mass (Tuch et al. 2004)</string>
</property>
<property name="statusTip">
<string comment="sum of raw signal on equator, normalized to unit mass (Tuch et al. 2004)" extracomment="sum of raw signal on equator, normalized to unit mass (Tuch et al. 2004)">sum of raw signal on equator, normalized to unit mass (Tuch et al. 2004)</string>
</property>
<property name="whatsThis">
<string notr="true" comment="sum of raw signal on equator, normalized to unit mass (Tuch et al. 2004)" extracomment="sum of raw signal on equator, normalized to unit mass (Tuch et al. 2004)">sum of raw signal on equator, normalized to unit mass (Tuch et al. 2004)</string>
</property>
<property name="text">
<string>Diffusion Image Estimation</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_4">
+ <property name="title">
+ <string>Estimate Q-Ball Image from Tensors</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_5">
+ <item>
+ <widget class="QCommandLinkButton" name="m_TensorsToQbiButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="toolTip">
+ <string comment="sum of raw signal on equator, normalized to unit mass (Tuch et al. 2004)" extracomment="sum of raw signal on equator, normalized to unit mass (Tuch et al. 2004)">sum of raw signal on equator, normalized to unit mass (Tuch et al. 2004)</string>
+ </property>
+ <property name="statusTip">
+ <string comment="sum of raw signal on equator, normalized to unit mass (Tuch et al. 2004)" extracomment="sum of raw signal on equator, normalized to unit mass (Tuch et al. 2004)">sum of raw signal on equator, normalized to unit mass (Tuch et al. 2004)</string>
+ </property>
+ <property name="whatsThis">
+ <string notr="true" comment="sum of raw signal on equator, normalized to unit mass (Tuch et al. 2004)" extracomment="sum of raw signal on equator, normalized to unit mass (Tuch et al. 2004)">sum of raw signal on equator, normalized to unit mass (Tuch et al. 2004)</string>
+ </property>
+ <property name="text">
+ <string>Q-Ball Image Estimation</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
<item>
<widget class="QCheckBox" name="m_TeemToggle">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Teem Reconstruction</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Teem Reconstruction</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QCheckBox" name="m_Advanced2">
<property name="text">
<string>Advanced Settings</string>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_2">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QFormLayout" name="formLayout_2">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="3" column="0">
<widget class="QLabel" name="m_TensorEstimationTeemNumItsLabel_2">
<property name="toolTip">
<string>important in case of method wls</string>
</property>
<property name="text">
<string># Iterations </string>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="m_TensorEstimationTeemNumItsSpin"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="m_TensorEstimationTeemFuzzyLabel">
<property name="toolTip">
<string comment="how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;" extracomment="how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;">how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;</string>
</property>
<property name="statusTip">
<string comment="how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;" extracomment="how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;">how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;</string>
</property>
<property name="whatsThis">
<string comment="how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;" extracomment="how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;">how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;</string>
</property>
<property name="text">
<string>Fuzzy confidence</string>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="m_TensorEstimationTeemFuzzyEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string comment="how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;" extracomment="how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;">how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;</string>
</property>
<property name="statusTip">
<string comment="how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;" extracomment="how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;">how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;</string>
</property>
<property name="whatsThis">
<string comment="how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;" extracomment="how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;">how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: &quot;0&quot;</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="m_TensorEstimationTeemMinValLabel_2">
<property name="toolTip">
<string comment="minimum plausible value (especially important for linear least squares estimation) (double); default: &quot;1.0&quot;" extracomment="minimum plausible value (especially important for linear least squares estimation) (double); default: &quot;1.0&quot;">minimum plausible value (especially important for linear least squares estimation) (double); default: &quot;1.0&quot;</string>
</property>
<property name="statusTip">
<string comment="minimum plausible value (especially important for linear least squares estimation) (double); default: &quot;1.0&quot;" extracomment="minimum plausible value (especially important for linear least squares estimation) (double); default: &quot;1.0&quot;">minimum plausible value (especially important for linear least squares estimation) (double); default: &quot;1.0&quot;</string>
</property>
<property name="whatsThis">
<string comment="minimum plausible value (especially important for linear least squares estimation) (double); default: &quot;1.0&quot;" extracomment="minimum plausible value (especially important for linear least squares estimation) (double); default: &quot;1.0&quot;">minimum plausible value (especially important for linear least squares estimation) (double); default: &quot;1.0&quot;</string>
</property>
<property name="text">
<string>Min plausible value</string>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="m_TensorEstimationTeemSigmaLabel_2">
<property name="toolTip">
<string comment="Rician noise parameter (float)" extracomment="Rician noise parameter (float)">Rician noise parameter (float)</string>
</property>
<property name="statusTip">
<string comment="Rician noise parameter (float)" extracomment="Rician noise parameter (float)">Rician noise parameter (float)</string>
</property>
<property name="whatsThis">
<string comment="Rician noise parameter (float)" extracomment="Rician noise parameter (float)">Rician noise parameter (float)</string>
</property>
<property name="text">
<string>Sigma</string>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="m_TensorEstimationTeemMinValEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string comment="minimum plausible value (especially important for linear least squares estimation) (double); default: &quot;1.0&quot;" extracomment="minimum plausible value (especially important for linear least squares estimation) (double); default: &quot;1.0&quot;">minimum plausible value (especially important for linear least squares estimation) (double); default: &quot;1.0&quot;</string>
</property>
<property name="statusTip">
<string comment="minimum plausible value (especially important for linear least squares estimation) (double); default: &quot;1.0&quot;" extracomment="minimum plausible value (especially important for linear least squares estimation) (double); default: &quot;1.0&quot;">minimum plausible value (especially important for linear least squares estimation) (double); default: &quot;1.0&quot;</string>
</property>
<property name="whatsThis">
<string comment="minimum plausible value (especially important for linear least squares estimation) (double); default: &quot;1.0&quot;" extracomment="minimum plausible value (especially important for linear least squares estimation) (double); default: &quot;1.0&quot;">minimum plausible value (especially important for linear least squares estimation) (double); default: &quot;1.0&quot;</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLineEdit" name="m_TensorEstimationTeemSigmaEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string comment="Rician noise parameter (float)" extracomment="Rician noise parameter (float)">Rician noise parameter (float)</string>
</property>
<property name="statusTip">
<string comment="Rician noise parameter (float)" extracomment="Rician noise parameter (float)">Rician noise parameter (float)</string>
</property>
<property name="whatsThis">
<string comment="Rician noise parameter (float)" extracomment="Rician noise parameter (float)">Rician noise parameter (float)</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="m_TensorEstimationTeemEstimationMethodCombo"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Method</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="m_TensorEstimationManualThreashold">
<property name="text">
<string>B0-Threshold</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="m_TensorReconstructionThreasholdEdit_2">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>0</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QCommandLinkButton" name="m_TeemReconstruction">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Teem Tensor Reconstruction</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>1150</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/GUI_Commented.png b/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/GUI_Commented.png
deleted file mode 100644
index 22ca0a4211..0000000000
Binary files a/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/GUI_Commented.png and /dev/null differ
diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/Open_Perspective.png b/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/Open_Perspective.png
deleted file mode 100644
index 5d48dea11e..0000000000
Binary files a/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/Open_Perspective.png and /dev/null differ
diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/QmitkDiffusionImagingAppUserManual.dox b/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/QmitkDiffusionImagingAppUserManual.dox
index 4c0d37c6a0..1e4f442d2b 100644
--- a/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/QmitkDiffusionImagingAppUserManual.dox
+++ b/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/QmitkDiffusionImagingAppUserManual.dox
@@ -1,120 +1,10 @@
/**
-\bundlemainpage{org_diffusionapplication} The Main Application
+\bundlemainpage{org_diffusionapplication} Using The Diffusion Imaging Application
-Welcome to the MITK ExtApplication, build with the <B>M</B>edical <B>I</B>maging <B>T</B>ool<B>k</B>it ( http://mitk.org/ ).
+\section What is the Diffusion Imaging Application
-Available sections:
- - \ref QmitkDiffusionApplicationUserManualOverview
- - \ref QmitkDiffusionApplicationUserManualUserInterface
- - \ref QmitkDiffusionApplicationUserManualPerspectives
+The Diffusion Imaging Application contains selected views for the analysis of images of the human brain. These encompass the views developed by the <a href="http://www.dkfz.de/en/mbi/projects/neuroimaging.html">Neuroimaging Group</a> of the Division Medical and Biological Informatics as well as basic image processing views such as segmentation and volumevisualization.
-\section QmitkDiffusionApplicationUserManualOverview About MITK and MITK ExtApplication
+For a basic guide to MITK see \ref MITKManualMainPage .
-MITK is an open-source framework that was originally developed as a common framework for Ph.D. students in the Division of Medical and Biological Informatics (MBI) at the German Cancer Research Center. MITK aims at supporting the development of leading-edge medical imaging software with a high degree of interaction.
-
-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 features not supported by VTK or ITK.
-
-Research institutes, medical professionals and companies alike can use MITK as a basic framework for their research and even commercial (thorough code research needed) software due to the BSD-like software license.
-
-Research institutes will profit from the high level of integration of ITK and VTK enhanced with data management, advanced visualization and interaction functionality in a single framework that is supported by a wide variety of researchers and developers. You will not have to reinvent the wheel over and over and can concentrate on your work.
-
-Medical Professionals will profit from MITK and the MITK ExtApplication by using its basic functionalities for research projects. But nonetheless they will be better off, unless they are programmers themselves, to cooperate with a research institute developing with MITK to get the functionalitiy they need. MITK and the presented MITK ExtApplication are not certified medical products and may be used in a research setting only. They must not be used in patient care.
-
-MITK ExtApplication is a demonstration of the capabilites of the MITK framework and has been created by the Division of Medical and Biological Informatics (MBI) at the German Cancer Research Center.
-
-\section QmitkDiffusionApplicationUserManualUserInterface The User Interface
-
-The layout of the MITK ExtApplication is designed to give a clear distinction between the different work areas. The following figure gives an overview of the main sections of the user interface.
-
-\image html GUI_Commented.png "The MITK ExtApplication User Interface"
-
-The datamanager and the \ref QmitkDiffusionApplicationUserManualPerspectives have their own help sections. This document explains the use of:
- - The \ref QmitkDiffusionApplicationUserManualMultiWidget
- - The \ref QmitkDiffusionApplicationUserManualMenu
- - The \ref QmitkDiffusionApplicationUserManualLevelWindow
- - The \ref QmitkDiffusionApplicationUserManualMemoryUsage
- - The \ref QmitkDiffusionApplicationUserManualViews
-
-\section QmitkDiffusionApplicationUserManualMultiWidget Four Window View
-
-\subsection QmitkDiffusionApplicationUserManualMultiWidgetOverview Overview
-
-The four window view is the heart of the MITK ExtApplication image viewing. The standard layout is three 2D windows and one 3D window, with the transversal window in the top left quarter, the sagittal window in the top right quarter, the coronal window in the lower left quarter and the 3D window in the lower right quarter. The different planes form a crosshair that can be seen in the 3D window.
-
-Once you select a point within the picture, informations about it are displayed at the bottom of the screen.
-
-\subsection QmitkDiffusionApplicationUserManualMultiWidgetNavigation Navigation
-
-Left click in any of the 2D windows centers the crosshair on that point. Pressing the right mouse button and moving the mouse <B>zooms</B> in and out. By scrolling with the mouse wheel you can <B>navigate through</B> the slices of the active window and pressing the mouse wheel while moving the mouse <B>pans</B> the image section.
-
-In the 3D window you can <B>rotate</B> the object by pressing the left mouse button and moving the mouse, <B>zoom</B> either with the right mouse button as in 2D or with the mouse wheel, and <B>pan</B> the object by moving the mouse while the mouse wheel is pressed. Placing the cursor within the 3D window and holding the "F" key allows <B>free flight</B> into the 3D view.
-
-\subsection QmitkDiffusionApplicationUserManualMultiWidgetCustomizingViews Customizing
-
-By moving the cursor to the upper right corner of any window you can activate the window menu. It consists of three buttons.
-
-\image html Crosshair_Modes.png "Crosshair"
-
-The crosshair button allows you toggle the crosshair, reset the view and change the behaviour of the planes.
-
-Activating either of the rotation modes allows you to rotate the planes visible in a 2D window by moving the mouse cursor close to them and click and dragging once it changes to indicate that rotation can be done.
-
-The swivel mode is recommended only for advanced users as the planes can be moved freely by clicking and dragging anywhere within a 2D window.
-
-
-The middle button expands the corresponding window to fullscreen within the four window view.
-
-\image html Views_Choices.png "Layout Choices"
-
-The right button allows you to choose between many different layouts of the four window view to use the one most suited to your task.
-
-\section QmitkDiffusionApplicationUserManualMenu Menu
-
-\subsection QmitkDiffusionApplicationUserManualFile File
-This dialog allows you to save, load and clear entire projects, this includes any nodes in the data manager.
-
-\subsection QmitkDiffusionApplicationUserManualEdit Edit
-This dialog supports undo and redo operations as well as the image navigator, which gives you sliders to navigate through the data quickly.
-
-\subsection QmitkDiffusionApplicationUserManualWindow Window
-
-This dialog allows you to open a new window, change between perspectives and reset your current one to default settings.
-
-
-If you want to use an operation of a certain perspective within another perspective the "Show View" menu allows to select a specific function that is opened and can be moved within the working areas according to your wishes. Be aware that not every function works with every perspective in a meaningful way.
-
-The Preferences dialog allows you to adjust and save your custom settings.
-
-\image html Window_Dropdown.png "Preferences"
-
-\subsection QmitkDiffusionApplicationUserManualHelp Help
-This dialog contains this help, the welcome screen and information about MITK 3M3.
-
-\section QmitkDiffusionApplicationUserManualLevelWindow Levelwindow
-
-Once an image is loaded the levelwindow appears to the right hand side of the four window view. With this tool you can adjust the range of grey values displayed and the gradient between them. Moving the lower boundary up results in any pixels having a value lower than that boundary to be displayed as black. Lowering the upper boundary causes all pixels having a value higher than it to be displayed as white.
-
-The pixels with a value between the lower and upper boundary are displayed in different shades of grey. This way a smaller levelwindow results in higher contrasts while cutting of the information outside its range whereas a larger levelwindow displays more information at the cost of contrast and detail.
-
-You can pick the levelwindow with the mouse to move it up and down, while moving the mouse cursor to the left or right to change its size. Picking one of the boundaries with a left click allows you to change the size symmetrically. Holding CTRL and clicking a boundary adjusts only that value.
-
-\section QmitkDiffusionApplicationUserManualMemoryUsage System Load Indicator
-
-The System Load Indicator in the lower right hand corner of the screen gives information about the memory currently required by the MITK ExtApplication. Keep in mind that image processing is a highly memory intensive task and monitor the indicator to avoid your system freezing while constantly swapping to the hard drive.
-
-\section QmitkDiffusionApplicationUserManualViews Views
-
-Each solution for a specific problem that is self contained is realized as a single view. Thus you can create a workflow for your problem by combining the capabilities of different views to suit your needs.
-One elegant way to do this is by combining views in \ref QmitkDiffusionApplicationUserManualPerspectives.
-
-By pressing and holding the left mouse button on a views tab you can move it around to suit your needs, even out of the application window.
-
-\section QmitkDiffusionApplicationUserManualPerspectives Perspectives
-
-The different tasks that arise in medical imaging need very different approaches. To acknowledge this circumstance MITK supplies a framework that can be build uppon by very different solutions to those tasks. These solutions are called perspectives, each of them works independently of others although they might be used in sequence to achieve the solution of more difficult problems.
-
-It is possible to switch between the perspectives using the "Window"->"Open Perspective" dialog.
-
-
-See \ref QmitkDiffusionApplicationUserManualMenu for more information about switching perspectives.
*/
diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/Show_Views.png b/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/Show_Views.png
deleted file mode 100644
index 722ed00d39..0000000000
Binary files a/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/Show_Views.png and /dev/null differ
diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/Welcome.png b/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/Welcome.png
deleted file mode 100644
index 5d457e766c..0000000000
Binary files a/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/Welcome.png and /dev/null differ
diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/theme_black.png b/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/theme_black.png
deleted file mode 100644
index a6fefe17d6..0000000000
Binary files a/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/theme_black.png and /dev/null differ
diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/theme_default.png b/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/theme_default.png
deleted file mode 100644
index 4848e4f3c9..0000000000
Binary files a/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/documentation/UserManual/theme_default.png and /dev/null differ
diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/resources/welcome/pics/06aconnectomics.png b/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/resources/welcome/pics/06aconnectomics.png
index 15a9758f32..08c4084111 100644
Binary files a/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/resources/welcome/pics/06aconnectomics.png and b/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/resources/welcome/pics/06aconnectomics.png differ
diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/resources/welcome/pics/06connectomics.png b/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/resources/welcome/pics/06connectomics.png
index b00a6ebc45..3a3b66db14 100644
Binary files a/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/resources/welcome/pics/06connectomics.png and b/Modules/Bundles/org.mitk.gui.qt.diffusionimagingapp/resources/welcome/pics/06connectomics.png differ
diff --git a/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/Crosshair_Modes.png b/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/Crosshair_Modes.png
deleted file mode 100644
index ffc2717c6f..0000000000
Binary files a/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/Crosshair_Modes.png and /dev/null differ
diff --git a/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/GUI.png b/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/GUI.png
deleted file mode 100644
index a31fbfb5c2..0000000000
Binary files a/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/GUI.png and /dev/null differ
diff --git a/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/GUI_Commented.png b/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/GUI_Commented.png
deleted file mode 100644
index 22ca0a4211..0000000000
Binary files a/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/GUI_Commented.png and /dev/null differ
diff --git a/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/Open_Perspective.png b/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/Open_Perspective.png
deleted file mode 100644
index 5d48dea11e..0000000000
Binary files a/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/Open_Perspective.png and /dev/null differ
diff --git a/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/QmitkDTIAtlasAppUserManual.dox b/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/QmitkDTIAtlasAppUserManual.dox
index 02abe53277..b938423fe7 100644
--- a/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/QmitkDTIAtlasAppUserManual.dox
+++ b/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/QmitkDTIAtlasAppUserManual.dox
@@ -1,120 +1,10 @@
/**
-\bundlemainpage{org_dti_atlas_application} The Main Application
+\bundlemainpage{org_dti_atlas_application} Using The DTI Atlas Application
-Welcome to the MITK ExtApplication, build with the <B>M</B>edical <B>I</B>maging <B>T</B>ool<B>k</B>it ( http://mitk.org/ ).
+\section What is the DTI Atlas Application
-Available sections:
- - \ref QmitkDTIAtlasApplicationUserManualOverview
- - \ref QmitkDTIAtlasApplicationUserManualUserInterface
- - \ref QmitkDTIAtlasApplicationUserManualPerspectives
+The DTI Atlas Application is a viewer for MR, diffusion tensor and fibre images and contains no additional functionality. The welcome page allows the selection of which example data to examine.
-\section QmitkDTIAtlasApplicationUserManualOverview About MITK and MITK ExtApplication
+For a basic guide to MITK see \ref MITKManualMainPage .
-MITK is an open-source framework that was originally developed as a common framework for Ph.D. students in the Division of Medical and Biological Informatics (MBI) at the German Cancer Research Center. MITK aims at supporting the development of leading-edge medical imaging software with a high degree of interaction.
-
-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 features not supported by VTK or ITK.
-
-Research institutes, medical professionals and companies alike can use MITK as a basic framework for their research and even commercial (thorough code research needed) software due to the BSD-like software license.
-
-Research institutes will profit from the high level of integration of ITK and VTK enhanced with data management, advanced visualization and interaction functionality in a single framework that is supported by a wide variety of researchers and developers. You will not have to reinvent the wheel over and over and can concentrate on your work.
-
-Medical Professionals will profit from MITK and the MITK ExtApplication by using its basic functionalities for research projects. But nonetheless they will be better off, unless they are programmers themselves, to cooperate with a research institute developing with MITK to get the functionalitiy they need. MITK and the presented MITK ExtApplication are not certified medical products and may be used in a research setting only. They must not be used in patient care.
-
-MITK ExtApplication is a demonstration of the capabilites of the MITK framework and has been created by the Division of Medical and Biological Informatics (MBI) at the German Cancer Research Center.
-
-\section QmitkDTIAtlasApplicationUserManualUserInterface The User Interface
-
-The layout of the MITK ExtApplication is designed to give a clear distinction between the different work areas. The following figure gives an overview of the main sections of the user interface.
-
-\image html GUI_Commented.png "The MITK ExtApplication User Interface"
-
-The datamanager and the \ref QmitkDTIAtlasApplicationUserManualPerspectives have their own help sections. This document explains the use of:
- - The \ref QmitkDTIAtlasApplicationUserManualMultiWidget
- - The \ref QmitkDTIAtlasApplicationUserManualMenu
- - The \ref QmitkDTIAtlasApplicationUserManualLevelWindow
- - The \ref QmitkDTIAtlasApplicationUserManualMemoryUsage
- - The \ref QmitkDTIAtlasApplicationUserManualViews
-
-\section QmitkDTIAtlasApplicationUserManualMultiWidget Four Window View
-
-\subsection QmitkDTIAtlasApplicationUserManualMultiWidgetOverview Overview
-
-The four window view is the heart of the MITK ExtApplication image viewing. The standard layout is three 2D windows and one 3D window, with the transversal window in the top left quarter, the sagittal window in the top right quarter, the coronal window in the lower left quarter and the 3D window in the lower right quarter. The different planes form a crosshair that can be seen in the 3D window.
-
-Once you select a point within the picture, informations about it are displayed at the bottom of the screen.
-
-\subsection QmitkDTIAtlasApplicationUserManualMultiWidgetNavigation Navigation
-
-Left click in any of the 2D windows centers the crosshair on that point. Pressing the right mouse button and moving the mouse <B>zooms</B> in and out. By scrolling with the mouse wheel you can <B>navigate through</B> the slices of the active window and pressing the mouse wheel while moving the mouse <B>pans</B> the image section.
-
-In the 3D window you can <B>rotate</B> the object by pressing the left mouse button and moving the mouse, <B>zoom</B> either with the right mouse button as in 2D or with the mouse wheel, and <B>pan</B> the object by moving the mouse while the mouse wheel is pressed. Placing the cursor within the 3D window and holding the "F" key allows <B>free flight</B> into the 3D view.
-
-\subsection QmitkDTIAtlasApplicationUserManualMultiWidgetCustomizingViews Customizing
-
-By moving the cursor to the upper right corner of any window you can activate the window menu. It consists of three buttons.
-
-\image html Crosshair_Modes.png "Crosshair"
-
-The crosshair button allows you toggle the crosshair, reset the view and change the behaviour of the planes.
-
-Activating either of the rotation modes allows you to rotate the planes visible in a 2D window by moving the mouse cursor close to them and click and dragging once it changes to indicate that rotation can be done.
-
-The swivel mode is recommended only for advanced users as the planes can be moved freely by clicking and dragging anywhere within a 2D window.
-
-
-The middle button expands the corresponding window to fullscreen within the four window view.
-
-\image html Views_Choices.png "Layout Choices"
-
-The right button allows you to choose between many different layouts of the four window view to use the one most suited to your task.
-
-\section QmitkDTIAtlasApplicationUserManualMenu Menu
-
-\subsection QmitkDTIAtlasApplicationUserManualFile File
-This dialog allows you to save, load and clear entire projects, this includes any nodes in the data manager.
-
-\subsection QmitkDTIAtlasApplicationUserManualEdit Edit
-This dialog supports undo and redo operations as well as the image navigator, which gives you sliders to navigate through the data quickly.
-
-\subsection QmitkDTIAtlasApplicationUserManualWindow Window
-
-This dialog allows you to open a new window, change between perspectives and reset your current one to default settings.
-
-
-If you want to use an operation of a certain perspective within another perspective the "Show View" menu allows to select a specific function that is opened and can be moved within the working areas according to your wishes. Be aware that not every function works with every perspective in a meaningful way.
-
-The Preferences dialog allows you to adjust and save your custom settings.
-
-\image html Window_Dropdown.png "Preferences"
-
-\subsection QmitkDTIAtlasApplicationUserManualHelp Help
-This dialog contains this help, the welcome screen and information about MITK 3M3.
-
-\section QmitkDTIAtlasApplicationUserManualLevelWindow Levelwindow
-
-Once an image is loaded the levelwindow appears to the right hand side of the four window view. With this tool you can adjust the range of grey values displayed and the gradient between them. Moving the lower boundary up results in any pixels having a value lower than that boundary to be displayed as black. Lowering the upper boundary causes all pixels having a value higher than it to be displayed as white.
-
-The pixels with a value between the lower and upper boundary are displayed in different shades of grey. This way a smaller levelwindow results in higher contrasts while cutting of the information outside its range whereas a larger levelwindow displays more information at the cost of contrast and detail.
-
-You can pick the levelwindow with the mouse to move it up and down, while moving the mouse cursor to the left or right to change its size. Picking one of the boundaries with a left click allows you to change the size symmetrically. Holding CTRL and clicking a boundary adjusts only that value.
-
-\section QmitkDTIAtlasApplicationUserManualMemoryUsage System Load Indicator
-
-The System Load Indicator in the lower right hand corner of the screen gives information about the memory currently required by the MITK ExtApplication. Keep in mind that image processing is a highly memory intensive task and monitor the indicator to avoid your system freezing while constantly swapping to the hard drive.
-
-\section QmitkDTIAtlasApplicationUserManualViews Views
-
-Each solution for a specific problem that is self contained is realized as a single view. Thus you can create a workflow for your problem by combining the capabilities of different views to suit your needs.
-One elegant way to do this is by combining views in \ref QmitkDTIAtlasApplicationUserManualPerspectives.
-
-By pressing and holding the left mouse button on a views tab you can move it around to suit your needs, even out of the application window.
-
-\section QmitkDTIAtlasApplicationUserManualPerspectives Perspectives
-
-The different tasks that arise in medical imaging need very different approaches. To acknowledge this circumstance MITK supplies a framework that can be build uppon by very different solutions to those tasks. These solutions are called perspectives, each of them works independently of others although they might be used in sequence to achieve the solution of more difficult problems.
-
-It is possible to switch between the perspectives using the "Window"->"Open Perspective" dialog.
-
-
-See \ref QmitkDTIAtlasApplicationUserManualMenu for more information about switching perspectives.
*/
diff --git a/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/Show_Views.png b/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/Show_Views.png
deleted file mode 100644
index 722ed00d39..0000000000
Binary files a/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/Show_Views.png and /dev/null differ
diff --git a/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/Top_Right_Corner_Menu.png b/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/Top_Right_Corner_Menu.png
deleted file mode 100644
index 865400cc98..0000000000
Binary files a/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/Top_Right_Corner_Menu.png and /dev/null differ
diff --git a/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/Views_Choices.png b/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/Views_Choices.png
deleted file mode 100644
index 26c6c332d8..0000000000
Binary files a/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/Views_Choices.png and /dev/null differ
diff --git a/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/Welcome.png b/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/Welcome.png
deleted file mode 100644
index 5d457e766c..0000000000
Binary files a/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/Welcome.png and /dev/null differ
diff --git a/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/Window_Dropdown.png b/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/Window_Dropdown.png
deleted file mode 100644
index b3af19556e..0000000000
Binary files a/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/Window_Dropdown.png and /dev/null differ
diff --git a/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/theme_black.png b/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/theme_black.png
deleted file mode 100644
index a6fefe17d6..0000000000
Binary files a/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/theme_black.png and /dev/null differ
diff --git a/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/theme_default.png b/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/theme_default.png
deleted file mode 100644
index 4848e4f3c9..0000000000
Binary files a/Modules/Bundles/org.mitk.gui.qt.dtiatlasapp/documentation/UserManual/theme_default.png and /dev/null differ
diff --git a/Modules/Bundles/org.mitk.gui.qt.extapplication/documentation/UserManual/Crosshair_Modes.png b/Modules/Bundles/org.mitk.gui.qt.extapplication/documentation/UserManual/Crosshair_Modes.png
deleted file mode 100644
index ffc2717c6f..0000000000
Binary files a/Modules/Bundles/org.mitk.gui.qt.extapplication/documentation/UserManual/Crosshair_Modes.png and /dev/null differ
diff --git a/Modules/Bundles/org.mitk.gui.qt.extapplication/documentation/UserManual/GUI.png b/Modules/Bundles/org.mitk.gui.qt.extapplication/documentation/UserManual/GUI.png
deleted file mode 100644
index a31fbfb5c2..0000000000
Binary files a/Modules/Bundles/org.mitk.gui.qt.extapplication/documentation/UserManual/GUI.png and /dev/null differ
diff --git a/Modules/Bundles/org.mitk.gui.qt.extapplication/documentation/UserManual/QmitkExtapplicationUserManual.dox b/Modules/Bundles/org.mitk.gui.qt.extapplication/documentation/UserManual/QmitkExtapplicationUserManual.dox
index 63dccc44fe..7d3c597634 100644
--- a/Modules/Bundles/org.mitk.gui.qt.extapplication/documentation/UserManual/QmitkExtapplicationUserManual.dox
+++ b/Modules/Bundles/org.mitk.gui.qt.extapplication/documentation/UserManual/QmitkExtapplicationUserManual.dox
@@ -1,120 +1,14 @@
/**
-\bundlemainpage{org_extapplication} The Main Application
+\bundlemainpage{org_extapplication} Using The Ext Application
-Welcome to the MITK ExtApplication, build with the <B>M</B>edical <B>I</B>maging <B>T</B>ool<B>k</B>it ( http://mitk.org/ ).
+\section What is the Ext App
-Available sections:
- - \ref QmitkExtApplicationUserManualOverview
- - \ref QmitkExtApplicationUserManualUserInterface
- - \ref QmitkExtApplicationUserManualPerspectives
+The MITK Ext Application is used by developers. As such the kind and number of views it contains is highly variable and dependent on the specific build. Typically it contains no special perspectives and whatever views the developer deemed desirable. Be aware, that it may contain views which are work in progress and may behave erratically.
-\section QmitkExtApplicationUserManualOverview About MITK and MITK ExtApplication
+If you have been given such an executable by someone, please refer to the appropriate section of the \ref ModuleListPage for up to date usage information on any module.
-MITK is an open-source framework that was originally developed as a common framework for Ph.D. students in the Division of Medical and Biological Informatics (MBI) at the German Cancer Research Center. MITK aims at supporting the development of leading-edge medical imaging software with a high degree of interaction.
+If you are using a nightly installer, the Ext Application will contain nearly all views available in MITK and as such most likely will seem confusing. Again the \ref ModuleListPage might be a good starting point if you want to have a rough idea of what could be of interest to you.
-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 features not supported by VTK or ITK.
+For a basic guide to MITK see \ref MITKManualMainPage .
-Research institutes, medical professionals and companies alike can use MITK as a basic framework for their research and even commercial (thorough code research needed) software due to the BSD-like software license.
-
-Research institutes will profit from the high level of integration of ITK and VTK enhanced with data management, advanced visualization and interaction functionality in a single framework that is supported by a wide variety of researchers and developers. You will not have to reinvent the wheel over and over and can concentrate on your work.
-
-Medical Professionals will profit from MITK and the MITK ExtApplication by using its basic functionalities for research projects. But nonetheless they will be better off, unless they are programmers themselves, to cooperate with a research institute developing with MITK to get the functionalitiy they need. MITK and the presented MITK ExtApplication are not certified medical products and may be used in a research setting only. They must not be used in patient care.
-
-MITK ExtApplication is a demonstration of the capabilites of the MITK framework and has been created by the Division of Medical and Biological Informatics (MBI) at the German Cancer Research Center.
-
-\section QmitkExtApplicationUserManualUserInterface The User Interface
-
-The layout of the MITK ExtApplication is designed to give a clear distinction between the different work areas. The following figure gives an overview of the main sections of the user interface.
-
-\image html GUI_Commented.png "The MITK ExtApplication User Interface"
-
-The datamanager and the \ref QmitkExtApplicationUserManualPerspectives have their own help sections. This document explains the use of:
- - The \ref QmitkExtApplicationUserManualMultiWidget
- - The \ref QmitkExtApplicationUserManualMenu
- - The \ref QmitkExtApplicationUserManualLevelWindow
- - The \ref QmitkExtApplicationUserManualMemoryUsage
- - The \ref QmitkExtApplicationUserManualViews
-
-\section QmitkExtApplicationUserManualMultiWidget Four Window View
-
-\subsection QmitkExtApplicationUserManualMultiWidgetOverview Overview
-
-The four window view is the heart of the MITK ExtApplication image viewing. The standard layout is three 2D windows and one 3D window, with the transversal window in the top left quarter, the sagittal window in the top right quarter, the coronal window in the lower left quarter and the 3D window in the lower right quarter. The different planes form a crosshair that can be seen in the 3D window.
-
-Once you select a point within the picture, informations about it are displayed at the bottom of the screen.
-
-\subsection QmitkExtApplicationUserManualMultiWidgetNavigation Navigation
-
-Left click in any of the 2D windows centers the crosshair on that point. Pressing the right mouse button and moving the mouse <B>zooms</B> in and out. By scrolling with the mouse wheel you can <B>navigate through</B> the slices of the active window and pressing the mouse wheel while moving the mouse <B>pans</B> the image section.
-
-In the 3D window you can <B>rotate</B> the object by pressing the left mouse button and moving the mouse, <B>zoom</B> either with the right mouse button as in 2D or with the mouse wheel, and <B>pan</B> the object by moving the mouse while the mouse wheel is pressed. Placing the cursor within the 3D window and holding the "F" key allows <B>free flight</B> into the 3D view.
-
-\subsection QmitkExtApplicationUserManualMultiWidgetCustomizingViews Customizing
-
-By moving the cursor to the upper right corner of any window you can activate the window menu. It consists of three buttons.
-
-\image html Crosshair_Modes.png "Crosshair"
-
-The crosshair button allows you toggle the crosshair, reset the view and change the behaviour of the planes.
-
-Activating either of the rotation modes allows you to rotate the planes visible in a 2D window by moving the mouse cursor close to them and click and dragging once it changes to indicate that rotation can be done.
-
-The swivel mode is recommended only for advanced users as the planes can be moved freely by clicking and dragging anywhere within a 2D window.
-
-
-The middle button expands the corresponding window to fullscreen within the four window view.
-
-\image html Views_Choices.png "Layout Choices"
-
-The right button allows you to choose between many different layouts of the four window view to use the one most suited to your task.
-
-\section QmitkExtApplicationUserManualMenu Menu
-
-\subsection QmitkExtApplicationUserManualFile File
-This dialog allows you to save, load and clear entire projects, this includes any nodes in the data manager.
-
-\subsection QmitkExtApplicationUserManualEdit Edit
-This dialog supports undo and redo operations as well as the image navigator, which gives you sliders to navigate through the data quickly.
-
-\subsection QmitkExtApplicationUserManualWindow Window
-
-This dialog allows you to open a new window, change between perspectives and reset your current one to default settings.
-
-
-If you want to use an operation of a certain perspective within another perspective the "Show View" menu allows to select a specific function that is opened and can be moved within the working areas according to your wishes. Be aware that not every function works with every perspective in a meaningful way.
-
-The Preferences dialog allows you to adjust and save your custom settings.
-
-\image html Window_Dropdown.png "Preferences"
-
-\subsection QmitkExtApplicationUserManualHelp Help
-This dialog contains this help, the welcome screen and information about MITK 3M3.
-
-\section QmitkExtApplicationUserManualLevelWindow Levelwindow
-
-Once an image is loaded the levelwindow appears to the right hand side of the four window view. With this tool you can adjust the range of grey values displayed and the gradient between them. Moving the lower boundary up results in any pixels having a value lower than that boundary to be displayed as black. Lowering the upper boundary causes all pixels having a value higher than it to be displayed as white.
-
-The pixels with a value between the lower and upper boundary are displayed in different shades of grey. This way a smaller levelwindow results in higher contrasts while cutting of the information outside its range whereas a larger levelwindow displays more information at the cost of contrast and detail.
-
-You can pick the levelwindow with the mouse to move it up and down, while moving the mouse cursor to the left or right to change its size. Picking one of the boundaries with a left click allows you to change the size symmetrically. Holding CTRL and clicking a boundary adjusts only that value.
-
-\section QmitkExtApplicationUserManualMemoryUsage System Load Indicator
-
-The System Load Indicator in the lower right hand corner of the screen gives information about the memory currently required by the MITK ExtApplication. Keep in mind that image processing is a highly memory intensive task and monitor the indicator to avoid your system freezing while constantly swapping to the hard drive.
-
-\section QmitkExtApplicationUserManualViews Views
-
-Each solution for a specific problem that is self contained is realized as a single view. Thus you can create a workflow for your problem by combining the capabilities of different views to suit your needs.
-One elegant way to do this is by combining views in \ref QmitkExtApplicationUserManualPerspectives.
-
-By pressing and holding the left mouse button on a views tab you can move it around to suit your needs, even out of the application window.
-
-\section QmitkExtApplicationUserManualPerspectives Perspectives
-
-The different tasks that arise in medical imaging need very different approaches. To acknowledge this circumstance MITK supplies a framework that can be build uppon by very different solutions to those tasks. These solutions are called perspectives, each of them works independently of others although they might be used in sequence to achieve the solution of more difficult problems.
-
-It is possible to switch between the perspectives using the "Window"->"Open Perspective" dialog.
-
-
-See \ref QmitkExtApplicationUserManualMenu for more information about switching perspectives.
*/
diff --git a/Modules/Bundles/org.mitk.gui.qt.extapplication/documentation/UserManual/Top_Right_Corner_Menu.png b/Modules/Bundles/org.mitk.gui.qt.extapplication/documentation/UserManual/Top_Right_Corner_Menu.png
deleted file mode 100644
index 865400cc98..0000000000
Binary files a/Modules/Bundles/org.mitk.gui.qt.extapplication/documentation/UserManual/Top_Right_Corner_Menu.png and /dev/null differ
diff --git a/Modules/Bundles/org.mitk.gui.qt.extapplication/documentation/UserManual/Views_Choices.png b/Modules/Bundles/org.mitk.gui.qt.extapplication/documentation/UserManual/Views_Choices.png
deleted file mode 100644
index 26c6c332d8..0000000000
Binary files a/Modules/Bundles/org.mitk.gui.qt.extapplication/documentation/UserManual/Views_Choices.png and /dev/null differ
diff --git a/Modules/Bundles/org.mitk.gui.qt.extapplication/documentation/UserManual/Window_Dropdown.png b/Modules/Bundles/org.mitk.gui.qt.extapplication/documentation/UserManual/Window_Dropdown.png
deleted file mode 100644
index b3af19556e..0000000000
Binary files a/Modules/Bundles/org.mitk.gui.qt.extapplication/documentation/UserManual/Window_Dropdown.png and /dev/null differ
diff --git a/Modules/Bundles/org.mitk.gui.qt.igttrackingtoolbox/src/internal/QmitkMITKIGTTrackingToolboxViewControls.ui b/Modules/Bundles/org.mitk.gui.qt.igttrackingtoolbox/src/internal/QmitkMITKIGTTrackingToolboxViewControls.ui
index 0637d36613..03b12a8c52 100644
--- a/Modules/Bundles/org.mitk.gui.qt.igttrackingtoolbox/src/internal/QmitkMITKIGTTrackingToolboxViewControls.ui
+++ b/Modules/Bundles/org.mitk.gui.qt.igttrackingtoolbox/src/internal/QmitkMITKIGTTrackingToolboxViewControls.ui
@@ -1,485 +1,498 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QmitkMITKIGTTrackingToolboxViewControls</class>
<widget class="QWidget" name="QmitkMITKIGTTrackingToolboxViewControls">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
- <width>335</width>
- <height>685</height>
+ <width>371</width>
+ <height>697</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>QmitkTemplate</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QTabWidget" name="m_MainWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Tracking</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QGroupBox" name="groupBox_3">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
<property name="minimumSize">
<size>
<width>0</width>
- <height>280</height>
+ <height>300</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>280</height>
</size>
</property>
<property name="title">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
- <widget class="QmitkTrackingDeviceConfigurationWidget" name="m_configurationWidget" native="true"/>
+ <widget class="QmitkTrackingDeviceConfigurationWidget" name="m_configurationWidget" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:14pt; font-weight:600;&quot;&gt;Tracking Tools&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QLabel" name="m_toolLabel">
<property name="text">
<string>Loaded Tools: &lt;none&gt;</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_7">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="m_AutoDetectTools">
<property name="text">
<string>Auto Detection</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QmitkToolTrackingStatusWidget" name="m_TrackingToolsStatusWidget" native="true"/>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt; font-style:italic;&quot;&gt;(only load tool storage files which can be created &lt;/span&gt;&lt;/p&gt;
&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt; font-style:italic;&quot;&gt;with the bundle &amp;quot;NavigationToolManager&amp;quot;)&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignJustify|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="m_LoadTools">
<property name="text">
<string>Load Tools</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:14pt; font-weight:600;&quot;&gt;Tracking Control&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_TrackingControlLabel">
<property name="text">
<string>Status: &lt;not configured&gt;</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="m_StartTracking">
<property name="text">
<string>Start Tracking</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="m_StopTracking">
<property name="text">
<string>Stop Tracking</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Options</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<widget class="QCheckBox" name="m_ShowTrackingVolume">
<property name="text">
<string>Show Tracking Volume</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QLabel" name="m_OptionsUpdateRateLabel">
<property name="text">
<string>Update Rate (Times Per Second)</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QSpinBox" name="m_UpdateRate">
<property name="maximum">
<number>999</number>
</property>
<property name="value">
<number>10</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="m_ShowToolQuaternions">
<property name="text">
<string>Show Tool Quaternions</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>597</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_3">
<attribute name="title">
<string>Logging</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Filename:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="m_LoggingFileName">
<property name="text">
<string>C:/logfile.csv</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="m_ChooseFile">
<property name="text">
<string>Choose File</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QCheckBox" name="m_LoggingLimit">
<property name="text">
<string>Limit Number Of Logged Frames:</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QSpinBox" name="m_LoggedFramesLimit">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>9999</number>
</property>
<property name="value">
<number>300</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QRadioButton" name="m_csvFormat">
<property name="text">
<string>CSV format</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="m_xmlFormat">
<property name="text">
<string>XML format</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_4">
<property name="title">
<string>Logging Status</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QLabel" name="m_LoggingLabel">
<property name="text">
<string>Logging OFF</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_LoggedFramesLabel">
<property name="text">
<string>Logged Frames: 0</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="m_StartLogging">
<property name="text">
<string>Start Logging</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="m_StopLogging">
<property name="text">
<string>Stop Logging</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>QmitkTrackingDeviceConfigurationWidget</class>
<extends>QWidget</extends>
<header>QmitkTrackingDeviceConfigurationWidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QmitkToolTrackingStatusWidget</class>
<extends>QWidget</extends>
<header>QmitkToolTrackingStatusWidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkCreatePolygonModelAction.cpp b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkCreatePolygonModelAction.cpp
index e4e2f132b5..7cfbf7588f 100644
--- a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkCreatePolygonModelAction.cpp
+++ b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkCreatePolygonModelAction.cpp
@@ -1,160 +1,132 @@
#include "QmitkCreatePolygonModelAction.h"
-#include "mitkShowSegmentationAsSmoothedSurface.h"
-#include "mitkShowSegmentationAsSurface.h"
-#include "mitkProgressBar.h"
-#include "mitkStatusBar.h"
+// MITK
+#include <mitkShowSegmentationAsSmoothedSurface.h>
+#include <mitkShowSegmentationAsSurface.h>
+#include <mitkProgressBar.h>
+#include <mitkStatusBar.h>
+// Blueberry
#include <berryIPreferencesService.h>
#include <berryPlatform.h>
+using namespace berry;
+using namespace mitk;
+using namespace std;
+
QmitkCreatePolygonModelAction::QmitkCreatePolygonModelAction()
{
}
QmitkCreatePolygonModelAction::~QmitkCreatePolygonModelAction()
{
}
-void QmitkCreatePolygonModelAction::Run(const std::vector<mitk::DataNode*>& selectedNodes)
+void QmitkCreatePolygonModelAction::Run(const vector<DataNode *> &selectedNodes)
{
- NodeList selection = selectedNodes;
+ DataNode::Pointer selectedNode = selectedNodes[0];
+ Image::Pointer image = dynamic_cast<mitk::Image *>(selectedNode->GetData());
+
+ if (image.IsNull())
+ return;
- for ( NodeList::iterator iter = selection.begin(); iter != selection.end(); ++iter )
+ try
{
- mitk::DataNode* node = *iter;
-
- if (node)
+ if (!m_IsSmoothed)
{
- mitk::Image::Pointer image = dynamic_cast<mitk::Image*>( node->GetData() );
- if (image.IsNull()) return;
-
- try
- {
- if (!m_IsSmoothed)
- {
- mitk::ShowSegmentationAsSurface::Pointer surfaceFilter = mitk::ShowSegmentationAsSurface::New();
-
- // attach observer to get notified about result
- itk::SimpleMemberCommand<QmitkCreatePolygonModelAction>::Pointer goodCommand = itk::SimpleMemberCommand<QmitkCreatePolygonModelAction>::New();
- goodCommand->SetCallbackFunction(this, &QmitkCreatePolygonModelAction::OnSurfaceCalculationDone);
- surfaceFilter->AddObserver(mitk::ResultAvailable(), goodCommand);
- itk::SimpleMemberCommand<QmitkCreatePolygonModelAction>::Pointer badCommand = itk::SimpleMemberCommand<QmitkCreatePolygonModelAction>::New();
- badCommand->SetCallbackFunction(this, &QmitkCreatePolygonModelAction::OnSurfaceCalculationDone);
- surfaceFilter->AddObserver(mitk::ProcessingError(), badCommand);
-
- mitk::DataNode::Pointer nodepointer = node;
- surfaceFilter->SetPointerParameter("Input", image);
- surfaceFilter->SetPointerParameter("Group node", nodepointer);
- surfaceFilter->SetParameter("Show result", true );
- surfaceFilter->SetParameter("Sync visibility", false );
- surfaceFilter->SetDataStorage( *m_DataStorage );
-
- /*if (this->m_IsSmoothed)
- {
- surfaceFilter->SetParameter("Smooth", true );
- //surfaceFilter->SetParameter("Apply median", true );
- surfaceFilter->SetParameter("Apply median", false ); // median makes the resulting surfaces look like lego models
- surfaceFilter->SetParameter("Median kernel size", 3u );
- surfaceFilter->SetParameter("Gaussian SD", 2.5f );
- surfaceFilter->SetParameter("Decimate mesh", m_IsDecimated );
- surfaceFilter->SetParameter("Decimation rate", 0.8f );
- }
- else
- {*/
- surfaceFilter->SetParameter("Smooth", false );
- surfaceFilter->SetParameter("Apply median", false );
- surfaceFilter->SetParameter("Median kernel size", 3u );
- surfaceFilter->SetParameter("Gaussian SD", 1.5f );
- surfaceFilter->SetParameter("Decimate mesh", m_IsDecimated );
- surfaceFilter->SetParameter("Decimation rate", 0.8f );
- //}
-
- mitk::ProgressBar::GetInstance()->AddStepsToDo(10);
- mitk::ProgressBar::GetInstance()->Progress(2);
- mitk::StatusBar::GetInstance()->DisplayText("Surface creation started in background...");
- surfaceFilter->StartAlgorithm();
- }
- else
- {
- mitk::ShowSegmentationAsSmoothedSurface::Pointer filter = mitk::ShowSegmentationAsSmoothedSurface::New();
-
- itk::SimpleMemberCommand<QmitkCreatePolygonModelAction>::Pointer goodCommand = itk::SimpleMemberCommand<QmitkCreatePolygonModelAction>::New();
- goodCommand->SetCallbackFunction(this, &QmitkCreatePolygonModelAction::OnSurfaceCalculationDone);
- filter->AddObserver(mitk::ResultAvailable(), goodCommand);
-
- itk::SimpleMemberCommand<QmitkCreatePolygonModelAction>::Pointer badCommand = itk::SimpleMemberCommand<QmitkCreatePolygonModelAction>::New();
- badCommand->SetCallbackFunction(this, &QmitkCreatePolygonModelAction::OnSurfaceCalculationDone);
- filter->AddObserver(mitk::ProcessingError(), badCommand);
-
- mitk::DataNode::Pointer nodepointer = node;
- filter->SetPointerParameter("Input", image);
- filter->SetPointerParameter("Group node", nodepointer);
- filter->SetDataStorage(*m_DataStorage);
-
- berry::IPreferencesService::Pointer prefService = berry::Platform::GetServiceRegistry().GetServiceById<berry::IPreferencesService>(berry::IPreferencesService::ID);
- berry::IPreferences::Pointer segPref = prefService->GetSystemPreferences()->Node("/org.mitk.views.segmentation");
-
- bool smoothingHint = segPref->GetBool("smoothing hint", true);
- float smoothing = (float)segPref->GetDouble("smoothing value", 1.0);
- float decimation = (float)segPref->GetDouble("decimation rate", 0.5);
-
- if (smoothingHint)
- {
- smoothing = 0.0;
- mitk::Vector3D spacing = image->GetGeometry()->GetSpacing();
-
- for (mitk::Vector3D::Iterator iter = spacing.Begin(); iter != spacing.End(); ++iter)
- smoothing = std::max(smoothing, *iter);
-
- filter->SetParameter("Smoothing", smoothing);
- }
- else
- {
- filter->SetParameter("Smoothing", smoothing);
- }
-
- filter->SetParameter("Decimation", decimation);
-
- mitk::ProgressBar::GetInstance()->AddStepsToDo(8);
- mitk::StatusBar::GetInstance()->DisplayText("Smoothed surface creation started in background...");
-
- filter->StartAlgorithm();
- }
- }
- catch(...)
- {
- MITK_ERROR << "surface creation filter had an error";
- }
+ ShowSegmentationAsSurface::Pointer surfaceFilter = ShowSegmentationAsSurface::New();
+
+ itk::SimpleMemberCommand<QmitkCreatePolygonModelAction>::Pointer successCommand = itk::SimpleMemberCommand<QmitkCreatePolygonModelAction>::New();
+ successCommand->SetCallbackFunction(this, &QmitkCreatePolygonModelAction::OnSurfaceCalculationDone);
+ surfaceFilter->AddObserver(ResultAvailable(), successCommand);
+
+ itk::SimpleMemberCommand<QmitkCreatePolygonModelAction>::Pointer errorCommand = itk::SimpleMemberCommand<QmitkCreatePolygonModelAction>::New();
+ errorCommand->SetCallbackFunction(this, &QmitkCreatePolygonModelAction::OnSurfaceCalculationDone);
+ surfaceFilter->AddObserver(ProcessingError(), errorCommand);
+
+ surfaceFilter->SetDataStorage(*m_DataStorage);
+ surfaceFilter->SetPointerParameter("Input", image);
+ surfaceFilter->SetPointerParameter("Group node", selectedNode);
+ surfaceFilter->SetParameter("Show result", true);
+ surfaceFilter->SetParameter("Sync visibility", false);
+ surfaceFilter->SetParameter("Smooth", false);
+ surfaceFilter->SetParameter("Apply median", false);
+ surfaceFilter->SetParameter("Median kernel size", 3u);
+ surfaceFilter->SetParameter("Gaussian SD", 1.5f);
+ surfaceFilter->SetParameter("Decimate mesh", m_IsDecimated);
+ surfaceFilter->SetParameter("Decimation rate", 0.8f);
+
+ StatusBar::GetInstance()->DisplayText("Surface creation started in background...");
+
+ surfaceFilter->StartAlgorithm();
}
else
{
- MITK_INFO << " a NULL node selected";
+ ShowSegmentationAsSmoothedSurface::Pointer surfaceFilter = ShowSegmentationAsSmoothedSurface::New();
+
+ itk::SimpleMemberCommand<QmitkCreatePolygonModelAction>::Pointer successCommand = itk::SimpleMemberCommand<QmitkCreatePolygonModelAction>::New();
+ successCommand->SetCallbackFunction(this, &QmitkCreatePolygonModelAction::OnSurfaceCalculationDone);
+ surfaceFilter->AddObserver(mitk::ResultAvailable(), successCommand);
+
+ itk::SimpleMemberCommand<QmitkCreatePolygonModelAction>::Pointer errorCommand = itk::SimpleMemberCommand<QmitkCreatePolygonModelAction>::New();
+ errorCommand->SetCallbackFunction(this, &QmitkCreatePolygonModelAction::OnSurfaceCalculationDone);
+ surfaceFilter->AddObserver(mitk::ProcessingError(), errorCommand);
+
+ surfaceFilter->SetDataStorage(*m_DataStorage);
+ surfaceFilter->SetPointerParameter("Input", image);
+ surfaceFilter->SetPointerParameter("Group node", selectedNode);
+
+ IPreferencesService::Pointer prefService = Platform::GetServiceRegistry().GetServiceById<IPreferencesService>(IPreferencesService::ID);
+ IPreferences::Pointer segPref = prefService->GetSystemPreferences()->Node("/org.mitk.views.segmentation");
+
+ bool smoothingHint = segPref->GetBool("smoothing hint", true);
+ float smoothing = (float)segPref->GetDouble("smoothing value", 1.0);
+ float decimation = (float)segPref->GetDouble("decimation rate", 0.5);
+
+ if (smoothingHint)
+ {
+ smoothing = 0.0;
+ Vector3D spacing = image->GetGeometry()->GetSpacing();
+
+ for (Vector3D::Iterator iter = spacing.Begin(); iter != spacing.End(); ++iter)
+ smoothing = max(smoothing, *iter);
+ }
+
+ surfaceFilter->SetParameter("Smoothing", smoothing);
+ surfaceFilter->SetParameter("Decimation", decimation);
+
+ ProgressBar::GetInstance()->AddStepsToDo(8);
+ StatusBar::GetInstance()->DisplayText("Smoothed surface creation started in background...");
+
+ surfaceFilter->StartAlgorithm();
}
}
+ catch(...)
+ {
+ MITK_ERROR << "Surface creation failed!";
+ }
}
void QmitkCreatePolygonModelAction::OnSurfaceCalculationDone()
{
- mitk::ProgressBar::GetInstance()->Progress(8);
+ StatusBar::GetInstance()->Clear();
}
-void QmitkCreatePolygonModelAction::SetSmoothed(bool smoothed)
+void QmitkCreatePolygonModelAction::SetDataStorage(DataStorage *dataStorage)
{
- this->m_IsSmoothed = smoothed;
+ m_DataStorage = dataStorage;
}
-void QmitkCreatePolygonModelAction::SetDecimated(bool decimated)
+void QmitkCreatePolygonModelAction::SetSmoothed(bool smoothed)
{
- this->m_IsDecimated = decimated;
+ m_IsSmoothed = smoothed;
}
-void QmitkCreatePolygonModelAction::SetDataStorage(mitk::DataStorage* dataStorage)
+void QmitkCreatePolygonModelAction::SetDecimated(bool decimated)
{
- this->m_DataStorage = dataStorage;
+ m_IsDecimated = decimated;
}
-void QmitkCreatePolygonModelAction::SetFunctionality(berry::QtViewPart *functionality)
+void QmitkCreatePolygonModelAction::SetFunctionality(QtViewPart *)
{
- //not needed
}
diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkCreatePolygonModelAction.h b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkCreatePolygonModelAction.h
index d345998db7..9b8272a9e2 100644
--- a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkCreatePolygonModelAction.h
+++ b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkCreatePolygonModelAction.h
@@ -1,45 +1,40 @@
-#ifndef QMITK_CREATEPOLYGONMODELACTION_H
-#define QMITK_CREATEPOLYGONMODELACTION_H
+#ifndef QMITKCREATEPOLYGONMODELACTION_H
+#define QMITKCREATEPOLYGONMODELACTION_H
-#include "berryQtViewPart.h"
-#include "mitkIContextMenuAction.h"
+#include <org_mitk_gui_qt_segmentation_Export.h>
-#include "org_mitk_gui_qt_segmentation_Export.h"
+// Parent classes
+#include <QObject>
+#include <mitkIContextMenuAction.h>
-#include "mitkDataNode.h"
+// Data members
+#include <mitkDataNode.h>
-class MITK_QT_SEGMENTATION QmitkCreatePolygonModelAction: public QObject, public mitk::IContextMenuAction
+class MITK_QT_SEGMENTATION QmitkCreatePolygonModelAction : public QObject, public mitk::IContextMenuAction
{
Q_OBJECT
Q_INTERFACES(mitk::IContextMenuAction)
public:
QmitkCreatePolygonModelAction();
- QmitkCreatePolygonModelAction(const QmitkCreatePolygonModelAction& other)
- {
- Q_UNUSED(other)
- throw std::runtime_error("Copy constructor not implemented");
- }
- virtual ~QmitkCreatePolygonModelAction();
-
- //interface methods
- void Run( const std::vector<mitk::DataNode*>& selectedNodes );
- void SetDataStorage(mitk::DataStorage* dataStorage);
+ ~QmitkCreatePolygonModelAction();
+
+ // IContextMenuAction
+ void Run(const std::vector<mitk::DataNode *> &selectedNodes);
+ void SetDataStorage(mitk::DataStorage *dataStorage);
void SetSmoothed(bool smoothed);
void SetDecimated(bool decimated);
- void SetFunctionality(berry::QtViewPart* functionality);
+ void SetFunctionality(berry::QtViewPart *functionality);
- // for receiving messages
void OnSurfaceCalculationDone();
-protected:
-
- typedef std::vector<mitk::DataNode*> NodeList;
+private:
+ QmitkCreatePolygonModelAction(const QmitkCreatePolygonModelAction &);
+ QmitkCreatePolygonModelAction & operator=(const QmitkCreatePolygonModelAction &);
mitk::DataStorage::Pointer m_DataStorage;
-
bool m_IsSmoothed;
bool m_IsDecimated;
-
};
-#endif // QMITK_CREATEPOLYGONMODELACTION_H
+
+#endif
diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkThresholdAction.cpp b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkThresholdAction.cpp
index d9dfa42728..d36f253df0 100644
--- a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkThresholdAction.cpp
+++ b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkThresholdAction.cpp
@@ -1,104 +1,99 @@
#include "QmitkThresholdAction.h"
-#include "mitkBinaryThresholdTool.h"
-#include "mitkRenderingManager.h"
+// MITK
+#include <mitkBinaryThresholdTool.h>
+#include <mitkRenderingManager.h>
+#include <QmitkToolGUI.h>
-#include "QmitkToolGUI.h"
-#include <QtGui>
+// Qt
+#include <QDialog>
+#include <QVBoxLayout>
+using namespace berry;
+using namespace mitk;
+using namespace std;
QmitkThresholdAction::QmitkThresholdAction()
+ : m_ThresholdingDialog(NULL)
{
}
QmitkThresholdAction::~QmitkThresholdAction()
{
}
-void QmitkThresholdAction::Run(const std::vector<mitk::DataNode*> &selectedNodes)
+void QmitkThresholdAction::Run(const vector<DataNode *> &selectedNodes)
{
- m_ThresholdingToolManager = mitk::ToolManager::New( m_DataStorage );
+ m_ThresholdingToolManager = ToolManager::New(m_DataStorage);
+
m_ThresholdingToolManager->RegisterClient();
- m_ThresholdingToolManager->ActiveToolChanged +=
- mitk::MessageDelegate<QmitkThresholdAction>( this, &QmitkThresholdAction::OnThresholdingToolManagerToolModified );
+ m_ThresholdingToolManager->ActiveToolChanged += mitk::MessageDelegate<QmitkThresholdAction>(this, &QmitkThresholdAction::OnThresholdingToolManagerToolModified);
- m_ThresholdingDialog = new QDialog(NULL);
- connect( m_ThresholdingDialog, SIGNAL(finished(int)), this, SLOT(ThresholdingDone(int)) );
+ m_ThresholdingDialog = new QDialog;
+ connect(m_ThresholdingDialog, SIGNAL(finished(int)), this, SLOT(ThresholdingDone(int)));
- QVBoxLayout* layout = new QVBoxLayout;
+ QVBoxLayout *layout = new QVBoxLayout;
layout->setContentsMargins(0, 0, 0, 0);
- mitk::Tool* tool = m_ThresholdingToolManager->GetToolById( m_ThresholdingToolManager->GetToolIdByToolType<mitk::BinaryThresholdTool>() );
- if (tool)
+ Tool *binaryThresholdTool = m_ThresholdingToolManager->GetToolById(m_ThresholdingToolManager->GetToolIdByToolType<mitk::BinaryThresholdTool>());
+
+ if (binaryThresholdTool != NULL)
{
- itk::Object::Pointer possibleGUI = tool->GetGUI("Qmitk", "GUI");
- QmitkToolGUI* gui = dynamic_cast<QmitkToolGUI*>( possibleGUI.GetPointer() );
- if (gui)
+ QmitkToolGUI *gui = dynamic_cast<QmitkToolGUI *>(binaryThresholdTool->GetGUI("Qmitk", "GUI").GetPointer());
+
+ if (gui != NULL)
{
- gui->SetTool(tool);
+ gui->SetTool(binaryThresholdTool);
gui->setParent(m_ThresholdingDialog);
+
layout->addWidget(gui);
+
m_ThresholdingDialog->setLayout(layout);
- layout->activate();
- m_ThresholdingDialog->setFixedSize(300,80);
+ m_ThresholdingDialog->setFixedSize(300, 80);
+
m_ThresholdingDialog->open();
}
- }
-
- for ( NodeList::const_iterator iter = selectedNodes.begin(); iter != selectedNodes.end(); ++iter )
- {
- mitk::DataNode* node = *iter;
- if (node)
- {
- m_ThresholdingToolManager->SetReferenceData( node );
- m_ThresholdingToolManager->ActivateTool( m_ThresholdingToolManager->GetToolIdByToolType<mitk::BinaryThresholdTool>() );
- }
+ m_ThresholdingToolManager->SetReferenceData(selectedNodes[0]);
+ m_ThresholdingToolManager->ActivateTool(m_ThresholdingToolManager->GetToolIdByToolType<mitk::BinaryThresholdTool>());
}
}
void QmitkThresholdAction::ThresholdingDone(int result)
{
if (result == QDialog::Rejected)
- m_ThresholdingToolManager->ActivateTool(-1);
- MITK_INFO << "Thresholding done, cleaning up";
+ m_ThresholdingToolManager->ActivateTool(-1);
+
m_ThresholdingDialog->deleteLater();
m_ThresholdingDialog = NULL;
- m_ThresholdingToolManager->SetReferenceData( NULL );
- m_ThresholdingToolManager->SetWorkingData( NULL );
- mitk::RenderingManager::GetInstance()->RequestUpdateAll();
+ m_ThresholdingToolManager->SetReferenceData(NULL);
+ m_ThresholdingToolManager->SetWorkingData(NULL);
+
+ RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkThresholdAction::OnThresholdingToolManagerToolModified()
{
- if ( m_ThresholdingToolManager.IsNull() ) return;
-
- //MITK_INFO << "Now got tool " << m_ThresholdingToolManager->GetActiveToolID();
-
- if ( m_ThresholdingToolManager->GetActiveToolID() < 0)
- {
- if (m_ThresholdingDialog)
- m_ThresholdingDialog->accept();
- }
+ if (m_ThresholdingToolManager.IsNotNull())
+ if (m_ThresholdingToolManager->GetActiveToolID() < 0)
+ if (m_ThresholdingDialog != NULL)
+ m_ThresholdingDialog->accept();
}
-void QmitkThresholdAction::SetDataStorage(mitk::DataStorage* dataStorage)
+void QmitkThresholdAction::SetDataStorage(DataStorage *dataStorage)
{
- this->m_DataStorage = dataStorage;
+ m_DataStorage = dataStorage;
}
-void QmitkThresholdAction::SetSmoothed(bool smoothed)
+void QmitkThresholdAction::SetSmoothed(bool)
{
- //not needed
}
-void QmitkThresholdAction::SetDecimated(bool decimated)
+void QmitkThresholdAction::SetDecimated(bool)
{
- //not needed
}
-void QmitkThresholdAction::SetFunctionality(berry::QtViewPart* functionality)
+void QmitkThresholdAction::SetFunctionality(QtViewPart *functionality)
{
- //not needed
-}
\ No newline at end of file
+}
diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkThresholdAction.h b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkThresholdAction.h
index 692ccfd7f4..bc1780f49f 100644
--- a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkThresholdAction.h
+++ b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkThresholdAction.h
@@ -1,57 +1,46 @@
-#ifndef QMITK_THRESHOLDACTION_H
-#define QMITK_THRESHOLDACTION_H
+#ifndef QMITKTHRESHOLDACTION_H
+#define QMITKTHRESHOLDACTION_H
-#include <berryISelectionListener.h>
-#include "berryQtViewPart.h"
+#include <org_mitk_gui_qt_segmentation_Export.h>
-#include "mitkIContextMenuAction.h"
-
-#include "mitkDataStorage.h"
-#include "mitkToolManager.h"
+// Parent classes
+#include <QObject>
+#include <mitkIContextMenuAction.h>
-#include "org_mitk_gui_qt_segmentation_Export.h"
+// Data members
+#include <mitkDataStorage.h>
+#include <mitkToolManager.h>
-#include <QObject>
-#include <QDialog>
+class QDialog;
-class MITK_QT_SEGMENTATION QmitkThresholdAction: public QObject, public mitk::IContextMenuAction
+class MITK_QT_SEGMENTATION QmitkThresholdAction : public QObject, public mitk::IContextMenuAction
{
Q_OBJECT
Q_INTERFACES(mitk::IContextMenuAction)
public:
-
QmitkThresholdAction();
- QmitkThresholdAction(const QmitkThresholdAction& other)
- {
- Q_UNUSED(other)
- throw std::runtime_error("Copy constructor not implemented");
- }
- virtual ~QmitkThresholdAction();
-
- //interface methods
- void Run( const std::vector<mitk::DataNode*>& selectedNodes );
- void SetDataStorage(mitk::DataStorage* dataStorage);
+ ~QmitkThresholdAction();
+
+ // IContextMenuAction
+ void Run(const std::vector<mitk::DataNode *> &selectedNodes);
+ void SetDataStorage(mitk::DataStorage *dataStorage);
void SetSmoothed(bool smoothed);
void SetDecimated(bool decimated);
- void SetFunctionality(berry::QtViewPart* functionality);
+ void SetFunctionality(berry::QtViewPart *functionality);
- // for receiving messages
void OnThresholdingToolManagerToolModified();
-protected:
+private slots:
+ void ThresholdingDone(int);
- typedef std::vector<mitk::DataNode*> NodeList;
+private:
+ QmitkThresholdAction(const QmitkThresholdAction &);
+ QmitkThresholdAction & operator=(const QmitkThresholdAction &);
mitk::DataStorage::Pointer m_DataStorage;
mitk::ToolManager::Pointer m_ThresholdingToolManager;
-
- QDialog* m_ThresholdingDialog;
-
-protected slots:
-
- // class internal slot
- void ThresholdingDone(int);
+ QDialog *m_ThresholdingDialog;
};
-#endif // QMITK_THRESHOLDACTION_H
+#endif
diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.cpp b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.cpp
index a731a4ffbc..d82241db30 100644
--- a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.cpp
+++ b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.cpp
@@ -1,30 +1,26 @@
#include "mitkPluginActivator.h"
-#include <QtPlugin>
#include "QmitkSegmentationView.h"
#include "QmitkThresholdAction.h"
#include "QmitkCreatePolygonModelAction.h"
#include "QmitkStatisticsAction.h"
#include "QmitkAutocropAction.h"
#include "QmitkSegmentationPreferencePage.h"
-namespace mitk {
+using namespace mitk;
-void PluginActivator::start(ctkPluginContext* context)
+void PluginActivator::start(ctkPluginContext *context)
{
BERRY_REGISTER_EXTENSION_CLASS(QmitkSegmentationView, context);
BERRY_REGISTER_EXTENSION_CLASS(QmitkThresholdAction, context);
BERRY_REGISTER_EXTENSION_CLASS(QmitkCreatePolygonModelAction, context);
BERRY_REGISTER_EXTENSION_CLASS(QmitkStatisticsAction, context);
BERRY_REGISTER_EXTENSION_CLASS(QmitkAutocropAction, context);
BERRY_REGISTER_EXTENSION_CLASS(QmitkSegmentationPreferencePage, context);
}
-void PluginActivator::stop(ctkPluginContext* context)
+void PluginActivator::stop(ctkPluginContext *)
{
- Q_UNUSED(context)
-}
-
}
Q_EXPORT_PLUGIN2(org_mitk_gui_qt_segmentation, mitk::PluginActivator)
diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.h b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.h
index a34be34be4..a14d585bbb 100644
--- a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.h
+++ b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.h
@@ -1,23 +1,21 @@
#ifndef MITKPLUGINACTIVATOR_H
#define MITKPLUGINACTIVATOR_H
+// Parent classes
+#include <QObject>
#include <ctkPluginActivator.h>
-namespace mitk {
-
-class PluginActivator :
- public QObject, public ctkPluginActivator
+namespace mitk
{
- Q_OBJECT
- Q_INTERFACES(ctkPluginActivator)
-
-public:
-
- void start(ctkPluginContext* context);
- void stop(ctkPluginContext* context);
-
-}; // PluginActivator
-
+ class PluginActivator : public QObject, public ctkPluginActivator
+ {
+ Q_OBJECT
+ Q_INTERFACES(ctkPluginActivator)
+
+ public:
+ void start(ctkPluginContext *context);
+ void stop(ctkPluginContext *context);
+ };
}
-#endif // MITKPLUGINACTIVATOR_H
+#endif
diff --git a/Modules/DiffusionImaging/Algorithms/itkTensorImageToDiffusionImageFilter.txx b/Modules/DiffusionImaging/Algorithms/itkTensorImageToDiffusionImageFilter.txx
index d88a7f5d48..4c7022e389 100644
--- a/Modules/DiffusionImaging/Algorithms/itkTensorImageToDiffusionImageFilter.txx
+++ b/Modules/DiffusionImaging/Algorithms/itkTensorImageToDiffusionImageFilter.txx
@@ -1,212 +1,213 @@
/*=========================================================================
Program: Tensor ToolKit - TTK
Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkTensorImageToDiffusionImageFilter.txx $
Language: C++
Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $
Version: $Revision: 68 $
Copyright (c) INRIA 2010. All rights reserved.
See LICENSE.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef _itk_TensorImageToDiffusionImageFilter_txx_
#define _itk_TensorImageToDiffusionImageFilter_txx_
#endif
#include "itkTensorImageToDiffusionImageFilter.h"
#include "itkTensorToL2NormImageFilter.h"
#include "itkRescaleIntensityImageFilter.h"
#include <itkImageRegionIterator.h>
#include <itkImageRegionConstIterator.h>
namespace itk
{
//template <class TInputScalarType, class TOutputScalarType>
//void
// TensorImageToDiffusionImageFilter<TInputScalarType, TOutputScalarType>
// ::GenerateData()
//{
// // Call a method that can be overriden by a subclass to allocate
// // memory for the filter's outputs
// this->AllocateOutputs();
// // Call a method that can be overridden by a subclass to perform
// // some calculations prior to splitting the main computations into
// // separate threads
// this->BeforeThreadedGenerateData();
// // Set up the multithreaded processing
// ThreadStruct str;
// str.Filter = this;
// this->GetMultiThreader()->SetNumberOfThreads(this->GetNumberOfThreads());
// this->GetMultiThreader()->SetSingleMethod(this->ThreaderCallback, &str);
// // multithread the execution
// this->GetMultiThreader()->SingleMethodExecute();
// // Call a method that can be overridden by a subclass to perform
// // some calculations after all the threads have completed
// this->AfterThreadedGenerateData();
//}
template <class TInputScalarType, class TOutputScalarType>
void
TensorImageToDiffusionImageFilter<TInputScalarType, TOutputScalarType>
::BeforeThreadedGenerateData()
{
if( m_GradientList.size()==0 )
{
- throw itk::ExceptionObject (__FILE__,__LINE__,"Error: gradient list is empty, cannot generate DWI.");
+ throw itk::ExceptionObject (__FILE__,__LINE__,"Error: gradient list is empty, cannot generate DWI.");
}
// create a B0 image by taking the norm of the tensor field * scale:
typedef itk::TensorToL2NormImageFilter<InputImageType, itk::Image<InputScalarType,3> >
TensorToL2NormFilterType;
typename TensorToL2NormFilterType::Pointer myFilter1 = TensorToL2NormFilterType::New();
myFilter1->SetInput (this->GetInput());
try
{
myFilter1->Update();
}
catch (itk::ExceptionObject &e)
{
std::cerr << e;
return;
}
typename itk::RescaleIntensityImageFilter< itk::Image<InputScalarType,3>, BaselineImageType>::Pointer rescaler=
itk::RescaleIntensityImageFilter<itk::Image<InputScalarType,3>, BaselineImageType>::New();
rescaler->SetOutputMinimum ( 0 );
- rescaler->SetOutputMaximum ( 32767 );
+ rescaler->SetOutputMaximum ( 10000 );
rescaler->SetInput ( myFilter1->GetOutput() );
try
{
rescaler->Update();
}
catch (itk::ExceptionObject &e)
{
std::cerr << e;
return;
}
m_BaselineImage = rescaler->GetOutput();
typename OutputImageType::Pointer outImage = OutputImageType::New();
outImage->SetSpacing( this->GetInput()->GetSpacing() ); // Set the image spacing
outImage->SetOrigin( this->GetInput()->GetOrigin() ); // Set the image origin
outImage->SetDirection( this->GetInput()->GetDirection() ); // Set the image direction
outImage->SetLargestPossibleRegion( this->GetInput()->GetLargestPossibleRegion());
outImage->SetBufferedRegion( this->GetInput()->GetLargestPossibleRegion() );
outImage->SetRequestedRegion( this->GetInput()->GetLargestPossibleRegion() );
outImage->SetVectorLength(m_GradientList.size()+1);
outImage->Allocate();
this->SetNumberOfRequiredOutputs (1);
this->SetNthOutput (0, outImage);
}
template <class TInputScalarType, class TOutputScalarType>
void
TensorImageToDiffusionImageFilter<TInputScalarType, TOutputScalarType>
::ThreadedGenerateData ( const OutputImageRegionType &outputRegionForThread, int threadId )
{
typedef ImageRegionIterator<OutputImageType> IteratorOutputType;
typedef ImageRegionConstIterator<InputImageType> IteratorInputType;
typedef ImageRegionConstIterator<BaselineImageType> IteratorBaselineType;
unsigned long numPixels = outputRegionForThread.GetNumberOfPixels();
unsigned long step = numPixels/100;
unsigned long progress = 0;
IteratorOutputType itOut (this->GetOutput(0), outputRegionForThread);
IteratorInputType itIn (this->GetInput(), outputRegionForThread);
IteratorBaselineType itB0 (m_BaselineImage, outputRegionForThread);
if( threadId==0 )
{
this->UpdateProgress (0.0);
}
while(!itIn.IsAtEnd())
{
if( this->GetAbortGenerateData() )
{
throw itk::ProcessAborted(__FILE__,__LINE__);
}
InputPixelType T = itIn.Get();
BaselinePixelType b0 = itB0.Get();
- OutputPixelType out;
+ OutputPixelType out;
out.SetSize(m_GradientList.size()+1);
+ out.Fill(0);
- for( unsigned int i=0; i<m_GradientList.size(); i++)
+ if( b0 > 0)
{
-
- if( b0 > 0)
+ for( unsigned int i=0; i<m_GradientList.size(); i++)
{
+
GradientType g = m_GradientList[i];
-
+
InputPixelType S;
S[0] = g[0]*g[0];
S[1] = g[1]*g[0];
S[2] = g[2]*g[0];
S[3] = g[1]*g[1];
S[4] = g[2]*g[1];
S[5] = g[2]*g[2];
-
- double res =
- T[0]*S[0] + T[1]*S[1] + T[2]*S[2] +
- T[1]*S[1] + T[3]*S[3] + T[4]*S[4] +
+
+ double res =
+ T[0]*S[0] + T[1]*S[1] + T[2]*S[2] +
+ T[1]*S[1] + T[3]*S[3] + T[4]*S[4] +
T[2]*S[2] + T[4]*S[4] + T[5]*S[5];
-
+
out[i] = static_cast<OutputScalarType>( 1.0*b0*exp ( -1.0 * m_BValue * res ) );
- }
+ }
}
out[m_GradientList.size()] = b0;
itOut.Set(out);
if( threadId==0 && step>0)
- {
+ {
if( (progress%step)==0 )
{
this->UpdateProgress ( double(progress)/double(numPixels) );
}
}
++progress;
++itB0;
++itIn;
++itOut;
}
if( threadId==0 )
- {
+ {
this->UpdateProgress (1.0);
- }
+ }
}
} // end of namespace
diff --git a/Modules/DiffusionImaging/Algorithms/itkTensorImageToQBallImageFilter.h b/Modules/DiffusionImaging/Algorithms/itkTensorImageToQBallImageFilter.h
new file mode 100644
index 0000000000..1e78dd559a
--- /dev/null
+++ b/Modules/DiffusionImaging/Algorithms/itkTensorImageToQBallImageFilter.h
@@ -0,0 +1,92 @@
+/*=========================================================================
+
+Program: Tensor ToolKit - TTK
+Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkTensorImageToQBallImageFilter.h $
+Language: C++
+Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $
+Version: $Revision: 68 $
+
+Copyright (c) INRIA 2010. All rights reserved.
+See LICENSE.txt for details.
+
+This software is distributed WITHOUT ANY WARRANTY; without even
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef _itk_TensorImageToQBallImageFilter_h_
+#define _itk_TensorImageToQBallImageFilter_h_
+
+#include "itkImageToImageFilter.h"
+#include <mitkQBallImage.h>
+#include <itkDiffusionTensor3D.h>
+
+
+namespace itk
+{
+
+ template <class TInputScalarType, class TOutputScalarType>
+ class TensorImageToQBallImageFilter
+ : public ImageToImageFilter<itk::Image<itk::DiffusionTensor3D<TInputScalarType>,3>, itk::Image<itk::Vector<TOutputScalarType,QBALL_ODFSIZE>,3> >
+ {
+
+ public:
+
+ typedef TInputScalarType InputScalarType;
+ typedef itk::DiffusionTensor3D<InputScalarType> InputPixelType;
+ typedef itk::Image<InputPixelType,3> InputImageType;
+ typedef typename InputImageType::RegionType InputImageRegionType;
+
+ typedef TOutputScalarType OutputScalarType;
+ typedef itk::Vector<OutputScalarType,QBALL_ODFSIZE> OutputPixelType;
+ typedef itk::Image<OutputPixelType,3> OutputImageType;
+ typedef typename OutputImageType::RegionType OutputImageRegionType;
+
+ typedef TensorImageToQBallImageFilter Self;
+ typedef ImageToImageFilter<InputImageType, OutputImageType> Superclass;
+
+ typedef SmartPointer<Self> Pointer;
+ typedef SmartPointer<const Self> ConstPointer;
+
+ itkTypeMacro (TensorImageToQBallImageFilter, ImageToImageFilter);
+
+ itkStaticConstMacro (ImageDimension, unsigned int,
+ OutputImageType::ImageDimension);
+
+ itkNewMacro (Self);
+
+
+ protected:
+ TensorImageToQBallImageFilter(){};
+ ~TensorImageToQBallImageFilter(){};
+
+ void PrintSelf (std::ostream& os, Indent indent) const
+ {
+ Superclass::PrintSelf (os, indent);
+ }
+
+ void BeforeThreadedGenerateData( void );
+
+ void ThreadedGenerateData( const
+ OutputImageRegionType &outputRegionForThread, int);
+
+ //void GenerateData();
+
+ private:
+
+ TensorImageToQBallImageFilter (const Self&);
+ void operator=(const Self&);
+
+ typename InputImageType::Pointer m_ItkTensorImage;
+ typename OutputImageType::Pointer m_ItkQBallImage;
+ };
+
+} // end of namespace
+
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "itkTensorImageToQBallImageFilter.txx"
+#endif
+
+
+#endif
diff --git a/Modules/DiffusionImaging/Algorithms/itkTensorImageToQBallImageFilter.txx b/Modules/DiffusionImaging/Algorithms/itkTensorImageToQBallImageFilter.txx
new file mode 100644
index 0000000000..bb2c8199dd
--- /dev/null
+++ b/Modules/DiffusionImaging/Algorithms/itkTensorImageToQBallImageFilter.txx
@@ -0,0 +1,114 @@
+/*=========================================================================
+
+Program: Tensor ToolKit - TTK
+Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkTensorImageToQBallImageFilter.txx $
+Language: C++
+Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $
+Version: $Revision: 68 $
+
+Copyright (c) INRIA 2010. All rights reserved.
+See LICENSE.txt for details.
+
+This software is distributed WITHOUT ANY WARRANTY; without even
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef _itk_TensorImageToQBallImageFilter_txx_
+#define _itk_TensorImageToQBallImageFilter_txx_
+#endif
+
+#include "itkTensorImageToQBallImageFilter.h"
+#include <itkImageRegionIterator.h>
+#include <itkImageRegionConstIterator.h>
+#include <itkOrientationDistributionFunction.h>
+
+namespace itk
+{
+ template <class TInputScalarType, class TOutputScalarType>
+ void
+ TensorImageToQBallImageFilter<TInputScalarType, TOutputScalarType>
+ ::BeforeThreadedGenerateData()
+ {
+ typename OutputImageType::Pointer outImage = OutputImageType::New();
+ outImage->SetSpacing( this->GetInput()->GetSpacing() ); // Set the image spacing
+ outImage->SetOrigin( this->GetInput()->GetOrigin() ); // Set the image origin
+ outImage->SetDirection( this->GetInput()->GetDirection() ); // Set the image direction
+ outImage->SetLargestPossibleRegion( this->GetInput()->GetLargestPossibleRegion());
+ outImage->SetBufferedRegion( this->GetInput()->GetLargestPossibleRegion() );
+ outImage->SetRequestedRegion( this->GetInput()->GetLargestPossibleRegion() );
+ outImage->Allocate();
+
+ this->SetNumberOfRequiredOutputs (1);
+ this->SetNthOutput (0, outImage);
+ }
+
+ template <class TInputScalarType, class TOutputScalarType>
+ void
+ TensorImageToQBallImageFilter<TInputScalarType, TOutputScalarType>
+ ::ThreadedGenerateData ( const OutputImageRegionType &outputRegionForThread, int threadId )
+ {
+
+ typedef ImageRegionIterator<OutputImageType> IteratorOutputType;
+ typedef ImageRegionConstIterator<InputImageType> IteratorInputType;
+
+ unsigned long numPixels = outputRegionForThread.GetNumberOfPixels();
+ unsigned long step = numPixels/100;
+ unsigned long progress = 0;
+
+ IteratorOutputType itOut (this->GetOutput(0), outputRegionForThread);
+ IteratorInputType itIn (this->GetInput(), outputRegionForThread);
+
+ if( threadId==0 )
+ this->UpdateProgress (0.0);
+
+
+ while(!itIn.IsAtEnd())
+ {
+ if( this->GetAbortGenerateData() )
+ {
+ throw itk::ProcessAborted(__FILE__,__LINE__);
+ }
+
+ InputPixelType T = itIn.Get();
+
+ OutputPixelType out;
+
+ float tensorelems[6] = {
+ (float)T[0],
+ (float)T[1],
+ (float)T[2],
+ (float)T[3],
+ (float)T[4],
+ (float)T[5],
+ };
+ itk::DiffusionTensor3D<float> tensor(tensorelems);
+
+ itk::OrientationDistributionFunction<TOutputScalarType, QBALL_ODFSIZE> odf;
+ odf.InitFromTensor(tensor);
+
+ for( unsigned int i=0; i<QBALL_ODFSIZE; i++)
+ out[i] = odf.GetElement(i);
+
+ itOut.Set(out);
+
+ if( threadId==0 && step>0)
+ {
+ if( (progress%step)==0 )
+ {
+ this->UpdateProgress ( double(progress)/double(numPixels) );
+ }
+ }
+
+ ++progress;
+ ++itIn;
+ ++itOut;
+ }
+
+ if( threadId==0 )
+ {
+ this->UpdateProgress (1.0);
+ }
+ MITK_INFO << "one thread finished Q-Ball estimation";
+ }
+} // end of namespace
diff --git a/Modules/DiffusionImaging/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.cpp b/Modules/DiffusionImaging/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.cpp
index df76bbd6b1..3946d616e7 100644
--- a/Modules/DiffusionImaging/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.cpp
+++ b/Modules/DiffusionImaging/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.cpp
@@ -1,1214 +1,1235 @@
/*=========================================================================
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "mitkPartialVolumeAnalysisHistogramCalculator.h"
#include "mitkImageAccessByItk.h"
#include "mitkExtractImageFilter.h"
#include <itkScalarImageToHistogramGenerator.h>
#include <itkStatisticsImageFilter.h>
#include <itkLabelStatisticsImageFilter.h>
#include <itkBSplineUpsampleImageFilter.h>
#include <itkBSplineResampleImageFilterBase.h>
#include "itkResampleImageFilter.h"
#include "itkGaussianInterpolateImageFunction.h"
#include <itkCastImageFilter.h>
#include <itkImageFileWriter.h>
#include <itkVTKImageImport.h>
#include <itkVTKImageExport.h>
#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkPolyData.h>
#include <vtkLinearExtrusionFilter.h>
#include <vtkPolyDataToImageStencil.h>
#include <vtkImageStencil.h>
#include <vtkImageImport.h>
#include <vtkImageExport.h>
#include <vtkImageData.h>
#include <vtkMetaImageWriter.h>
#include <exception>
#include "itkGaussianInterpolateImageFunction.h"
#include "itkBSplineInterpolateImageFunction.h"
#include "itkNearestNeighborInterpolateImageFunction.h"
#include "itkImageMaskSpatialObject.h"
#include "itkRegionOfInterestImageFilter.h"
#include "itkListSample.h"
namespace mitk
{
PartialVolumeAnalysisHistogramCalculator::PartialVolumeAnalysisHistogramCalculator()
: m_MaskingMode( MASKING_MODE_NONE ),
m_MaskingModeChanged( false ),
m_NumberOfBins(256),
m_UpsamplingFactor(1),
m_GaussianSigma(0),
- m_ForceUpdate(false)
+ m_ForceUpdate(false),
+ m_PlanarFigureThickness(0)
{
m_EmptyHistogram = HistogramType::New();
HistogramType::SizeType histogramSize;
histogramSize.Fill( 256 );
m_EmptyHistogram->Initialize( histogramSize );
m_EmptyStatistics.Reset();
}
PartialVolumeAnalysisHistogramCalculator::~PartialVolumeAnalysisHistogramCalculator()
{
}
void PartialVolumeAnalysisHistogramCalculator::SetImage( const mitk::Image *image )
{
if ( m_Image != image )
{
m_Image = image;
this->Modified();
m_ImageStatisticsTimeStamp.Modified();
m_ImageStatisticsCalculationTriggerBool = true;
}
}
void PartialVolumeAnalysisHistogramCalculator::AddAdditionalResamplingImage( const mitk::Image *image )
{
m_AdditionalResamplingImages.push_back(image);
this->Modified();
m_ImageStatisticsTimeStamp.Modified();
m_ImageStatisticsCalculationTriggerBool = true;
}
void PartialVolumeAnalysisHistogramCalculator::SetModified( )
{
this->Modified();
m_ImageStatisticsTimeStamp.Modified();
m_ImageStatisticsCalculationTriggerBool = true;
m_MaskedImageStatisticsTimeStamp.Modified();
m_MaskedImageStatisticsCalculationTriggerBool = true;
m_PlanarFigureStatisticsTimeStamp.Modified();
m_PlanarFigureStatisticsCalculationTriggerBool = true;
}
void PartialVolumeAnalysisHistogramCalculator::SetImageMask( const mitk::Image *imageMask )
{
if ( m_Image.IsNull() )
{
itkExceptionMacro( << "Image needs to be set first!" );
}
if ( m_Image->GetTimeSteps() != imageMask->GetTimeSteps() )
{
itkExceptionMacro( << "Image and image mask need to have equal number of time steps!" );
}
if ( m_ImageMask != imageMask )
{
m_ImageMask = imageMask;
this->Modified();
m_MaskedImageStatisticsTimeStamp.Modified();
m_MaskedImageStatisticsCalculationTriggerBool = true;
}
}
void PartialVolumeAnalysisHistogramCalculator::SetPlanarFigure( const mitk::PlanarFigure *planarFigure )
{
if ( m_Image.IsNull() )
{
itkExceptionMacro( << "Image needs to be set first!" );
}
if ( m_PlanarFigure != planarFigure )
{
m_PlanarFigure = planarFigure;
this->Modified();
m_PlanarFigureStatisticsTimeStamp.Modified();
m_PlanarFigureStatisticsCalculationTriggerBool = true;
}
}
void PartialVolumeAnalysisHistogramCalculator::SetMaskingMode( unsigned int mode )
{
if ( m_MaskingMode != mode )
{
m_MaskingMode = mode;
m_MaskingModeChanged = true;
this->Modified();
}
}
void PartialVolumeAnalysisHistogramCalculator::SetMaskingModeToNone()
{
if ( m_MaskingMode != MASKING_MODE_NONE )
{
m_MaskingMode = MASKING_MODE_NONE;
m_MaskingModeChanged = true;
this->Modified();
}
}
void PartialVolumeAnalysisHistogramCalculator::SetMaskingModeToImage()
{
if ( m_MaskingMode != MASKING_MODE_IMAGE )
{
m_MaskingMode = MASKING_MODE_IMAGE;
m_MaskingModeChanged = true;
this->Modified();
}
}
void PartialVolumeAnalysisHistogramCalculator::SetMaskingModeToPlanarFigure()
{
if ( m_MaskingMode != MASKING_MODE_PLANARFIGURE )
{
m_MaskingMode = MASKING_MODE_PLANARFIGURE;
m_MaskingModeChanged = true;
this->Modified();
}
}
bool PartialVolumeAnalysisHistogramCalculator::ComputeStatistics()
{
MITK_INFO << "ComputeStatistics() start";
if ( m_Image.IsNull() )
{
itkExceptionMacro( << "Image not set!" );
}
if ( m_Image->GetReferenceCount() == 1 )
{
MITK_INFO << "No Stats calculated; no one else holds a reference on it";
return false;
}
// If a mask was set but we are the only ones to still hold a reference on
// it, delete it.
if ( m_ImageMask.IsNotNull() && (m_ImageMask->GetReferenceCount() == 1) )
{
m_ImageMask = NULL;
}
// Check if statistics is already up-to-date
unsigned long imageMTime = m_ImageStatisticsTimeStamp.GetMTime();
unsigned long maskedImageMTime = m_MaskedImageStatisticsTimeStamp.GetMTime();
unsigned long planarFigureMTime = m_PlanarFigureStatisticsTimeStamp.GetMTime();
bool imageStatisticsCalculationTrigger = m_ImageStatisticsCalculationTriggerBool;
bool maskedImageStatisticsCalculationTrigger = m_MaskedImageStatisticsCalculationTriggerBool;
bool planarFigureStatisticsCalculationTrigger = m_PlanarFigureStatisticsCalculationTriggerBool;
if ( /*prevent calculation without mask*/!m_ForceUpdate &&( m_MaskingMode == MASKING_MODE_NONE || (
((m_MaskingMode != MASKING_MODE_NONE) || (imageMTime > m_Image->GetMTime() && !imageStatisticsCalculationTrigger))
&& ((m_MaskingMode != MASKING_MODE_IMAGE) || (m_ImageMask.IsNotNull() && maskedImageMTime > m_ImageMask->GetMTime() && !maskedImageStatisticsCalculationTrigger))
&& ((m_MaskingMode != MASKING_MODE_PLANARFIGURE) || (m_PlanarFigure.IsNotNull() && planarFigureMTime > m_PlanarFigure->GetMTime() && !planarFigureStatisticsCalculationTrigger)) ) ) )
{
MITK_INFO << "Returning, statistics already up to date!";
if ( m_MaskingModeChanged )
{
m_MaskingModeChanged = false;
return true;
}
else
{
return false;
}
}
// Reset state changed flag
m_MaskingModeChanged = false;
// Depending on masking mode, extract and/or generate the required image
// and mask data from the user input
this->ExtractImageAndMask( );
Statistics *statistics;
HistogramType::ConstPointer *histogram;
switch ( m_MaskingMode )
{
case MASKING_MODE_NONE:
default:
statistics = &m_ImageStatistics;
histogram = &m_ImageHistogram;
m_ImageStatisticsTimeStamp.Modified();
m_ImageStatisticsCalculationTriggerBool = false;
break;
case MASKING_MODE_IMAGE:
statistics = &m_MaskedImageStatistics;
histogram = &m_MaskedImageHistogram;
m_MaskedImageStatisticsTimeStamp.Modified();
m_MaskedImageStatisticsCalculationTriggerBool = false;
break;
case MASKING_MODE_PLANARFIGURE:
statistics = &m_PlanarFigureStatistics;
histogram = &m_PlanarFigureHistogram;
m_PlanarFigureStatisticsTimeStamp.Modified();
m_PlanarFigureStatisticsCalculationTriggerBool = false;
break;
}
// Calculate statistics and histogram(s)
if ( m_InternalImage->GetDimension() == 3 )
{
if ( m_MaskingMode == MASKING_MODE_NONE )
{
// Reset state changed flag
AccessFixedDimensionByItk_2(
m_InternalImage,
InternalCalculateStatisticsUnmasked,
3,
*statistics,
histogram );
}
else
{
AccessFixedDimensionByItk_3(
m_InternalImage,
InternalCalculateStatisticsMasked,
3,
m_InternalImageMask3D.GetPointer(),
*statistics,
histogram );
}
}
else if ( m_InternalImage->GetDimension() == 2 )
{
if ( m_MaskingMode == MASKING_MODE_NONE )
{
AccessFixedDimensionByItk_2(
m_InternalImage,
InternalCalculateStatisticsUnmasked,
2,
*statistics,
histogram );
}
else
{
AccessFixedDimensionByItk_3(
m_InternalImage,
InternalCalculateStatisticsMasked,
2,
m_InternalImageMask2D.GetPointer(),
*statistics,
histogram );
}
}
else
{
MITK_ERROR << "ImageStatistics: Image dimension not supported!";
}
// Release unused image smart pointers to free memory
// m_InternalImage = mitk::Image::Pointer();
m_InternalImageMask3D = MaskImage3DType::Pointer();
m_InternalImageMask2D = MaskImage2DType::Pointer();
return true;
}
const PartialVolumeAnalysisHistogramCalculator::HistogramType *
PartialVolumeAnalysisHistogramCalculator::GetHistogram( ) const
{
if ( m_Image.IsNull() )
{
return NULL;
}
switch ( m_MaskingMode )
{
case MASKING_MODE_NONE:
default:
return m_ImageHistogram;
case MASKING_MODE_IMAGE:
return m_MaskedImageHistogram;
case MASKING_MODE_PLANARFIGURE:
return m_PlanarFigureHistogram;
}
}
const PartialVolumeAnalysisHistogramCalculator::Statistics &
PartialVolumeAnalysisHistogramCalculator::GetStatistics( ) const
{
if ( m_Image.IsNull() )
{
return m_EmptyStatistics;
}
switch ( m_MaskingMode )
{
case MASKING_MODE_NONE:
default:
return m_ImageStatistics;
case MASKING_MODE_IMAGE:
return m_MaskedImageStatistics;
case MASKING_MODE_PLANARFIGURE:
return m_PlanarFigureStatistics;
}
}
void PartialVolumeAnalysisHistogramCalculator::ExtractImageAndMask( )
{
MITK_INFO << "ExtractImageAndMask( ) start";
if ( m_Image.IsNull() )
{
throw std::runtime_error( "Error: image empty!" );
}
mitk::Image *timeSliceImage = const_cast<mitk::Image*>(m_Image.GetPointer());//imageTimeSelector->GetOutput();
switch ( m_MaskingMode )
{
case MASKING_MODE_NONE:
{
m_InternalImage = timeSliceImage;
int s = m_AdditionalResamplingImages.size();
m_InternalAdditionalResamplingImages.resize(s);
for(int i=0; i<s; i++)
{
m_InternalAdditionalResamplingImages[i] = const_cast<mitk::Image*>(m_AdditionalResamplingImages[i].GetPointer());
}
m_InternalImageMask2D = NULL;
m_InternalImageMask3D = NULL;
break;
}
case MASKING_MODE_IMAGE:
{
if ( m_ImageMask.IsNotNull() && (m_ImageMask->GetReferenceCount() > 1) )
{
ImageTimeSelector::Pointer maskedImageTimeSelector = ImageTimeSelector::New();
maskedImageTimeSelector->SetInput( m_ImageMask );
maskedImageTimeSelector->SetTimeNr( 0 );
maskedImageTimeSelector->UpdateLargestPossibleRegion();
mitk::Image *timeSliceMaskedImage = maskedImageTimeSelector->GetOutput();
InternalMaskImage(timeSliceMaskedImage);
if(m_UpsamplingFactor != 1)
{
InternalResampleImage(m_InternalImageMask3D);
}
AccessFixedDimensionByItk_1(
timeSliceImage,
InternalResampleImageFromMask, 3, -1 );
int s = m_AdditionalResamplingImages.size();
m_InternalAdditionalResamplingImages.resize(s);
for(int i=0; i<s; i++)
{
AccessFixedDimensionByItk_1(
m_AdditionalResamplingImages[i],
InternalResampleImageFromMask, 3, i );
}
}
else
{
throw std::runtime_error( "Error: image mask empty!" );
}
break;
}
case MASKING_MODE_PLANARFIGURE:
{
m_InternalImageMask2D = NULL;
if ( m_PlanarFigure.IsNull() )
{
throw std::runtime_error( "Error: planar figure empty!" );
}
if ( !m_PlanarFigure->IsClosed() )
{
throw std::runtime_error( "Masking not possible for non-closed figures" );
}
const Geometry3D *imageGeometry = timeSliceImage->GetUpdatedGeometry();
if ( imageGeometry == NULL )
{
throw std::runtime_error( "Image geometry invalid!" );
}
const Geometry2D *planarFigureGeometry2D = m_PlanarFigure->GetGeometry2D();
if ( planarFigureGeometry2D == NULL )
{
throw std::runtime_error( "Planar-Figure not yet initialized!" );
}
const PlaneGeometry *planarFigureGeometry =
dynamic_cast< const PlaneGeometry * >( planarFigureGeometry2D );
if ( planarFigureGeometry == NULL )
{
throw std::runtime_error( "Non-planar planar figures not supported!" );
}
// unsigned int axis = 2;
// unsigned int slice = 0;
AccessFixedDimensionByItk_3(
timeSliceImage,
InternalReorientImagePlane, 3,
timeSliceImage->GetGeometry(),
m_PlanarFigure->GetGeometry(), -1 );
AccessFixedDimensionByItk_1(
m_InternalImage,
InternalCalculateMaskFromPlanarFigure,
3, 2 );
int s = m_AdditionalResamplingImages.size();
for(int i=0; i<s; i++)
{
AccessFixedDimensionByItk_3(
m_AdditionalResamplingImages[i],
InternalReorientImagePlane, 3,
timeSliceImage->GetGeometry(),
m_PlanarFigure->GetGeometry(), i );
AccessFixedDimensionByItk_1(
m_InternalAdditionalResamplingImages[i],
InternalCropAdditionalImage, 3, i );
}
}
}
}
bool PartialVolumeAnalysisHistogramCalculator::GetPrincipalAxis(
const Geometry3D *geometry, Vector3D vector,
unsigned int &axis )
{
vector.Normalize();
for ( unsigned int i = 0; i < 3; ++i )
{
Vector3D axisVector = geometry->GetAxisVector( i );
axisVector.Normalize();
if ( fabs( fabs( axisVector * vector ) - 1.0) < mitk::eps )
{
axis = i;
return true;
}
}
return false;
}
void PartialVolumeAnalysisHistogramCalculator::InternalMaskImage(
mitk::Image *image )
{
typedef itk::ImageMaskSpatialObject<3> ImageMaskSpatialObject;
typedef itk::Image< unsigned char, 3 > ImageType;
typedef itk::ImageRegion<3> RegionType;
typedef mitk::ImageToItk<ImageType> CastType;
CastType::Pointer caster = CastType::New();
caster->SetInput(image);
caster->Update();
ImageMaskSpatialObject::Pointer maskSO = ImageMaskSpatialObject::New();
maskSO->SetImage ( caster->GetOutput() );
m_InternalMask3D =
maskSO->GetAxisAlignedBoundingBoxRegion();
MITK_INFO << "Bounding Box Region: " << m_InternalMask3D;
typedef itk::RegionOfInterestImageFilter< ImageType, MaskImage3DType > ROIFilterType;
ROIFilterType::Pointer roi = ROIFilterType::New();
roi->SetRegionOfInterest(m_InternalMask3D);
roi->SetInput(caster->GetOutput());
roi->Update();
m_InternalImageMask3D = roi->GetOutput();
MITK_INFO << "Created m_InternalImageMask3D";
}
template < typename TPixel, unsigned int VImageDimension >
void PartialVolumeAnalysisHistogramCalculator::InternalReorientImagePlane(
const itk::Image< TPixel, VImageDimension > *image,
mitk::Geometry3D* imggeo, mitk::Geometry3D* planegeo3D, int additionalIndex )
{
MITK_INFO << "InternalReorientImagePlane() start";
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::Image< float, VImageDimension > FloatImageType;
typedef itk::ResampleImageFilter<ImageType, FloatImageType, double> ResamplerType;
typename ResamplerType::Pointer resampler = ResamplerType::New();
mitk::PlaneGeometry* planegeo = dynamic_cast<mitk::PlaneGeometry*>(planegeo3D);
float upsamp = m_UpsamplingFactor;
float gausssigma = m_GaussianSigma;
// Spacing
typename ResamplerType::SpacingType spacing = planegeo->GetSpacing();
spacing[0] = image->GetSpacing()[0] / upsamp;
spacing[1] = image->GetSpacing()[1] / upsamp;
- spacing[2] = image->GetSpacing()[2];
+ spacing[2] = image->GetSpacing()[2] / upsamp; // klaus add /upsamp
resampler->SetOutputSpacing( spacing );
// Size
typename ResamplerType::SizeType size;
size[0] = planegeo->GetParametricExtentInMM(0) / spacing[0];
size[1] = planegeo->GetParametricExtentInMM(1) / spacing[1];
- size[2] = 1;
+ size[2] = 1+2*m_PlanarFigureThickness; // klaus add +2*m_PlanarFigureThickness
resampler->SetSize( size );
// Origin
typename mitk::Point3D orig = planegeo->GetOrigin();
typename mitk::Point3D corrorig;
planegeo3D->WorldToIndex(orig,corrorig);
corrorig[0] += 0.5/upsamp;
corrorig[1] += 0.5/upsamp;
- corrorig[2] += 0;
+ corrorig[2] -= (float)m_PlanarFigureThickness/upsamp; // klaus add -= (float)m_PlanarFigureThickness/upsamp statt += 0
planegeo3D->IndexToWorld(corrorig,corrorig);
resampler->SetOutputOrigin(corrorig );
// Direction
typename ResamplerType::DirectionType direction;
typename mitk::AffineTransform3D::MatrixType matrix = planegeo->GetIndexToWorldTransform()->GetMatrix();
for(int c=0; c<matrix.ColumnDimensions; c++)
{
double sum = 0;
for(int r=0; r<matrix.RowDimensions; r++)
{
sum += matrix(r,c)*matrix(r,c);
}
for(int r=0; r<matrix.RowDimensions; r++)
{
direction(r,c) = matrix(r,c)/sqrt(sum);
}
}
resampler->SetOutputDirection( direction );
// Gaussian interpolation
if(gausssigma != 0)
{
double sigma[3];
for( unsigned int d = 0; d < 3; d++ )
{
sigma[d] = gausssigma * image->GetSpacing()[d];
}
double alpha = 2.0;
typedef itk::GaussianInterpolateImageFunction<ImageType, double>
GaussianInterpolatorType;
typename GaussianInterpolatorType::Pointer interpolator
= GaussianInterpolatorType::New();
interpolator->SetInputImage( image );
interpolator->SetParameters( sigma, alpha );
resampler->SetInterpolator( interpolator );
}
else
{
// typedef typename itk::BSplineInterpolateImageFunction<ImageType, double>
// InterpolatorType;
typedef typename itk::LinearInterpolateImageFunction<ImageType, double> InterpolatorType;
typename InterpolatorType::Pointer interpolator
= InterpolatorType::New();
interpolator->SetInputImage( image );
resampler->SetInterpolator( interpolator );
}
// Other resampling options
resampler->SetInput( image );
resampler->SetDefaultPixelValue(0);
MITK_INFO << "Resampling requested image plane ... ";
resampler->Update();
MITK_INFO << " ... done";
if(additionalIndex < 0)
{
this->m_InternalImage = mitk::Image::New();
this->m_InternalImage->InitializeByItk( resampler->GetOutput() );
this->m_InternalImage->SetVolume( resampler->GetOutput()->GetBufferPointer() );
}
else
{
unsigned int myIndex = additionalIndex;
this->m_InternalAdditionalResamplingImages.push_back(mitk::Image::New());
this->m_InternalAdditionalResamplingImages[myIndex]->InitializeByItk( resampler->GetOutput() );
this->m_InternalAdditionalResamplingImages[myIndex]->SetVolume( resampler->GetOutput()->GetBufferPointer() );
}
}
template < typename TPixel, unsigned int VImageDimension >
void PartialVolumeAnalysisHistogramCalculator::InternalResampleImageFromMask(
const itk::Image< TPixel, VImageDimension > *image, int additionalIndex )
{
typedef itk::Image< TPixel, VImageDimension > ImageType;
typename ImageType::Pointer outImage = ImageType::New();
outImage->SetSpacing( m_InternalImageMask3D->GetSpacing() ); // Set the image spacing
outImage->SetOrigin( m_InternalImageMask3D->GetOrigin() ); // Set the image origin
outImage->SetDirection( m_InternalImageMask3D->GetDirection() ); // Set the image direction
outImage->SetRegions( m_InternalImageMask3D->GetLargestPossibleRegion() );
outImage->Allocate();
outImage->FillBuffer(0);
typedef itk::InterpolateImageFunction<ImageType, double>
BaseInterpType;
typedef itk::GaussianInterpolateImageFunction<ImageType, double>
GaussianInterpolatorType;
typedef itk::BSplineInterpolateImageFunction<ImageType, double>
BSplineInterpolatorType;
typename BaseInterpType::Pointer interpolator;
if(m_GaussianSigma != 0)
{
double sigma[3];
for( unsigned int d = 0; d < 3; d++ )
{
sigma[d] = m_GaussianSigma * image->GetSpacing()[d];
}
double alpha = 2.0;
interpolator = GaussianInterpolatorType::New();
dynamic_cast<GaussianInterpolatorType*>(interpolator.GetPointer())->SetParameters( sigma, alpha );
}
else
{
interpolator = BSplineInterpolatorType::New();
}
interpolator->SetInputImage( image );
itk::ImageRegionConstIterator<MaskImage3DType>
itmask(m_InternalImageMask3D, m_InternalImageMask3D->GetLargestPossibleRegion());
itk::ImageRegionIterator<ImageType>
itimage(outImage, outImage->GetLargestPossibleRegion());
itmask = itmask.Begin();
itimage = itimage.Begin();
itk::Point< double, 3 > point;
itk::ContinuousIndex< double, 3 > index;
while( !itmask.IsAtEnd() )
{
if(itmask.Get() != 0)
{
outImage->TransformIndexToPhysicalPoint (itimage.GetIndex(), point);
image->TransformPhysicalPointToContinuousIndex(point, index);
itimage.Set(interpolator->EvaluateAtContinuousIndex(index));
}
++itmask;
++itimage;
}
if(additionalIndex < 0)
{
this->m_InternalImage = mitk::Image::New();
this->m_InternalImage->InitializeByItk( outImage.GetPointer() );
this->m_InternalImage->SetVolume( outImage->GetBufferPointer() );
}
else
{
this->m_InternalAdditionalResamplingImages[additionalIndex] = mitk::Image::New();
this->m_InternalAdditionalResamplingImages[additionalIndex]->InitializeByItk( outImage.GetPointer() );
this->m_InternalAdditionalResamplingImages[additionalIndex]->SetVolume( outImage->GetBufferPointer() );
}
}
void PartialVolumeAnalysisHistogramCalculator::InternalResampleImage(
const MaskImage3DType *image )
{
typedef itk::ResampleImageFilter<MaskImage3DType, MaskImage3DType, double> ResamplerType;
ResamplerType::Pointer resampler = ResamplerType::New();
// Size
ResamplerType::SizeType size;
size[0] = m_UpsamplingFactor * image->GetLargestPossibleRegion().GetSize()[0];
size[1] = m_UpsamplingFactor * image->GetLargestPossibleRegion().GetSize()[1];
size[2] = m_UpsamplingFactor * image->GetLargestPossibleRegion().GetSize()[2];;
resampler->SetSize( size );
// Origin
mitk::Point3D orig = image->GetOrigin();
resampler->SetOutputOrigin(orig );
// Spacing
ResamplerType::SpacingType spacing;
spacing[0] = image->GetSpacing()[0] / m_UpsamplingFactor;
spacing[1] = image->GetSpacing()[1] / m_UpsamplingFactor;
spacing[2] = image->GetSpacing()[2] / m_UpsamplingFactor;
resampler->SetOutputSpacing( spacing );
resampler->SetOutputDirection( image->GetDirection() );
typedef itk::NearestNeighborInterpolateImageFunction<MaskImage3DType, double>
InterpolatorType;
InterpolatorType::Pointer interpolator
= InterpolatorType::New();
interpolator->SetInputImage( image );
resampler->SetInterpolator( interpolator );
// Other resampling options
resampler->SetInput( image );
resampler->SetDefaultPixelValue(0);
resampler->Update();
m_InternalImageMask3D = resampler->GetOutput();
}
template < typename TPixel, unsigned int VImageDimension >
void PartialVolumeAnalysisHistogramCalculator::InternalCalculateStatisticsUnmasked(
const itk::Image< TPixel, VImageDimension > *image,
Statistics &statistics,
typename HistogramType::ConstPointer *histogram )
{
MITK_INFO << "InternalCalculateStatisticsUnmasked()";
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::Image< unsigned char, VImageDimension > MaskImageType;
typedef typename ImageType::IndexType IndexType;
// Progress listening...
typedef itk::SimpleMemberCommand< PartialVolumeAnalysisHistogramCalculator > ITKCommandType;
ITKCommandType::Pointer progressListener;
progressListener = ITKCommandType::New();
progressListener->SetCallbackFunction( this,
&PartialVolumeAnalysisHistogramCalculator::UnmaskedStatisticsProgressUpdate );
// Issue 100 artificial progress events since ScalarIMageToHistogramGenerator
// does not (yet?) support progress reporting
this->InvokeEvent( itk::StartEvent() );
for ( unsigned int i = 0; i < 100; ++i )
{
this->UnmaskedStatisticsProgressUpdate();
}
// Calculate statistics (separate filter)
typedef itk::StatisticsImageFilter< ImageType > StatisticsFilterType;
typename StatisticsFilterType::Pointer statisticsFilter = StatisticsFilterType::New();
statisticsFilter->SetInput( image );
unsigned long observerTag = statisticsFilter->AddObserver(
itk::ProgressEvent(), progressListener );
statisticsFilter->Update();
statisticsFilter->RemoveObserver( observerTag );
this->InvokeEvent( itk::EndEvent() );
statistics.N = image->GetBufferedRegion().GetNumberOfPixels();
statistics.Min = statisticsFilter->GetMinimum();
statistics.Max = statisticsFilter->GetMaximum();
statistics.Mean = statisticsFilter->GetMean();
statistics.Median = 0.0;
statistics.Sigma = statisticsFilter->GetSigma();
statistics.RMS = sqrt( statistics.Mean * statistics.Mean
+ statistics.Sigma * statistics.Sigma );
typename ImageType::Pointer inImage = const_cast<ImageType*>(image);
// Calculate histogram
typedef itk::Statistics::ScalarImageToHistogramGenerator< ImageType >
HistogramGeneratorType;
typename HistogramGeneratorType::Pointer histogramGenerator = HistogramGeneratorType::New();
histogramGenerator->SetInput( inImage );
histogramGenerator->SetMarginalScale( 10 ); // Defines y-margin width of histogram
histogramGenerator->SetNumberOfBins( m_NumberOfBins ); // CT range [-1024, +2048] --> bin size 4 values
histogramGenerator->SetHistogramMin( statistics.Min );
histogramGenerator->SetHistogramMax( statistics.Max );
histogramGenerator->Compute();
*histogram = histogramGenerator->GetOutput();
}
template < typename TPixel, unsigned int VImageDimension >
void PartialVolumeAnalysisHistogramCalculator::InternalCalculateStatisticsMasked(
const itk::Image< TPixel, VImageDimension > *image,
itk::Image< unsigned char, VImageDimension > *maskImage,
Statistics &statistics,
typename HistogramType::ConstPointer *histogram )
{
MITK_INFO << "InternalCalculateStatisticsMasked() start";
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::Image< unsigned char, VImageDimension > MaskImageType;
typedef typename ImageType::IndexType IndexType;
// generate a list sample of angles at positions
// where the fiber-prob is higher than .2*maxprob
typedef TPixel MeasurementType;
const unsigned int MeasurementVectorLength = 1;
typedef itk::Vector< MeasurementType , MeasurementVectorLength >
MeasurementVectorType;
typedef itk::Statistics::ListSample< MeasurementVectorType > ListSampleType;
typename ListSampleType::Pointer listSample = ListSampleType::New();
listSample->SetMeasurementVectorSize( MeasurementVectorLength );
itk::ImageRegionConstIterator<MaskImageType>
itmask(maskImage, maskImage->GetLargestPossibleRegion());
itk::ImageRegionConstIterator<ImageType>
itimage(image, image->GetLargestPossibleRegion());
itmask = itmask.Begin();
itimage = itimage.Begin();
while( !itmask.IsAtEnd() )
{
if(itmask.Get() != 0)
{
// apend to list
MeasurementVectorType mv;
mv[0] = ( MeasurementType ) itimage.Get();
listSample->PushBack(mv);
}
++itmask;
++itimage;
}
// generate a histogram from the list sample
typedef float HistogramMeasurementType;
typedef itk::Statistics::ListSampleToHistogramGenerator
< ListSampleType, HistogramMeasurementType,
itk::Statistics::DenseFrequencyContainer,
MeasurementVectorLength > GeneratorType;
typename GeneratorType::Pointer generator = GeneratorType::New();
typename GeneratorType::HistogramType::SizeType size;
size.Fill(m_NumberOfBins);
generator->SetNumberOfBins( size );
generator->SetListSample( listSample );
generator->SetMarginalScale( 10.0 );
generator->Update();
*histogram = generator->GetOutput();
}
template < typename TPixel, unsigned int VImageDimension >
void PartialVolumeAnalysisHistogramCalculator::InternalCropAdditionalImage(
itk::Image< TPixel, VImageDimension > *image, int additionalIndex )
{
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::RegionOfInterestImageFilter< ImageType, ImageType > ROIFilterType;
typename ROIFilterType::Pointer roi = ROIFilterType::New();
roi->SetRegionOfInterest(m_CropRegion);
roi->SetInput(image);
roi->Update();
m_InternalAdditionalResamplingImages[additionalIndex] = mitk::Image::New();
m_InternalAdditionalResamplingImages[additionalIndex]->InitializeByItk(roi->GetOutput());
m_InternalAdditionalResamplingImages[additionalIndex]->SetVolume(roi->GetOutput()->GetBufferPointer());
}
template < typename TPixel, unsigned int VImageDimension >
void PartialVolumeAnalysisHistogramCalculator::InternalCalculateMaskFromPlanarFigure(
itk::Image< TPixel, VImageDimension > *image, unsigned int axis )
{
MITK_INFO << "InternalCalculateMaskFromPlanarFigure() start";
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::CastImageFilter< ImageType, MaskImage3DType > CastFilterType;
// Generate mask image as new image with same header as input image and
// initialize with "1".
MaskImage3DType::Pointer newMaskImage = MaskImage3DType::New();
newMaskImage->SetSpacing( image->GetSpacing() ); // Set the image spacing
newMaskImage->SetOrigin( image->GetOrigin() ); // Set the image origin
newMaskImage->SetDirection( image->GetDirection() ); // Set the image direction
newMaskImage->SetRegions( image->GetLargestPossibleRegion() );
newMaskImage->Allocate();
newMaskImage->FillBuffer( 1 );
// Generate VTK polygon from (closed) PlanarFigure polyline
// (The polyline points are shifted by -0.5 in z-direction to make sure
// that the extrusion filter, which afterwards elevates all points by +0.5
// in z-direction, creates a 3D object which is cut by the the plane z=0)
const mitk::Geometry2D *planarFigureGeometry2D = m_PlanarFigure->GetGeometry2D();
const typename PlanarFigure::PolyLineType planarFigurePolyline = m_PlanarFigure->GetPolyLine( 0 );
const mitk::Geometry3D *imageGeometry3D = m_InternalImage->GetGeometry( 0 );
vtkPolyData *polyline = vtkPolyData::New();
polyline->Allocate( 1, 1 );
// Determine x- and y-dimensions depending on principal axis
int i0, i1;
switch ( axis )
{
case 0:
i0 = 1;
i1 = 2;
break;
case 1:
i0 = 0;
i1 = 2;
break;
case 2:
default:
i0 = 0;
i1 = 1;
break;
}
// Create VTK polydata object of polyline contour
bool outOfBounds = false;
vtkPoints *points = vtkPoints::New();
typename PlanarFigure::PolyLineType::const_iterator it;
for ( it = planarFigurePolyline.begin();
it != planarFigurePolyline.end();
++it )
{
Point3D point3D;
// Convert 2D point back to the local index coordinates of the selected
// image
mitk::Point2D point2D = it->Point;
planarFigureGeometry2D->WorldToIndex(point2D, point2D);
point2D[0] -= 0.5/m_UpsamplingFactor;
point2D[1] -= 0.5/m_UpsamplingFactor;
planarFigureGeometry2D->IndexToWorld(point2D, point2D);
planarFigureGeometry2D->Map( point2D, point3D );
// Polygons (partially) outside of the image bounds can not be processed
// further due to a bug in vtkPolyDataToImageStencil
if ( !imageGeometry3D->IsInside( point3D ) )
{
outOfBounds = true;
}
imageGeometry3D->WorldToIndex( point3D, point3D );
point3D[i0] += 0.5;
point3D[i1] += 0.5;
// Add point to polyline array
points->InsertNextPoint( point3D[i0], point3D[i1], -0.5 );
}
polyline->SetPoints( points );
points->Delete();
if ( outOfBounds )
{
polyline->Delete();
throw std::runtime_error( "Figure at least partially outside of image bounds!" );
}
unsigned int numberOfPoints = planarFigurePolyline.size();
vtkIdType *ptIds = new vtkIdType[numberOfPoints];
for ( vtkIdType i = 0; i < numberOfPoints; ++i )
{
ptIds[i] = i;
}
polyline->InsertNextCell( VTK_POLY_LINE, numberOfPoints, ptIds );
// Extrude the generated contour polygon
vtkLinearExtrusionFilter *extrudeFilter = vtkLinearExtrusionFilter::New();
extrudeFilter->SetInput( polyline );
extrudeFilter->SetScaleFactor( 1 );
extrudeFilter->SetExtrusionTypeToNormalExtrusion();
extrudeFilter->SetVector( 0.0, 0.0, 1.0 );
// Make a stencil from the extruded polygon
vtkPolyDataToImageStencil *polyDataToImageStencil = vtkPolyDataToImageStencil::New();
polyDataToImageStencil->SetInput( extrudeFilter->GetOutput() );
// Export from ITK to VTK (to use a VTK filter)
typedef itk::VTKImageImport< MaskImage3DType > ImageImportType;
typedef itk::VTKImageExport< MaskImage3DType > ImageExportType;
typename ImageExportType::Pointer itkExporter = ImageExportType::New();
itkExporter->SetInput( newMaskImage );
vtkImageImport *vtkImporter = vtkImageImport::New();
this->ConnectPipelines( itkExporter, vtkImporter );
vtkImporter->Update();
// Apply the generated image stencil to the input image
vtkImageStencil *imageStencilFilter = vtkImageStencil::New();
imageStencilFilter->SetInput( vtkImporter->GetOutput() );
imageStencilFilter->SetStencil( polyDataToImageStencil->GetOutput() );
imageStencilFilter->ReverseStencilOff();
imageStencilFilter->SetBackgroundValue( 0 );
imageStencilFilter->Update();
// Export from VTK back to ITK
vtkImageExport *vtkExporter = vtkImageExport::New();
vtkExporter->SetInput( imageStencilFilter->GetOutput() );
vtkExporter->Update();
typename ImageImportType::Pointer itkImporter = ImageImportType::New();
this->ConnectPipelines( vtkExporter, itkImporter );
itkImporter->Update();
// calculate cropping bounding box
m_InternalImageMask3D = itkImporter->GetOutput();
m_InternalImageMask3D->SetDirection(image->GetDirection());
- itk::ImageRegionConstIterator<MaskImage3DType>
+ itk::ImageRegionIterator<MaskImage3DType>
itmask(m_InternalImageMask3D, m_InternalImageMask3D->GetLargestPossibleRegion());
- itk::ImageRegionIterator<ImageType>
- itimage(image, image->GetLargestPossibleRegion());
+ itmask = itmask.Begin();
+ while( !itmask.IsAtEnd() )
+ {
+ if(itmask.Get() != 0)
+ {
+ typename ImageType::IndexType index = itmask.GetIndex();
+ for(int thick=0; thick<2*m_PlanarFigureThickness+1; thick++)
+ {
+ index[axis] = thick;
+ m_InternalImageMask3D->SetPixel(index, itmask.Get());
+ }
+ }
+ ++itmask;
+ }
+
+// typedef itk::ImageFileWriter< MaskImage3DType > WriterType;
+// WriterType::Pointer writer = WriterType::New();
+// writer->SetFileName( "/home/fritzsck/Desktop/mask.nrrd" );
+// writer->SetInput( m_InternalImageMask3D );
+// writer->Update();
itmask = itmask.Begin();
+ itk::ImageRegionIterator<ImageType>
+ itimage(image, image->GetLargestPossibleRegion());
itimage = itimage.Begin();
typename ImageType::SizeType lowersize = {{9999999999.0,9999999999.0,9999999999.0}};
typename ImageType::SizeType uppersize = {{0,0,0}};
while( !itmask.IsAtEnd() )
{
if(itmask.Get() == 0)
{
itimage.Set(0);
}
else
{
typename ImageType::IndexType index = itimage.GetIndex();
typename ImageType::SizeType signedindex;
signedindex[0] = index[0];
signedindex[1] = index[1];
signedindex[2] = index[2];
lowersize[0] = signedindex[0] < lowersize[0] ? signedindex[0] : lowersize[0];
lowersize[1] = signedindex[1] < lowersize[1] ? signedindex[1] : lowersize[1];
lowersize[2] = signedindex[2] < lowersize[2] ? signedindex[2] : lowersize[2];
uppersize[0] = signedindex[0] > uppersize[0] ? signedindex[0] : uppersize[0];
uppersize[1] = signedindex[1] > uppersize[1] ? signedindex[1] : uppersize[1];
uppersize[2] = signedindex[2] > uppersize[2] ? signedindex[2] : uppersize[2];
}
++itmask;
++itimage;
}
typename ImageType::IndexType index;
index[0] = lowersize[0];
index[1] = lowersize[1];
index[2] = lowersize[2];
typename ImageType::SizeType size;
size[0] = uppersize[0] - lowersize[0] + 1;
size[1] = uppersize[1] - lowersize[1] + 1;
size[2] = uppersize[2] - lowersize[2] + 1;
m_CropRegion = itk::ImageRegion<3>(index, size);
// crop internal image
typedef itk::RegionOfInterestImageFilter< ImageType, ImageType > ROIFilterType;
typename ROIFilterType::Pointer roi = ROIFilterType::New();
roi->SetRegionOfInterest(m_CropRegion);
roi->SetInput(image);
roi->Update();
m_InternalImage = mitk::Image::New();
m_InternalImage->InitializeByItk(roi->GetOutput());
m_InternalImage->SetVolume(roi->GetOutput()->GetBufferPointer());
// crop internal mask
typedef itk::RegionOfInterestImageFilter< MaskImage3DType, MaskImage3DType > ROIMaskFilterType;
typename ROIMaskFilterType::Pointer roi2 = ROIMaskFilterType::New();
roi2->SetRegionOfInterest(m_CropRegion);
roi2->SetInput(m_InternalImageMask3D);
roi2->Update();
m_InternalImageMask3D = roi2->GetOutput();
// Clean up VTK objects
polyline->Delete();
extrudeFilter->Delete();
polyDataToImageStencil->Delete();
vtkImporter->Delete();
imageStencilFilter->Delete();
//vtkExporter->Delete(); // TODO: crashes when outcommented; memory leak??
delete[] ptIds;
}
void PartialVolumeAnalysisHistogramCalculator::UnmaskedStatisticsProgressUpdate()
{
// Need to throw away every second progress event to reach a final count of
// 100 since two consecutive filters are used in this case
static int updateCounter = 0;
if ( updateCounter++ % 2 == 0 )
{
this->InvokeEvent( itk::ProgressEvent() );
}
}
void PartialVolumeAnalysisHistogramCalculator::MaskedStatisticsProgressUpdate()
{
this->InvokeEvent( itk::ProgressEvent() );
}
}
diff --git a/Modules/DiffusionImaging/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.h b/Modules/DiffusionImaging/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.h
index 35092554a8..a89c6e5331 100644
--- a/Modules/DiffusionImaging/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.h
+++ b/Modules/DiffusionImaging/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.h
@@ -1,360 +1,378 @@
/*========================================================================
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef _MITK_PartialVolumeAnalysisHistogramCalculator_H
#define _MITK_PartialVolumeAnalysisHistogramCalculator_H
#include "MitkDiffusionImagingExports.h"
#include <itkObject.h>
#include <itkImage.h>
#include <itkTimeStamp.h>
#include "mitkImage.h"
#include "mitkImageTimeSelector.h"
#include "mitkPlanarFigure.h"
namespace mitk
{
/**
* \brief Class for calculating statistics and histogram for an (optionally
* masked) image.
*
* Images can be masked by either a (binary) image (of the same dimensions as
* the original image) or by a closed mitk::PlanarFigure, e.g. a circle or
* polygon. When masking with a planar figure, the slice corresponding to the
* plane containing the figure is extracted and then clipped with contour
* defined by the figure. Planar figures need to be aligned along the main axes
* of the image (transversal, sagittal, coronal). Planar figures on arbitrary
* rotated planes are not supported.
*
* For each operating mode (no masking, masking by image, masking by planar
* figure), the calculated statistics and histogram are cached so that, when
* switching back and forth between operation modes without modifying mask or
* image, the information doesn't need to be recalculated.
*
* Note: currently time-resolved and multi-channel pictures are not properly
* supported.
*/
class MitkDiffusionImaging_EXPORT PartialVolumeAnalysisHistogramCalculator : public itk::Object
{
public:
enum
{
MASKING_MODE_NONE = 0,
MASKING_MODE_IMAGE,
MASKING_MODE_PLANARFIGURE
};
typedef mitk::Image::HistogramType HistogramType;
typedef mitk::Image::HistogramType::ConstIterator HistogramConstIteratorType;
struct Statistics
{
unsigned int N;
double Min;
double Max;
double Mean;
double Median;
double Variance;
double Sigma;
double RMS;
void Reset()
{
N = 0;
Min = 0.0;
Max = 0.0;
Mean = 0.0;
Median = 0.0;
Variance = 0.0;
Sigma = 0.0;
RMS = 0.0;
}
};
typedef Statistics StatisticsType;
typedef itk::TimeStamp TimeStampType;
typedef bool BoolType;
typedef itk::Image< unsigned char, 3 > MaskImage3DType;
typedef itk::Image< unsigned char, 2 > MaskImage2DType;
typedef itk::Image< float, 2 > InternalImage2DType;
mitkClassMacro( PartialVolumeAnalysisHistogramCalculator, itk::Object )
itkNewMacro( PartialVolumeAnalysisHistogramCalculator )
/** \brief Set image from which to compute statistics. */
void SetImage( const mitk::Image *image );
/** \brief Set binary image for masking. */
void SetImageMask( const mitk::Image *imageMask );
/** \brief Set planar figure for masking. */
void SetPlanarFigure( const mitk::PlanarFigure *planarFigure );
/** \brief Set image for which the same resampling will be applied.
and available via GetAdditionalResampledImage() */
void AddAdditionalResamplingImage( const mitk::Image *image );
/** \brief Set/Get operation mode for masking */
void SetMaskingMode( unsigned int mode );
/** \brief Set/Get operation mode for masking */
itkGetMacro( MaskingMode, unsigned int );
/** \brief Set/Get operation mode for masking */
void SetMaskingModeToNone();
/** \brief Set/Get operation mode for masking */
void SetMaskingModeToImage();
/** \brief Set/Get operation mode for masking */
void SetMaskingModeToPlanarFigure();
/** \brief Set histogram number of bins. */
void SetNumberOfBins( unsigned int number )
{
if(m_NumberOfBins != number)
{
m_NumberOfBins = number;
SetModified();
}
}
/** \brief Get histogram number of bins. */
unsigned int GetNumberOfBins( )
{ return m_NumberOfBins; }
/** \brief Set upsampling factor. */
void SetUpsamplingFactor( float number )
{
if(m_UpsamplingFactor != number)
{
m_UpsamplingFactor = number;
SetModified();
}
}
/** \brief Get upsampling factor. */
float GetUpsamplingFactor( )
{ return m_UpsamplingFactor; }
/** \brief Set gaussian sigma. */
void SetGaussianSigma( float number )
{
if(m_GaussianSigma != number)
{
m_GaussianSigma = number;
SetModified();
}
}
+ /** \brief Get thickness of planar figure. */
+ unsigned int GetPlanarFigureThickness( )
+ { return m_PlanarFigureThickness; }
+
+
+ /** \brief Set thickness of planar figure. */
+ void SetPlanarFigureThickness( unsigned int number )
+ {
+ if(m_PlanarFigureThickness != number)
+ {
+ m_PlanarFigureThickness = number;
+ SetModified();
+ }
+ }
+
/** \brief Get histogram number of bins. */
float GetGaussianSigma( )
{ return m_GaussianSigma; }
void SetModified();
/** \brief Compute statistics (together with histogram) for the current
* masking mode.
*
* Computation is not executed if statistics is already up to date. In this
* case, false is returned; otherwise, true.*/
virtual bool ComputeStatistics( );
/** \brief Retrieve the histogram depending on the current masking mode. */
const HistogramType *GetHistogram( ) const;
/** \brief Retrieve statistics depending on the current masking mode. */
const Statistics &GetStatistics( ) const;
const Image::Pointer GetInternalImage()
{
return m_InternalImage;
}
const Image::Pointer GetInternalAdditionalResampledImage(unsigned int i)
{
if(i < m_InternalAdditionalResamplingImages.size())
{
return m_InternalAdditionalResamplingImages[i];
}
else
{
return NULL;
}
}
void SetForceUpdate(bool b)
{
m_ForceUpdate = b;
}
protected:
PartialVolumeAnalysisHistogramCalculator();
virtual ~PartialVolumeAnalysisHistogramCalculator();
/** \brief Depending on the masking mode, the image and mask from which to
* calculate statistics is extracted from the original input image and mask
* data.
*
* For example, a when using a PlanarFigure as mask, the 2D image slice
* corresponding to the PlanarFigure will be extracted from the original
* image. If masking is disabled, the original image is simply passed
* through. */
void ExtractImageAndMask( );
/** \brief If the passed vector matches any of the three principal axes
* of the passed geometry, the ínteger value corresponding to the axis
* is set and true is returned. */
bool GetPrincipalAxis( const Geometry3D *geometry, Vector3D vector,
unsigned int &axis );
template < typename TPixel, unsigned int VImageDimension >
void InternalCalculateStatisticsUnmasked(
const itk::Image< TPixel, VImageDimension > *image,
Statistics &statistics,
typename HistogramType::ConstPointer *histogram );
template < typename TPixel, unsigned int VImageDimension >
void InternalCalculateStatisticsMasked(
const itk::Image< TPixel, VImageDimension > *image,
itk::Image< unsigned char, VImageDimension > *maskImage,
Statistics &statistics,
typename HistogramType::ConstPointer *histogram );
template < typename TPixel, unsigned int VImageDimension >
void InternalCalculateMaskFromPlanarFigure(
itk::Image< TPixel, VImageDimension > *image, unsigned int axis );
template < typename TPixel, unsigned int VImageDimension >
void InternalReorientImagePlane(
const itk::Image< TPixel, VImageDimension > *image, mitk::Geometry3D* imggeo, mitk::Geometry3D* planegeo3D, int additionalIndex );
template < typename TPixel, unsigned int VImageDimension >
void InternalResampleImageFromMask(
const itk::Image< TPixel, VImageDimension > *image, int additionalIndex );
void InternalResampleImage(
const MaskImage3DType *image/*, mitk::Geometry3D* imggeo*/ );
template < typename TPixel, unsigned int VImageDimension >
void InternalCropAdditionalImage(
itk::Image< TPixel, VImageDimension > *image, int additionalIndex );
void InternalMaskImage( mitk::Image *image );
/** Connection from ITK to VTK */
template <typename ITK_Exporter, typename VTK_Importer>
void ConnectPipelines(ITK_Exporter exporter, VTK_Importer* importer)
{
importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback());
importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback());
importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback());
importer->SetSpacingCallback(exporter->GetSpacingCallback());
importer->SetOriginCallback(exporter->GetOriginCallback());
importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback());
importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback());
importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback());
importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback());
importer->SetDataExtentCallback(exporter->GetDataExtentCallback());
importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback());
importer->SetCallbackUserData(exporter->GetCallbackUserData());
}
/** Connection from VTK to ITK */
template <typename VTK_Exporter, typename ITK_Importer>
void ConnectPipelines(VTK_Exporter* exporter, ITK_Importer importer)
{
importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback());
importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback());
importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback());
importer->SetSpacingCallback(exporter->GetSpacingCallback());
importer->SetOriginCallback(exporter->GetOriginCallback());
importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback());
importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback());
importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback());
importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback());
importer->SetDataExtentCallback(exporter->GetDataExtentCallback());
importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback());
importer->SetCallbackUserData(exporter->GetCallbackUserData());
}
void UnmaskedStatisticsProgressUpdate();
void MaskedStatisticsProgressUpdate();
mitk::Image::ConstPointer m_Image;
mitk::Image::ConstPointer m_ImageMask;
mitk::PlanarFigure::ConstPointer m_PlanarFigure;
HistogramType::ConstPointer m_ImageHistogram;
HistogramType::ConstPointer m_MaskedImageHistogram;
HistogramType::ConstPointer m_PlanarFigureHistogram;
HistogramType::Pointer m_EmptyHistogram;
StatisticsType m_ImageStatistics;
StatisticsType m_MaskedImageStatistics;
StatisticsType m_PlanarFigureStatistics;
Statistics m_EmptyStatistics;
unsigned int m_MaskingMode;
bool m_MaskingModeChanged;
mitk::Image::Pointer m_InternalImage;
MaskImage3DType::Pointer m_InternalImageMask3D;
MaskImage2DType::Pointer m_InternalImageMask2D;
itk::ImageRegion<3> m_InternalMask3D;
std::vector<mitk::Image::ConstPointer> m_AdditionalResamplingImages;
std::vector<mitk::Image::Pointer> m_InternalAdditionalResamplingImages;
TimeStampType m_ImageStatisticsTimeStamp;
TimeStampType m_MaskedImageStatisticsTimeStamp;
TimeStampType m_PlanarFigureStatisticsTimeStamp;
BoolType m_ImageStatisticsCalculationTriggerBool;
BoolType m_MaskedImageStatisticsCalculationTriggerBool;
BoolType m_PlanarFigureStatisticsCalculationTriggerBool;
unsigned int m_NumberOfBins;
float m_UpsamplingFactor;
float m_GaussianSigma;
itk::ImageRegion<3> m_CropRegion;
bool m_ForceUpdate;
+
+ unsigned int m_PlanarFigureThickness;
+
};
}
#endif // #define _MITK_PartialVolumeAnalysisHistogramCalculator_H
diff --git a/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleXThreadMonitor.cpp b/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleXThreadMonitor.cpp
index 269a655d56..856f833f4e 100644
--- a/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleXThreadMonitor.cpp
+++ b/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleXThreadMonitor.cpp
@@ -1,61 +1,255 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date: 2010-03-31 16:40:27 +0200 (Mi, 31 Mrz 2010) $
Version: $Revision: 21975 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "mitkFiberBundleXThreadMonitor.h"
-#include <mitkGeometry3D.h> // without geometry, fibers are not rendered
+
mitk::FiberBundleXThreadMonitor::FiberBundleXThreadMonitor()
+: m_monitorBracketOpen("[")
+, m_monitorBracketClose("]")
+, m_monitorHeading("Monitoring Fiberprocessing Threads")
+, m_monitorMask("Thread Status:\nStarted: Finished: Terminated:")
+, m_monitorStatus("_initialized")
+, m_monitorStarted(0)
+, m_monitorFinished(0)
+, m_monitorTerminated(0)
{
-
+ m_monitorBracketOpenPosition[0] = 0;
+ m_monitorBracketOpenPosition[1] = 0;
+ m_monitorBracketClosePosition[0] = 0;
+ m_monitorBracketClosePosition[1] = 0;
+ m_monitorHeadingPosition[0] = 0;
+ m_monitorHeadingPosition[1] = 0;
+ m_monitorMaskPosition[0] = 0;
+ m_monitorMaskPosition[1] = 0;
+ m_monitorStatusPosition[0] = 0;
+ m_monitorStatusPosition[1] = 0;
+ m_monitorStartedPosition[0] = 0;
+ m_monitorStartedPosition[1] = 0;
+ m_monitorFinishedPosition[0] = 0;
+ m_monitorFinishedPosition[1] = 0;
+ m_monitorTerminatedPosition[0] = 0;
+ m_monitorTerminatedPosition[1] = 0;
+
+ m_monitorHeadingOpacity = 0;
+ m_monitorMaskOpacity = 0;
+ m_monitorTerminatedOpacity = 0;
+ m_monitorFinishedOpacity = 0;
+ m_monitorStartedOpacity = 0;
+ m_monitorStatusOpacity = 0;
}
mitk::FiberBundleXThreadMonitor::~FiberBundleXThreadMonitor()
{
+
+}
+
+
+QString mitk::FiberBundleXThreadMonitor::getBracketOpen(){
+ return m_monitorBracketOpen;
+}
+mitk::Point2D mitk::FiberBundleXThreadMonitor::getBracketOpenPosition(){
+ return m_monitorBracketOpenPosition;
+}
+void mitk::FiberBundleXThreadMonitor::setBracketOpenPosition(mitk::Point2D pnt){
+ m_monitorBracketOpenPosition[0] = pnt[0];
+ m_monitorBracketOpenPosition[1] = pnt[1];
+}
+
+
+
+
+QString mitk::FiberBundleXThreadMonitor::getBracketClose(){
+ return m_monitorBracketClose;
+}
+mitk::Point2D mitk::FiberBundleXThreadMonitor::getBracketClosePosition(){
+ return m_monitorBracketClosePosition;
+}
+void mitk::FiberBundleXThreadMonitor::setBracketClosePosition(mitk::Point2D pnt){
+ m_monitorBracketClosePosition[0] = pnt[0];
+ m_monitorBracketClosePosition[1] = pnt[1];
+}
+
+
+
+QString mitk::FiberBundleXThreadMonitor::getHeading(){
+ return m_monitorHeading;
+}
+mitk::Point2D mitk::FiberBundleXThreadMonitor::getHeadingPosition(){
+ return m_monitorHeadingPosition;
+}
+void mitk::FiberBundleXThreadMonitor::setHeadingPosition(mitk::Point2D pnt){
+ m_monitorHeadingPosition[0] = pnt[0];
+ m_monitorHeadingPosition[1] = pnt[1];
+}
+int mitk::FiberBundleXThreadMonitor::getHeadingOpacity(){
+ return m_monitorHeadingOpacity;
+}
+void mitk::FiberBundleXThreadMonitor::setHeadingOpacity(int opacity){
+ m_monitorHeadingOpacity = opacity;
+}
+
+
+
+
+QString mitk::FiberBundleXThreadMonitor::getMask(){
+ return m_monitorMask;
+}
+mitk::Point2D mitk::FiberBundleXThreadMonitor::getMaskPosition(){
+ return m_monitorMaskPosition;
+}
+void mitk::FiberBundleXThreadMonitor::setMaskPosition(mitk::Point2D pnt){
+ m_monitorMaskPosition[0] = pnt[0];
+ m_monitorMaskPosition[1] = pnt[1];
+}
+int mitk::FiberBundleXThreadMonitor::getMaskOpacity(){
+ return m_monitorMaskOpacity;
+}
+void mitk::FiberBundleXThreadMonitor::setMaskOpacity(int opacity){
+ m_monitorMaskOpacity = opacity;
+}
+
+
+
+
+
+QString mitk::FiberBundleXThreadMonitor::getStatus(){
+ return m_monitorStatus;
+}
+void mitk::FiberBundleXThreadMonitor::setStatus(QString status){
+ m_statusMutex.lock();
+ m_monitorStatus = status;
+ m_statusMutex.unlock();
+}
+mitk::Point2D mitk::FiberBundleXThreadMonitor::getStatusPosition(){
+ return m_monitorStatusPosition;
+}
+void mitk::FiberBundleXThreadMonitor::setStatusPosition(mitk::Point2D pnt){
+ m_monitorStatusPosition[0] = pnt[0];
+ m_monitorStatusPosition[1] = pnt[1];
+}
+int mitk::FiberBundleXThreadMonitor::getStatusOpacity(){
+ return m_monitorStatusOpacity;
+}
+void mitk::FiberBundleXThreadMonitor::setStatusOpacity(int opacity){
+ m_monitorStatusOpacity = opacity;
+}
+
+
+int mitk::FiberBundleXThreadMonitor::getStarted(){
+ return m_monitorStarted;
+}
+/* is thread safe :) */
+void mitk::FiberBundleXThreadMonitor::setStarted(int val)
+{
+ m_startedMutex.lock();
+ m_monitorStarted = val;
+ m_startedMutex.unlock();
+}
+mitk::Point2D mitk::FiberBundleXThreadMonitor::getStartedPosition(){
+ return m_monitorStartedPosition;
+}
+void mitk::FiberBundleXThreadMonitor::setStartedPosition(mitk::Point2D pnt){
+ m_monitorStartedPosition[0] = pnt[0];
+ m_monitorStartedPosition[1] = pnt[1];
+}
+int mitk::FiberBundleXThreadMonitor::getStartedOpacity(){
+ return m_monitorStartedOpacity;
+}
+void mitk::FiberBundleXThreadMonitor::setStartedOpacity(int opacity){
+ m_monitorStartedOpacity = opacity;
+}
+
+
+
+int mitk::FiberBundleXThreadMonitor::getFinished(){
+ return m_monitorFinished;
+}
+void mitk::FiberBundleXThreadMonitor::setFinished(int val)
+{
+ m_finishedMutex.lock();
+ m_monitorFinished = val;
+ m_finishedMutex.unlock();
+}
+mitk::Point2D mitk::FiberBundleXThreadMonitor::getFinishedPosition(){
+ return m_monitorFinishedPosition;
+}
+void mitk::FiberBundleXThreadMonitor::setFinishedPosition(mitk::Point2D pnt){
+ m_monitorFinishedPosition[0] = pnt[0];
+ m_monitorFinishedPosition[1] = pnt[1];
+}
+int mitk::FiberBundleXThreadMonitor::getFinishedOpacity(){
+ return m_monitorFinishedOpacity;
+}
+void mitk::FiberBundleXThreadMonitor::setFinishedOpacity(int opacity){
+ m_monitorFinishedOpacity = opacity;
}
-//setter textproperty opacity etc....
-//setter color
-//setter text
+
+
+int mitk::FiberBundleXThreadMonitor::getTerminated(){
+ return m_monitorTerminated;
+}
+void mitk::FiberBundleXThreadMonitor::setTerminated(int val)
+{
+ m_terminatedMutex.lock();
+ m_monitorTerminated = val;
+ m_terminatedMutex.unlock();
+}
+mitk::Point2D mitk::FiberBundleXThreadMonitor::getTerminatedPosition(){
+ return m_monitorTerminatedPosition;
+}
+void mitk::FiberBundleXThreadMonitor::setTerminatedPosition(mitk::Point2D pnt){
+ m_monitorTerminatedPosition[0] = pnt[0];
+ m_monitorTerminatedPosition[1] = pnt[1];
+}
+int mitk::FiberBundleXThreadMonitor::getTerminatedOpacity(){
+ return m_monitorTerminatedOpacity;
+}
+void mitk::FiberBundleXThreadMonitor::setTerminatedOpacity(int opacity){
+ m_monitorTerminatedOpacity = opacity;
+}
/* ESSENTIAL IMPLEMENTATION OF SUPERCLASS METHODS */
void mitk::FiberBundleXThreadMonitor::UpdateOutputInformation()
{
}
void mitk::FiberBundleXThreadMonitor::SetRequestedRegionToLargestPossibleRegion()
{
}
bool mitk::FiberBundleXThreadMonitor::RequestedRegionIsOutsideOfTheBufferedRegion()
{
return false;
}
bool mitk::FiberBundleXThreadMonitor::VerifyRequestedRegion()
{
return true;
}
void mitk::FiberBundleXThreadMonitor::SetRequestedRegion( itk::DataObject *data )
{
-
-}
\ No newline at end of file
+
+}
+
diff --git a/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleXThreadMonitor.h b/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleXThreadMonitor.h
index 22a4a54b82..1540cff458 100644
--- a/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleXThreadMonitor.h
+++ b/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleXThreadMonitor.h
@@ -1,64 +1,155 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Module: $RCSfile$
Language: C++
Date: $Date$
Version: $Revision: 11989 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef _MITK_FiberBundleXThreadMonitor_H
#define _MITK_FiberBundleXThreadMonitor_H
//includes for MITK datastructure
#include "mitkBaseData.h"
#include "MitkDiffusionImagingExports.h"
+#include <QString>
+#include <QMutex>
namespace mitk {
/**
* \brief Base Class for Fiber Bundles; */
class MitkDiffusionImaging_EXPORT FiberBundleXThreadMonitor : public BaseData
{
+
public:
-
// ======virtual methods must have======
virtual void UpdateOutputInformation();
virtual void SetRequestedRegionToLargestPossibleRegion();
virtual bool RequestedRegionIsOutsideOfTheBufferedRegion();
virtual bool VerifyRequestedRegion();
virtual void SetRequestedRegion( itk::DataObject *data );
//=======================================
mitkClassMacro( FiberBundleXThreadMonitor, BaseData );
itkNewMacro( Self );
-
+ void setTextL1(QString);
+ QString getTextL1();
+
+ QString getBracketOpen();
+ mitk::Point2D getBracketOpenPosition();
+ void setBracketOpenPosition(mitk::Point2D);
+ int getBracketOpenOpacity(); // range 0 - 10, multiplicationfactor 0.1 (in mapper)
+
+ QString getBracketClose();
+ mitk::Point2D getBracketClosePosition();
+ void setBracketClosePosition(mitk::Point2D);
+ int getBracketCloseOpacity(); // range 0 - 10, multiplicationfactor 0.1 (in mapper)
+
+ QString getHeading();
+ mitk::Point2D getHeadingPosition();
+ void setHeadingPosition(mitk::Point2D);
+ int getHeadingOpacity(); // range 0 - 10, multiplicationfactor 0.1 (in mapper)
+ void setHeadingOpacity(int);
+
+ QString getMask();
+ mitk::Point2D getMaskPosition();
+ void setMaskPosition(mitk::Point2D);
+ int getMaskOpacity(); // multiplicationfactor 0.1 (in mapper)
+ void setMaskOpacity(int);
+
+ QString getStatus();
+ void setStatus(QString);
+ mitk::Point2D getStatusPosition();
+ void setStatusPosition(mitk::Point2D);
+ int getStatusOpacity(); // multiplicationfactor 0.1 (in mapper)
+ void setStatusOpacity(int);
+
+ int getStarted();
+ void setStarted(int);
+ mitk::Point2D getStartedPosition();
+ void setStartedPosition(mitk::Point2D);
+ int getStartedOpacity(); // multiplicationfactor 0.1 (in mapper)
+ void setStartedOpacity(int);
+
+ int getFinished();
+ void setFinished(int);
+ mitk::Point2D getFinishedPosition();
+ void setFinishedPosition(mitk::Point2D);
+ int getFinishedOpacity(); // multiplicationfactor 0.1 (in mapper)
+ void setFinishedOpacity(int);
+
+ int getTerminated();
+ void setTerminated(int);
+ mitk::Point2D getTerminatedPosition();
+ void setTerminatedPosition(mitk::Point2D);
+ int getTerminatedOpacity(); // multiplicationfactor 0.1 (in mapper)
+ void setTerminatedOpacity(int);
+
+
protected:
FiberBundleXThreadMonitor();
virtual ~FiberBundleXThreadMonitor();
+
private:
+ QString m_monitorBracketOpen;
+ mitk::Point2D m_monitorBracketOpenPosition;
+
+ QString m_monitorBracketClose;
+ mitk::Point2D m_monitorBracketClosePosition;
+
+ QString m_monitorHeading;
+ mitk::Point2D m_monitorHeadingPosition;
+ int m_monitorHeadingOpacity;
+
+ QString m_monitorMask;
+ mitk::Point2D m_monitorMaskPosition;
+ int m_monitorMaskOpacity;
+
+ QString m_monitorStatus;
+ mitk::Point2D m_monitorStatusPosition;
+ int m_monitorStatusOpacity;
+
+ int m_monitorStarted;
+ mitk::Point2D m_monitorStartedPosition;
+ int m_monitorStartedOpacity;
+
+ int m_monitorFinished;
+ mitk::Point2D m_monitorFinishedPosition;
+ int m_monitorFinishedOpacity;
+
+ int m_monitorTerminated;
+ mitk::Point2D m_monitorTerminatedPosition;
+ int m_monitorTerminatedOpacity;
+
+ QMutex m_startedMutex;
+ QMutex m_finishedMutex;
+ QMutex m_terminatedMutex;
+ QMutex m_statusMutex;
+
};
} // namespace mitk
#endif /* _MITK_FiberBundleX_H */
diff --git a/Modules/DiffusionImaging/IODataStructures/PlanarFigureComposite/mitkPlanarFigureComposite.cpp b/Modules/DiffusionImaging/IODataStructures/PlanarFigureComposite/mitkPlanarFigureComposite.cpp
index a59aaefbf0..71ac766641 100644
--- a/Modules/DiffusionImaging/IODataStructures/PlanarFigureComposite/mitkPlanarFigureComposite.cpp
+++ b/Modules/DiffusionImaging/IODataStructures/PlanarFigureComposite/mitkPlanarFigureComposite.cpp
@@ -1,132 +1,131 @@
/*
* mitkPlanarFigureComposite.cpp
* mitk-all
*
* Created by HAL9000 on 2/4/11.
* Copyright 2011 __MyCompanyName__. All rights reserved.
*
*/
#include "mitkPlanarFigureComposite.h"
mitk::PlanarFigureComposite::PlanarFigureComposite()
{
m_PFVector = CompositionContainer::New();
m_DNVector = DataNodeContainer::New();
-
}
mitk::PlanarFigureComposite::~PlanarFigureComposite()
{
}
void mitk::PlanarFigureComposite::addDataNode(mitk::DataNode::Pointer dnode)
{
m_DNVector->InsertElement(m_DNVector->Size(), dnode);
}
void mitk::PlanarFigureComposite::addPlanarFigure(PlanarFigure::Pointer pf)
{
MITK_INFO << "addPlanarFigure: size before: " << this->getNumberOfChildren();
m_PFVector->InsertElement(m_PFVector->Size(), pf);
MITK_INFO << "addPlanarFigure: size after: " << this->getNumberOfChildren();
}
void mitk::PlanarFigureComposite::replaceDataNodeAt(int idx, mitk::DataNode::Pointer dn)
{
MITK_INFO << "replace: size before: " << this->getNumberOfChildren();
m_DNVector->SetElement( idx, dn );
MITK_INFO << "replace: size after: " << this->getNumberOfChildren();
}
void mitk::PlanarFigureComposite::setOperationType(PFCompositionOperation pfcOp)
{
this->m_compOperation = pfcOp;
MITK_INFO << "Composition set to: " << this->getOperationType();
}
mitk::PFCompositionOperation mitk::PlanarFigureComposite::getOperationType()
{
return this->m_compOperation;
}
void mitk::PlanarFigureComposite::setDisplayName(std::string displName)
{
m_name = displName;
}
std::string mitk::PlanarFigureComposite::getDisplayName()
{
return m_name;
}
int mitk::PlanarFigureComposite::getNumberOfChildren()
{
return m_PFVector->Size();
}
mitk::PlanarFigure::Pointer mitk::PlanarFigureComposite::getChildAt(int idx)
{
return m_PFVector->ElementAt(idx);
}
mitk::DataNode::Pointer mitk::PlanarFigureComposite::getDataNodeAt(int idx)
{
return m_DNVector->ElementAt(idx);
}
//musthave implementations from superclass.... not sure if return true makes sense
bool mitk::PlanarFigureComposite::SetControlPoint( unsigned int index, const Point2D &point, bool createIfDoesNotExist )
{
return true;
}
void mitk::PlanarFigureComposite::GeneratePolyLine()
{
}
void mitk::PlanarFigureComposite::GenerateHelperPolyLine(double /*mmPerDisplayUnit*/, unsigned int /*displayHeight*/)
{
// A circle does not require a helper object
}
void mitk::PlanarFigureComposite::EvaluateFeaturesInternal()
{
}
void mitk::PlanarFigureComposite::PrintSelf( std::ostream& os, itk::Indent indent) const
{
}
diff --git a/Modules/DiffusionImaging/IODataStructures/QBallImages/mitkNrrdQBallImageReader.cpp b/Modules/DiffusionImaging/IODataStructures/QBallImages/mitkNrrdQBallImageReader.cpp
index 58c177ed84..339ca20aeb 100644
--- a/Modules/DiffusionImaging/IODataStructures/QBallImages/mitkNrrdQBallImageReader.cpp
+++ b/Modules/DiffusionImaging/IODataStructures/QBallImages/mitkNrrdQBallImageReader.cpp
@@ -1,158 +1,181 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date: 2009-07-14 19:11:20 +0200 (Tue, 14 Jul 2009) $
Version: $Revision: 18127 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "mitkNrrdQBallImageReader.h"
#include "itkImageFileReader.h"
#include "itkImageRegionIterator.h"
#include "itkMetaDataObject.h"
#include "itkNrrdImageIO.h"
#include "mitkITKImageImport.h"
#include "mitkImageDataItem.h"
namespace mitk
{
void NrrdQBallImageReader
::GenerateData()
- {
- if ( m_FileName == "")
+ {
+ if ( m_FileName == "")
{
throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, the filename of the vessel tree to be read is empty!");
}
else
{
try
{
+ const std::string& locale = "C";
+ const std::string& currLocale = setlocale( LC_ALL, NULL );
+
+ if ( locale.compare(currLocale)!=0 )
+ {
+ try
+ {
+ setlocale(LC_ALL, locale.c_str());
+ }
+ catch(...)
+ {
+ MITK_INFO << "Could not set locale " << locale;
+ }
+ }
+
typedef itk::VectorImage<float,3> ImageType;
itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New();
typedef itk::ImageFileReader<ImageType> FileReaderType;
FileReaderType::Pointer reader = FileReaderType::New();
reader->SetImageIO(io);
reader->SetFileName(this->m_FileName);
reader->Update();
ImageType::Pointer img = reader->GetOutput();
typedef itk::Image<itk::Vector<float,QBALL_ODFSIZE>,3> VecImgType;
VecImgType::Pointer vecImg = VecImgType::New();
vecImg->SetSpacing( img->GetSpacing() ); // Set the image spacing
vecImg->SetOrigin( img->GetOrigin() ); // Set the image origin
vecImg->SetDirection( img->GetDirection() ); // Set the image direction
vecImg->SetLargestPossibleRegion( img->GetLargestPossibleRegion());
vecImg->SetBufferedRegion( img->GetLargestPossibleRegion() );
vecImg->Allocate();
itk::ImageRegionIterator<VecImgType> ot (vecImg, vecImg->GetLargestPossibleRegion() );
ot = ot.Begin();
itk::ImageRegionIterator<ImageType> it (img, img->GetLargestPossibleRegion() );
typedef ImageType::PixelType VarPixType;
typedef VecImgType::PixelType FixPixType;
for (it = it.Begin(); !it.IsAtEnd(); ++it)
{
VarPixType vec = it.Get();
FixPixType fixVec(vec.GetDataPointer());
ot.Set(fixVec);
++ot;
}
this->GetOutput()->InitializeByItk(vecImg.GetPointer());
this->GetOutput()->SetVolume(vecImg->GetBufferPointer());
+ try
+ {
+ setlocale(LC_ALL, currLocale.c_str());
+ }
+ catch(...)
+ {
+ MITK_INFO << "Could not reset locale " << currLocale;
+ }
}
catch(std::exception& e)
{
- throw itk::ImageFileReaderException(__FILE__, __LINE__, e.what());
+ throw itk::ImageFileReaderException(__FILE__, __LINE__, e.what());
}
catch(...)
{
throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, an error occurred while reading the requested vessel tree file!");
}
}
}
void NrrdQBallImageReader::GenerateOutputInformation()
{
}
-
+
const char* NrrdQBallImageReader
::GetFileName() const
{
return m_FileName.c_str();
}
-
+
void NrrdQBallImageReader
::SetFileName(const char* aFileName)
{
m_FileName = aFileName;
}
-
+
const char* NrrdQBallImageReader
::GetFilePrefix() const
{
return m_FilePrefix.c_str();
}
-
+
void NrrdQBallImageReader
::SetFilePrefix(const char* aFilePrefix)
{
m_FilePrefix = aFilePrefix;
}
-
+
const char* NrrdQBallImageReader
::GetFilePattern() const
{
return m_FilePattern.c_str();
}
-
+
void NrrdQBallImageReader
::SetFilePattern(const char* aFilePattern)
{
m_FilePattern = aFilePattern;
}
-
+
bool NrrdQBallImageReader
- ::CanReadFile(const std::string filename, const std::string /*filePrefix*/, const std::string /*filePattern*/)
+ ::CanReadFile(const std::string filename, const std::string /*filePrefix*/, const std::string /*filePattern*/)
{
// First check the extension
if( filename == "" )
{
return false;
}
std::string ext = itksys::SystemTools::GetFilenameLastExtension(filename);
ext = itksys::SystemTools::LowerCase(ext);
if (ext == ".hqbi" || ext == ".qbi")
{
return true;
}
return false;
}
} //namespace MITK
diff --git a/Modules/DiffusionImaging/IODataStructures/TensorImages/mitkNrrdTensorImageReader.cpp b/Modules/DiffusionImaging/IODataStructures/TensorImages/mitkNrrdTensorImageReader.cpp
index 4aed036ab7..b5f57ff7cb 100644
--- a/Modules/DiffusionImaging/IODataStructures/TensorImages/mitkNrrdTensorImageReader.cpp
+++ b/Modules/DiffusionImaging/IODataStructures/TensorImages/mitkNrrdTensorImageReader.cpp
@@ -1,188 +1,280 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date: 2009-07-14 19:11:20 +0200 (Tue, 14 Jul 2009) $
Version: $Revision: 18127 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "mitkNrrdTensorImageReader.h"
#include "itkImageFileReader.h"
#include "itkImageRegionIterator.h"
#include "itkMetaDataObject.h"
#include "itkNrrdImageIO.h"
#include "itkDiffusionTensor3D.h"
#include "mitkITKImageImport.h"
#include "mitkImageDataItem.h"
namespace mitk
{
void NrrdTensorImageReader
::GenerateData()
{
if ( m_FileName == "")
{
throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, the filename is empty!");
}
else
{
try
{
+ const std::string& locale = "C";
+ const std::string& currLocale = setlocale( LC_ALL, NULL );
+
+ if ( locale.compare(currLocale)!=0 )
+ {
+ try
+ {
+ MITK_INFO << " ** Changing locale from " << setlocale(LC_ALL, NULL) << " to '" << locale << "'";
+ setlocale(LC_ALL, locale.c_str());
+ }
+ catch(...)
+ {
+ MITK_INFO << "Could not set locale " << locale;
+ }
+ }
+
typedef itk::VectorImage<float,3> ImageType;
itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New();
typedef itk::ImageFileReader<ImageType> FileReaderType;
FileReaderType::Pointer reader = FileReaderType::New();
reader->SetImageIO(io);
reader->SetFileName(this->m_FileName);
reader->Update();
ImageType::Pointer img = reader->GetOutput();
typedef itk::Image<itk::DiffusionTensor3D<float>,3> VecImgType;
VecImgType::Pointer vecImg = VecImgType::New();
vecImg->SetSpacing( img->GetSpacing() ); // Set the image spacing
vecImg->SetOrigin( img->GetOrigin() ); // Set the image origin
vecImg->SetDirection( img->GetDirection() ); // Set the image direction
vecImg->SetRegions( img->GetLargestPossibleRegion());
vecImg->Allocate();
itk::ImageRegionIterator<VecImgType> ot (vecImg, vecImg->GetLargestPossibleRegion() );
ot = ot.Begin();
itk::ImageRegionIterator<ImageType> it (img, img->GetLargestPossibleRegion() );
it = it.Begin();
typedef ImageType::PixelType VarPixType;
typedef VecImgType::PixelType FixPixType;
int numComponents = img->GetNumberOfComponentsPerPixel();
+ itk::MetaDataDictionary imgMetaDictionary = img->GetMetaDataDictionary();
+ std::vector<std::string> imgMetaKeys = imgMetaDictionary.GetKeys();
+ std::vector<std::string>::const_iterator itKey = imgMetaKeys.begin();
+ std::string metaString;
+
+ bool readFrame = false;
+ double xx, xy, xz, yx, yy, yz, zx, zy, zz;
+ MeasurementFrameType measFrame;
+ measFrame.SetIdentity();
+ MeasurementFrameType measFrameTransp;
+ measFrameTransp.SetIdentity();
+
+ for (; itKey != imgMetaKeys.end(); itKey ++)
+ {
+ itk::ExposeMetaData<std::string> (imgMetaDictionary, *itKey, metaString);
+ if (itKey->find("measurement frame") != std::string::npos)
+ {
+ MITK_INFO << *itKey << " ---> " << metaString.c_str();
+ sscanf(metaString.c_str(), " ( %lf , %lf , %lf ) ( %lf , %lf , %lf ) ( %lf , %lf , %lf ) \n", &xx, &xy, &xz, &yx, &yy, &yz, &zx, &zy, &zz);
+
+ if (xx>10e-10 || xy>10e-10 || xz>10e-10 ||
+ yx>10e-10 || yy>10e-10 || yz>10e-10 ||
+ zx>10e-10 || zy>10e-10 || zz>10e-10 )
+ {
+ readFrame = true;
+
+ measFrame(0,0) = xx;
+ measFrame(0,1) = xy;
+ measFrame(0,2) = xz;
+ measFrame(1,0) = yx;
+ measFrame(1,1) = yy;
+ measFrame(1,2) = yz;
+ measFrame(2,0) = zx;
+ measFrame(2,1) = zy;
+ measFrame(2,2) = zz;
+
+ measFrameTransp = measFrame.GetTranspose();
+
+ MITK_INFO << "Will apply following measurement frame: \n" << measFrame;
+ }
+ }
+ }
+
if (numComponents==6)
{
while (!it.IsAtEnd())
{
+ // T'=RTR'
VarPixType vec = it.Get();
FixPixType fixVec(vec.GetDataPointer());
+
+ if(readFrame)
+ {
+ itk::DiffusionTensor3D<float> tensor;
+ tensor.SetElement(0, vec.GetElement(0));
+ tensor.SetElement(1, vec.GetElement(1));
+ tensor.SetElement(2, vec.GetElement(2));
+ tensor.SetElement(3, vec.GetElement(3));
+ tensor.SetElement(4, vec.GetElement(4));
+ tensor.SetElement(5, vec.GetElement(5));
+
+ tensor = tensor.PreMultiply(measFrame);
+ tensor = tensor.PostMultiply(measFrameTransp);
+ fixVec = tensor;
+ }
+
ot.Set(fixVec);
++ot;
++it;
}
}
else if(numComponents==9)
{
while (!it.IsAtEnd())
{
VarPixType vec = it.Get();
itk::DiffusionTensor3D<float> tensor;
tensor.SetElement(0, vec.GetElement(0));
tensor.SetElement(1, vec.GetElement(1));
tensor.SetElement(2, vec.GetElement(2));
tensor.SetElement(3, vec.GetElement(4));
tensor.SetElement(4, vec.GetElement(5));
tensor.SetElement(5, vec.GetElement(8));
+ if(readFrame)
+ {
+ tensor = tensor.PreMultiply(measFrame);
+ tensor = tensor.PostMultiply(measFrameTransp);
+ }
+
FixPixType fixVec(tensor);
ot.Set(fixVec);
++ot;
++it;
}
}
else
{
throw itk::ImageFileReaderException(__FILE__, __LINE__, "Image has wrong number of pixel components!");
}
this->GetOutput()->InitializeByItk(vecImg.GetPointer());
this->GetOutput()->SetVolume(vecImg->GetBufferPointer());
+ try
+ {
+ MITK_INFO << " ** Changing locale back from " << setlocale(LC_ALL, NULL) << " to '" << currLocale << "'";
+ setlocale(LC_ALL, currLocale.c_str());
+ }
+ catch(...)
+ {
+ MITK_INFO << "Could not reset locale " << currLocale;
+ }
+
}
catch(std::exception& e)
{
throw itk::ImageFileReaderException(__FILE__, __LINE__, e.what());
}
catch(...)
{
throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, an error occurred while reading the requested DTI file!");
}
}
}
void NrrdTensorImageReader::GenerateOutputInformation()
{
}
const char* NrrdTensorImageReader
::GetFileName() const
{
return m_FileName.c_str();
}
void NrrdTensorImageReader
::SetFileName(const char* aFileName)
{
m_FileName = aFileName;
}
const char* NrrdTensorImageReader
::GetFilePrefix() const
{
return m_FilePrefix.c_str();
}
void NrrdTensorImageReader
::SetFilePrefix(const char* aFilePrefix)
{
m_FilePrefix = aFilePrefix;
}
const char* NrrdTensorImageReader
::GetFilePattern() const
{
return m_FilePattern.c_str();
}
void NrrdTensorImageReader
::SetFilePattern(const char* aFilePattern)
{
m_FilePattern = aFilePattern;
}
bool NrrdTensorImageReader
::CanReadFile(const std::string filename, const std::string /*filePrefix*/, const std::string /*filePattern*/)
{
// First check the extension
if( filename == "" )
{
return false;
}
std::string ext = itksys::SystemTools::GetFilenameLastExtension(filename);
ext = itksys::SystemTools::LowerCase(ext);
if (ext == ".hdti" || ext == ".dti")
{
return true;
}
return false;
}
} //namespace MITK
diff --git a/Modules/DiffusionImaging/IODataStructures/TensorImages/mitkNrrdTensorImageReader.h b/Modules/DiffusionImaging/IODataStructures/TensorImages/mitkNrrdTensorImageReader.h
index e706eff361..16d9e13a18 100644
--- a/Modules/DiffusionImaging/IODataStructures/TensorImages/mitkNrrdTensorImageReader.h
+++ b/Modules/DiffusionImaging/IODataStructures/TensorImages/mitkNrrdTensorImageReader.h
@@ -1,70 +1,71 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date: 2009-07-14 19:11:20 +0200 (Tue, 14 Jul 2009) $
Version: $Revision: 18127 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef __mitkNrrdTensorImageReader_h
#define __mitkNrrdTensorImageReader_h
#include "mitkCommon.h"
#include "itkVectorContainer.h"
#include "mitkFileReader.h"
#include "vnl/vnl_vector_fixed.h"
#include "mitkTensorImage.h"
#include "mitkTensorImageSource.h"
#include "itkVectorImage.h"
namespace mitk
{
/** \brief
*/
class NrrdTensorImageReader : public mitk::TensorImageSource, public FileReader
{
public:
typedef mitk::TensorImage OutputType;
typedef mitk::TensorImageSource DTImgSourceType;
-
+ typedef itk::Matrix< float, 3, 3 > MeasurementFrameType;
+
mitkClassMacro( NrrdTensorImageReader, DTImgSourceType );
itkNewMacro(Self);
const char* GetFileName() const;
void SetFileName(const char* aFileName);
const char* GetFilePrefix() const;
void SetFilePrefix(const char* aFilePrefix);
const char* GetFilePattern() const;
void SetFilePattern(const char* aFilePattern);
static bool CanReadFile(const std::string filename, const std::string filePrefix, const std::string filePattern);
protected:
/** Does the real work. */
virtual void GenerateData();
virtual void GenerateOutputInformation();
std::string m_FileName;
std::string m_FilePrefix;
std::string m_FilePattern;
private:
void operator=(const Self&); //purposely not implemented
};
} //namespace MITK
#endif // __mitkNrrdTensorImageReader_h
diff --git a/Modules/DiffusionImaging/Rendering/mitkFiberBundleXThreadMonitorMapper3D.cpp b/Modules/DiffusionImaging/Rendering/mitkFiberBundleXThreadMonitorMapper3D.cpp
index a44b6aae06..66cea542fa 100644
--- a/Modules/DiffusionImaging/Rendering/mitkFiberBundleXThreadMonitorMapper3D.cpp
+++ b/Modules/DiffusionImaging/Rendering/mitkFiberBundleXThreadMonitorMapper3D.cpp
@@ -1,120 +1,214 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date: 2009-05-12 19:56:03 +0200 (Di, 12 Mai 2009) $
Version: $Revision: 17179 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "mitkFiberBundleXThreadMonitorMapper3D.h"
#include <mitkProperties.h>
#include <vtkPropAssembly.h>
//#include <vtkTextActor.h>
#include <vtkTextProperty.h>
mitk::FiberBundleXThreadMonitorMapper3D::FiberBundleXThreadMonitorMapper3D()
-:m_FiberMonitorMapper(vtkSmartPointer<vtkPolyDataMapper>::New()),
- m_TextActor(vtkSmartPointer<vtkTextActor>::New()),
- m_FiberAssembly(vtkPropAssembly::New())
+: m_FiberMonitorMapper(vtkSmartPointer<vtkPolyDataMapper>::New())
+, m_TextActorClose(vtkSmartPointer<vtkTextActor>::New())
+, m_TextActorOpen(vtkSmartPointer<vtkTextActor>::New())
+, m_TextActorHeading(vtkSmartPointer<vtkTextActor>::New())
+, m_TextActorMask(vtkSmartPointer<vtkTextActor>::New())
+, m_TextActorStatus(vtkSmartPointer<vtkTextActor>::New())
+, m_TextActorStarted(vtkSmartPointer<vtkTextActor>::New())
+, m_TextActorFinished(vtkSmartPointer<vtkTextActor>::New())
+, m_TextActorTerminated(vtkSmartPointer<vtkTextActor>::New())
+, m_FiberAssembly(vtkPropAssembly::New())
+, m_lastModifiedMonitorNodeTime(-1)
{
-m_FiberAssembly->AddPart(m_TextActor);
+ 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<const mitk::FiberBundleXThreadMonitor * > ( 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()
{
+// MITK_INFO << m_LastUpdateTime;
FiberBundleXThreadMonitor* monitor = dynamic_cast<FiberBundleXThreadMonitor * > ( GetData() );
- m_TextActor->SetInput("FIBER MONITOR\n[activated]");
- vtkTextProperty* tprop = m_TextActor->GetTextProperty();
- tprop->SetFontFamilyToArial ();
- tprop->SetLineSpacing(1.0);
- tprop->SetFontSize(20);
- tprop->SetColor(1.0,0.0,0.0);
- m_TextActor->SetDisplayPosition( 20, 20 );
- m_TextActor->Modified();
+// 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();
+
+
}
void mitk::FiberBundleXThreadMonitorMapper3D::GenerateDataForRenderer( mitk::BaseRenderer *renderer )
{
- //MITK_INFO << "FiberBundleXxXXMapper3D()DataForRenderer";
- //ToDo do update checks
- this->GenerateData();
+ if ( !this->IsVisible( renderer ) )
+ {
+ 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/Rendering/mitkFiberBundleXThreadMonitorMapper3D.h b/Modules/DiffusionImaging/Rendering/mitkFiberBundleXThreadMonitorMapper3D.h
index d24fb53dbc..8c4db2f9a1 100644
--- a/Modules/DiffusionImaging/Rendering/mitkFiberBundleXThreadMonitorMapper3D.h
+++ b/Modules/DiffusionImaging/Rendering/mitkFiberBundleXThreadMonitorMapper3D.h
@@ -1,82 +1,91 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date: 2009-05-12 19:56:03 +0200 (Di, 12 Mai 2009) $
Version: $Revision: 17179 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef FiberBundleXThreadMonitorMapper3D_H_HEADER_INCLUDED
#define FiberBundleXThreadMonitorMapper3D_H_HEADER_INCLUDED
//#include <mitkBaseData.h> //?? necessary
#include <MitkDiffusionImagingExports.h>
#include <mitkVtkMapper3D.h>
#include <mitkFiberBundleXThreadMonitor.h>
#include <vtkSmartPointer.h>
#include <vtkPolyDataMapper.h>
#include <vtkTextActor.h>
class vtkPropAssembly;
namespace mitk {
//##Documentation
//## @brief Mapper for FiberBundleX
//## @ingroup Mapper
class MitkDiffusionImaging_EXPORT FiberBundleXThreadMonitorMapper3D : public VtkMapper3D
{
public:
mitkClassMacro(FiberBundleXThreadMonitorMapper3D, VtkMapper3D);
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<vtkPolyDataMapper> m_FiberMonitorMapper;
- vtkSmartPointer<vtkTextActor> m_TextActor;
+ vtkSmartPointer<vtkTextActor> m_TextActorClose;
+ vtkSmartPointer<vtkTextActor> m_TextActorOpen;
+ vtkSmartPointer<vtkTextActor> m_TextActorHeading;
+ vtkSmartPointer<vtkTextActor> m_TextActorMask;
+ vtkSmartPointer<vtkTextActor> m_TextActorStatus;
+ vtkSmartPointer<vtkTextActor> m_TextActorStarted;
+ vtkSmartPointer<vtkTextActor> m_TextActorFinished;
+ vtkSmartPointer<vtkTextActor> m_TextActorTerminated;
vtkPropAssembly* m_FiberAssembly;
+ private:
+ double m_lastModifiedMonitorNodeTime;
};
} // end namespace mitk
#endif /* FiberBundleXMapper3D_H_HEADER_INCLUDED */
diff --git a/Modules/DiffusionImaging/Tractography/itkGibbsTrackingFilter.h b/Modules/DiffusionImaging/Tractography/itkGibbsTrackingFilter.h
index 8760c6fdf9..23405b88fb 100644
--- a/Modules/DiffusionImaging/Tractography/itkGibbsTrackingFilter.h
+++ b/Modules/DiffusionImaging/Tractography/itkGibbsTrackingFilter.h
@@ -1,164 +1,164 @@
#ifndef itkGibbsTrackingFilter_h
#define itkGibbsTrackingFilter_h
#include "itkProcessObject.h"
#include "itkVectorContainer.h"
#include "itkImage.h"
#include "GibbsTracking/pcRJMCMC.cpp"
#include "GibbsTracking/auxilary_classes.cpp"
#include <fstream>
namespace itk{
template< class TInputQBallImage, class TInputROIImage >
class GibbsTrackingFilter :
public ProcessObject{
public:
typedef GibbsTrackingFilter Self;
typedef ProcessObject Superclass;
typedef SmartPointer< Self > Pointer;
typedef SmartPointer< const Self > ConstPointer;
itkNewMacro(Self);
itkTypeMacro( GibbsTrackingFilter, ProcessObject );
/** Types for the DWI Input Image **/
typedef TInputQBallImage InputQBallImageType;
/** Types for the Mask Image **/
typedef TInputROIImage MaskImageType;
typedef typename MaskImageType::Pointer MaskImageTypePointer;
typedef std::vector< itk::Point<float, 3> > FiberTractType;
typedef std::vector< FiberTractType > FiberBundleType;
itkSetMacro( TempStart, float );
itkGetMacro( TempStart, float );
itkSetMacro( TempEnd, float );
itkGetMacro( TempEnd, float );
itkSetMacro( NumIt, int );
itkGetMacro( NumIt, int );
itkSetMacro( ParticleWeight, float );
itkGetMacro( ParticleWeight, float );
/** width of particle sigma (std-dev of gaussian around center) **/
itkSetMacro( ParticleWidth, float );
itkGetMacro( ParticleWidth, float );
/** length of particle from midpoint to ends **/
itkSetMacro( ParticleLength, float );
itkGetMacro( ParticleLength, float );
itkSetMacro( ChempotConnection, float );
itkGetMacro( ChempotConnection, float );
itkSetMacro( ChempotParticle, float );
itkGetMacro( ChempotParticle, float );
itkSetMacro( InexBalance, float );
itkGetMacro( InexBalance, float );
itkSetMacro( Chempot2, float );
itkGetMacro( Chempot2, float );
itkSetMacro( FiberLength, int );
itkGetMacro( FiberLength, int );
itkGetMacro( Steps, int );
itkSetMacro( AbortTracking, bool );
itkGetMacro( AbortTracking, bool );
itkSetMacro( CurrentStep, unsigned long );
itkGetMacro( CurrentStep, unsigned long );
itkSetMacro( SubtractMean, bool);
itkGetMacro( SubtractMean, bool);
/** Set/Get the Odf Input Image **/
itkSetInputMacro(OdfImage, InputQBallImageType, 0);
itkGetInputMacro(OdfImage, InputQBallImageType, 0);
/** Set/Get the Input mask image **/
itkSetMacro(MaskImage, MaskImageTypePointer);
itkGetMacro(MaskImage, MaskImageTypePointer);
itkGetMacro(NumParticles, unsigned long);
itkGetMacro(NumConnections, unsigned long);
itkGetMacro(NumAcceptedFibers, int);
itkGetMacro(ProposalAcceptance, float);
/** Entry Point For the Algorithm: Is invoked when Update() is called
either directly or through itk pipeline propagation
**/
void GenerateData();
/** override the Process Object Update because we don't have a
dataobject as an outpgnome themeut. We can change this later by wrapping the
tractcontainer in a dataobject decorator and letting the Superclass
know about it.
**/
struct StochasticTractGenerationCallbackStruct{
Pointer Filter;
};
virtual void Update(){
this->GenerateData();
}
FiberBundleType* GetFiberBundle();
float GetMemoryUsage();
protected:
GibbsTrackingFilter();
virtual ~GibbsTrackingFilter();
void ComputeFiberCorrelation();
void BuildFibers(float* points, int numPoints);
// Input Images
typename InputQBallImageType::Pointer m_ItkQBallImage;
typename MaskImageType::Pointer m_MaskImage;
// Tracking parameters
float m_TempStart; // Start temperature
float m_TempEnd; // End temperature
unsigned long m_NumIt; // Total number of iterations
unsigned long m_CurrentStep; // current tracking step
float m_ParticleWeight; //w (unitless)
float m_ParticleWidth; //sigma (mm)
float m_ParticleLength; // ell (mm)
float m_ChempotConnection; // gross L (chemisches potential)
float m_ChempotParticle;// unbenutzt (immer null, wenn groesser dann insgesamt weniger teilchen)
float m_InexBalance; // gewichtung zwischen den lambdas
// -5 ... 5 -> nur intern ... nur extern,default 0
float m_Chempot2; // typischerweise 0,
// korrektur fuer das geschaetzte integral
int m_FiberLength;
bool m_AbortTracking;
bool m_SubtractMean;
int m_NumAcceptedFibers;
- bool m_BuildFibers;
+ volatile bool m_BuildFibers;
int m_Steps;
float m_Memory;
float m_ProposalAcceptance;
RJMCMC* m_Sampler;
FiberBundleType m_FiberBundle;
unsigned long m_NumParticles;
unsigned long m_NumConnections;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkGibbsTrackingFilter.cpp"
#endif
#endif
diff --git a/Modules/IGT/IGTTrackingDevices/mitkNDITrackingDevice.cpp b/Modules/IGT/IGTTrackingDevices/mitkNDITrackingDevice.cpp
index 1e6a5dfd85..a7f0cc3ba3 100644
--- a/Modules/IGT/IGTTrackingDevices/mitkNDITrackingDevice.cpp
+++ b/Modules/IGT/IGTTrackingDevices/mitkNDITrackingDevice.cpp
@@ -1,1321 +1,1322 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "mitkNDITrackingDevice.h"
#include "mitkTimeStamp.h"
#include <stdio.h>
#include <itksys/SystemTools.hxx>
#include <itkMutexLockHolder.h>
typedef itk::MutexLockHolder<itk::FastMutexLock> MutexLockHolder;
const unsigned char CR = 0xD; // == '\r' - carriage return
const unsigned char LF = 0xA; // == '\n' - line feed
mitk::NDITrackingDevice::NDITrackingDevice() :
TrackingDevice(),m_DeviceName(""), m_PortNumber(mitk::SerialCommunication::COM5), m_BaudRate(mitk::SerialCommunication::BaudRate9600),
m_DataBits(mitk::SerialCommunication::DataBits8), m_Parity(mitk::SerialCommunication::None), m_StopBits(mitk::SerialCommunication::StopBits1),
m_HardwareHandshake(mitk::SerialCommunication::HardwareHandshakeOff), m_NDITrackingVolume(Standard),
m_IlluminationActivationRate(Hz20), m_DataTransferMode(TX), m_6DTools(), m_ToolsMutex(NULL),
m_SerialCommunication(NULL), m_SerialCommunicationMutex(NULL), m_DeviceProtocol(NULL),
m_MultiThreader(NULL), m_ThreadID(0), m_OperationMode(ToolTracking6D), m_MarkerPointsMutex(NULL), m_MarkerPoints()
{
this->m_Type = TrackingSystemNotSpecified; //NDIPolaris; // = 0; //set the type = 0 (=Polaris, default)
m_6DTools.clear();
m_SerialCommunicationMutex = itk::FastMutexLock::New();
m_DeviceProtocol = NDIProtocol::New();
m_DeviceProtocol->SetTrackingDevice(this);
m_DeviceProtocol->UseCRCOn();
m_MultiThreader = itk::MultiThreader::New();
m_ToolsMutex = itk::FastMutexLock::New();
m_MarkerPointsMutex = itk::FastMutexLock::New();
m_MarkerPoints.reserve(50); // a maximum of 50 marker positions can be reported by the tracking device
}
bool mitk::NDITrackingDevice::UpdateTool(mitk::TrackingTool* tool)
{
if (this->GetState() != Setup)
{
mitk::NDIPassiveTool* ndiTool = dynamic_cast<mitk::NDIPassiveTool*>(tool);
if (ndiTool == NULL)
return false;
std::string portHandle = ndiTool->GetPortHandle();
//return false if the SROM Data has not been set
if (ndiTool->GetSROMData() == NULL)
return false;
NDIErrorCode returnvalue;
returnvalue = m_DeviceProtocol->PVWR(&portHandle, ndiTool->GetSROMData(), ndiTool->GetSROMDataLength());
if (returnvalue != NDIOKAY)
return false;
returnvalue = m_DeviceProtocol->PINIT(&portHandle);
if (returnvalue != NDIOKAY)
return false;
returnvalue = m_DeviceProtocol->PENA(&portHandle, ndiTool->GetTrackingPriority()); // Enable tool
if (returnvalue != NDIOKAY)
return false;
return true;
}
else
{
return false;
}
}
mitk::NDITrackingDevice::~NDITrackingDevice()
{
/* stop tracking and disconnect from tracking device */
if (GetState() == Tracking)
{
this->StopTracking();
}
if (GetState() == Ready)
{
this->CloseConnection();
}
/* cleanup tracking thread */
if ((m_ThreadID != 0) && (m_MultiThreader.IsNotNull()))
{
m_MultiThreader->TerminateThread(m_ThreadID);
}
m_MultiThreader = NULL;
/* free serial communication interface */
if (m_SerialCommunication.IsNotNull())
{
m_SerialCommunication->ClearReceiveBuffer();
m_SerialCommunication->ClearSendBuffer();
m_SerialCommunication->CloseConnection();
m_SerialCommunication = NULL;
}
}
void mitk::NDITrackingDevice::SetPortNumber(const PortNumber _arg)
{
if (this->GetState() != Setup)
return;
itkDebugMacro("setting PortNumber to " << _arg);
if (this->m_PortNumber != _arg)
{
this->m_PortNumber = _arg;
this->Modified();
}
}
void mitk::NDITrackingDevice::SetDeviceName(std::string _arg)
{
if (this->GetState() != Setup)
return;
itkDebugMacro("setting eviceName to " << _arg);
if (this->m_DeviceName != _arg)
{
this->m_DeviceName = _arg;
this->Modified();
}
}
void mitk::NDITrackingDevice::SetBaudRate(const BaudRate _arg)
{
if (this->GetState() != Setup)
return;
itkDebugMacro("setting BaudRate to " << _arg);
if (this->m_BaudRate != _arg)
{
this->m_BaudRate = _arg;
this->Modified();
}
}
void mitk::NDITrackingDevice::SetDataBits(const DataBits _arg)
{
if (this->GetState() != Setup)
return;
itkDebugMacro("setting DataBits to " << _arg);
if (this->m_DataBits != _arg)
{
this->m_DataBits = _arg;
this->Modified();
}
}
void mitk::NDITrackingDevice::SetParity(const Parity _arg)
{
if (this->GetState() != Setup)
return;
itkDebugMacro("setting Parity to " << _arg);
if (this->m_Parity != _arg)
{
this->m_Parity = _arg;
this->Modified();
}
}
void mitk::NDITrackingDevice::SetStopBits(const StopBits _arg)
{
if (this->GetState() != Setup)
return;
itkDebugMacro("setting StopBits to " << _arg);
if (this->m_StopBits != _arg)
{
this->m_StopBits = _arg;
this->Modified();
}
}
void mitk::NDITrackingDevice::SetHardwareHandshake(const HardwareHandshake _arg)
{
if (this->GetState() != Setup)
return;
itkDebugMacro("setting HardwareHandshake to " << _arg);
if (this->m_HardwareHandshake != _arg)
{
this->m_HardwareHandshake = _arg;
this->Modified();
}
}
void mitk::NDITrackingDevice::SetIlluminationActivationRate(const IlluminationActivationRate _arg)
{
if (this->GetState() == Tracking)
return;
itkDebugMacro("setting IlluminationActivationRate to " << _arg);
if (this->m_IlluminationActivationRate != _arg)
{
this->m_IlluminationActivationRate = _arg;
this->Modified();
if (this->GetState() == Ready) // if the connection to the tracking system is established, send the new rate to the tracking device too
m_DeviceProtocol->IRATE(this->m_IlluminationActivationRate);
}
}
void mitk::NDITrackingDevice::SetDataTransferMode(const DataTransferMode _arg)
{
itkDebugMacro("setting DataTransferMode to " << _arg);
if (this->m_DataTransferMode != _arg)
{
this->m_DataTransferMode = _arg;
this->Modified();
}
}
mitk::NDIErrorCode mitk::NDITrackingDevice::Send(const std::string* input, bool addCRC)
{
if (input == NULL)
return SERIALSENDERROR;
std::string message;
if (addCRC == true)
message = *input + CalcCRC(input) + std::string(1, CR);
else
message = *input + std::string(1, CR);
//unsigned int messageLength = message.length() + 1; // +1 for CR
// Clear send buffer
this->ClearSendBuffer();
// Send the date to the device
MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex
long returnvalue = m_SerialCommunication->Send(message);
if (returnvalue == 0)
return SERIALSENDERROR;
else
return NDIOKAY;
}
mitk::NDIErrorCode mitk::NDITrackingDevice::Receive(std::string* answer, unsigned int numberOfBytes)
{
if (answer == NULL)
return SERIALRECEIVEERROR;
MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex
long returnvalue = m_SerialCommunication->Receive(*answer, numberOfBytes); // never read more bytes than the device has send, the function will block until enough bytes are send...
if (returnvalue == 0)
return SERIALRECEIVEERROR;
else
return NDIOKAY;
}
mitk::NDIErrorCode mitk::NDITrackingDevice::ReceiveByte(char* answer)
{
if (answer == NULL)
return SERIALRECEIVEERROR;
std::string m;
MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex
long returnvalue = m_SerialCommunication->Receive(m, 1);
if ((returnvalue == 0) ||(m.size() != 1))
return SERIALRECEIVEERROR;
*answer = m.at(0);
return NDIOKAY;
}
mitk::NDIErrorCode mitk::NDITrackingDevice::ReceiveLine(std::string* answer)
{
if (answer == NULL)
return SERIALRECEIVEERROR;
std::string m;
MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex
do
{
long returnvalue = m_SerialCommunication->Receive(m, 1);
if ((returnvalue == 0) ||(m.size() != 1))
return SERIALRECEIVEERROR;
*answer += m;
} while (m.at(0) != LF);
return NDIOKAY;
}
void mitk::NDITrackingDevice::ClearSendBuffer()
{
MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex
m_SerialCommunication->ClearSendBuffer();
}
void mitk::NDITrackingDevice::ClearReceiveBuffer()
{
MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex
m_SerialCommunication->ClearReceiveBuffer();
}
const std::string mitk::NDITrackingDevice::CalcCRC(const std::string* input)
{
if (input == NULL)
return "";
/* the crc16 calculation code is taken from the NDI API guide example code section */
static int oddparity[16] = {0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0};
unsigned int data; // copy of the input string's current character
unsigned int crcValue = 0; // the crc value is stored here
unsigned int* puCRC16 = &crcValue; // the algorithm uses a pointer to crcValue, so it's easier to provide that than to change the algorithm
for (unsigned int i = 0; i < input->length(); i++)
{
data = (*input)[i];
data = (data ^ (*(puCRC16) & 0xff)) & 0xff;
*puCRC16 >>= 8;
if (oddparity[data & 0x0f] ^ oddparity[data >> 4])
{
*(puCRC16) ^= 0xc001;
}
data <<= 6;
*puCRC16 ^= data;
data <<= 1;
*puCRC16 ^= data;
}
// crcValue contains now the CRC16 value. Convert it to a string and return it
char returnvalue[13];
sprintf(returnvalue,"%04X", crcValue); // 4 hexadecimal digit with uppercase format
return std::string(returnvalue);
}
bool mitk::NDITrackingDevice::OpenConnection()
{
//this->m_ModeMutex->Lock();
if (this->GetState() != Setup)
{
this->SetErrorMessage("Can only try to open the connection if in setup mode");
return false;
}
//
m_SerialCommunication = mitk::SerialCommunication::New();
/* init local com port to standard com settings for a NDI tracking device:
9600 baud, 8 data bits, no parity, 1 stop bit, no hardware handshake
*/
if (m_DeviceName.empty())
m_SerialCommunication->SetPortNumber(m_PortNumber);
else
m_SerialCommunication->SetDeviceName(m_DeviceName);
m_SerialCommunication->SetBaudRate(mitk::SerialCommunication::BaudRate9600);
m_SerialCommunication->SetDataBits(mitk::SerialCommunication::DataBits8);
m_SerialCommunication->SetParity(mitk::SerialCommunication::None);
m_SerialCommunication->SetStopBits(mitk::SerialCommunication::StopBits1);
m_SerialCommunication->SetSendTimeout(5000);
m_SerialCommunication->SetReceiveTimeout(5000);
if (m_SerialCommunication->OpenConnection() == 0) // 0 == ERROR_VALUE
{
this->SetErrorMessage("Can not open serial port");
m_SerialCommunication->CloseConnection();
m_SerialCommunication = NULL;
return false;
}
/* Reset Tracking device by sending a serial break for 500ms */
m_SerialCommunication->SendBreak(400);
/* Read answer from tracking device (RESETBE6F) */
static const std::string reset("RESETBE6F\r");
std::string answer = "";
this->Receive(&answer, reset.length()); // read answer (should be RESETBE6F)
this->ClearReceiveBuffer(); // flush the receive buffer of all remaining data (carriage return, strings other than reset
if (reset.compare(answer) != 0) // check for RESETBE6F
{
this->SetErrorMessage("Hardware Reset of tracking device did not work");
if (m_SerialCommunication.IsNotNull())
{
m_SerialCommunication->CloseConnection();
m_SerialCommunication = NULL;
}
return false;
}
/* Now the tracking device is reset, start initialization */
NDIErrorCode returnvalue;
/* set device com settings to new values and wait for the device to change them */
returnvalue = m_DeviceProtocol->COMM(m_BaudRate, m_DataBits, m_Parity, m_StopBits, m_HardwareHandshake);
if (returnvalue != NDIOKAY)
{
this->SetErrorMessage("Could not set comm settings in trackingdevice");
return false;
}
//after changing COMM wait at least 100ms according to NDI Api documentation page 31
itksys::SystemTools::Delay(500);
/* now change local com settings accordingly */
m_SerialCommunication->CloseConnection();
m_SerialCommunication->SetBaudRate(m_BaudRate);
m_SerialCommunication->SetDataBits(m_DataBits);
m_SerialCommunication->SetParity(m_Parity);
m_SerialCommunication->SetStopBits(m_StopBits);
m_SerialCommunication->SetHardwareHandshake(m_HardwareHandshake);
m_SerialCommunication->SetSendTimeout(5000);
m_SerialCommunication->SetReceiveTimeout(5000);
m_SerialCommunication->OpenConnection();
/* initialize the tracking device */
returnvalue = m_DeviceProtocol->INIT();
if (returnvalue != NDIOKAY)
{
this->SetErrorMessage("Could not initialize the tracking device");
return false;
}
if (this->GetType() == mitk::TrackingSystemNotSpecified) // if the type of tracking device is not specified, try to query the connected device
{
mitk::TrackingDeviceType deviceType;
returnvalue = m_DeviceProtocol->VER(deviceType);
if ((returnvalue != NDIOKAY) || (deviceType == mitk::TrackingSystemNotSpecified))
{
this->SetErrorMessage("Could not determine tracking device type. Please set manually and try again.");
return false;
}
this->SetType(deviceType);
}
/**** Optional Polaris specific code, Work in progress
// start diagnostic mode
returnvalue = m_DeviceProtocol->DSTART();
if (returnvalue != NDIOKAY)
{
this->SetErrorMessage("Could not start diagnostic mode");
return false;
}
else // we are in diagnostic mode
{
// initialize extensive IR checking
returnvalue = m_DeviceProtocol->IRINIT();
if (returnvalue != NDIOKAY)
{
this->SetErrorMessage("Could not initialize intense infrared light checking");
return false;
}
bool intenseIR = false;
returnvalue = m_DeviceProtocol->IRCHK(&intenseIR);
if (returnvalue != NDIOKAY)
{
this->SetErrorMessage("Could not execute intense infrared light checking");
return false;
}
if (intenseIR == true)
// do something - warn the user, raise exception, write to protocol or similar
std::cout << "Warning: Intense infrared light detected. Accurate tracking will probably not be possible.\n";
// stop diagnictic mode
returnvalue = m_DeviceProtocol->DSTOP();
if (returnvalue != NDIOKAY)
{
this->SetErrorMessage("Could not stop diagnostic mode");
return false;
}
}
*** end of optional polaris code ***/
/**
* now add tools to the tracking system
**/
/* First, check if the tracking device has port handles that need to be freed and free them */
returnvalue = FreePortHandles();
// non-critical, therefore no error handling
/**
* POLARIS: initialize the tools that were added manually
**/
{
MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex
std::string portHandle;
Tool6DContainerType::iterator endIt = m_6DTools.end();
for(Tool6DContainerType::iterator it = m_6DTools.begin(); it != endIt; ++it)
{
/* get a port handle for the tool */
returnvalue = m_DeviceProtocol->PHRQ(&portHandle);
if (returnvalue == NDIOKAY)
{
(*it)->SetPortHandle(portHandle.c_str());
/* now write the SROM file of the tool to the tracking system using PVWR */
if (this->m_Type == NDIPolaris)
{
returnvalue = m_DeviceProtocol->PVWR(&portHandle, (*it)->GetSROMData(), (*it)->GetSROMDataLength());
if (returnvalue != NDIOKAY)
{
this->SetErrorMessage((std::string("Could not write SROM file for tool '") + (*it)->GetToolName() + std::string("' to tracking device")).c_str());
return false;
}
returnvalue = m_DeviceProtocol->PINIT(&portHandle);
if (returnvalue != NDIOKAY)
{
this->SetErrorMessage((std::string("Could not initialize tool '") + (*it)->GetToolName()).c_str());
return false;
}
if ((*it)->IsEnabled() == true)
{
returnvalue = m_DeviceProtocol->PENA(&portHandle, (*it)->GetTrackingPriority()); // Enable tool
if (returnvalue != NDIOKAY)
{
this->SetErrorMessage((std::string("Could not enable port '") + portHandle +
std::string("' for tool '")+ (*it)->GetToolName() + std::string("'")).c_str());
return false;
}
}
}
}
}
} // end of toolsmutexlockholder scope
/* check for wired tools and add them too */
if (this->DiscoverWiredTools() == false) // query the tracking device for wired tools and add them to our tool list
return false; // \TODO: could we continue anyways?
/*POLARIS: set the illuminator activation rate */
if (this->m_Type == NDIPolaris)
{
returnvalue = m_DeviceProtocol->IRATE(this->m_IlluminationActivationRate);
if (returnvalue != NDIOKAY)
{
this->SetErrorMessage("Could not set the illuminator activation rate");
return false;
}
}
/* finish - now all tools should be added, initialized and enabled, so that tracking can be started */
this->SetState(Ready);
this->SetErrorMessage("");
return true;
}
bool mitk::NDITrackingDevice::InitializeWiredTools()
{
NDIErrorCode returnvalue;
std::string portHandle;
returnvalue = m_DeviceProtocol->PHSR(OCCUPIED, &portHandle);
if (returnvalue != NDIOKAY)
{
this->SetErrorMessage("Could not obtain a list of port handles that are connected");
return false; // ToDo: Is this a fatal error?
}
/* if there are port handles that need to be initialized, initialize them. Furthermore instantiate tools for each handle that has no tool yet. */
std::string ph;
for (unsigned int i = 0; i < portHandle.size(); i += 2)
{
ph = portHandle.substr(i, 2);
mitk::NDIPassiveTool* pt = this->GetInternalTool(ph);
if ( pt == NULL) // if we don't have a tool, something is wrong. Tools should be discovered first by calling DiscoverWiredTools()
continue;
if (pt->GetSROMData() == NULL)
continue;
returnvalue = m_DeviceProtocol->PVWR(&ph, pt->GetSROMData(), pt->GetSROMDataLength());
if (returnvalue != NDIOKAY)
{
this->SetErrorMessage((std::string("Could not write SROM file for tool '") + pt->GetToolName() + std::string("' to tracking device")).c_str());
return false;
}
returnvalue = m_DeviceProtocol->PINIT(&ph);
if (returnvalue != NDIOKAY)
{
this->SetErrorMessage((std::string("Could not initialize tool '") + pt->GetToolName()).c_str());
return false;
}
if (pt->IsEnabled() == true)
{
returnvalue = m_DeviceProtocol->PENA(&ph, pt->GetTrackingPriority()); // Enable tool
if (returnvalue != NDIOKAY)
{
this->SetErrorMessage((std::string("Could not enable port '") + portHandle +
std::string("' for tool '")+ pt->GetToolName() + std::string("'")).c_str());
return false;
}
}
}
return true;
}
mitk::TrackingDeviceType mitk::NDITrackingDevice::TestConnection()
{
if (this->GetState() != Setup)
{
return mitk::TrackingSystemNotSpecified;
}
m_SerialCommunication = mitk::SerialCommunication::New();
//m_DeviceProtocol = mitk::NDIProtocol::New();
//m_DeviceProtocol->SetTrackingDevice(this);
//m_DeviceProtocol->UseCRCOn();
/* init local com port to standard com settings for a NDI tracking device:
9600 baud, 8 data bits, no parity, 1 stop bit, no hardware handshake
*/
if (m_DeviceName.empty())
m_SerialCommunication->SetPortNumber(m_PortNumber);
else
m_SerialCommunication->SetDeviceName(m_DeviceName);
m_SerialCommunication->SetBaudRate(mitk::SerialCommunication::BaudRate9600);
m_SerialCommunication->SetDataBits(mitk::SerialCommunication::DataBits8);
m_SerialCommunication->SetParity(mitk::SerialCommunication::None);
m_SerialCommunication->SetStopBits(mitk::SerialCommunication::StopBits1);
m_SerialCommunication->SetSendTimeout(5000);
m_SerialCommunication->SetReceiveTimeout(5000);
if (m_SerialCommunication->OpenConnection() == 0) // error
{
m_SerialCommunication = NULL;
return mitk::TrackingSystemNotSpecified;
}
/* Reset Tracking device by sending a serial break for 500ms */
m_SerialCommunication->SendBreak(400);
/* Read answer from tracking device (RESETBE6F) */
static const std::string reset("RESETBE6F\r");
std::string answer = "";
this->Receive(&answer, reset.length()); // read answer (should be RESETBE6F)
this->ClearReceiveBuffer(); // flush the receive buffer of all remaining data (carriage return, strings other than reset
if (reset.compare(answer) != 0) // check for RESETBE6F
{
this->SetErrorMessage("Hardware Reset of tracking device did not work");
m_SerialCommunication->CloseConnection();
m_SerialCommunication = NULL;
return mitk::TrackingSystemNotSpecified;
}
/* Now the tracking device is reset, start initialization */
NDIErrorCode returnvalue;
/* initialize the tracking device */
//returnvalue = m_DeviceProtocol->INIT();
//if (returnvalue != NDIOKAY)
//{
// this->SetErrorMessage("Could not initialize the tracking device");
// return mitk::TrackingSystemNotSpecified;
//}
mitk::TrackingDeviceType deviceType;
returnvalue = m_DeviceProtocol->VER(deviceType);
if ((returnvalue != NDIOKAY) || (deviceType == mitk::TrackingSystemNotSpecified))
{
m_SerialCommunication = NULL;
return mitk::TrackingSystemNotSpecified;
}
m_SerialCommunication = NULL;
return deviceType;
}
bool mitk::NDITrackingDevice::CloseConnection()
{
if (this->GetState() != Setup)
{
//init before closing to force the field generator from aurora to switch itself off
m_DeviceProtocol->INIT();
/* close the serial connection */
m_SerialCommunication->CloseConnection();
/* invalidate all tools */
this->InvalidateAll();
/* return to setup mode */
this->SetState(Setup);
this->SetErrorMessage("");
m_SerialCommunication = NULL;
}
return true;
}
ITK_THREAD_RETURN_TYPE mitk::NDITrackingDevice::ThreadStartTracking(void* pInfoStruct)
{
/* extract this pointer from Thread Info structure */
struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct;
if (pInfo == NULL)
{
return ITK_THREAD_RETURN_VALUE;
}
if (pInfo->UserData == NULL)
{
return ITK_THREAD_RETURN_VALUE;
}
NDITrackingDevice *trackingDevice = (NDITrackingDevice*)pInfo->UserData;
if (trackingDevice != NULL)
{
if (trackingDevice->GetOperationMode() == ToolTracking6D)
trackingDevice->TrackTools(); // call TrackTools() from the original object
else if (trackingDevice->GetOperationMode() == MarkerTracking3D)
trackingDevice->TrackMarkerPositions(); // call TrackMarkerPositions() from the original object
else if (trackingDevice->GetOperationMode() == ToolTracking5D)
trackingDevice->TrackMarkerPositions(); // call TrackMarkerPositions() from the original object
else if (trackingDevice->GetOperationMode() == HybridTracking)
{
trackingDevice->TrackToolsAndMarkers();
}
}
trackingDevice->m_ThreadID = 0; // erase thread id, now that this thread will end.
return ITK_THREAD_RETURN_VALUE;
}
bool mitk::NDITrackingDevice::StartTracking()
{
if (this->GetState() != Ready)
return false;
this->SetState(Tracking); // go to mode Tracking
this->m_StopTrackingMutex->Lock(); // update the local copy of m_StopTracking
this->m_StopTracking = false;
this->m_StopTrackingMutex->Unlock();
m_TrackingFinishedMutex->Unlock(); // transfer the execution rights to tracking thread
m_ThreadID = m_MultiThreader->SpawnThread(this->ThreadStartTracking, this); // start a new thread that executes the TrackTools() method
mitk::TimeStamp::GetInstance()->Start(this);
return true;
}
void mitk::NDITrackingDevice::TrackTools()
{
if (this->GetState() != Tracking)
return;
NDIErrorCode returnvalue;
returnvalue = m_DeviceProtocol->TSTART();
if (returnvalue != NDIOKAY)
return;
/* lock the TrackingFinishedMutex to signal that the execution rights are now transfered to the tracking thread */
MutexLockHolder trackingFinishedLockHolder(*m_TrackingFinishedMutex); // keep lock until end of scope
bool localStopTracking; // Because m_StopTracking is used by two threads, access has to be guarded by a mutex. To minimize thread locking, a local copy is used here
this->m_StopTrackingMutex->Lock(); // update the local copy of m_StopTracking
localStopTracking = this->m_StopTracking;
this->m_StopTrackingMutex->Unlock();
while ((this->GetState() == Tracking) && (localStopTracking == false))
{
if (this->m_DataTransferMode == TX)
{
returnvalue = this->m_DeviceProtocol->TX();
if (!((returnvalue == NDIOKAY) || (returnvalue == NDICRCERROR) || (returnvalue == NDICRCDOESNOTMATCH))) // right now, do not stop on crc errors
break;
}
else
{
returnvalue = this->m_DeviceProtocol->BX();
if (returnvalue != NDIOKAY)
break;
}
/* Update the local copy of m_StopTracking */
this->m_StopTrackingMutex->Lock();
localStopTracking = m_StopTracking;
this->m_StopTrackingMutex->Unlock();
}
/* StopTracking was called, thus the mode should be changed back to Ready now that the tracking loop has ended. */
returnvalue = m_DeviceProtocol->TSTOP();
if (returnvalue != NDIOKAY)
{
/* insert error handling/notification here */
; // how can this thread tell the application, that an error has occurred?
}
return; // returning from this function (and ThreadStartTracking()) this will end the thread and transfer control back to main thread by releasing trackingFinishedLockHolder
}
void mitk::NDITrackingDevice::TrackMarkerPositions()
{
if (m_OperationMode == ToolTracking6D)
return;
if (this->GetState() != Tracking)
return;
NDIErrorCode returnvalue;
returnvalue = m_DeviceProtocol->DSTART(); // Start Diagnostic Mode
if (returnvalue != NDIOKAY)
return;
MutexLockHolder trackingFinishedLockHolder(*m_TrackingFinishedMutex); // keep lock until end of scope
bool localStopTracking; // Because m_StopTracking is used by two threads, access has to be guarded by a mutex. To minimize thread locking, a local copy is used here
this->m_StopTrackingMutex->Lock(); // update the local copy of m_StopTracking
localStopTracking = this->m_StopTracking;
this->m_StopTrackingMutex->Unlock();
while ((this->GetState() == Tracking) && (localStopTracking == false))
{
m_MarkerPointsMutex->Lock(); // lock points data structure
returnvalue = this->m_DeviceProtocol->POS3D(&m_MarkerPoints); // update points data structure with new position data from tracking device
m_MarkerPointsMutex->Unlock();
if (!((returnvalue == NDIOKAY) || (returnvalue == NDICRCERROR) || (returnvalue == NDICRCDOESNOTMATCH))) // right now, do not stop on crc errors
{
std::cout << "Error in POS3D: could not read data. Possibly no markers present." << std::endl;
}
/* Update the local copy of m_StopTracking */
this->m_StopTrackingMutex->Lock();
localStopTracking = m_StopTracking;
this->m_StopTrackingMutex->Unlock();
itksys::SystemTools::Delay(1);
}
/* StopTracking was called, thus the mode should be changed back to Ready now that the tracking loop has ended. */
returnvalue = m_DeviceProtocol->DSTOP();
if (returnvalue != NDIOKAY)
return; // how can this thread tell the application, that an error has occured?
this->SetState(Ready);
return; // returning from this function (and ThreadStartTracking()) this will end the thread
}
void mitk::NDITrackingDevice::TrackToolsAndMarkers()
{
if (m_OperationMode != HybridTracking)
return;
NDIErrorCode returnvalue;
returnvalue = m_DeviceProtocol->TSTART(); // Start Diagnostic Mode
if (returnvalue != NDIOKAY)
return;
MutexLockHolder trackingFinishedLockHolder(*m_TrackingFinishedMutex); // keep lock until end of scope
bool localStopTracking; // Because m_StopTracking is used by two threads, access has to be guarded by a mutex. To minimize thread locking, a local copy is used here
this->m_StopTrackingMutex->Lock(); // update the local copy of m_StopTracking
localStopTracking = this->m_StopTracking;
this->m_StopTrackingMutex->Unlock();
while ((this->GetState() == Tracking) && (localStopTracking == false))
{
m_MarkerPointsMutex->Lock(); // lock points data structure
returnvalue = this->m_DeviceProtocol->TX(true, &m_MarkerPoints); // update points data structure with new position data from tracking device
m_MarkerPointsMutex->Unlock();
if (!((returnvalue == NDIOKAY) || (returnvalue == NDICRCERROR) || (returnvalue == NDICRCDOESNOTMATCH))) // right now, do not stop on crc errors
{
std::cout << "Error in TX: could not read data. Possibly no markers present." << std::endl;
}
/* Update the local copy of m_StopTracking */
this->m_StopTrackingMutex->Lock();
localStopTracking = m_StopTracking;
this->m_StopTrackingMutex->Unlock();
}
/* StopTracking was called, thus the mode should be changed back to Ready now that the tracking loop has ended. */
returnvalue = m_DeviceProtocol->TSTOP();
if (returnvalue != NDIOKAY)
return; // how can this thread tell the application, that an error has occurred?
this->SetState(Ready);
return; // returning from this function (and ThreadStartTracking()) this will end the thread
}
mitk::TrackingTool* mitk::NDITrackingDevice::GetTool(unsigned int toolNumber) const
{
MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex
if (toolNumber < m_6DTools.size())
return m_6DTools.at(toolNumber);
return NULL;
}
mitk::TrackingTool* mitk::NDITrackingDevice::GetToolByName(std::string name) const
{
MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex
Tool6DContainerType::const_iterator end = m_6DTools.end();
for (Tool6DContainerType::const_iterator iterator = m_6DTools.begin(); iterator != end; ++iterator)
if (name.compare((*iterator)->GetToolName()) == 0)
return *iterator;
return NULL;
}
mitk::NDIPassiveTool* mitk::NDITrackingDevice::GetInternalTool(std::string portHandle)
{
MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex
Tool6DContainerType::iterator end = m_6DTools.end();
for (Tool6DContainerType::iterator iterator = m_6DTools.begin(); iterator != end; ++iterator)
if (portHandle.compare((*iterator)->GetPortHandle()) == 0)
return *iterator;
return NULL;
}
unsigned int mitk::NDITrackingDevice::GetToolCount() const
{
MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex
return m_6DTools.size();
}
bool mitk::NDITrackingDevice::Beep(unsigned char count)
{
if (this->GetState() != Setup)
{
return (m_DeviceProtocol->BEEP(count) == NDIOKAY);
}
else
{
return false;
}
}
mitk::TrackingTool* mitk::NDITrackingDevice::AddTool( const char* toolName, const char* fileName, TrackingPriority p /*= NDIPassiveTool::Dynamic*/ )
{
mitk::NDIPassiveTool::Pointer t = mitk::NDIPassiveTool::New();
if (t->LoadSROMFile(fileName) == false)
return NULL;
t->SetToolName(toolName);
t->SetTrackingPriority(p);
if (this->InternalAddTool(t) == false)
return NULL;
return t.GetPointer();
}
bool mitk::NDITrackingDevice::InternalAddTool(mitk::NDIPassiveTool* tool)
{
if (tool == NULL)
return false;
NDIPassiveTool::Pointer p = tool;
/* if the connection to the tracking device is already established, add the new tool to the device now */
if (this->GetState() == Ready)
{
/* get a port handle for the tool */
std::string newPortHandle;
NDIErrorCode returnvalue;
returnvalue = m_DeviceProtocol->PHRQ(&newPortHandle);
if (returnvalue == NDIOKAY)
{
p->SetPortHandle(newPortHandle.c_str());
/* now write the SROM file of the tool to the tracking system using PVWR */
returnvalue = m_DeviceProtocol->PVWR(&newPortHandle, p->GetSROMData(), p->GetSROMDataLength());
if (returnvalue != NDIOKAY)
{
this->SetErrorMessage((std::string("Could not write SROM file for tool '") + p->GetToolName() + std::string("' to tracking device")).c_str());
return false;
}
/* initialize the port handle */
returnvalue = m_DeviceProtocol->PINIT(&newPortHandle);
if (returnvalue != NDIOKAY)
{
this->SetErrorMessage((std::string("Could not initialize port '") + newPortHandle +
std::string("' for tool '")+ p->GetToolName() + std::string("'")).c_str());
return false;
}
/* enable the port handle */
if (p->IsEnabled() == true)
{
returnvalue = m_DeviceProtocol->PENA(&newPortHandle, p->GetTrackingPriority()); // Enable tool
if (returnvalue != NDIOKAY)
{
this->SetErrorMessage((std::string("Could not enable port '") + newPortHandle +
std::string("' for tool '")+ p->GetToolName() + std::string("'")).c_str());
return false;
}
}
}
/* now that the tool is added to the device, add it to list too */
m_ToolsMutex->Lock();
this->m_6DTools.push_back(p);
m_ToolsMutex->Unlock();
this->Modified();
return true;
}
else if (this->GetState() == Setup)
{
/* In Setup mode, we only add it to the list, so that OpenConnection() can add it later */
m_ToolsMutex->Lock();
this->m_6DTools.push_back(p);
m_ToolsMutex->Unlock();
this->Modified();
return true;
}
else // in Tracking mode, no tools can be added
return false;
}
bool mitk::NDITrackingDevice::RemoveTool(mitk::TrackingTool* tool)
{
mitk::NDIPassiveTool* ndiTool = dynamic_cast<mitk::NDIPassiveTool*>(tool);
if (ndiTool == NULL)
return false;
std::string portHandle = ndiTool->GetPortHandle();
/* a valid portHandle has length 2. If a valid handle exists, the tool is already added to the tracking device, so we have to remove it there
if the connection to the tracking device has already been established.
*/
if ((portHandle.length() == 2) && (this->GetState() == Ready)) // do not remove a tool in tracking mode
{
NDIErrorCode returnvalue;
returnvalue = m_DeviceProtocol->PHF(&portHandle);
if (returnvalue != NDIOKAY)
return false;
/* Now that the tool is removed from the tracking device, remove it from our tool list too */
MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex (scope is inside the if-block
Tool6DContainerType::iterator end = m_6DTools.end();
for (Tool6DContainerType::iterator iterator = m_6DTools.begin(); iterator != end; ++iterator)
{
if (iterator->GetPointer() == ndiTool)
{
m_6DTools.erase(iterator);
this->Modified();
return true;
}
}
return false;
}
else if (this->GetState() == Setup) // in Setup Mode, we are not connected to the tracking device, so we can just remove the tool from the tool list
{
MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex
Tool6DContainerType::iterator end = m_6DTools.end();
for (Tool6DContainerType::iterator iterator = m_6DTools.begin(); iterator != end; ++iterator)
{
if ((*iterator).GetPointer() == ndiTool)
{
m_6DTools.erase(iterator);
this->Modified();
return true;
}
}
return false;
}
return false;
}
void mitk::NDITrackingDevice::InvalidateAll()
{
MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex
Tool6DContainerType::iterator end = m_6DTools.end();
for (Tool6DContainerType::iterator iterator = m_6DTools.begin(); iterator != end; ++iterator)
(*iterator)->SetDataValid(false);
}
bool mitk::NDITrackingDevice::SetOperationMode(OperationMode mode)
{
if (GetState() == Tracking)
return false;
m_OperationMode = mode;
return true;
}
mitk::OperationMode mitk::NDITrackingDevice::GetOperationMode()
{
return m_OperationMode;
}
bool mitk::NDITrackingDevice::GetMarkerPositions(MarkerPointContainerType* markerpositions)
{
m_MarkerPointsMutex->Lock();
*markerpositions = m_MarkerPoints; // copy the internal vector to the one provided
m_MarkerPointsMutex->Unlock();
return (markerpositions->size() != 0) ;
}
bool mitk::NDITrackingDevice::DiscoverWiredTools()
{
/* First, check for disconnected tools and remove them */
this->FreePortHandles();
/* check for new tools, add and initialize them */
NDIErrorCode returnvalue;
std::string portHandle;
returnvalue = m_DeviceProtocol->PHSR(OCCUPIED, &portHandle);
if (returnvalue != NDIOKAY)
{
this->SetErrorMessage("Could not obtain a list of port handles that are connected");
return false; // ToDo: Is this a fatal error?
}
/* if there are port handles that need to be initialized, initialize them. Furthermore instantiate tools for each handle that has no tool yet. */
std::string ph;
/* we need to remember the ports which are occupied to be able to readout the serial numbers of the connected tools later */
std::vector<int> occupiedPorts = std::vector<int>();
int numberOfToolsAtStart = this->GetToolCount(); //also remember the number of tools at start to identify the automatically detected tools later
for (unsigned int i = 0; i < portHandle.size(); i += 2)
{
ph = portHandle.substr(i, 2);
if (this->GetInternalTool(ph) != NULL) // if we already have a tool with this handle
continue; // then skip the initialization
//instantiate an object for each tool that is connected
mitk::NDIPassiveTool::Pointer newTool = mitk::NDIPassiveTool::New();
newTool->SetPortHandle(ph.c_str());
newTool->SetTrackingPriority(mitk::NDIPassiveTool::Dynamic);
//set a name for identification
newTool->SetToolName((std::string("Port ") + ph).c_str());
returnvalue = m_DeviceProtocol->PINIT(&ph);
if (returnvalue != NDIINITIALIZATIONFAILED) //if the initialization failed (AURORA) it can not be enabled. A srom file will have to be specified manually first. Still return true to be able to continue
{
if (returnvalue != NDIOKAY)
{
this->SetErrorMessage((std::string("Could not initialize port '") + ph +
std::string("' for tool '")+ newTool->GetToolName() + std::string("'")).c_str());
return false;
}
/* enable the port handle */
returnvalue = m_DeviceProtocol->PENA(&ph, newTool->GetTrackingPriority()); // Enable tool
if (returnvalue != NDIOKAY)
{
this->SetErrorMessage((std::string("Could not enable port '") + ph +
std::string("' for tool '")+ newTool->GetToolName() + std::string("'")).c_str());
return false;
}
}
//we have to temporarily unlock m_ModeMutex here to avoid a deadlock with another lock inside InternalAddTool()
if (this->InternalAddTool(newTool) == false)
this->SetErrorMessage("Error while adding new tool");
else occupiedPorts.push_back(i);
}
// after initialization readout serial numbers of automatically detected tools
for (unsigned int i = 0; i < occupiedPorts.size(); i++)
{
ph = portHandle.substr(occupiedPorts.at(i), 2);
std::string portInfo;
NDIErrorCode returnvaluePort = m_DeviceProtocol->PHINF(ph, &portInfo);
if ((returnvaluePort==NDIOKAY) && (portInfo.size()>31)) dynamic_cast<mitk::NDIPassiveTool*>(this->GetTool(i+numberOfToolsAtStart))->SetSerialNumber(portInfo.substr(23,8));
+ itksys::SystemTools::Delay(10);
}
return true;
}
mitk::NDIErrorCode mitk::NDITrackingDevice::FreePortHandles()
{
/* first search for port handles that need to be freed: e.g. because of a reset of the tracking system */
NDIErrorCode returnvalue = NDIOKAY;
std::string portHandle;
returnvalue = m_DeviceProtocol->PHSR(FREED, &portHandle);
if (returnvalue != NDIOKAY)
{
this->SetErrorMessage("Could not obtain a list of port handles that need to be freed");
return returnvalue; // ToDo: Is this a fatal error?
}
/* if there are port handles that need to be freed, free them */
if (portHandle.empty() == true)
return returnvalue;
std::string ph;
for (unsigned int i = 0; i < portHandle.size(); i += 2)
{
ph = portHandle.substr(i, 2);
mitk::NDIPassiveTool* t = this->GetInternalTool(ph);
if (t != NULL) // if we have a tool for the port handle that needs to be freed
{
if (this->RemoveTool(t) == false) // remove it (this will free the port too)
returnvalue = NDIERROR;
}
else // we don't have a tool, the port handle exists only in the tracking device
{
returnvalue = m_DeviceProtocol->PHF(&ph); // free it there
// What to do if port handle could not be freed? This seems to be a non critical error
if (returnvalue != NDIOKAY)
{
this->SetErrorMessage("Could not free all port handles");
// return false; // could not free all Handles
}
}
}
return returnvalue;
}
int mitk::NDITrackingDevice::GetMajorFirmwareRevisionNumber()
{
std::string revision;
if (m_DeviceProtocol->APIREV(&revision) != mitk::NDIOKAY || revision.empty() || (revision.size() != 9) )
{
this->SetErrorMessage("Could not receive firmware revision number!");
return 0;
}
const std::string majrevno = revision.substr(2,3); //cut out "004" from "D.004.001"
return std::atoi(majrevno.c_str());
}
const char* mitk::NDITrackingDevice::GetFirmwareRevisionNumber()
{
static std::string revision;
if (m_DeviceProtocol->APIREV(&revision) != mitk::NDIOKAY || revision.empty() || (revision.size() != 9) )
{
this->SetErrorMessage("Could not receive firmware revision number!");
revision = "";
return revision.c_str();
}
return revision.c_str();
}
bool mitk::NDITrackingDevice::GetSupportedVolumes(unsigned int* numberOfVolumes, mitk::NDITrackingDevice::NDITrackingVolumeContainerType* volumes, mitk::NDITrackingDevice::TrackingVolumeDimensionType* volumesDimensions)
{
if (numberOfVolumes == NULL || volumes == NULL || volumesDimensions == NULL)
return false;
static std::string info;
if (m_DeviceProtocol->SFLIST(&info) != mitk::NDIOKAY || info.empty())
{
this->SetErrorMessage("Could not receive tracking volume information of tracking system!");
return false;
}
/*info contains the following:
<HEX:number of volumes> (+n times:) <HEX:shape type> <shape parameters D1-D10> <HEX:reserved / number of wavelength supported> <metal resistant / supported wavelength>
*/
(*numberOfVolumes) = (unsigned int) std::atoi(info.substr(0,1).c_str());
for (unsigned int i=0; i<(*numberOfVolumes); i++)
{
//e.g. for cube: "9-025000+025000-025000+025000-055000-005000+000000+000000+000000+00000011"
//for dome: "A+005000+048000+005000+066000+000000+000000+000000+000000+000000+00000011"
std::string::size_type offset, end;
offset = (i*73)+1;
end = 73+(i*73);
std::string currentVolume = info.substr(offset, end);//i=0: from 1 to 73 characters; i=1: from 75 to 148 char;
// if i>0 then we have a return statement <LF> infront
if (i>0)
currentVolume = currentVolume.substr(1, currentVolume.size());
std::string standard = "0";
std::string pyramid = "4";
std::string spectraPyramid = "5";
std::string vicraVolume = "7";
std::string cube = "9";
std::string dome = "A";
if (currentVolume.compare(0,1,standard)==0)
volumes->push_back(mitk::Standard);
if (currentVolume.compare(0,1,pyramid)==0)
volumes->push_back(mitk::Pyramid);
if (currentVolume.compare(0,1,spectraPyramid)==0)
volumes->push_back(mitk::SpectraPyramid);
if (currentVolume.compare(0,1,vicraVolume)==0)
volumes->push_back(mitk::VicraVolume);
else if (currentVolume.compare(0,1,cube)==0)
volumes->push_back(mitk::Cube);//alias cube
else if (currentVolume.compare(0,1,dome)==0)
volumes->push_back(mitk::Dome);
//fill volumesDimensions
for (unsigned int index = 0; index < 10; index++)
{
std::string::size_type offD, endD;
offD = 1+(index*7); //7 digits per dimension and the first is the type of volume
endD = offD+7;
int dimension = std::atoi(currentVolume.substr(offD, endD).c_str());
dimension /= 100; //given in mm. 7 digits are xxxx.xx according to NDI //strange, the last two digits (11) also for the metal flag get read also...
volumesDimensions->push_back(dimension);
}
}
return true;
}
bool mitk::NDITrackingDevice::SetVolume(NDITrackingVolume volume)
{
if (m_DeviceProtocol->VSEL(volume) != mitk::NDIOKAY)
{
this->SetErrorMessage("Could not set volume!");
return false;
}
return true;
}
diff --git a/Modules/IGT/IGTTrackingDevices/mitkTrackingDevice.cpp b/Modules/IGT/IGTTrackingDevices/mitkTrackingDevice.cpp
index bdf0258c94..1fecec507b 100644
--- a/Modules/IGT/IGTTrackingDevices/mitkTrackingDevice.cpp
+++ b/Modules/IGT/IGTTrackingDevices/mitkTrackingDevice.cpp
@@ -1,93 +1,91 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "mitkTrackingDevice.h"
#include "mitkTimeStamp.h"
#include "mitkTrackingTool.h"
#include <itkMutexLockHolder.h>
typedef itk::MutexLockHolder<itk::FastMutexLock> MutexLockHolder;
mitk::TrackingDevice::TrackingDevice() :
m_Type(TrackingSystemNotSpecified),
m_State(mitk::TrackingDevice::Setup),
m_StopTracking(false), m_ErrorMessage("")
{
m_StopTrackingMutex = itk::FastMutexLock::New();
m_StateMutex = itk::FastMutexLock::New();
m_TrackingFinishedMutex = itk::FastMutexLock::New();
m_TrackingFinishedMutex->Lock(); // execution rights are owned by the application thread at the beginning
}
mitk::TrackingDevice::~TrackingDevice()
{
- m_TrackingFinishedMutex = NULL;
- m_StopTrackingMutex = NULL;
}
mitk::TrackingDevice::TrackingDeviceState mitk::TrackingDevice::GetState() const
{
MutexLockHolder lock(*m_StateMutex);
return m_State;
}
void mitk::TrackingDevice::SetState( TrackingDeviceState state )
{
itkDebugMacro("setting m_State to " << state);
MutexLockHolder lock(*m_StateMutex); // lock and unlock the mutex
if (m_State == state)
{
return;
}
m_State = state;
this->Modified();
}
bool mitk::TrackingDevice::StopTracking()
{
if (this->GetState() == Tracking) // Only if the object is in the correct state
{
m_StopTrackingMutex->Lock(); // m_StopTracking is used by two threads, so we have to ensure correct thread handling
m_StopTracking = true;
m_StopTrackingMutex->Unlock();
//we have to wait here that the other thread recognizes the STOP-command and executes it
m_TrackingFinishedMutex->Lock();
mitk::TimeStamp::GetInstance()->Stop(this); // notify realtime clock
// StopTracking was called, thus the mode should be changed back
// to Ready now that the tracking loop has ended.
this->SetState(Ready);
}
return true;
}
mitk::TrackingTool* mitk::TrackingDevice::GetToolByName( std::string name ) const
{
unsigned int toolCount = this->GetToolCount();
for (unsigned int i = 0; i < toolCount; ++i)
if (name == this->GetTool(i)->GetToolName())
return this->GetTool(i);
return NULL;
}
diff --git a/Modules/IGT/Testing/mitkClaronTrackingDeviceTest.cpp b/Modules/IGT/Testing/mitkClaronTrackingDeviceTest.cpp
index 402a086c01..9c2d1e156c 100644
--- a/Modules/IGT/Testing/mitkClaronTrackingDeviceTest.cpp
+++ b/Modules/IGT/Testing/mitkClaronTrackingDeviceTest.cpp
@@ -1,149 +1,149 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date: 2008-02-25 17:27:17 +0100 (Mo, 25 Feb 2008) $
Version: $Revision: 7837 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "mitkClaronTrackingDevice.h"
#include "mitkClaronTool.h"
#include "mitkTestingMacros.h"
#include "mitkStandardFileLocations.h"
class mitkClaronTrackingDeviceTestClass
{
public:
static bool TestIsMicronTrackerInstalled()
{
mitk::ClaronTrackingDevice::Pointer myClaronTrackingDevice = mitk::ClaronTrackingDevice::New();
bool returnValue = myClaronTrackingDevice->IsMicronTrackerInstalled();
if (returnValue) {MITK_TEST_OUTPUT(<< "MicronTracker is installed on this system!")}
else {MITK_TEST_OUTPUT(<< "MicronTracker is not installed on this system!")}
return returnValue;
}
static void TestInstantiation()
{
// let's create an object of our class
mitk::ClaronTrackingDevice::Pointer testInstance;
testInstance = mitk::ClaronTrackingDevice::New();
MITK_TEST_CONDITION_REQUIRED(testInstance.IsNotNull(),"Testing instantiation:")
}
static void TestToolConfiguration()
{
std::string toolFileName = mitk::StandardFileLocations::GetInstance()->FindFile("ClaronTool", "Modules/IGT/Testing/Data/");
MITK_TEST_CONDITION(toolFileName.empty() == false, "Check if tool calibration file exists");
mitk::ClaronTrackingDevice::Pointer testInstance = mitk::ClaronTrackingDevice::New();
MITK_TEST_CONDITION(testInstance->AddTool("Tool1", toolFileName.c_str()) != NULL, "Testing AddTool() for tool 1");
MITK_TEST_CONDITION(testInstance->GetToolCount() == 1, "Testing adding tool 1");
MITK_TEST_CONDITION(testInstance->AddTool("Tool2", toolFileName.c_str()) != NULL, "Testing AddTool() for tool 2");
MITK_TEST_CONDITION(testInstance->GetToolCount() == 2, "Testing adding tool 2");
MITK_TEST_CONDITION(testInstance->AddTool("Tool3", toolFileName.c_str()) != NULL, "Testing AddTool() for tool 3");
MITK_TEST_CONDITION(testInstance->GetToolCount() == 3, "Testing adding tool 3");
//std::vector<mitk::ClaronTool::Pointer> myTools = testInstance->GetAllTools();
MITK_TEST_CONDITION(testInstance->GetTool(0)->GetToolName() == std::string("Tool1"), "Testing GetTool() for tool 1");
MITK_TEST_CONDITION(testInstance->GetTool(1)->GetToolName() == std::string("Tool2"), "Testing GetTool() for tool 2");
MITK_TEST_CONDITION(testInstance->GetTool(2)->GetToolName() == std::string("Tool3"), "Testing GetTool() for tool 3");
//Testing 100 tools (maximum by MicronTracker)
testInstance = NULL;
testInstance = mitk::ClaronTrackingDevice::New();
for (unsigned int i = 0; i < 100; i++)
testInstance->AddTool("Tool", toolFileName.c_str());
MITK_TEST_CONDITION(testInstance->GetToolCount() == 100, "Testing adding 100 tools");
bool failed = false;
unsigned int max = 100;
testInstance = mitk::ClaronTrackingDevice::New();
for (unsigned int i = 0; i < max; i++)
testInstance->AddTool("Tool", toolFileName.c_str());
if ((testInstance->GetToolCount() != max))
failed = true;
MITK_TEST_CONDITION(!failed, "Testing tool configuration (maximum of 100 tools):");
}
static void TestAllMethodsOnSystemsWithoutMicronTracker()
{
//In this case we won't receive valid data but defined invalid return values.
//initialize
mitk::ClaronTrackingDevice::Pointer myClaronTrackingDevice = mitk::ClaronTrackingDevice::New();
//OpenConnection
MITK_TEST_CONDITION( (!myClaronTrackingDevice->OpenConnection()), "Testing behavior of method OpenConnection() (Errors should occur because MicronTracker is not activated).\n");
std::string toolFileName = mitk::StandardFileLocations::GetInstance()->FindFile("ClaronTool", "Testing/Data/");
MITK_TEST_CONDITION(toolFileName.empty() == false, "Check if tool calibration file exists");
//add a few tools
myClaronTrackingDevice->AddTool("Tool1", toolFileName.c_str());
myClaronTrackingDevice->AddTool("Tool2", toolFileName.c_str());
myClaronTrackingDevice->AddTool("Tool3", toolFileName.c_str());
//test IsMicronTrackerInstalled
MITK_TEST_CONDITION(!myClaronTrackingDevice->IsMicronTrackerInstalled(),"Testing method IsMicronTrackerInstalled().\n")
- //test getToolCount
- int toolCount = myClaronTrackingDevice->GetToolCount();
+ //test getToolCount
+ int toolCount = myClaronTrackingDevice->GetToolCount();
MITK_TEST_CONDITION((toolCount==3), "Testing method GetToolCount().\n");
//test getTool
mitk::TrackingTool* myTool = myClaronTrackingDevice->GetTool(2);
- MITK_TEST_CONDITION((std::string(myTool->GetToolName()) == "Tool3"), "Testing method GetTool().\n");
+ MITK_TEST_CONDITION((std::string(myTool->GetToolName()) == "Tool3"), "Testing method GetTool().\n");
//StartTracking
MITK_TEST_CONDITION( (!myClaronTrackingDevice->StartTracking()), "Testing behavior of method StartTracking().\n");
//StopTracking
MITK_TEST_CONDITION( (myClaronTrackingDevice->StopTracking()), "Testing behavior of method StopTracking().\n");
//CloseConnection
MITK_TEST_CONDITION( (myClaronTrackingDevice->CloseConnection()), "Testing behavior of method CloseConnection().\n");
}
};
/**
* This function is testing methods of the class ClaronTrackingDevice which are independent from the hardware. For more tests we would need
* the MicronTracker hardware, so only a few simple tests, which can run without the hardware are tested here. More tests can be found in the
* class ClaronTrackingDeviceHardwareTests which tests the interaction with the hardware.
*/
int mitkClaronTrackingDeviceTest(int /* argc */, char* /*argv*/[])
{
MITK_TEST_BEGIN("ClaronTrackingDevice");
mitkClaronTrackingDeviceTestClass::TestInstantiation();
mitkClaronTrackingDeviceTestClass::TestToolConfiguration();
/* The following tests don't run under linux environments. This is or could be caused by the fact that the MicronTracker interface
* is developed under windows and not tested under linux yet (26.2.2009). So - in my opinion - the best approach is to first test
* the MicronTracker code under linux (and make the necessary changes of course) and in parallel write the linux tests or make this
* tests runnable under linux.
*/
#ifdef WIN32
if (mitkClaronTrackingDeviceTestClass::TestIsMicronTrackerInstalled())
{
MITK_TEST_OUTPUT(<< "... MicronTracker is installed on your System, so we don't run any further tests. (All tests run on systems without MicronTracker)");
}
else
{
MITK_TEST_OUTPUT(<< ".Test");
mitkClaronTrackingDeviceTestClass::TestAllMethodsOnSystemsWithoutMicronTracker();
}
#endif
MITK_TEST_END();
}
\ No newline at end of file
diff --git a/Modules/IGT/Testing/mitkTrackingDeviceSourceTest.cpp b/Modules/IGT/Testing/mitkTrackingDeviceSourceTest.cpp
index a3cbd8b5ee..22dbcb9c6e 100644
--- a/Modules/IGT/Testing/mitkTrackingDeviceSourceTest.cpp
+++ b/Modules/IGT/Testing/mitkTrackingDeviceSourceTest.cpp
@@ -1,121 +1,138 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date: 2009-05-13 14:52:01 +0200 (Mi, 13. Mai 2009) $
Version: $Revision: 17230 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "mitkTrackingDeviceSource.h"
#include "mitkVirtualTrackingDevice.h"
#include "mitkTestingMacros.h"
#include <mitkReferenceCountWatcher.h>
#include "itksys/SystemTools.hxx"
/**Documentation
* test for the class "NavigationDataSource".
*/
int mitkTrackingDeviceSourceTest(int /* argc */, char* /*argv*/[])
{
MITK_TEST_BEGIN("TrackingDeviceSource");
// let's create an object of our class
mitk::TrackingDeviceSource::Pointer mySource = mitk::TrackingDeviceSource::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(mySource.IsNotNull(), "Testing instantiation");
mySource->SetTrackingDevice(NULL);
MITK_TEST_CONDITION(mySource->GetTrackingDevice() == NULL, "Testing Set/GetTrackingDevice(NULL)");
MITK_TEST_CONDITION(mySource->GetNumberOfOutputs() == 0, "Testing GetNumberOfOutputs with NULL td");
MITK_TEST_FOR_EXCEPTION(std::invalid_argument, mySource->Connect());
MITK_TEST_FOR_EXCEPTION(std::invalid_argument, mySource->StartTracking());
mitk::VirtualTrackingDevice::Pointer tracker = mitk::VirtualTrackingDevice::New();
tracker->SetRefreshRate(10);
mySource->SetTrackingDevice(tracker);
MITK_TEST_CONDITION(mySource->GetTrackingDevice() == tracker.GetPointer(), "Testing Set/GetTrackingDevice(tracker)");
MITK_TEST_CONDITION(mySource->GetNumberOfOutputs() == 0, "Testing GetNumberOfOutputs with no tool tracker");
tracker = mitk::VirtualTrackingDevice::New();
mitk::ReferenceCountWatcher::Pointer watch = new mitk::ReferenceCountWatcher(tracker);
tracker->AddTool("T0");
tracker->AddTool("T1");
mySource->SetTrackingDevice(tracker);
MITK_TEST_CONDITION(mySource->GetTrackingDevice() == tracker.GetPointer(), "Testing Set/GetTrackingDevice(tracker2)");
MITK_TEST_CONDITION(mySource->GetNumberOfOutputs() == 2, "Testing GetNumberOfOutputs with 2 tools tracker");
MITK_TEST_CONDITION(mySource->IsConnected() == false, "Testing IsConnected()");
mySource->Connect();
MITK_TEST_CONDITION(mySource->IsConnected() == true, "Testing Connect()/IsConnected()");
MITK_TEST_CONDITION(tracker->GetState() == mitk::TrackingDevice::Ready, "Testing Connect()/IsConnected() 2");
mySource->Disconnect();
MITK_TEST_CONDITION(mySource->IsConnected() == false, "Testing Disconnect()/IsConnected()");
MITK_TEST_CONDITION(tracker->GetState() == mitk::TrackingDevice::Setup, "Testing Disconnect()/IsConnected() 2");
mySource->Connect();
mySource->StartTracking();
MITK_TEST_CONDITION(mySource->IsConnected() == true, "Testing StartTracking()/IsConnected()");
MITK_TEST_CONDITION(mySource->IsTracking() == true, "Testing StartTracking()/IsTracking()");
MITK_TEST_CONDITION(tracker->GetState() == mitk::TrackingDevice::Tracking, "Testing StartTracking()/IsTracking() 2");
unsigned long modTime = mySource->GetMTime();
mySource->UpdateOutputInformation();
MITK_TEST_CONDITION(mySource->GetMTime() != modTime, "Testing if UpdateOutputInformation() modifies the object");
+ //test getOutput()
mitk::NavigationData* nd0 = mySource->GetOutput(0);
+ MITK_TEST_CONDITION(nd0!=NULL,"Testing GetOutput() [1]");
+ nd0 = mySource->GetOutput(nd0->GetName());
+ MITK_TEST_CONDITION(nd0!=NULL,"Testing GetOutput() [2]");
+
+ //test getOutputIndex()
+ MITK_TEST_CONDITION(mySource->GetOutputIndex(nd0->GetName())==0,"Testing GetOutputIndex()");
+ //test GraftNthOutput()
+ mitk::NavigationData::Pointer ndCopy = mitk::NavigationData::New();
+ mySource->GraftNthOutput(1,nd0);
+ ndCopy = mySource->GetOutput(1);
+ MITK_TEST_CONDITION(std::string(ndCopy->GetName())==std::string(nd0->GetName()),"Testing GraftNthOutput()");
+
+ //test GetParameters()
+ mitk::PropertyList::ConstPointer p = mySource->GetParameters();
+ MITK_TEST_CONDITION(p.IsNotNull(),"Testing GetParameters()");
+
nd0->Update();
mitk::NavigationData::PositionType pos = nd0->GetPosition();
unsigned long tmpMTime0 = nd0->GetMTime();
itksys::SystemTools::Delay(500); // allow the tracking thread to advance the tool position
nd0->Update();
mitk::NavigationData::PositionType newPos = nd0->GetPosition();
if(nd0->GetMTime() == tmpMTime0) //tool not modified yet
{
MITK_TEST_CONDITION(mitk::Equal(newPos, pos) == true, "Testing if output changes on each update");
}
else
{
MITK_TEST_CONDITION(mitk::Equal(newPos, pos) == false, "Testing if output changes on each update");
}
mySource->StopTracking();
mySource->Disconnect();
tracker = mitk::VirtualTrackingDevice::New();
mySource->SetTrackingDevice(tracker);
MITK_TEST_CONDITION(watch->GetReferenceCount() == 0, "Testing if reference to previous tracker object is released");
watch = NULL;
MITK_TEST_FOR_EXCEPTION(std::runtime_error, mySource->StartTracking()); // new tracker, needs Connect() before StartTracking()
mySource->Connect();
mySource->StartTracking();
// itksys::SystemTools::Delay(800); // wait for tracking thread to start properly //DEBUG ONLY --> race condition. will the thread start before the object is destroyed? --> maybe hold a smartpointer?
try
{
mySource = NULL; // delete source
tracker = NULL; // delete tracker --> both should not result in any exceptions or deadlocks
}
catch (...)
{
MITK_TEST_FAILED_MSG(<< "exception during destruction of source or tracker!");
}
// always end with this!
MITK_TEST_END();
}
diff --git a/Modules/IGTUI/Qmitk/QmitkNDIConfigurationWidget.cpp b/Modules/IGTUI/Qmitk/QmitkNDIConfigurationWidget.cpp
index 870a077602..eb0f9dd940 100644
--- a/Modules/IGTUI/Qmitk/QmitkNDIConfigurationWidget.cpp
+++ b/Modules/IGTUI/Qmitk/QmitkNDIConfigurationWidget.cpp
@@ -1,653 +1,880 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date: 2009-03-21 19:27:37 +0100 (Sa, 21 Mrz 2009) $
Version: $Revision: 16719 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "QmitkNDIConfigurationWidget.h"
#include <QTableWidget>
#include <QMessageBox>
#include <QFileDialog>
#include <QInputDialog>
#include <QDir>
#include <QFileInfo>
+#include <mitkNavigationToolWriter.h>
+#include <mitkNavigationToolReader.h>
+#include <mitkSTLFileReader.h>
+
#include "QmitkCustomVariants.h"
//#include <QtConcurrentMap>
#include "QmitkNDIToolDelegate.h"
/* VIEW MANAGEMENT */
QmitkNDIConfigurationWidget::QmitkNDIConfigurationWidget(QWidget* parent)
: QWidget(parent), m_Controls(NULL), m_Tracker(NULL), m_Source(NULL),
-m_Delegate(NULL)
+m_Delegate(NULL), m_SROMCellDefaultText("<click to load SROM file>"), m_RepresentatonCellDefaultText("<click to select representation>")
{
this->CreateQtPartControl(this);
}
QmitkNDIConfigurationWidget::~QmitkNDIConfigurationWidget()
{
m_Controls = NULL;
m_Tracker = NULL;
m_Source = NULL;
}
void QmitkNDIConfigurationWidget::CreateQtPartControl(QWidget *parent)
{
if (!m_Controls)
{
// create GUI widgets
m_Controls = new Ui::QmitkNDIConfigurationWidget;
m_Controls->setupUi(parent);
QStringList comPorts;
#ifdef WIN32
comPorts << "COM1" << "COM2" << "COM3" << "COM4" << "COM5" << "COM6" << "COM7" << "COM8" << "COM9";
#else
comPorts << "/dev/ttyS1" << "/dev/ttyS2" << "/dev/ttyS3" << "/dev/ttyS4" << "/dev/ttyS5" << "/dev/ttyUSB0" << "/dev/ttyUSB1" << "/dev/ttyUSB2" << "/dev/ttyUSB3";
#endif
m_Controls->m_ComPortSelector->addItems(comPorts);
m_Delegate = new QmitkNDIToolDelegate(m_Controls->m_ToolTable);
m_Delegate->SetDataStorage(NULL); //needs to be set later using the setter methods
m_Delegate->SetPredicate(NULL);
m_Delegate->SetTypes(QStringList());
m_Controls->m_ToolTable->setItemDelegate(m_Delegate);
this->CreateConnections();
this->HidePolarisOptionsGroupbox(true);
this->HideAuroraOptionsGroupbox(true);
}
}
void QmitkNDIConfigurationWidget::CreateConnections()
{
connect(m_Controls->m_Connect, SIGNAL(clicked()), this, SLOT(OnConnect()));
connect(m_Controls->m_DiscoverToolsBtn, SIGNAL(clicked()), this, SLOT(OnDiscoverTools()));
connect(m_Controls->m_AddToolBtn, SIGNAL(clicked()), this, SLOT(OnAddPassiveTool()));
connect(m_Controls->m_DisoverDevicesBtn, SIGNAL(clicked()), this, SLOT(OnDiscoverDevices()));
connect(m_Controls->m_ToolTable->model(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(UpdateTrackerFromToolTable(const QModelIndex &, const QModelIndex &)));
connect(m_Controls->m_DisoverDevicesBtnInfo, SIGNAL(clicked()), this, SLOT(OnDisoverDevicesBtnInfo()));
-}
+
+ connect(m_Controls->m_SaveToolPushButton, SIGNAL(clicked()), this, SLOT(OnSaveTool()) );
+ connect(m_Controls->m_LoadToolPushButton, SIGNAL(clicked()), this, SLOT(OnLoadTool()) );
+
+ }
void QmitkNDIConfigurationWidget::OnConnect()
{
if (m_Tracker.IsNotNull())
{
m_Tracker->CloseConnection();
m_Tracker = NULL;
}
this->CreateTracker();
this->SetupTracker();
bool okay = m_Tracker->OpenConnection();
if (okay)
{
// show/hide options according to connected device
if(m_Tracker->GetType() == mitk::NDIPolaris)
{
this->HideAuroraOptionsGroupbox(true);
this->HidePolarisOptionsGroupbox(false);
}
else if(m_Tracker->GetType() == mitk::NDIAurora)
{
this->HidePolarisOptionsGroupbox(true);
this->HideAuroraOptionsGroupbox(false);
}
this->UpdateWidgets();
this->UpdateToolTable();
+
+ connect(m_Controls->m_ToolTable, SIGNAL(cellChanged(int,int)), this, SLOT(OnTableCellChanged(int,int)));
+
emit ToolsAdded(this->GetToolNamesList());
emit Connected();
}
else
{
QMessageBox::warning(NULL, "Error", QString("Connection failed. Tracking device error message is '%1'").arg(m_Tracker->GetErrorMessage()));
m_Tracker->CloseConnection();
this->m_Tracker = NULL;
}
}
void QmitkNDIConfigurationWidget::OnDisconnect()
{
if (m_Tracker.IsNull())
return;
m_Tracker->CloseConnection();
m_Tracker = NULL;
+ disconnect(m_Controls->m_ToolTable, SIGNAL(cellChanged(int,int)), this, SLOT(OnTableCellChanged(int,int)));
+ m_Controls->m_ToolSelectionComboBox->clear();
+
this->UpdateToolTable();
- this->UpdateWidgets();
+ this->UpdateWidgets();
emit ToolsAdded(this->GetToolNamesList());
emit Disconnected();
this->HidePolarisOptionsGroupbox(true);
this->HideAuroraOptionsGroupbox(true);
}
void QmitkNDIConfigurationWidget::UpdateWidgets()
{
m_Controls->m_DeviceStatus->setText(this->GetStatusText());
if (m_Tracker.IsNull()) // not connected to tracker
{
m_Controls->m_Connect->setText("Connect");
m_Controls->m_lConnection->setText("III. Enable connection to device ");
disconnect(m_Controls->m_Connect, SIGNAL(clicked()), this, SLOT(OnDisconnect()));
connect(m_Controls->m_Connect, SIGNAL(clicked()), this, SLOT(OnConnect()));
m_Controls->m_DiscoverToolsBtn->setDisabled(true);
m_Controls->m_AddToolBtn->setDisabled(true);
return;
}
if (m_Tracker->GetState() == mitk::TrackingDevice::Setup)
{
m_Controls->m_Connect->setText("Connect");
m_Controls->m_lConnection->setText("III. Enable connection to device ");
disconnect(m_Controls->m_Connect, SIGNAL(clicked()), this, SLOT(OnDisconnect()));
connect(m_Controls->m_Connect, SIGNAL(clicked()), this, SLOT(OnConnect()));
m_Controls->m_DiscoverToolsBtn->setDisabled(true);
m_Controls->m_AddToolBtn->setDisabled(true);
return;
}
if ((m_Tracker->GetState() == mitk::TrackingDevice::Ready) || (m_Tracker->GetState() == mitk::TrackingDevice::Tracking))
{
m_Controls->m_Connect->setText("Disconnect");
m_Controls->m_lConnection->setText("III. Disable connection to device ");
disconnect(m_Controls->m_Connect, SIGNAL(clicked()), this, SLOT(OnConnect()));
connect(m_Controls->m_Connect, SIGNAL(clicked()), this, SLOT(OnDisconnect()));
m_Controls->m_DiscoverToolsBtn->setEnabled(true);
m_Controls->m_AddToolBtn->setEnabled(true);
}
}
QString QmitkNDIConfigurationWidget::GetStatusText()
{
if (m_Tracker.IsNull())
return QString("Not connected");
QString devName;
switch (m_Tracker->GetType())
{
case mitk::NDIAurora:
devName = "NDI Aurora";
break;
case mitk::NDIPolaris:
devName = "NDI Polaris";
break;
case mitk::TrackingSystemNotSpecified:
default:
devName = "unknown tracking device";
break;
}
if (m_Tracker->GetState() == mitk::TrackingDevice::Ready)
return QString("Connected to %1 on %2. Device is ready.").arg(devName).arg(m_Tracker->GetDeviceName());
if (m_Tracker->GetState() == mitk::TrackingDevice::Tracking)
return QString("%1 is tracking.").arg(devName);
return QString("");
}
void QmitkNDIConfigurationWidget::OnDiscoverTools()
{
if (m_Tracker.IsNull())
{
QMessageBox::warning(NULL, "Error", QString("Connection failed. No tracking device found."));
return;
}
m_Tracker->DiscoverWiredTools();
this->UpdateToolTable();
emit ToolsAdded(this->GetToolNamesList());
}
void QmitkNDIConfigurationWidget::OnAddPassiveTool()
{
if (m_Tracker.IsNull())
this->CreateTracker();
QStringList filenames = QFileDialog::getOpenFileNames(this, "Select NDI SROM file", QDir::currentPath(),"NDI SROM files (*.rom)");
if (filenames.isEmpty())
{
this->m_Tracker = NULL;
return;
}
foreach(QString fileName, filenames)
{
//QString toolName = QInputDialog::getText(this, "Enter a name for the tool", "Name of the tool: ", QLineEdit::Normal, QFileInfo(filename).baseName(), &ok);
//if (ok == false || toolName.isEmpty())
// return;
m_Tracker->AddTool(QFileInfo(fileName).baseName().toLatin1(), fileName.toLatin1());
}
emit ToolsAdded(this->GetToolNamesList());
this->UpdateToolTable();
}
void QmitkNDIConfigurationWidget::CreateTracker()
{
m_Tracker = mitk::NDITrackingDevice::New();
}
void QmitkNDIConfigurationWidget::SetupTracker()
{
if (m_Tracker.IsNull())
return;
m_Tracker->SetDeviceName(this->GetDeviceName());
m_Tracker->SetBaudRate(mitk::SerialCommunication::BaudRate115200);
}
std::string QmitkNDIConfigurationWidget::GetDeviceName() const
{
if (m_Controls == NULL)
return NULL;
QString deviceName = m_Controls->m_ComPortSelector->currentText();
#if WIN32
deviceName.prepend("\\\\.\\"); // always prepend "\\.\ to all COM ports, to be able to connect to ports > 9"
#endif
return deviceName.toStdString();
}
void QmitkNDIConfigurationWidget::SetDeviceName( const char* dev )
{
if (m_Controls == NULL)
return;
m_Controls->m_ComPortSelector->setCurrentIndex(m_Controls->m_ComPortSelector->findText(dev));
}
void QmitkNDIConfigurationWidget::UpdateToolTable()
{
- disconnect(m_Controls->m_ToolTable, SIGNAL(itemChanged(QTableWidgetItem*)), this, SLOT(OnTableItemChanged(QTableWidgetItem*))); // stop listening to table changes
+ //disconnect(m_Controls->m_ToolTable, SIGNAL(itemChanged(QTableWidgetItem*)), this, SLOT(OnTableItemChanged(QTableWidgetItem*))); // stop listening to table changes
disconnect(m_Controls->m_ToolTable->model(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(UpdateTrackerFromToolTable(const QModelIndex &, const QModelIndex &)));
m_Controls->m_ToolTable->clearContents();
m_Controls->m_ToolTable->setRowCount(0);
if (m_Tracker.IsNull() || (m_Controls == NULL))
return;
+
+ m_Controls->m_ToolSelectionComboBox->clear();
m_Controls->m_ToolTable->setRowCount(m_Tracker->GetToolCount());
for (unsigned int i = 0; i < m_Tracker->GetToolCount(); ++i)
{
mitk::TrackingTool* t = m_Tracker->GetTool(i);
if (t == NULL)
{
m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::IndexCol, new QTableWidgetItem("INVALID")); // Index
continue;
}
+
+ m_Controls->m_ToolSelectionComboBox->addItem(m_Tracker->GetTool(i)->GetToolName());
+
m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::IndexCol, new QTableWidgetItem(QString::number(i))); // Index
m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::NameCol, new QTableWidgetItem(t->GetToolName())); // Name
if (dynamic_cast<mitk::NDIPassiveTool*>(t)->GetSROMDataLength() > 0)
m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::SROMCol, new QTableWidgetItem("SROM file loaded")); // SROM file
else
- m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::SROMCol, new QTableWidgetItem("<click to load SROM file>")); // SROM file
+ m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::SROMCol, new QTableWidgetItem(m_SROMCellDefaultText)); // SROM file
m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::TypeCol, new QTableWidgetItem("<click to set type>")); // Type
if (t->IsEnabled())
m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::StatusCol, new QTableWidgetItem("Enabled")); // Status
else
m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::StatusCol, new QTableWidgetItem("Disabled")); // Status
m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::NodeCol, new QTableWidgetItem("<click to select node>")); // Node
-
+
+ m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::RepCol, new QTableWidgetItem(m_RepresentatonCellDefaultText)); // Representation
+
/* set read-only/editable flags */
m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::IndexCol)->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); // Index
m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::NodeCol)->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); // Name
m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::SROMCol)->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); // SROM file
m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::TypeCol)->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); // Type
m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::StatusCol)->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); // Status
m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::NodeCol)->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); // Node
-
-
+ m_Controls->m_ToolTable->item(i, QmitkNDIToolDelegate::RepCol)->setFlags(Qt::NoItemFlags); // Representation surface file
}
m_Controls->m_ToolTable->resizeColumnsToContents();
- connect(m_Controls->m_ToolTable, SIGNAL(itemChanged(QTableWidgetItem*)), this, SLOT(OnTableItemChanged(QTableWidgetItem*))); // listen to table changes again
+ //connect(m_Controls->m_ToolTable, SIGNAL(itemChanged(QTableWidgetItem*)), this, SLOT(OnTableItemChanged(QTableWidgetItem*))); // listen to table changes again
connect(m_Controls->m_ToolTable->model(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(UpdateTrackerFromToolTable(const QModelIndex &, const QModelIndex &)));
+ connect(m_Controls->m_ToolTable, SIGNAL( clicked ( const QModelIndex & )), this, SLOT ( OnTableItemClicked( const QModelIndex & )));
+
}
void QmitkNDIConfigurationWidget::OnDiscoverDevices()
{
PortDeviceMap portsAndDevices;
QString status = "Scanning ";
#ifdef WIN32
QString devName;
for (unsigned int i = 1; i < 20; ++i)
{
if (i<10)
devName = QString("COM%1").arg(i);
else
devName = QString("\\\\.\\COM%1").arg(i); // prepend "\\.\ to COM ports >9, to be able to allow connection"
portsAndDevices[devName];
status += QString("COM%1").arg(i) + ", ";
}
#else //linux/posix systems
for(unsigned int i = 1; i < 6; ++i)
{
QString devName = QString("/dev/ttyS%1").arg(i);
portsAndDevices[devName];
status += devName + ", ";
}
for(unsigned int i = 0; i <7; ++i)
{
QString devName = QString("/dev/ttyUSB%1").arg(i);
portsAndDevices[devName];
status += devName + ", ";
}
#endif
status.chop(2); // remove last ", "
status += " for NDI tracking devices...";
m_Controls->m_DeviceStatus->setText(status);
ScanPortsForNDITrackingDevices(portsAndDevices);
m_Controls->m_ComPortSelector->clear();
QString result = "The following tracking devices were found:<BR/>\n";
for (PortDeviceMap::const_iterator it = portsAndDevices.begin(); it != portsAndDevices.end(); ++it)
{
QString tmpComPort = it.key();
if (tmpComPort.startsWith("\\"))
{
tmpComPort.remove(0,4); // remove "\\.\" for nice ui visualisation
}
result += tmpComPort + ": ";
switch (it.value())
{
case mitk::NDIPolaris:
result += "NDI Polaris<BR/>\n";
m_Controls->m_ComPortSelector->addItem(tmpComPort);
break;
case mitk::NDIAurora:
result += "NDI Aurora<BR/>\n";
m_Controls->m_ComPortSelector->addItem(tmpComPort);
break;
default:
result += "No NDI tracking device found<BR/>\n";
}
}
//QMessageBox::information(NULL, "Tracking Device Discovery", result);
m_Controls->m_DeviceStatus->setText(result);
}
mitk::TrackingDeviceType QmitkNDIConfigurationWidget::ScanPort(QString port)
{
mitk::NDITrackingDevice::Pointer tracker = mitk::NDITrackingDevice::New();
tracker->SetDeviceName(port.toStdString());
return tracker->TestConnection();
}
void QmitkNDIConfigurationWidget::ScanPortsForNDITrackingDevices( PortDeviceMap& portsAndDevices )
{
// Iterative scanning:
for (PortDeviceMap::iterator it = portsAndDevices.begin(); it != portsAndDevices.end(); ++it)
it.value() = this->ScanPort(it.key());
// \Todo: use parallel scanning
//QtConcurrent::blockingMap( portsAndDevices.begin(), portsAndDevices.end(), ScanPort );
//MITK_INFO << portsAndDevices;
}
QStringList QmitkNDIConfigurationWidget::GetToolNamesList()
{
QStringList toolNames;
if (m_Tracker.IsNull())
return toolNames;
for (unsigned int i = 0; i < m_Tracker->GetToolCount(); ++i)
{
mitk::TrackingTool* t = m_Tracker->GetTool(i);
if (t == NULL)
continue;
toolNames << t->GetToolName();
}
return toolNames;
}
mitk::NDITrackingDevice* QmitkNDIConfigurationWidget::GetTracker() const
{
return m_Tracker.GetPointer();
}
void QmitkNDIConfigurationWidget::SetToolTypes(const QStringList& types)
{
m_Delegate->SetTypes(types);
}
void QmitkNDIConfigurationWidget::SetDataStorage(mitk::DataStorage* ds)
{
m_Delegate->SetDataStorage(ds);
}
void QmitkNDIConfigurationWidget::SetPredicate(mitk::NodePredicateBase::Pointer p)
{
m_Delegate->SetPredicate(p);
}
void QmitkNDIConfigurationWidget::SetTagPropertyName( const std::string& name )
{
m_Delegate->SetTagPropertyName(name);
}
void QmitkNDIConfigurationWidget::SetTagProperty( mitk::BaseProperty::Pointer prop )
{
m_Delegate->SetTagProperty(prop);
}
void QmitkNDIConfigurationWidget::OnTableItemClicked(const QModelIndex & topLeft )
{
QString filename;
QTableWidgetItem* filenameItem;
switch (topLeft.column())
{
case QmitkNDIToolDelegate::RepCol:
filename = QFileDialog::getOpenFileName(this, "Select Surface File", QDir::currentPath(),"STL files (*.stl)");
filenameItem = new QTableWidgetItem(filename);
m_Controls->m_ToolTable->setItem( topLeft.row(), topLeft.column(), filenameItem );
if(QFileInfo(filename).exists())
- emit RepresentationChanged( topLeft.row(), filename.toStdString() );
+ {
+ mitk::Surface::Pointer surface = this->LoadSurfaceFromSTLFile(filename);
+
+ if(surface.IsNotNull())
+ emit RepresentationChanged( topLeft.row(), surface);
+ }
break;
default:
break;
}
}
void QmitkNDIConfigurationWidget::UpdateTrackerFromToolTable(const QModelIndex & topLeft, const QModelIndex & /*bottomRight*/)
{
//Colums ID doesn't have to be processed.
if (topLeft.column()<1)
return;
if (m_Tracker.IsNull())
return;
if (topLeft.row() >= (int) m_Tracker->GetToolCount())
return;
QAbstractItemModel* model = m_Controls->m_ToolTable->model();
//define topleft contains row and column; row 0 is tool 0; column is index =0, Name =1, SROMFileName = 2; Type = 3; Status = 4; Node (?) = 5
//only update the changed item
mitk::NDIPassiveTool* tool = dynamic_cast<mitk::NDIPassiveTool*> (m_Tracker->GetTool(topLeft.row()));
if (tool == NULL)
return;
switch (topLeft.column())
{
- case 0: //index
+ case QmitkNDIToolDelegate::IndexCol: //index
break;
- case 1: //name
+ case QmitkNDIToolDelegate::NameCol: //name
tool->SetToolName(model->data(model->index(topLeft.row(), 1)).toString().toLatin1());
emit ToolsChanged();
break;
case QmitkNDIToolDelegate::SROMCol: //SROM File Name
{
QString romfile = model->data(model->index(topLeft.row(), QmitkNDIToolDelegate::SROMCol)).toString();
if (QFileInfo(romfile).exists())
tool->LoadSROMFile(romfile.toLatin1());
m_Tracker->UpdateTool(tool);
break;
}
//TODO: Add Node Status and Type here as well
default:
break;
}
}
const QString QmitkNDIConfigurationWidget::GetToolType( unsigned int index ) const
{
if (m_Controls == NULL)
return QString("");
QAbstractItemModel* model = m_Controls->m_ToolTable->model();
QModelIndex modelIndex = model->index(index, QmitkNDIToolDelegate::TypeCol);
if (modelIndex.isValid() == false)
return QString("");
return model->data(modelIndex).toString();
}
const QString QmitkNDIConfigurationWidget::GetToolName( unsigned int index ) const
{
if (m_Controls == NULL)
return QString("");
QAbstractItemModel* model = m_Controls->m_ToolTable->model();
QModelIndex modelIndex = model->index(index, QmitkNDIToolDelegate::NameCol);
if (modelIndex.isValid() == false)
return QString("");
return model->data(modelIndex).toString();
}
QMap<QString, unsigned int> QmitkNDIConfigurationWidget::GetToolAndTypes() const
{
QMap<QString, unsigned int> map;
if (m_Controls == NULL)
return map;
QAbstractItemModel* model = m_Controls->m_ToolTable->model();
for (int i = 0; i < model->rowCount(); ++i)
{
QModelIndex indexIndex = model->index(i, QmitkNDIToolDelegate::IndexCol);
QModelIndex typeIndex = model->index(i, QmitkNDIToolDelegate::TypeCol);
if ((indexIndex.isValid() == false) || (typeIndex.isValid() == false))
continue;
map.insert(model->data(typeIndex).toString(), model->data(indexIndex).toUInt());
}
return map;
}
QList<unsigned int> QmitkNDIConfigurationWidget::GetToolsByToolType( QString toolType ) const
{
QList<unsigned int> list;
if (m_Controls == NULL)
return list;
QAbstractItemModel* model = m_Controls->m_ToolTable->model();
for (int i = 0; i < model->rowCount(); ++i)
{
QModelIndex indexIndex = model->index(i, QmitkNDIToolDelegate::IndexCol);
QModelIndex typeIndex = model->index(i, QmitkNDIToolDelegate::TypeCol);
if ((indexIndex.isValid() == false) || (typeIndex.isValid() == false))
continue;
if (model->data(typeIndex).toString() == toolType)
list.append(model->data(indexIndex).toUInt());
}
return list;
}
mitk::DataNode* QmitkNDIConfigurationWidget::GetNode( unsigned int index ) const
{
if (m_Controls == NULL)
return NULL;
QAbstractItemModel* model = m_Controls->m_ToolTable->model();
QVariant data = model->data(model->index(index, QmitkNDIToolDelegate::NodeCol), QmitkNDIToolDelegate::OrganNodeRole);
return data.value<mitk::DataNode*>();
}
void QmitkNDIConfigurationWidget::HidePolarisOptionsGroupbox( bool on )
{
m_Controls->m_gbPolarisOptions->setHidden(on);
}
void QmitkNDIConfigurationWidget::HideAuroraOptionsGroupbox( bool on )
{
m_Controls->m_gbAuroraOptions->setHidden(on);
}
void QmitkNDIConfigurationWidget::ShowToolRepresentationColumn()
{
int cols = m_Controls->m_ToolTable->columnCount();
//checking if representation column is inserted at right index
if(cols != QmitkNDIToolDelegate::RepCol)
{
//throw std::exception("Representation Column is not inserted at it's designated index!");
return;
}
m_Controls->m_ToolTable->insertColumn(cols); // insert new column at end of table
m_Controls->m_ToolTable->setHorizontalHeaderItem(QmitkNDIToolDelegate::RepCol, new QTableWidgetItem(QString("Representation"))); // inser column header for new colum
//m_Controls->m_ToolTable->setEditTriggers(QAbstractItemView::EditTrigger::NoEditTriggers);
int rows = m_Controls->m_ToolTable->rowCount();
// make all representation colum items not editable
for(int i=0; i < rows; ++i)
{
m_Controls->m_ToolTable->setItem(i, QmitkNDIToolDelegate::RepCol, new QTableWidgetItem("<click to select representation>")); // Representation
m_Controls->m_ToolTable->item(i,QmitkNDIToolDelegate::RepCol)->setFlags(Qt::NoItemFlags);
- }
-
- // connect tool table to click slot
- connect(m_Controls->m_ToolTable, SIGNAL( clicked ( const QModelIndex & )), this, SLOT ( OnTableItemClicked( const QModelIndex & )));
+ }
+
+ connect(m_Controls->m_ToolTable, SIGNAL( clicked ( const QModelIndex & )), this, SLOT ( OnTableItemClicked( const QModelIndex & )));
+
}
void QmitkNDIConfigurationWidget::OnDisoverDevicesBtnInfo()
{
QMessageBox *infoBox = new QMessageBox(this);
infoBox->setText("Click \"Scan Ports\" to get a list of all connected NDI tracking devices. This will clear the selection menu below and add the ports for discovered NDI tracking devices. Use this function, if a port is not listed.");
infoBox->exec();
delete infoBox;
}
+
+void QmitkNDIConfigurationWidget::OnTableCellChanged(int row, int column)
+{
+
+ if(m_Tracker.IsNull())
+ return;
+
+ QString toolName;
+
+ switch (column)
+ {
+ case QmitkNDIToolDelegate::NameCol:
+ toolName = m_Controls->m_ToolTable->item(row,column)->text();
+ m_Controls->m_ToolSelectionComboBox->setItemText(row, toolName);
+
+ emit SignalToolNameChanged(row, toolName);
+
+ break;
+
+ default:
+ break;
+ }
+
+}
+
+
+void QmitkNDIConfigurationWidget::OnSaveTool()
+{
+ if(m_Tracker.IsNull() || m_Tracker->GetToolCount() <= 0)
+ return;
+
+ int currId = m_Controls->m_ToolSelectionComboBox->currentIndex();
+ QString filename = QFileDialog::getSaveFileName(NULL, "Save NDI-Tool", QString(QDir::currentPath()+QString(m_Tracker->GetTool(currId)->GetToolName())),"NDI Tracking Tool file(*.ntf)");
+
+ mitk::TrackingTool* selectedTool = m_Tracker->GetTool(currId);
+
+ if(filename.isEmpty())
+ return;
+
+ mitk::NavigationTool::Pointer navTool = mitk::NavigationTool::New();
+
+
+ mitk::NavigationToolWriter::Pointer toolWriter = mitk::NavigationToolWriter::New();
+ try {
+ toolWriter->DoWrite(filename.toStdString(), this->GenerateNavigationTool(selectedTool));
+ }
+ catch( ... )
+ {
+ QMessageBox::warning(NULL, "Saving Tool Error", QString("An error occured! Could not save tool!\n\n"));
+ MBI_ERROR<<"Could not save tool surface!";
+ MBI_ERROR<< toolWriter->GetErrorMessage();
+
+ QFile maybeCorruptFile(filename);
+
+ if(maybeCorruptFile.exists())
+ maybeCorruptFile.remove();
+ }
+
+ emit SignalSavedTool(currId, filename);
+}
+
+
+void QmitkNDIConfigurationWidget::OnLoadTool()
+{
+ if(m_Tracker.IsNull() || m_Tracker->GetToolCount() <= 0)
+ return;
+
+ QString filename = QFileDialog::getOpenFileName(NULL, "Load NDI-Tools", QDir::currentPath(),"NDI Tracking Tool file(*.ntf)");
+ int currId = m_Controls->m_ToolSelectionComboBox->currentIndex();
+
+ if(filename.isEmpty())
+ return;
+
+ mitk::DataNode::Pointer toolNode;
+ mitk::NavigationToolReader::Pointer toolReader = mitk::NavigationToolReader::New();
+ mitk::NavigationTool::Pointer navTool;
+
+ try {
+ navTool = toolReader->DoRead(filename.toStdString());
+ }
+ catch( ... )
+ {
+ QMessageBox::warning(NULL, "Loading Tool Error", QString("An error occured! Could not load tool!\n\n"));
+ MBI_ERROR<<"Could not load tool surface!";
+ MBI_ERROR<< toolReader->GetErrorMessage();
+ }
+
+ int currSelectedToolID = m_Controls->m_ToolSelectionComboBox->currentIndex();
+
+ // name
+ m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::NameCol)->setText(navTool->GetToolName().c_str());
+
+ //calibration file (.srom) filename
+ m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::SROMCol)->setText(navTool->GetCalibrationFile().c_str());
+
+ //type
+ if(navTool->GetType() == mitk::NavigationTool::Instrument)
+ m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::TypeCol)->setText("Instrument");
+ else if(navTool->GetType() == mitk::NavigationTool::Fiducial)
+ m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::TypeCol)->setText("Fiducial");
+ else if(navTool->GetType() == mitk::NavigationTool::Skinmarker)
+ m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::TypeCol)->setText("Skinmarker");
+ else
+ m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::TypeCol)->setText("Unknown");
+
+
+ //representation
+ m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::SROMCol)->setText(m_RepresentatonCellDefaultText);
+
+ emit SignalLoadTool(currId, navTool->GetDataNode());
+}
+
+
+mitk::NavigationTool::Pointer QmitkNDIConfigurationWidget::GenerateNavigationTool(mitk::TrackingTool* tool)
+{
+ mitk::NavigationTool::Pointer navTool = mitk::NavigationTool::New();
+ mitk::NDIPassiveTool::Pointer passiveTool = dynamic_cast<mitk::NDIPassiveTool*>(tool);
+
+ if(passiveTool.IsNull())
+ throw std::runtime_error("Could not cast TrackingTool to PassiveTool");
+
+ int currSelectedToolID = m_Controls->m_ToolSelectionComboBox->currentIndex();
+
+ QString sromFileName = m_Controls->m_ToolTable->item(currSelectedToolID, QmitkNDIToolDelegate::SROMCol)->text();
+ QString surfaceFileName = m_Controls->m_ToolTable->item(currSelectedToolID, QmitkNDIToolDelegate::RepCol)->text();
+
+ //calibration file (.srom) filename
+ QFile sromFile(sromFileName);
+ if(sromFile.exists())
+ navTool->SetCalibrationFile(sromFileName.toStdString());
+
+ //serial number
+ navTool->SetSerialNumber(passiveTool->GetSerialNumber());
+
+ // name and surface as dataNode
+ mitk::DataNode::Pointer node = mitk::DataNode::New();
+
+ mitk::Surface::Pointer toolSurface;
+
+ try{
+ toolSurface = this->LoadSurfaceFromSTLFile(surfaceFileName);
+ }
+ catch( ... )
+ {
+ QMessageBox::warning(NULL, "Loading Surface Error", QString("An error occured! Could not load surface from .stl file!\n\n"));
+ MBI_ERROR<<"Could not load .stl tool surface!";
+ }
+
+
+ if(toolSurface.IsNotNull())
+ {
+ node->SetData(toolSurface);
+ node->SetName(tool->GetToolName());
+ }
+
+ navTool->SetDataNode(node);
+
+ // type
+ mitk::NavigationTool::NavigationToolType type;
+ QString currentToolType = m_Controls->m_ToolTable->item(currSelectedToolID,QmitkNDIToolDelegate::TypeCol)->text();
+
+ if(currentToolType.compare("Instrument") == 0)
+ type = mitk::NavigationTool::Instrument;
+ else if(currentToolType.compare("Fiducial") == 0)
+ type = mitk::NavigationTool::Fiducial;
+ else if(currentToolType.compare("Skinmarker") == 0)
+ type = mitk::NavigationTool::Skinmarker;
+ else
+ type = mitk::NavigationTool::Unknown;
+
+ navTool->SetType(type);
+
+ return navTool;
+}
+
+
+mitk::Surface::Pointer QmitkNDIConfigurationWidget::LoadSurfaceFromSTLFile(QString surfaceFilename)
+{
+ mitk::Surface::Pointer toolSurface;
+
+ QFile surfaceFile(surfaceFilename);
+ if(surfaceFile.exists())
+ {
+ mitk::STLFileReader::Pointer stlReader = mitk::STLFileReader::New();
+
+ try{
+ stlReader->SetFileName(surfaceFilename.toStdString().c_str());
+ stlReader->Update();//load surface
+ toolSurface = stlReader->GetOutput();
+ }
+ catch(std::exception& e )
+ {
+ MBI_ERROR<<"Could not load surface for tool!";
+ MBI_ERROR<< e.what();
+ throw e;
+ }
+ }
+
+ return toolSurface;
+}
\ No newline at end of file
diff --git a/Modules/IGTUI/Qmitk/QmitkNDIConfigurationWidget.h b/Modules/IGTUI/Qmitk/QmitkNDIConfigurationWidget.h
index 8c3891215e..51942515ed 100644
--- a/Modules/IGTUI/Qmitk/QmitkNDIConfigurationWidget.h
+++ b/Modules/IGTUI/Qmitk/QmitkNDIConfigurationWidget.h
@@ -1,120 +1,136 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date: 2009-03-21 19:27:37 +0100 (Sa, 21 Mrz 2009) $
Version: $Revision: 16719 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef _QmitkNDIConfigurationWidget_H_INCLUDED
#define _QmitkNDIConfigurationWidget_H_INCLUDED
#include "ui_QmitkNDIConfigurationWidget.h"
#include "mitkNDITrackingDevice.h"
#include "mitkTrackingDeviceSource.h"
#include "QStringList"
#include "MitkIGTUIExports.h"
#include "mitkNodePredicateBase.h"
+#include "mitkNavigationTool.h"
+
class QmitkNDIToolDelegate;
namespace mitk
{
class DataStorage;
};
/*!
\brief Heidelberg Minimally Invasive Navigation Device
Functionality for visualizing a tracking instrument in relation to a tracked patient.
\sa QmitkFunctionality
\sa IGT
\ingroup Functionalities
*/
class MitkIGTUI_EXPORT QmitkNDIConfigurationWidget : public QWidget
{
Q_OBJECT // this is needed for all Qt objects that should have a MOC object (everything that derives from QObject)
public:
QmitkNDIConfigurationWidget(QWidget* parent);
virtual ~QmitkNDIConfigurationWidget();
std::string GetDeviceName() const;
mitk::NDITrackingDevice* GetTracker() const;
mitk::DataStorage* GetDataStorage() const;
mitk::NodePredicateBase* GetPredicate() const;
const QStringList& GetToolTypes() const;
void SetToolTypes(const QStringList& types); ///< set types list for type editor combobox
void SetDataStorage(mitk::DataStorage* ds); ///< set datastorage for organ node editor
void SetPredicate(mitk::NodePredicateBase::Pointer p); ///< set predicate for organ node editor
void SetTagPropertyName(const std::string& name); ///< set name of the property that is used to tag selected nodes
void SetTagProperty(mitk::BaseProperty::Pointer prop); ///< set the property that is used to tag selected nodes
const QString GetToolType(unsigned int index) const;
const QString GetToolName(unsigned int index) const;
QMap<QString, unsigned int> GetToolAndTypes() const;
QList<unsigned int> GetToolsByToolType(QString toolType) const;
mitk::DataNode* GetNode(unsigned int index) const;
signals:
void ToolsAdded(QStringList tools);
void ToolsChanged();
void Connected();
void Disconnected();
- void RepresentationChanged( const int & row , const std::string & filename ); // returns the row number of the clicked tableitem for changing tool representation
+ void RepresentationChanged( int id , mitk::Surface::Pointer surface ); // returns the row number of the clicked tableitem for changing tool representation
+ void SignalToolNameChanged(int id, QString name);
+ void SignalSavedTool(int id, QString surfaceFilename);
+ void SignalLoadTool(int id, mitk::DataNode::Pointer dn);
public slots:
void SetDeviceName(const char* dev); ///< set the device name (e.g. "COM1", "/dev/ttyS0") that will be used to connect to the tracking device
void ShowToolRepresentationColumn(); ///< show or hide the tooltable column "Tool Representation". This SLOT should be called after SIGNAL "Connected" is emitted
protected slots:
void OnConnect();
void OnDisconnect();
void OnDiscoverTools();
void OnDiscoverDevices();
void OnAddPassiveTool();
void UpdateTrackerFromToolTable(const QModelIndex & topLeft, const QModelIndex & /*bottomRight*/);
void OnTableItemClicked(const QModelIndex & topLeft); ///< for clicking on tooltable items
void OnDisoverDevicesBtnInfo();
+ void OnTableCellChanged(int row, int column);
+ void OnSaveTool();
+ void OnLoadTool();
+
protected:
typedef QMap<QString, mitk::TrackingDeviceType> PortDeviceMap; // key is port name (e.g. "COM1", "/dev/ttyS0"), value will be filled with the type of tracking device at this port
/**Documentation
* \brief scans the ports provided as key in the portsAndDevices and fills the respective value of portsAndDevices with the tracking device type at that port
*
*
* \param[in] portsAndDevices keys are used to query serial ports
* \param[out] portsAndDevices values of the existing keys will be filled with the tracking device type
*/
void ScanPortsForNDITrackingDevices(PortDeviceMap& portsAndDevices);
mitk::TrackingDeviceType ScanPort(QString port);
+ mitk::NavigationTool::Pointer GenerateNavigationTool(mitk::TrackingTool* tool);
QStringList GetToolNamesList(); ///< returns a string list with the names of all tools of the current tracking device
void CreateTracker(); ///< creates new NDITrackingDevice object
void SetupTracker(); ///< sets the parameters from the gui to the tracking device object
QString GetStatusText(); ///< construct a status text depending on the current state of the tracking device object
void UpdateWidgets();
void UpdateToolTable(); ///< read all tools from the tracking device object and display them in the gui
virtual void CreateQtPartControl(QWidget *parent);
virtual void CreateConnections(); ///< \brief Creation of the connections of main and control widget
void HidePolarisOptionsGroupbox( bool on ); ///< show or hide polaris options in the UI
void HideAuroraOptionsGroupbox( bool on ); ///< show or hide aurora options in the UI
Ui::QmitkNDIConfigurationWidget* m_Controls; ///< gui widgets
mitk::NDITrackingDevice::Pointer m_Tracker; ///< tracking device object
mitk::TrackingDeviceSource::Pointer m_Source;
QmitkNDIToolDelegate* m_Delegate;
+
+ QString m_SROMCellDefaultText;
+ QString m_RepresentatonCellDefaultText;
+
+ mitk::Surface::Pointer LoadSurfaceFromSTLFile(QString surfaceFilename);
+
};
#endif // _QmitkNDIConfigurationWidget_H_INCLUDED
diff --git a/Modules/IGTUI/Qmitk/QmitkNDIConfigurationWidget.ui b/Modules/IGTUI/Qmitk/QmitkNDIConfigurationWidget.ui
index b28cc92180..5859a7830a 100644
--- a/Modules/IGTUI/Qmitk/QmitkNDIConfigurationWidget.ui
+++ b/Modules/IGTUI/Qmitk/QmitkNDIConfigurationWidget.ui
@@ -1,317 +1,362 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QmitkNDIConfigurationWidget</class>
<widget class="QWidget" name="QmitkNDIConfigurationWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>393</width>
<height>586</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QGroupBox" name="groupBox_4">
<property name="title">
<string>Connection Setup</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>I. List all plugged tracking devices </string>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>II. Select port for tracking device </string>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="m_ComPortSelector">
<property name="minimumSize">
<size>
<width>95</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>95</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="m_lConnection">
<property name="text">
<string>III. Enable connection to device </string>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QPushButton" name="m_Connect">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>95</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>95</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Connect</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="m_DisoverDevicesBtn">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>95</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Click to get a list of all connected NDI tracking devices.
This will clear the selection menu below and add the ports for discovered NDI tracking devices. Use this function, if a port is not listed.
</string>
</property>
<property name="text">
<string>Scan ports</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="m_DisoverDevicesBtnInfo">
<property name="minimumSize">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>20</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>?</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="m_gbPolarisOptions">
<property name="title">
<string>Polaris Tracking Device Options</string>
</property>
<layout class="QFormLayout" name="formLayout_2">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Load tool definition as *.rom </string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="m_AddToolBtn">
<property name="maximumSize">
<size>
<width>110</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Add new tools</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="m_gbAuroraOptions">
<property name="title">
<string>Aurora Tracking Device Options</string>
</property>
<layout class="QFormLayout" name="formLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Check for new plugged in tools </string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="m_DiscoverToolsBtn">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>110</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Discover new tools</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>General Information</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="m_DeviceStatus">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Navigation is &lt;/span&gt;&lt;span style=&quot; font-size:8pt; font-style:italic;&quot;&gt;stopped&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Navigation Tools</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QComboBox" name="m_ToolSelectionComboBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>3</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="m_SaveToolPushButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+ <horstretch>3</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Save</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="m_LoadToolPushButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+ <horstretch>2</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Load</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
<item>
<widget class="QTableWidget" name="m_ToolTable">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="editTriggers">
<set>QAbstractItemView::AllEditTriggers</set>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<column>
<property name="text">
<string>Index</string>
</property>
</column>
<column>
<property name="text">
<string>Name</string>
</property>
</column>
<column>
<property name="text">
<string>SROM File</string>
</property>
</column>
<column>
<property name="text">
<string>Type</string>
</property>
</column>
<column>
<property name="text">
<string>Status</string>
</property>
</column>
<column>
<property name="text">
<string>Node</string>
</property>
</column>
+ <column>
+ <property name="text">
+ <string>Representation</string>
+ </property>
+ </column>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
diff --git a/Modules/IGTUI/Qmitk/QmitkUpdateTimerWidget.cpp b/Modules/IGTUI/Qmitk/QmitkUpdateTimerWidget.cpp
index 41ecfad52d..5fbdd12dd0 100644
--- a/Modules/IGTUI/Qmitk/QmitkUpdateTimerWidget.cpp
+++ b/Modules/IGTUI/Qmitk/QmitkUpdateTimerWidget.cpp
@@ -1,183 +1,189 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date: 2009-03-21 19:27:37 +0100 (Sa, 21 Mrz 2009) $
Version: $Revision: 16719 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "QmitkUpdateTimerWidget.h"
#include <QTimer>
#include <math.h>
static unsigned int DEFAULTUPDATEVALUE = 50; // default update value (in msec) for the timer
static unsigned int MINIMUMUPDATEVALUE = 10; // smallest value for the update rate spinbox
static unsigned int MAXIMUMUPDATEVALUE = 1000; // greatest value for the update rate spinbox
static unsigned int UPDATEVALUESTEP = 10; // step size for the update rate spinbox
QmitkUpdateTimerWidget::QmitkUpdateTimerWidget(QWidget* parent)
: QWidget(parent), m_Controls(NULL)
{
this->m_UpdateTimer = new QTimer( this );
this->CreateQtPartControl( this );
this->m_Controls->m_StopNavigationBtn->setEnabled( false );
this->SetupUpdateRateSB( MINIMUMUPDATEVALUE, MAXIMUMUPDATEVALUE, UPDATEVALUESTEP );
this->m_UpdateTimer->setInterval( DEFAULTUPDATEVALUE );
this->m_Controls->m_UpdateRateSB->setValue( DEFAULTUPDATEVALUE );
this->DisableWidget();
}
QmitkUpdateTimerWidget::~QmitkUpdateTimerWidget()
{
m_UpdateTimer->stop();
m_UpdateTimer = NULL;
m_Controls = NULL;
}
void QmitkUpdateTimerWidget::CreateQtPartControl(QWidget *parent)
{
if (!m_Controls)
{
// create GUI widgets
m_Controls = new Ui::QmitkUpdateTimerWidgetControls;
m_Controls->setupUi(parent);
this->CreateConnections();
}
}
void QmitkUpdateTimerWidget::CreateConnections()
{
connect( (QObject*)(m_Controls->m_StartNavigationBtn), SIGNAL(clicked()), this, SLOT(OnStartTimer()) );
connect( (QObject*)(m_Controls->m_StopNavigationBtn), SIGNAL(clicked()), this, SLOT(OnStopTimer()) );
connect( m_Controls->m_UpdateRateSB, SIGNAL(valueChanged(int)), this, SLOT(OnChangeTimerInterval(int)) );
}
unsigned int QmitkUpdateTimerWidget::GetTimerInterval()
{
return this->m_UpdateTimer->interval();
}
void QmitkUpdateTimerWidget::OnChangeTimerInterval( int interval )
{
this->SetTimerInterval(interval);
this->SetFrameRateLabel();
}
void QmitkUpdateTimerWidget::SetTimerInterval( unsigned int msec )
{
this->m_UpdateTimer->setInterval( msec );
this->m_Controls->m_UpdateRateSB->setValue( msec );
}
void QmitkUpdateTimerWidget::StartTimer()
{
if(!m_UpdateTimer->isActive())
{
this->m_UpdateTimer->start();
this->m_Controls->m_StartNavigationBtn->setEnabled( false );
this->m_Controls->m_StopNavigationBtn->setEnabled( true );
this->m_Controls->m_NavigationStateLbl->setStyleSheet( "QLabel{background-color: #96e066 }" );
this->m_Controls->m_NavigationStateLbl->setText( "Started ... " );
emit Started();
}
}
void QmitkUpdateTimerWidget::StopTimer()
{
if(m_UpdateTimer->isActive())
{
m_UpdateTimer->stop();
this->m_Controls->m_StopNavigationBtn->setEnabled( false );
this->m_Controls->m_StartNavigationBtn->setEnabled( true );
this->m_Controls->m_NavigationStateLbl->setStyleSheet( "QLabel{background-color: #ffcccc }" );
this->m_Controls->m_NavigationStateLbl->setText( "Stopped ... " );
emit Stopped();
}
}
QTimer* QmitkUpdateTimerWidget::GetUpdateTimer()
{
return this->m_UpdateTimer;
}
void QmitkUpdateTimerWidget::OnStartTimer()
{
this->StartTimer();
}
void QmitkUpdateTimerWidget::OnStopTimer()
{
this->StopTimer();
}
void QmitkUpdateTimerWidget::SetPurposeLabelText( QString text )
{
m_Controls->m_StartNavigationBtn->setText( " Start " + text );
m_Controls->m_StopNavigationBtn->setText( " Stop " + text );
}
void QmitkUpdateTimerWidget::SetupUpdateRateSB( int min, int max, int step )
{
this->m_Controls->m_UpdateRateSB->setRange( min , max );
this->m_Controls->m_UpdateRateSB->setSingleStep( step );
}
void QmitkUpdateTimerWidget::SetFrameRateLabel()
{
float frameRate = floor(1000 / (float) this->GetTimerInterval() + 0.5); // floor rounding can be used because there are no negative values
QString frameRateString = QString::number( frameRate, 'g', 4 );
this->m_Controls->m_FrameRateLbl->setText("msec (" + frameRateString + " Hz)");
}
void QmitkUpdateTimerWidget::HideFramerateSettings( bool hidden )
{
this->m_Controls->m_UpdatesInMsecLbl->setVisible( !hidden );
this->m_Controls->m_UpdateRateSB->setVisible ( !hidden );
this->m_Controls->m_FrameRateLbl->setVisible ( !hidden );
}
void QmitkUpdateTimerWidget::EnableWidget()
{
this->setEnabled( true );
}
void QmitkUpdateTimerWidget::DisableWidget()
{
this->StopTimer();
this->setEnabled( false );
}
void QmitkUpdateTimerWidget::SetIcon( WidgetButtons button, const QIcon& icon )
{
switch( button )
{
- case StartButton: m_Controls->m_StartNavigationBtn->setIcon(icon);
+ case StartButton:
+ m_Controls->m_StartNavigationBtn->setIcon(icon);
+ break;
- case StopButton: m_Controls->m_StartNavigationBtn->setIcon(icon);
+ case StopButton: m_Controls->m_StopNavigationBtn->setIcon(icon);
+ break;
+
+ default:
+ break;
}
}
diff --git a/Modules/MitkExt/Algorithms/mitkShowSegmentationAsSmoothedSurface.cpp b/Modules/MitkExt/Algorithms/mitkShowSegmentationAsSmoothedSurface.cpp
index 28fe3053ee..7a6c4c6841 100644
--- a/Modules/MitkExt/Algorithms/mitkShowSegmentationAsSmoothedSurface.cpp
+++ b/Modules/MitkExt/Algorithms/mitkShowSegmentationAsSmoothedSurface.cpp
@@ -1,509 +1,507 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "mitkShowSegmentationAsSmoothedSurface.h"
#include "mitkImageToItk.h"
#include "itkIntelligentBinaryClosingFilter.h"
#include <mitkUIDGenerator.h>
#include <mitkGeometry3D.h>
#include <mitkProgressBar.h>
#include <mitkStatusBar.h>
#include <mitkImageToSurfaceFilter.h>
#include <mitkVtkRepresentationProperty.h>
#include <itkImageRegionIteratorWithIndex.h>
#include <itkRegionOfInterestImageFilter.h>
#include <itkConstantPadImageFilter.h>
#include <itkBinaryMedianImageFilter.h>
#include <itkBinaryThresholdImageFilter.h>
#include <itkDiscreteGaussianImageFilter.h>
#include <itkMultiplyImageFilter.h>
#include <itkConnectedThresholdImageFilter.h>
#include <itkAddImageFilter.h>
#include <vtkQuadricDecimation.h>
#include <vtkCleanPolyData.h>
#include <vtkPolyDataNormals.h>
using namespace mitk;
using namespace std;
ShowSegmentationAsSmoothedSurface::ShowSegmentationAsSmoothedSurface()
{
}
ShowSegmentationAsSmoothedSurface::~ShowSegmentationAsSmoothedSurface()
{
}
void ShowSegmentationAsSmoothedSurface::Initialize(const NonBlockingAlgorithm *other)
{
Superclass::Initialize(other);
bool syncVisibility = false;
if (other != NULL)
other->GetParameter("Sync visibility", syncVisibility);
SetParameter("Sync visibility", syncVisibility);
SetParameter("Wireframe", false);
// The Smoothing value is used as variance for a Gauß filter.
// A reasonable default value equals the image spacing in mm.
SetParameter("Smoothing", 1.0f);
// Valid range for decimation value is [0, 1). High values
// increase decimation, especially when very close to 1.
// A value of 0 disables decimation.
SetParameter("Decimation", 0.5f);
}
bool ShowSegmentationAsSmoothedSurface::ReadyToRun()
{
try
{
mitk::Image::Pointer image;
GetPointerParameter("Input", image);
return image.IsNotNull() && GetGroupNode();
}
catch (const invalid_argument &)
{
return false;
}
}
bool ShowSegmentationAsSmoothedSurface::ThreadedUpdateFunction()
{
Image::Pointer image;
GetPointerParameter("Input", image);
float smoothing;
GetParameter("Smoothing", smoothing);
float decimation;
GetParameter("Decimation", decimation);
MITK_INFO << "CREATING SMOOTHED POLYGON MODEL" << endl;
MITK_INFO << " Smoothing = " << smoothing << endl;
MITK_INFO << " Decimation = " << decimation << endl;
Geometry3D::Pointer geometry = dynamic_cast<Geometry3D *>(image->GetGeometry()->Clone().GetPointer());
// Make ITK image out of MITK image
typedef itk::Image<unsigned char, 3> CharImageType;
typedef itk::Image<unsigned short, 3> ShortImageType;
typedef itk::Image<float, 3> FloatImageType;
ImageToItk<CharImageType>::Pointer imageToItkFilter = ImageToItk<CharImageType>::New();
try
{
imageToItkFilter->SetInput(image);
}
catch (const itk::ExceptionObject &e)
{
// Most probably the input image type is wrong. Binary images are expected to be
// >unsigned< char images.
MITK_ERROR << e.GetDescription() << endl;
return false;
}
imageToItkFilter->Update();
CharImageType::Pointer itkImage = imageToItkFilter->GetOutput();
// Get bounding box and relabel
MITK_INFO << "Extracting VOI..." << endl;
int imageLabel = 1;
bool roiFound = false;
CharImageType::IndexType minIndex;
minIndex.Fill(numeric_limits<CharImageType::IndexValueType>::max());
CharImageType::IndexType maxIndex;
maxIndex.Fill(numeric_limits<CharImageType::IndexValueType>::min());
itk::ImageRegionIteratorWithIndex<CharImageType> iter(itkImage, itkImage->GetLargestPossibleRegion());
for (iter.GoToBegin(); !iter.IsAtEnd(); ++iter)
{
if (iter.Get() == imageLabel)
{
roiFound = true;
iter.Set(1);
CharImageType::IndexType currentIndex = iter.GetIndex();
for (unsigned int dim = 0; dim < 3; ++dim)
{
minIndex[dim] = min(currentIndex[dim], minIndex[dim]);
maxIndex[dim] = max(currentIndex[dim], maxIndex[dim]);
}
}
else
{
iter.Set(0);
}
}
if (!roiFound)
{
- ProgressBar::GetInstance()->Progress(10);
+ ProgressBar::GetInstance()->Progress(8);
MITK_ERROR << "Didn't found segmentation labeled with " << imageLabel << "!" << endl;
return false;
}
ProgressBar::GetInstance()->Progress(1);
// Extract and pad bounding box
typedef itk::RegionOfInterestImageFilter<CharImageType, CharImageType> ROIFilterType;
ROIFilterType::Pointer roiFilter = ROIFilterType::New();
CharImageType::RegionType region;
CharImageType::SizeType size;
for (unsigned int dim = 0; dim < 3; ++dim)
{
size[dim] = maxIndex[dim] - minIndex[dim] + 1;
}
region.SetIndex(minIndex);
region.SetSize(size);
roiFilter->SetInput(itkImage);
roiFilter->SetRegionOfInterest(region);
roiFilter->ReleaseDataFlagOn();
roiFilter->ReleaseDataBeforeUpdateFlagOn();
typedef itk::ConstantPadImageFilter<CharImageType, CharImageType> PadFilterType;
PadFilterType::Pointer padFilter = PadFilterType::New();
const PadFilterType::SizeValueType pad[3] = { 10, 10, 10 };
padFilter->SetInput(roiFilter->GetOutput());
padFilter->SetConstant(0);
padFilter->SetPadLowerBound(pad);
padFilter->SetPadUpperBound(pad);
padFilter->ReleaseDataFlagOn();
padFilter->ReleaseDataBeforeUpdateFlagOn();
padFilter->Update();
CharImageType::Pointer roiImage = padFilter->GetOutput();
roiImage->DisconnectPipeline();
roiFilter = 0;
padFilter = 0;
// Correct origin of real geometry (changed by cropping and padding)
typedef AffineGeometryFrame3D::TransformType TransformType;
TransformType::Pointer transform = TransformType::New();
TransformType::OutputVectorType translation;
for (unsigned int dim = 0; dim < 3; ++dim)
translation[dim] = (int)minIndex[dim] - (int)pad[dim];
transform->SetIdentity();
transform->Translate(translation);
geometry->Compose(transform, true);
ProgressBar::GetInstance()->Progress(1);
// Median
MITK_INFO << "Median..." << endl;
typedef itk::BinaryMedianImageFilter<CharImageType, CharImageType> MedianFilterType;
MedianFilterType::Pointer medianFilter = MedianFilterType::New();
CharImageType::SizeType radius = { 1, 1, 1 };
medianFilter->SetRadius(radius);
medianFilter->SetBackgroundValue(0);
medianFilter->SetForegroundValue(1);
medianFilter->SetInput(roiImage);
medianFilter->ReleaseDataFlagOn();
medianFilter->ReleaseDataBeforeUpdateFlagOn();
medianFilter->Update();
ProgressBar::GetInstance()->Progress(1);
// Intelligent closing
MITK_INFO << "Intelligent closing..." << endl;
unsigned int surfaceRatio = 70;
typedef itk::IntelligentBinaryClosingFilter<CharImageType, ShortImageType> ClosingFilterType;
ClosingFilterType::Pointer closingFilter = ClosingFilterType::New();
closingFilter->SetInput(medianFilter->GetOutput());
closingFilter->ReleaseDataFlagOn();
closingFilter->ReleaseDataBeforeUpdateFlagOn();
closingFilter->SetSurfaceRatio(surfaceRatio);
closingFilter->Update();
ShortImageType::Pointer closedImage = closingFilter->GetOutput();
closedImage->DisconnectPipeline();
roiImage = 0;
medianFilter = 0;
closingFilter = 0;
ProgressBar::GetInstance()->Progress(1);
// Gaussian blur
MITK_INFO << "Gauss..." << endl;
typedef itk::BinaryThresholdImageFilter<ShortImageType, FloatImageType> BinaryThresholdToFloatFilterType;
BinaryThresholdToFloatFilterType::Pointer binThresToFloatFilter = BinaryThresholdToFloatFilterType::New();
binThresToFloatFilter->SetInput(closedImage);
binThresToFloatFilter->SetLowerThreshold(1);
binThresToFloatFilter->SetUpperThreshold(1);
binThresToFloatFilter->SetInsideValue(100);
binThresToFloatFilter->SetOutsideValue(0);
binThresToFloatFilter->ReleaseDataFlagOn();
binThresToFloatFilter->ReleaseDataBeforeUpdateFlagOn();
typedef itk::DiscreteGaussianImageFilter<FloatImageType, FloatImageType> GaussianFilterType;
// From the following line on, IntelliSense (VS 2008) is broken. Any idea how to fix it?
GaussianFilterType::Pointer gaussFilter = GaussianFilterType::New();
gaussFilter->SetInput(binThresToFloatFilter->GetOutput());
gaussFilter->SetUseImageSpacing(true);
gaussFilter->SetVariance(smoothing);
gaussFilter->ReleaseDataFlagOn();
gaussFilter->ReleaseDataBeforeUpdateFlagOn();
typedef itk::BinaryThresholdImageFilter<FloatImageType, CharImageType> BinaryThresholdFromFloatFilterType;
BinaryThresholdFromFloatFilterType::Pointer binThresFromFloatFilter = BinaryThresholdFromFloatFilterType::New();
binThresFromFloatFilter->SetInput(gaussFilter->GetOutput());
binThresFromFloatFilter->SetLowerThreshold(50);
binThresFromFloatFilter->SetUpperThreshold(255);
binThresFromFloatFilter->SetInsideValue(1);
binThresFromFloatFilter->SetOutsideValue(0);
binThresFromFloatFilter->ReleaseDataFlagOn();
binThresFromFloatFilter->ReleaseDataBeforeUpdateFlagOn();
binThresFromFloatFilter->Update();
CharImageType::Pointer blurredImage = binThresFromFloatFilter->GetOutput();
blurredImage->DisconnectPipeline();
closedImage = 0;
binThresToFloatFilter = 0;
gaussFilter = 0;
ProgressBar::GetInstance()->Progress(1);
// Fill holes
MITK_INFO << "Filling cavities..." << endl;
typedef itk::ConnectedThresholdImageFilter<CharImageType, CharImageType> ConnectedThresholdFilterType;
ConnectedThresholdFilterType::Pointer connectedThresFilter = ConnectedThresholdFilterType::New();
CharImageType::IndexType corner;
corner[0] = 0;
corner[1] = 0;
corner[2] = 0;
connectedThresFilter->SetInput(blurredImage);
connectedThresFilter->SetSeed(corner);
connectedThresFilter->SetLower(0);
connectedThresFilter->SetUpper(0);
connectedThresFilter->SetReplaceValue(2);
connectedThresFilter->ReleaseDataFlagOn();
connectedThresFilter->ReleaseDataBeforeUpdateFlagOn();
typedef itk::BinaryThresholdImageFilter<CharImageType, CharImageType> BinaryThresholdFilterType;
BinaryThresholdFilterType::Pointer binThresFilter = BinaryThresholdFilterType::New();
binThresFilter->SetInput(connectedThresFilter->GetOutput());
binThresFilter->SetLowerThreshold(0);
binThresFilter->SetUpperThreshold(0);
binThresFilter->SetInsideValue(50);
binThresFilter->SetOutsideValue(0);
binThresFilter->ReleaseDataFlagOn();
binThresFilter->ReleaseDataBeforeUpdateFlagOn();
typedef itk::AddImageFilter<CharImageType, CharImageType, CharImageType> AddFilterType;
AddFilterType::Pointer addFilter = AddFilterType::New();
addFilter->SetInput1(blurredImage);
addFilter->SetInput2(binThresFilter->GetOutput());
addFilter->ReleaseDataFlagOn();
addFilter->ReleaseDataBeforeUpdateFlagOn();
addFilter->Update();
ProgressBar::GetInstance()->Progress(1);
// Surface extraction
MITK_INFO << "Surface extraction..." << endl;
Image::Pointer filteredImage = Image::New();
CastToMitkImage(addFilter->GetOutput(), filteredImage);
filteredImage->SetGeometry(geometry);
ImageToSurfaceFilter::Pointer imageToSurfaceFilter = ImageToSurfaceFilter::New();
imageToSurfaceFilter->SetInput(filteredImage);
imageToSurfaceFilter->SetThreshold(50);
imageToSurfaceFilter->SmoothOn();
imageToSurfaceFilter->SetDecimate(ImageToSurfaceFilter::NoDecimation);
m_Surface = imageToSurfaceFilter->GetOutput();
ProgressBar::GetInstance()->Progress(1);
// Mesh decimation
if (decimation > 0.0f && decimation < 1.0f)
{
MITK_INFO << "Quadric mesh decimation..." << endl;
vtkQuadricDecimation *quadricDecimation = vtkQuadricDecimation::New();
quadricDecimation->SetInput(m_Surface->GetVtkPolyData());
quadricDecimation->SetTargetReduction(decimation);
quadricDecimation->AttributeErrorMetricOn();
quadricDecimation->Update();
vtkCleanPolyData* cleaner = vtkCleanPolyData::New();
cleaner->SetInput(quadricDecimation->GetOutput());
cleaner->PieceInvariantOn();
cleaner->ConvertLinesToPointsOn();
cleaner->ConvertStripsToPolysOn();
cleaner->PointMergingOn();
cleaner->Update();
m_Surface->SetVtkPolyData(cleaner->GetOutput());
}
ProgressBar::GetInstance()->Progress(1);
// Compute Normals
vtkPolyDataNormals* computeNormals = vtkPolyDataNormals::New();
computeNormals->SetInput(m_Surface->GetVtkPolyData());
computeNormals->SetFeatureAngle(360.0f);
computeNormals->FlipNormalsOff();
computeNormals->Update();
m_Surface->SetVtkPolyData(computeNormals->GetOutput());
return true;
}
void ShowSegmentationAsSmoothedSurface::ThreadedUpdateSuccessful()
{
DataNode::Pointer node = LookForPointerTargetBelowGroupNode("Surface representation");
bool addToTree = node.IsNull();
if (addToTree)
{
node = DataNode::New();
bool wireframe = false;
GetParameter("Wireframe", wireframe);
if (wireframe)
{
VtkRepresentationProperty *representation = dynamic_cast<VtkRepresentationProperty *>(
node->GetProperty("material.representation"));
if (representation != NULL)
representation->SetRepresentationToWireframe();
}
node->SetProperty("opacity", FloatProperty::New(0.3));
node->SetProperty("line width", IntProperty::New(1));
node->SetProperty("scalar visibility", BoolProperty::New(false));
UIDGenerator uidGenerator("Surface_");
node->SetProperty("FILENAME", StringProperty::New(uidGenerator.GetUID() + ".vtk"));
std::string groupNodeName = "surface";
DataNode *groupNode = GetGroupNode();
if (groupNode != NULL)
groupNode->GetName(groupNodeName);
node->SetProperty("name", StringProperty::New(groupNodeName));
}
node->SetData(m_Surface);
if (addToTree)
{
DataNode* groupNode = GetGroupNode();
if (groupNode != NULL)
{
groupNode->SetProperty("Surface representation", SmartPointerProperty::New(node));
BaseProperty *colorProperty = groupNode->GetProperty("color");
if (colorProperty != NULL)
node->ReplaceProperty("color", colorProperty);
else
node->SetProperty("color", ColorProperty::New(1.0f, 1.0f, 0.0f));
bool showResult = true;
GetParameter("Show result", showResult);
bool syncVisibility = false;
GetParameter("Sync visibility", syncVisibility);
Image::Pointer image;
GetPointerParameter("Input", image);
BaseProperty *organTypeProperty = image->GetProperty("organ type");
if (organTypeProperty != NULL)
m_Surface->SetProperty("organ type", organTypeProperty);
BaseProperty *visibleProperty = groupNode->GetProperty("visible");
if (visibleProperty != NULL && syncVisibility)
node->ReplaceProperty("visible", visibleProperty);
else
node->SetProperty("visible", BoolProperty::New(showResult));
}
InsertBelowGroupNode(node);
}
- StatusBar::GetInstance()->Clear();
-
Superclass::ThreadedUpdateSuccessful();
}
diff --git a/Modules/MitkExt/Controllers/mitkToolManager.cpp b/Modules/MitkExt/Controllers/mitkToolManager.cpp
index 67b277ae68..b4aee92a31 100644
--- a/Modules/MitkExt/Controllers/mitkToolManager.cpp
+++ b/Modules/MitkExt/Controllers/mitkToolManager.cpp
@@ -1,493 +1,496 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "mitkToolManager.h"
#include "mitkGlobalInteraction.h"
#include "mitkCoreObjectFactory.h"
#include <itkObjectFactoryBase.h>
#include <itkCommand.h>
#include <list>
mitk::ToolManager::ToolManager(DataStorage* storage)
:m_ActiveTool(NULL),
m_ActiveToolID(-1),
m_RegisteredClients(0),
m_DataStorage(storage)
{
CoreObjectFactory::GetInstance(); // to make sure a CoreObjectFactory was instantiated (and in turn, possible tools are registered) - bug 1029
// get a list of all known mitk::Tools
std::list<itk::LightObject::Pointer> thingsThatClaimToBeATool = itk::ObjectFactoryBase::CreateAllInstance("mitkTool");
// remember these tools
for ( std::list<itk::LightObject::Pointer>::iterator iter = thingsThatClaimToBeATool.begin();
iter != thingsThatClaimToBeATool.end();
++iter )
{
if ( Tool* tool = dynamic_cast<Tool*>( iter->GetPointer() ) )
{
tool->SetToolManager(this); // important to call right after instantiation
tool->ErrorMessage += MessageDelegate1<mitk::ToolManager, std::string>( this, &ToolManager::OnToolErrorMessage );
tool->GeneralMessage += MessageDelegate1<mitk::ToolManager, std::string>( this, &ToolManager::OnGeneralToolMessage );
m_Tools.push_back( tool );
}
}
//ActivateTool(0); // first one is default
}
mitk::ToolManager::~ToolManager()
{
+ for (DataVectorType::iterator dataIter = m_WorkingData.begin(); dataIter != m_WorkingData.end(); ++dataIter)
+ (*dataIter)->RemoveObserver(m_WorkingDataObserverTags[(*dataIter)]);
+
if (m_ActiveTool)
{
m_ActiveTool->Deactivated();
GlobalInteraction::GetInstance()->RemoveListener( m_ActiveTool );
m_ActiveTool = NULL;
m_ActiveToolID = -1; // no tool active
ActiveToolChanged.Send();
}
for ( NodeTagMapType::iterator observerTagMapIter = m_ReferenceDataObserverTags.begin(); observerTagMapIter != m_ReferenceDataObserverTags.end(); ++observerTagMapIter )
{
observerTagMapIter->first->RemoveObserver( observerTagMapIter->second );
}
}
void mitk::ToolManager::OnToolErrorMessage(std::string s)
{
this->ToolErrorMessage(s);
}
void mitk::ToolManager::OnGeneralToolMessage(std::string s)
{
this->GeneralToolMessage(s);
}
const mitk::ToolManager::ToolVectorTypeConst mitk::ToolManager::GetTools()
{
ToolVectorTypeConst resultList;
for ( ToolVectorType::iterator iter = m_Tools.begin();
iter != m_Tools.end();
++iter )
{
resultList.push_back( iter->GetPointer() );
}
return resultList;
}
mitk::Tool* mitk::ToolManager::GetToolById(int id)
{
try
{
return m_Tools.at(id);
}
catch(std::exception&)
{
return NULL;
}
}
bool mitk::ToolManager::ActivateTool(int id)
{
//MITK_INFO << "ToolManager::ActivateTool("<<id<<")"<<std::endl;
//if( GetToolById(id) == NULL ) return false; // NO, invalid IDs are actually used here. Parameter -1 or anything that does not exists will deactivate all tools!
if ( GetToolById( id ) == m_ActiveTool ) return true; // no change needed
static int nextTool = -1;
nextTool = id;
//MITK_INFO << "ToolManager::ActivateTool("<<id<<"): nextTool = "<<nextTool<<std::endl;
static bool inActivateTool = false;
if (inActivateTool)
{
//MITK_INFO << "ToolManager::ActivateTool("<<id<<"): already inside ActivateTool somehow, returning now "<<std::endl;
return true;
}
inActivateTool = true;
while ( nextTool != m_ActiveToolID )
{
//MITK_INFO <<"ToolManager::ActivateTool: nextTool = " << nextTool << " (active tool = " << m_ActiveToolID<<")"<<std::endl;
if (m_ActiveTool)
{
m_ActiveTool->Deactivated();
GlobalInteraction::GetInstance()->RemoveListener( m_ActiveTool );
}
m_ActiveTool = GetToolById( nextTool );
m_ActiveToolID = m_ActiveTool ? nextTool : -1; // current ID if tool is valid, otherwise -1
ActiveToolChanged.Send();
if (m_ActiveTool)
{
if (m_RegisteredClients > 0)
{
m_ActiveTool->Activated();
GlobalInteraction::GetInstance()->AddListener( m_ActiveTool );
}
}
}
inActivateTool = false;
return (m_ActiveTool != NULL);
}
void mitk::ToolManager::SetReferenceData(DataVectorType data)
{
if (data != m_ReferenceData)
{
// remove observers from old nodes
for ( DataVectorType::iterator dataIter = m_ReferenceData.begin(); dataIter != m_ReferenceData.end(); ++dataIter )
{
NodeTagMapType::iterator searchIter = m_ReferenceDataObserverTags.find( *dataIter );
if ( searchIter != m_ReferenceDataObserverTags.end() )
{
//MITK_INFO << "Stopping observation of " << (void*)(*dataIter) << std::endl;
(*dataIter)->RemoveObserver( searchIter->second );
}
}
m_ReferenceData = data;
// TODO tell active tool?
// attach new observers
m_ReferenceDataObserverTags.clear();
for ( DataVectorType::iterator dataIter = m_ReferenceData.begin(); dataIter != m_ReferenceData.end(); ++dataIter )
{
//MITK_INFO << "Observing " << (void*)(*dataIter) << std::endl;
itk::MemberCommand<ToolManager>::Pointer command = itk::MemberCommand<ToolManager>::New();
command->SetCallbackFunction( this, &ToolManager::OnOneOfTheReferenceDataDeleted );
command->SetCallbackFunction( this, &ToolManager::OnOneOfTheReferenceDataDeletedConst );
m_ReferenceDataObserverTags.insert( std::pair<DataNode*, unsigned long>( (*dataIter), (*dataIter)->AddObserver( itk::DeleteEvent(), command ) ) );
}
ReferenceDataChanged.Send();
}
}
void mitk::ToolManager::OnOneOfTheReferenceDataDeletedConst(const itk::Object* caller, const itk::EventObject& e)
{
OnOneOfTheReferenceDataDeleted( const_cast<itk::Object*>(caller), e );
}
void mitk::ToolManager::OnOneOfTheReferenceDataDeleted(itk::Object* caller, const itk::EventObject& itkNotUsed(e))
{
//MITK_INFO << "Deleted: " << (void*)caller << " Removing from reference data list." << std::endl;
DataVectorType v;
for (DataVectorType::iterator dataIter = m_ReferenceData.begin(); dataIter != m_ReferenceData.end(); ++dataIter )
{
//MITK_INFO << " In list: " << (void*)(*dataIter);
if ( (void*)(*dataIter) != (void*)caller )
{
v.push_back( *dataIter );
//MITK_INFO << " kept" << std::endl;
}
else
{
//MITK_INFO << " removed" << std::endl;
m_ReferenceDataObserverTags.erase( *dataIter ); // no tag to remove anymore
}
}
this->SetReferenceData( v );
}
void mitk::ToolManager::SetReferenceData(DataNode* data)
{
//MITK_INFO << "ToolManager::SetReferenceData(" << (void*)data << ")" << std::endl;
DataVectorType v;
if (data)
{
v.push_back(data);
}
SetReferenceData(v);
}
void mitk::ToolManager::SetWorkingData(DataVectorType data)
{
if ( data != m_WorkingData )
{
// remove observers from old nodes
for ( DataVectorType::iterator dataIter = m_WorkingData.begin(); dataIter != m_WorkingData.end(); ++dataIter )
{
NodeTagMapType::iterator searchIter = m_WorkingDataObserverTags.find( *dataIter );
if ( searchIter != m_WorkingDataObserverTags.end() )
{
//MITK_INFO << "Stopping observation of " << (void*)(*dataIter) << std::endl;
(*dataIter)->RemoveObserver( searchIter->second );
}
}
m_WorkingData = data;
// TODO tell active tool?
// attach new observers
m_WorkingDataObserverTags.clear();
for ( DataVectorType::iterator dataIter = m_WorkingData.begin(); dataIter != m_WorkingData.end(); ++dataIter )
{
//MITK_INFO << "Observing " << (void*)(*dataIter) << std::endl;
itk::MemberCommand<ToolManager>::Pointer command = itk::MemberCommand<ToolManager>::New();
command->SetCallbackFunction( this, &ToolManager::OnOneOfTheWorkingDataDeleted );
command->SetCallbackFunction( this, &ToolManager::OnOneOfTheWorkingDataDeletedConst );
m_WorkingDataObserverTags.insert( std::pair<DataNode*, unsigned long>( (*dataIter), (*dataIter)->AddObserver( itk::DeleteEvent(), command ) ) );
}
WorkingDataChanged.Send();
}
}
void mitk::ToolManager::OnOneOfTheWorkingDataDeletedConst(const itk::Object* caller, const itk::EventObject& e)
{
OnOneOfTheWorkingDataDeleted( const_cast<itk::Object*>(caller), e );
}
void mitk::ToolManager::OnOneOfTheWorkingDataDeleted(itk::Object* caller, const itk::EventObject& itkNotUsed(e))
{
//MITK_INFO << "Deleted: " << (void*)caller << " Removing from reference data list." << std::endl;
DataVectorType v;
for (DataVectorType::iterator dataIter = m_WorkingData.begin(); dataIter != m_WorkingData.end(); ++dataIter )
{
//MITK_INFO << " In list: " << (void*)(*dataIter);
if ( (void*)(*dataIter) != (void*)caller )
{
v.push_back( *dataIter );
//MITK_INFO << " kept" << std::endl;
}
else
{
//MITK_INFO << " removed" << std::endl;
m_WorkingDataObserverTags.erase( *dataIter ); // no tag to remove anymore
}
}
this->SetWorkingData( v );
}
void mitk::ToolManager::SetWorkingData(DataNode* data)
{
DataVectorType v;
if (data) // don't allow for NULL nodes
{
v.push_back(data);
}
SetWorkingData(v);
}
void mitk::ToolManager::SetRoiData(DataVectorType data)
{
if (data != m_RoiData)
{
// remove observers from old nodes
for ( DataVectorType::iterator dataIter = m_RoiData.begin(); dataIter != m_RoiData.end(); ++dataIter )
{
NodeTagMapType::iterator searchIter = m_RoiDataObserverTags.find( *dataIter );
if ( searchIter != m_RoiDataObserverTags.end() )
{
//MITK_INFO << "Stopping observation of " << (void*)(*dataIter) << std::endl;
(*dataIter)->RemoveObserver( searchIter->second );
}
}
m_RoiData = data;
// TODO tell active tool?
// attach new observers
m_RoiDataObserverTags.clear();
for ( DataVectorType::iterator dataIter = m_RoiData.begin(); dataIter != m_RoiData.end(); ++dataIter )
{
//MITK_INFO << "Observing " << (void*)(*dataIter) << std::endl;
itk::MemberCommand<ToolManager>::Pointer command = itk::MemberCommand<ToolManager>::New();
command->SetCallbackFunction( this, &ToolManager::OnOneOfTheRoiDataDeleted );
command->SetCallbackFunction( this, &ToolManager::OnOneOfTheRoiDataDeletedConst );
m_RoiDataObserverTags.insert( std::pair<DataNode*, unsigned long>( (*dataIter), (*dataIter)->AddObserver( itk::DeleteEvent(), command ) ) );
}
RoiDataChanged.Send();
}
}
void mitk::ToolManager::SetRoiData(DataNode* data)
{
DataVectorType v;
if(data)
{
v.push_back(data);
}
this->SetRoiData(v);
}
void mitk::ToolManager::OnOneOfTheRoiDataDeletedConst(const itk::Object* caller, const itk::EventObject& e)
{
OnOneOfTheRoiDataDeleted( const_cast<itk::Object*>(caller), e );
}
void mitk::ToolManager::OnOneOfTheRoiDataDeleted(itk::Object* caller, const itk::EventObject& itkNotUsed(e))
{
//MITK_INFO << "Deleted: " << (void*)caller << " Removing from roi data list." << std::endl;
DataVectorType v;
for (DataVectorType::iterator dataIter = m_RoiData.begin(); dataIter != m_RoiData.end(); ++dataIter )
{
//MITK_INFO << " In list: " << (void*)(*dataIter);
if ( (void*)(*dataIter) != (void*)caller )
{
v.push_back( *dataIter );
//MITK_INFO << " kept" << std::endl;
}
else
{
//MITK_INFO << " removed" << std::endl;
m_RoiDataObserverTags.erase( *dataIter ); // no tag to remove anymore
}
}
this->SetRoiData( v );
}
mitk::ToolManager::DataVectorType mitk::ToolManager::GetReferenceData()
{
return m_ReferenceData;
}
mitk::DataNode* mitk::ToolManager::GetReferenceData(int idx)
{
try
{
return m_ReferenceData.at(idx);
}
catch(std::exception&)
{
return NULL;
}
}
mitk::ToolManager::DataVectorType mitk::ToolManager::GetWorkingData()
{
return m_WorkingData;
}
mitk::ToolManager::DataVectorType mitk::ToolManager::GetRoiData()
{
return m_RoiData;
}
mitk::DataNode* mitk::ToolManager::GetRoiData(int idx)
{
try
{
return m_RoiData.at(idx);
}
catch(std::exception&)
{
return NULL;
}
}
mitk::DataStorage* mitk::ToolManager::GetDataStorage()
{
if ( m_DataStorage.IsNotNull() )
{
return m_DataStorage;
}
else
{
return NULL;
}
}
void mitk::ToolManager::SetDataStorage(DataStorage& storage)
{
m_DataStorage = &storage;
}
mitk::DataNode* mitk::ToolManager::GetWorkingData(int idx)
{
try
{
return m_WorkingData.at(idx);
}
catch(std::exception&)
{
return NULL;
}
}
int mitk::ToolManager::GetActiveToolID()
{
return m_ActiveToolID;
}
mitk::Tool* mitk::ToolManager::GetActiveTool()
{
return m_ActiveTool;
}
void mitk::ToolManager::RegisterClient()
{
if ( m_RegisteredClients < 1 )
{
if ( m_ActiveTool )
{
m_ActiveTool->Activated();
GlobalInteraction::GetInstance()->AddListener( m_ActiveTool );
}
}
++m_RegisteredClients;
}
void mitk::ToolManager::UnregisterClient()
{
if ( m_RegisteredClients < 1) return;
--m_RegisteredClients;
if ( m_RegisteredClients < 1 )
{
if ( m_ActiveTool )
{
m_ActiveTool->Deactivated();
GlobalInteraction::GetInstance()->RemoveListener( m_ActiveTool );
}
}
}
int mitk::ToolManager::GetToolID( const Tool* tool )
{
int id(0);
for ( ToolVectorType::iterator iter = m_Tools.begin();
iter != m_Tools.end();
++iter, ++id )
{
if ( tool == iter->GetPointer() )
{
return id;
}
}
return -1;
}
diff --git a/Modules/MitkExt/Interactions/mitkBinaryThresholdTool.cpp b/Modules/MitkExt/Interactions/mitkBinaryThresholdTool.cpp
index 415e038983..d4d2a028e7 100644
--- a/Modules/MitkExt/Interactions/mitkBinaryThresholdTool.cpp
+++ b/Modules/MitkExt/Interactions/mitkBinaryThresholdTool.cpp
@@ -1,312 +1,336 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date$
Version: $Revision: 1.12 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "mitkBinaryThresholdTool.h"
#include "mitkBinaryThresholdTool.xpm"
#include "mitkToolManager.h"
#include "mitkBoundingObjectToSegmentationFilter.h"
#include <mitkCoreObjectFactory.h>
#include "mitkLevelWindowProperty.h"
#include "mitkColorProperty.h"
#include "mitkProperties.h"
#include "mitkOrganTypeProperty.h"
#include "mitkVtkResliceInterpolationProperty.h"
#include "mitkDataStorage.h"
#include "mitkRenderingManager.h"
#include "mitkImageCast.h"
#include "mitkImageAccessByItk.h"
#include "mitkImageTimeSelector.h"
#include <itkImageRegionIterator.h>
#include <itkBinaryThresholdImageFilter.h>
#include "mitkPadImageFilter.h"
#include "mitkMaskAndCutRoiImageFilter.h"
namespace mitk {
MITK_TOOL_MACRO(MitkExt_EXPORT, BinaryThresholdTool, "Thresholding tool");
}
mitk::BinaryThresholdTool::BinaryThresholdTool()
:m_SensibleMinimumThresholdValue(-100),
m_SensibleMaximumThresholdValue(+100),
-m_CurrentThresholdValue(1)
+m_CurrentThresholdValue(1),
+m_IsFloatImage(false)
{
this->SupportRoiOn();
m_ThresholdFeedbackNode = DataNode::New();
mitk::CoreObjectFactory::GetInstance()->SetDefaultProperties( m_ThresholdFeedbackNode );
m_ThresholdFeedbackNode->SetProperty( "color", ColorProperty::New(1.0, 0.0, 0.0) );
m_ThresholdFeedbackNode->SetProperty( "texture interpolation", BoolProperty::New(false) );
m_ThresholdFeedbackNode->SetProperty( "layer", IntProperty::New( 100 ) );
m_ThresholdFeedbackNode->SetProperty( "levelwindow", LevelWindowProperty::New( LevelWindow(100, 1) ) );
m_ThresholdFeedbackNode->SetProperty( "name", StringProperty::New("Thresholding feedback") );
m_ThresholdFeedbackNode->SetProperty( "opacity", FloatProperty::New(0.3) );
m_ThresholdFeedbackNode->SetProperty( "helper object", BoolProperty::New(true) );
}
mitk::BinaryThresholdTool::~BinaryThresholdTool()
{
}
const char** mitk::BinaryThresholdTool::GetXPM() const
{
return mitkBinaryThresholdTool_xpm;
}
const char* mitk::BinaryThresholdTool::GetName() const
{
return "Thresholding";
}
void mitk::BinaryThresholdTool::Activated()
{
m_ToolManager->RoiDataChanged += mitk::MessageDelegate<mitk::BinaryThresholdTool>(this, &mitk::BinaryThresholdTool::OnRoiDataChanged);
m_OriginalImageNode = m_ToolManager->GetReferenceData(0);
m_NodeForThresholding = m_OriginalImageNode;
if ( m_NodeForThresholding.IsNotNull() )
{
SetupPreviewNodeFor( m_NodeForThresholding );
}
else
{
m_ToolManager->ActivateTool(-1);
}
}
void mitk::BinaryThresholdTool::Deactivated()
{
m_ToolManager->RoiDataChanged -= mitk::MessageDelegate<mitk::BinaryThresholdTool>(this, &mitk::BinaryThresholdTool::OnRoiDataChanged);
m_NodeForThresholding = NULL;
m_OriginalImageNode = NULL;
try
{
if (DataStorage* storage = m_ToolManager->GetDataStorage())
{
storage->Remove( m_ThresholdFeedbackNode );
RenderingManager::GetInstance()->RequestUpdateAll();
}
}
catch(...)
{
// don't care
}
m_ThresholdFeedbackNode->SetData(NULL);
}
void mitk::BinaryThresholdTool::SetThresholdValue(int value)
{
if (m_ThresholdFeedbackNode.IsNotNull())
{
m_CurrentThresholdValue = value;
- m_ThresholdFeedbackNode->SetProperty( "levelwindow", LevelWindowProperty::New( LevelWindow(m_CurrentThresholdValue, 1) ) );
+
+ if (m_IsFloatImage)
+ m_ThresholdFeedbackNode->SetProperty( "levelwindow", LevelWindowProperty::New( LevelWindow(m_CurrentThresholdValue * 0.01f, 0.01f) ) );
+ else
+ m_ThresholdFeedbackNode->SetProperty( "levelwindow", LevelWindowProperty::New( LevelWindow(m_CurrentThresholdValue, 1) ) );
+
RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void mitk::BinaryThresholdTool::AcceptCurrentThresholdValue(const std::string& organName, const Color& color)
{
CreateNewSegmentationFromThreshold(m_NodeForThresholding, organName, color );
RenderingManager::GetInstance()->RequestUpdateAll();
m_ToolManager->ActivateTool(-1);
}
void mitk::BinaryThresholdTool::CancelThresholding()
{
m_ToolManager->ActivateTool(-1);
}
void mitk::BinaryThresholdTool::SetupPreviewNodeFor( DataNode* nodeForThresholding )
{
if (nodeForThresholding)
{
Image::Pointer image = dynamic_cast<Image*>( nodeForThresholding->GetData() );
Image::Pointer originalImage = dynamic_cast<Image*> (m_OriginalImageNode->GetData());
if (image.IsNotNull())
{
// initialize and a new node with the same image as our reference image
// use the level window property of this image copy to display the result of a thresholding operation
m_ThresholdFeedbackNode->SetData( image );
int layer(50);
nodeForThresholding->GetIntProperty("layer", layer);
m_ThresholdFeedbackNode->SetIntProperty("layer", layer+1);
if (DataStorage* storage = m_ToolManager->GetDataStorage())
{
if (storage->Exists(m_ThresholdFeedbackNode))
storage->Remove(m_ThresholdFeedbackNode);
storage->Add( m_ThresholdFeedbackNode, m_OriginalImageNode );
}
if (image.GetPointer() == originalImage.GetPointer())
{
- m_SensibleMinimumThresholdValue = static_cast<int>( originalImage->GetScalarValueMin() );
- m_SensibleMaximumThresholdValue = static_cast<int>( originalImage->GetScalarValueMax() );
+ if (originalImage->GetPixelType().GetType() == mitkIpPicFloat)
+ {
+ m_SensibleMinimumThresholdValue = static_cast<int>( originalImage->GetScalarValueMin() * 100.0f);
+ m_SensibleMaximumThresholdValue = static_cast<int>( originalImage->GetScalarValueMax() * 100.0f);
+ m_IsFloatImage = true;
+ }
+ else
+ {
+ m_SensibleMinimumThresholdValue = static_cast<int>( originalImage->GetScalarValueMin() );
+ m_SensibleMaximumThresholdValue = static_cast<int>( originalImage->GetScalarValueMax() );
+ m_IsFloatImage = false;
+ }
}
LevelWindowProperty::Pointer lwp = dynamic_cast<LevelWindowProperty*>( m_ThresholdFeedbackNode->GetProperty( "levelwindow" ));
if (lwp)
{
m_CurrentThresholdValue = static_cast<int>( lwp->GetLevelWindow().GetLevel() );
}
else
{
m_CurrentThresholdValue = (m_SensibleMaximumThresholdValue + m_SensibleMinimumThresholdValue)/2;
}
IntervalBordersChanged.Send(m_SensibleMinimumThresholdValue, m_SensibleMaximumThresholdValue);
ThresholdingValueChanged.Send(m_CurrentThresholdValue);
}
}
}
void mitk::BinaryThresholdTool::CreateNewSegmentationFromThreshold(DataNode* node, const std::string& organName, const Color& color)
{
if (node)
{
Image::Pointer image = dynamic_cast<Image*>( m_NodeForThresholding->GetData() );
if (image.IsNotNull())
{
// create a new image of the same dimensions and smallest possible pixel type
DataNode::Pointer emptySegmentation = Tool::CreateEmptySegmentationNode( image, organName, color );
if (emptySegmentation)
{
// actually perform a thresholding and ask for an organ type
for (unsigned int timeStep = 0; timeStep < image->GetTimeSteps(); ++timeStep)
{
try
{
ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New();
timeSelector->SetInput( image );
timeSelector->SetTimeNr( timeStep );
timeSelector->UpdateLargestPossibleRegion();
Image::Pointer image3D = timeSelector->GetOutput();
AccessFixedDimensionByItk_2( image3D, ITKThresholding, 3, dynamic_cast<Image*>(emptySegmentation->GetData()), timeStep );
}
catch(...)
{
Tool::ErrorMessage("Error accessing single time steps of the original image. Cannot create segmentation.");
}
}
if (m_OriginalImageNode.GetPointer() != m_NodeForThresholding.GetPointer())
{
mitk::PadImageFilter::Pointer padFilter = mitk::PadImageFilter::New();
padFilter->SetInput(0, dynamic_cast<mitk::Image*> (emptySegmentation->GetData()));
padFilter->SetInput(1, dynamic_cast<mitk::Image*> (m_OriginalImageNode->GetData()));
padFilter->SetBinaryFilter(true);
padFilter->SetUpperThreshold(1);
padFilter->SetLowerThreshold(1);
padFilter->Update();
emptySegmentation->SetData(padFilter->GetOutput());
}
if (DataStorage::Pointer storage = m_ToolManager->GetDataStorage())
{
storage->Add( emptySegmentation, m_OriginalImageNode ); // add as a child, because the segmentation "derives" from the original
}
m_ToolManager->SetWorkingData( emptySegmentation );
}
}
}
}
template <typename TPixel, unsigned int VImageDimension>
void mitk::BinaryThresholdTool::ITKThresholding( itk::Image<TPixel, VImageDimension>* originalImage, Image* segmentation, unsigned int timeStep )
{
ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New();
timeSelector->SetInput( segmentation );
timeSelector->SetTimeNr( timeStep );
timeSelector->UpdateLargestPossibleRegion();
Image::Pointer segmentation3D = timeSelector->GetOutput();
typedef itk::Image< Tool::DefaultSegmentationDataType, 3> SegmentationType; // this is sure for new segmentations
SegmentationType::Pointer itkSegmentation;
CastToItkImage( segmentation3D, itkSegmentation );
// iterate over original and segmentation
typedef itk::ImageRegionConstIterator< itk::Image<TPixel, VImageDimension> > InputIteratorType;
typedef itk::ImageRegionIterator< SegmentationType > SegmentationIteratorType;
InputIteratorType inputIterator( originalImage, originalImage->GetLargestPossibleRegion() );
SegmentationIteratorType outputIterator( itkSegmentation, itkSegmentation->GetLargestPossibleRegion() );
inputIterator.GoToBegin();
outputIterator.GoToBegin();
while (!outputIterator.IsAtEnd())
{
- if ( (signed)inputIterator.Get() >= m_CurrentThresholdValue )
+ if (m_IsFloatImage)
{
- outputIterator.Set( 1 );
+ float realThresholdValue = m_CurrentThresholdValue * 0.01f;
+
+ if (inputIterator.Get() >= realThresholdValue )
+ outputIterator.Set( 1 );
+ else
+ outputIterator.Set( 0 );
}
else
{
- outputIterator.Set( 0 );
+ if ( (signed)inputIterator.Get() >= m_CurrentThresholdValue )
+ outputIterator.Set( 1 );
+ else
+ outputIterator.Set( 0 );
}
++inputIterator;
++outputIterator;
}
}
void mitk::BinaryThresholdTool::OnRoiDataChanged()
{
mitk::DataNode::Pointer node = m_ToolManager->GetRoiData(0);
if (node.IsNotNull())
{
mitk::Image::Pointer image = dynamic_cast<mitk::Image*> (m_NodeForThresholding->GetData());
if (image.IsNull())
return;
mitk::MaskAndCutRoiImageFilter::Pointer roiFilter = mitk::MaskAndCutRoiImageFilter::New();
roiFilter->SetInput(image);
roiFilter->SetRegionOfInterest(node->GetData());
roiFilter->Update();
mitk::DataNode::Pointer tmpNode = mitk::DataNode::New();
mitk::Image::Pointer tmpImage = roiFilter->GetOutput();
tmpNode->SetData(tmpImage);
m_SensibleMaximumThresholdValue = static_cast<int> (roiFilter->GetMaxValue());
m_SensibleMinimumThresholdValue = static_cast<int> (roiFilter->GetMinValue());
SetupPreviewNodeFor( tmpNode );
m_NodeForThresholding = tmpNode;
return;
}
else
{
this->SetupPreviewNodeFor(m_OriginalImageNode);
m_NodeForThresholding = m_OriginalImageNode;
return;
}
}
diff --git a/Modules/MitkExt/Interactions/mitkBinaryThresholdTool.h b/Modules/MitkExt/Interactions/mitkBinaryThresholdTool.h
index a9f21155a4..54351bd655 100644
--- a/Modules/MitkExt/Interactions/mitkBinaryThresholdTool.h
+++ b/Modules/MitkExt/Interactions/mitkBinaryThresholdTool.h
@@ -1,88 +1,89 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date$
Version: $Revision: 1.0 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef mitkBinaryThresholdTool_h_Included
#define mitkBinaryThresholdTool_h_Included
#include "mitkCommon.h"
#include "MitkExtExports.h"
#include "mitkAutoSegmentationTool.h"
#include "mitkDataNode.h"
#include <itkImage.h>
namespace mitk
{
/**
\brief Calculates the segmented volumes for binary images.
\ingroup ToolManagerEtAl
\sa mitk::Tool
\sa QmitkInteractiveSegmentation
Last contributor: $Author$
*/
class MitkExt_EXPORT BinaryThresholdTool : public AutoSegmentationTool
{
public:
Message2<int,int> IntervalBordersChanged;
Message1<int> ThresholdingValueChanged;
mitkClassMacro(BinaryThresholdTool, AutoSegmentationTool);
itkNewMacro(BinaryThresholdTool);
virtual const char** GetXPM() const;
virtual const char* GetName() const;
virtual void Activated();
virtual void Deactivated();
virtual void SetThresholdValue(int value);
virtual void AcceptCurrentThresholdValue(const std::string& organName, const Color& color);
virtual void CancelThresholding();
protected:
BinaryThresholdTool(); // purposely hidden
virtual ~BinaryThresholdTool();
void SetupPreviewNodeFor( DataNode* nodeForThresholding );
void CreateNewSegmentationFromThreshold(DataNode* node, const std::string& organType, const Color& color);
void OnRoiDataChanged();
template <typename TPixel, unsigned int VImageDimension>
void ITKThresholding( itk::Image<TPixel, VImageDimension>* originalImage, mitk::Image* segmentation, unsigned int timeStep );
DataNode::Pointer m_ThresholdFeedbackNode;
DataNode::Pointer m_OriginalImageNode;
DataNode::Pointer m_NodeForThresholding;
int m_SensibleMinimumThresholdValue;
int m_SensibleMaximumThresholdValue;
int m_CurrentThresholdValue;
+ bool m_IsFloatImage;
};
} // namespace
#endif
diff --git a/Modules/MitkExt/Interactions/mitkSurfaceDeformationInteractor3D.cpp b/Modules/MitkExt/Interactions/mitkSurfaceDeformationInteractor3D.cpp
index 03bc4a1e65..a53a19c7f9 100644
--- a/Modules/MitkExt/Interactions/mitkSurfaceDeformationInteractor3D.cpp
+++ b/Modules/MitkExt/Interactions/mitkSurfaceDeformationInteractor3D.cpp
@@ -1,499 +1,498 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date: 2008-10-02 16:21:08 +0200 (Do, 02 Okt 2008) $
Version: $Revision: 13129 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "mitkSurfaceDeformationInteractor3D.h"
#include "mitkPointOperation.h"
#include "mitkDisplayPositionEvent.h"
#include "mitkWheelEvent.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"
#include "mitkSurface.h"
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyle.h>
#include <vtkPolyData.h>
#include <vtkPointData.h>
#include <vtkDataArray.h>
#include <vtkPointData.h>
#include <vtkDataArray.h>
//how precise must the user pick the point
//default value
mitk::SurfaceDeformationInteractor3D
::SurfaceDeformationInteractor3D(const char * type, DataNode* dataNode, int /* n */ )
: Interactor( type, dataNode ),
m_Precision( 6.5 ),
m_PickedSurfaceNode( NULL ),
m_PickedSurface( NULL ),
m_GaussSigma( 30.0 )
{
m_OriginalPolyData = vtkPolyData::New();
// Initialize vector arithmetic
m_ObjectNormal[0] = 0.0;
m_ObjectNormal[1] = 0.0;
m_ObjectNormal[2] = 1.0;
}
mitk::SurfaceDeformationInteractor3D::~SurfaceDeformationInteractor3D()
{
m_OriginalPolyData->Delete();
}
void mitk::SurfaceDeformationInteractor3D::SetPrecision( mitk::ScalarType precision )
{
m_Precision = precision;
}
// Overwritten since this class can handle it better!
float mitk::SurfaceDeformationInteractor3D
::CanHandleEvent(StateEvent const* stateEvent) const
{
float returnValue = 0.5;
// If it is a key event that can be handled in the current state,
// then return 0.5
mitk::DisplayPositionEvent const *disPosEvent =
dynamic_cast <const mitk::DisplayPositionEvent *> (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;
}
else
{
return 0.0;
}
}
//on MouseMove do nothing!
//if (stateEvent->GetEvent()->GetType() == mitk::Type_MouseMove)
//{
// return 0.0;
//}
//if the event can be understood and if there is a transition waiting for that event
if (this->GetCurrentState()->GetTransition(stateEvent->GetId())!=NULL)
{
returnValue = 0.5;//it can be understood
}
//int timeStep = disPosEvent->GetSender()->GetTimeStep();
//mitk::CurveModel *curveModel = dynamic_cast<mitk::CurveModel *>(
// m_DataNode->GetData() );
//if ( curveModel != NULL )
//{
// // Get the Geometry2D of the window the user interacts with (for 2D point
// // projection)
// mitk::BaseRenderer *renderer = stateEvent->GetEvent()->GetSender();
// const Geometry2D *projectionPlane = renderer->GetCurrentWorldGeometry2D();
// // For reading on the points, Ids etc
// //mitk::CurveModel::PointSetType *pointSet = curveModel->GetPointSet( timeStep );
// //if ( pointSet == NULL )
// //{
// // return 0.0;
// //}
//}
return returnValue;
}
bool mitk::SurfaceDeformationInteractor3D
::ExecuteAction( Action *action, mitk::StateEvent const *stateEvent )
{
bool ok = false;
// Get data object
mitk::BaseData *data = m_DataNode->GetData();
if ( data == NULL )
{
MITK_ERROR << "No data object present!";
return ok;
}
// Get mitk::Event and extract renderer
const mitk::Event *event = stateEvent->GetEvent();
mitk::BaseRenderer *renderer = NULL;
vtkRenderWindow *renderWindow = NULL;
vtkRenderWindowInteractor *renderWindowInteractor = NULL;
if ( event != NULL )
{
renderer = event->GetSender();
if ( renderer != NULL )
{
renderWindow = renderer->GetRenderWindow();
if ( renderWindow != NULL )
{
renderWindowInteractor = renderWindow->GetInteractor();
}
}
}
// Check if we have a DisplayPositionEvent
const mitk::DisplayPositionEvent *dpe =
dynamic_cast< const mitk::DisplayPositionEvent * >( stateEvent->GetEvent() );
if ( dpe != NULL )
{
m_PickedSurfaceNode = dpe->GetPickedObjectNode();
m_CurrentPickedPoint = dpe->GetWorldPosition();
m_CurrentPickedDisplayPoint = dpe->GetDisplayPosition();
}
// Get the timestep to also support 3D+t
int timeStep = 0;
mitk::ScalarType timeInMS = 0.0;
if ( renderer != NULL )
{
timeStep = renderer->GetTimeStep( data );
timeInMS = renderer->GetTime();
}
// Extract surface
m_Surface = dynamic_cast< Surface * >( data );
if ( m_Surface != NULL )
{
m_PolyData = m_Surface->GetVtkPolyData( timeStep );
}
else
{
m_PolyData = NULL;
}
// Extract surface normal from surface (if existent, otherwise use default)
vtkPointData *pointData = m_PolyData->GetPointData();
if ( pointData != NULL )
{
vtkDataArray *normal = m_PolyData->GetPointData()->GetVectors( "planeNormal" );
if ( normal != NULL )
{
m_ObjectNormal[0] = normal->GetComponent( 0, 0 );
m_ObjectNormal[1] = normal->GetComponent( 0, 1 );
m_ObjectNormal[2] = normal->GetComponent( 0, 2 );
}
}
// Get geometry object
m_Geometry = data->GetGeometry( timeStep );
// Make sure that the data (if time-resolved) has enough entries;
// if not, create the required extra ones (empty)
data->Expand( timeStep+1 );
switch (action->GetActionId())
{
case AcDONOTHING:
ok = true;
break;
case AcCHECKOBJECT:
{
// Check if an object is present at the current mouse position
m_PickedSurface = NULL;
m_PickedPolyData = NULL;
if ( m_PickedSurfaceNode != NULL )
{
m_PickedSurface = dynamic_cast< mitk::Surface * >( m_PickedSurfaceNode->GetData() );
if ( m_PickedSurface != NULL )
{
m_PickedPolyData = m_PickedSurface->GetVtkPolyData( timeStep );
}
}
mitk::StateEvent *newStateEvent;
if ( (m_PickedSurfaceNode == m_DataNode) && (m_PickedSurface != NULL) )
{
// Yes: object will be selected
newStateEvent = new mitk::StateEvent( EIDYES );
// Disable VTK interactor until MITK interaction has been completed
if ( renderWindowInteractor != NULL )
{
renderWindowInteractor->Disable();
}
}
else
{
// No: back to start state
newStateEvent = new mitk::StateEvent( EIDNO );
// Re-enable VTK interactor (may have been disabled previously)
if ( renderWindowInteractor != NULL )
{
renderWindowInteractor->Enable();
}
}
this->HandleEvent( newStateEvent );
// Colorized surface at current picked position
m_SurfaceColorizationCenter = m_CurrentPickedPoint;
ok = true;
break;
}
case AcDESELECTOBJECT:
{
// Color object white
m_DataNode->SetColor( 1.0, 1.0, 1.0 );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
// Colorize surface / wireframe as inactive
this->ColorizeSurface( m_PolyData,
m_SurfaceColorizationCenter, COLORIZATION_CONSTANT, -1.0 );
ok = true;
break;
}
case AcSELECTPICKEDOBJECT:
{
// Color object red
m_DataNode->SetColor( 1.0, 0.0, 0.0 );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
// Colorize surface / wireframe dependend on distance from picked point
this->ColorizeSurface( m_PolyData,
m_SurfaceColorizationCenter, COLORIZATION_GAUSS );
ok = true;
break;
}
case AcINITMOVE:
{
// Store current picked point
m_InitialPickedPoint = m_CurrentPickedPoint;
m_InitialPickedDisplayPoint = m_CurrentPickedDisplayPoint;
if ( renderWindowInteractor != NULL )
{
vtkInteractorObserver::ComputeDisplayToWorld(
renderWindowInteractor->GetInteractorStyle()->GetCurrentRenderer(),
m_InitialPickedDisplayPoint[0],
m_InitialPickedDisplayPoint[1],
0.0, //m_InitialInteractionPickedPoint[2],
m_InitialPickedPointWorld );
}
// Make deep copy of vtkPolyData interacted on
m_OriginalPolyData->DeepCopy( m_PolyData );
ok = true;
break;
}
case AcMOVE:
{
if ( renderWindowInteractor != NULL )
{
vtkInteractorObserver::ComputeDisplayToWorld(
renderWindowInteractor->GetInteractorStyle()->GetCurrentRenderer(),
m_CurrentPickedDisplayPoint[0],
m_CurrentPickedDisplayPoint[1],
0.0, //m_InitialInteractionPickedPoint[2],
m_CurrentPickedPointWorld );
}
// Calculate mouse move in 3D space
mitk::Vector3D interactionMove;
interactionMove[0] = m_CurrentPickedPointWorld[0] - m_InitialPickedPointWorld[0];
interactionMove[1] = m_CurrentPickedPointWorld[1] - m_InitialPickedPointWorld[1];
interactionMove[2] = m_CurrentPickedPointWorld[2] - m_InitialPickedPointWorld[2];
// Transform mouse move into geometry space
data->UpdateOutputInformation(); // make sure that the Geometry is up-to-date
mitk::Point3D origin; origin.Fill( 0.0 );
m_Geometry->WorldToIndex( interactionMove, interactionMove );
// Get picked point and transform into local coordinates
mitk::Point3D pickedPoint;
m_Geometry->WorldToIndex( m_InitialPickedPoint, pickedPoint );
mitk::Vector3D v1 = pickedPoint.GetVectorFromOrigin();
mitk::Vector3D v2 = m_ObjectNormal * (interactionMove * m_ObjectNormal);
vtkPoints *originalPoints = m_OriginalPolyData->GetPoints();
vtkPoints *deformedPoints = m_PolyData->GetPoints();
double denom = m_GaussSigma * m_GaussSigma * 2;
double point[3];
for ( unsigned int i = 0; i < deformedPoints->GetNumberOfPoints(); ++i )
{
// Get original point
vtkFloatingPointType *originalPoint = originalPoints->GetPoint( i );
mitk::Vector3D v0;
v0[0] = originalPoint[0];
v0[1] = originalPoint[1];
v0[2] = originalPoint[2];
// Calculate distance of this point from line through picked point
double d = itk::CrossProduct( m_ObjectNormal, (v1 - v0) ).GetNorm();
mitk::Vector3D t = v2 * exp( - d * d / denom );
point[0] = originalPoint[0] + t[0];
point[1] = originalPoint[1] + t[1];
point[2] = originalPoint[2] + t[2];
deformedPoints->SetPoint( i, point );
}
// Make sure that surface is colorized at initial picked position
// as long as we are in deformation state
m_SurfaceColorizationCenter = m_InitialPickedPoint;
m_PolyData->Modified();
m_Surface->Modified();
- mitk::RenderingManager::GetInstance()->RequestUpdateAll(
- mitk::RenderingManager::REQUEST_UPDATE_3DWINDOWS );
+ mitk::RenderingManager::GetInstance()->RequestUpdateAll();
ok = false;
break;
}
case AcMODIFY:
{
// Check if we have an mitk::WheelEvent
const mitk::WheelEvent *we =
dynamic_cast< const mitk::WheelEvent * >( stateEvent->GetEvent() );
if ( we == NULL )
{
ok = true;
break;
}
m_GaussSigma += (double) (we->GetDelta()) / 20;;
if ( m_GaussSigma < 10.0 )
{
m_GaussSigma = 10.0;
}
else if ( m_GaussSigma > 128.0 )
{
m_GaussSigma = 128.0;
}
// Colorize surface / wireframe dependend on sigma and distance from picked point
this->ColorizeSurface( m_PolyData,
m_SurfaceColorizationCenter, COLORIZATION_GAUSS );
mitk::RenderingManager::GetInstance()->RequestUpdateAll(
mitk::RenderingManager::REQUEST_UPDATE_3DWINDOWS );
ok = true;
break;
}
default:
return Superclass::ExecuteAction( action, stateEvent );
}
return ok;
}
bool mitk::SurfaceDeformationInteractor3D::ColorizeSurface( vtkPolyData *polyData,
const Point3D &pickedPoint, int mode, double scalar )
{
if ( polyData == NULL )
{
return false;
}
vtkPoints *points = polyData->GetPoints();
vtkPointData *pointData = polyData->GetPointData();
if ( pointData == NULL )
{
return false;
}
vtkDataArray *scalars = pointData->GetScalars();
if ( scalars == NULL )
{
return false;
}
if ( mode == COLORIZATION_GAUSS )
{
// Get picked point and transform into local coordinates
mitk::Point3D localPickedPoint;
m_Geometry->WorldToIndex( pickedPoint, localPickedPoint );
mitk::Vector3D v1 = localPickedPoint.GetVectorFromOrigin();
double denom = m_GaussSigma * m_GaussSigma * 2;
for ( unsigned int i = 0; i < points->GetNumberOfPoints(); ++i )
{
// Get original point
vtkFloatingPointType *point = points->GetPoint( i );
mitk::Vector3D v0;
v0[0] = point[0];
v0[1] = point[1];
v0[2] = point[2];
// Calculate distance of this point from line through picked point
double d = itk::CrossProduct( m_ObjectNormal, (v1 - v0) ).GetNorm();
double t = exp( - d * d / denom );
scalars->SetComponent( i, 0, t );
}
}
else if ( mode == COLORIZATION_CONSTANT )
{
for ( unsigned int i = 0; i < pointData->GetNumberOfTuples(); ++i )
{
scalars->SetComponent( i, 0, scalar );
}
}
polyData->Modified();
pointData->Update();
return true;
}
diff --git a/Modules/PlanarFigure/Interactions/mitkPlanarFigureInteractor.cpp b/Modules/PlanarFigure/Interactions/mitkPlanarFigureInteractor.cpp
index 8d39e62d1d..55e7a909e5 100644
--- a/Modules/PlanarFigure/Interactions/mitkPlanarFigureInteractor.cpp
+++ b/Modules/PlanarFigure/Interactions/mitkPlanarFigureInteractor.cpp
@@ -1,935 +1,932 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date: 2008-10-02 16:21:08 +0200 (Do, 02 Okt 2008) $
Version: $Revision: 13129 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "mitkPlanarFigureInteractor.h"
#include "mitkPointOperation.h"
#include "mitkPositionEvent.h"
#include "mitkPlanarFigure.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"
#include "mitkNodePredicateDataType.h"
#include "mitkNodePredicateOr.h"
//how precise must the user pick the point
//default value
mitk::PlanarFigureInteractor
::PlanarFigureInteractor(const char * type, DataNode* dataNode, int /* n */ )
: Interactor( type, dataNode ),
m_Precision( 6.5 ),
-m_IsHovering( false )
+m_IsHovering( false ),
+m_LastPointWasValid( false )
{
}
mitk::PlanarFigureInteractor::~PlanarFigureInteractor()
{
}
void mitk::PlanarFigureInteractor::SetPrecision( mitk::ScalarType precision )
{
m_Precision = precision;
}
// Overwritten since this class can handle it better!
float mitk::PlanarFigureInteractor
::CanHandleEvent(StateEvent const* stateEvent) const
{
float returnValue = 0.5;
// If it is a key event that can be handled in the current state,
// then return 0.5
mitk::DisplayPositionEvent const *disPosEvent =
dynamic_cast <const mitk::DisplayPositionEvent *> (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;
}
else
{
return 0.0;
}
}
mitk::PlanarFigure *planarFigure = dynamic_cast<mitk::PlanarFigure *>(
m_DataNode->GetData() );
if ( planarFigure != NULL )
{
// Give higher priority if this figure is currently selected
if ( planarFigure->GetSelectedControlPoint() >= 0 )
{
return 1.0;
}
}
return returnValue;
}
bool mitk::PlanarFigureInteractor
::ExecuteAction( Action *action, mitk::StateEvent const *stateEvent )
{
bool ok = false;
// Check corresponding data; has to be sub-class of mitk::PlanarFigure
mitk::PlanarFigure *planarFigure =
dynamic_cast< mitk::PlanarFigure * >( m_DataNode->GetData() );
if ( planarFigure == NULL )
{
return false;
}
// Get the timestep to also support 3D+t
const mitk::Event *theEvent = stateEvent->GetEvent();
int timeStep = 0;
mitk::ScalarType timeInMS = 0.0;
if ( theEvent )
{
if (theEvent->GetSender() != NULL)
{
timeStep = theEvent->GetSender()->GetTimeStep( planarFigure );
timeInMS = theEvent->GetSender()->GetTime();
}
}
// Get Geometry2D of PlanarFigure
mitk::Geometry2D *planarFigureGeometry =
dynamic_cast< mitk::Geometry2D * >( planarFigure->GetGeometry( timeStep ) );
// Get the Geometry2D of the window the user interacts with (for 2D point
// projection)
mitk::BaseRenderer *renderer = NULL;
const Geometry2D *projectionPlane = NULL;
if ( theEvent )
{
renderer = theEvent->GetSender();
projectionPlane = renderer->GetCurrentWorldGeometry2D();
}
// TODO: Check if display and PlanarFigure geometries are parallel (if they are PlaneGeometries)
switch (action->GetActionId())
{
case AcDONOTHING:
ok = true;
break;
case AcCHECKOBJECT:
{
if ( planarFigure->IsPlaced() )
{
this->HandleEvent( new mitk::StateEvent( EIDYES, NULL ) );
}
else
{
this->HandleEvent( new mitk::StateEvent( EIDNO, NULL ) );
}
ok = false;
break;
}
case AcADD:
{
// Invoke event to notify listeners that placement of this PF starts now
planarFigure->InvokeEvent( StartPlacementPlanarFigureEvent() );
// Use Geometry2D of the renderer clicked on for this PlanarFigure
mitk::PlaneGeometry *planeGeometry = const_cast< mitk::PlaneGeometry * >(
dynamic_cast< const mitk::PlaneGeometry * >(
renderer->GetSliceNavigationController()->GetCurrentPlaneGeometry() ) );
if ( planeGeometry != NULL )
{
planarFigureGeometry = planeGeometry;
planarFigure->SetGeometry2D( planeGeometry );
}
else
{
ok = false;
break;
}
// Extract point in 2D world coordinates (relative to Geometry2D of
// PlanarFigure)
Point2D point2D;
if ( !this->TransformPositionEventToPoint2D( stateEvent, point2D,
planarFigureGeometry ) )
{
ok = false;
break;
}
// Place PlanarFigure at this point
planarFigure->PlaceFigure( point2D );
// Re-evaluate features
planarFigure->EvaluateFeatures();
//this->LogPrintPlanarFigureQuantities( planarFigure );
// Set a bool property indicating that the figure has been placed in
// the current RenderWindow. This is required so that the same render
// window can be re-aligned to the Geometry2D of the PlanarFigure later
// on in an application.
m_DataNode->SetBoolProperty( "PlanarFigureInitializedWindow", true, renderer );
// Update rendered scene
renderer->GetRenderingManager()->RequestUpdateAll();
ok = true;
break;
}
case AcMOVEPOINT:
{
bool isEditable = true;
m_DataNode->GetBoolProperty( "planarfigure.iseditable", isEditable );
// Extract point in 2D world coordinates (relative to Geometry2D of
// PlanarFigure)
Point2D point2D;
if ( !this->TransformPositionEventToPoint2D( stateEvent, point2D,
planarFigureGeometry ) || !isEditable )
{
ok = false;
break;
}
// Move current control point to this point
planarFigure->SetCurrentControlPoint( point2D );
// Re-evaluate features
planarFigure->EvaluateFeatures();
//this->LogPrintPlanarFigureQuantities( planarFigure );
// Update rendered scene
renderer->GetRenderingManager()->RequestUpdateAll();
ok = true;
break;
}
case AcCHECKNMINUS1:
{
if ( planarFigure->GetNumberOfControlPoints() >=
planarFigure->GetMaximumNumberOfControlPoints() )
{
// Initial placement finished: deselect control point and send an
// event to notify application listeners
planarFigure->Modified();
planarFigure->DeselectControlPoint();
planarFigure->InvokeEvent( EndPlacementPlanarFigureEvent() );
planarFigure->InvokeEvent( EndInteractionPlanarFigureEvent() );
planarFigure->SetProperty( "initiallyplaced", mitk::BoolProperty::New( true ) );
m_DataNode->Modified();
this->HandleEvent( new mitk::StateEvent( EIDYES, stateEvent->GetEvent() ) );
}
else
{
this->HandleEvent( new mitk::StateEvent( EIDNO, stateEvent->GetEvent() ) );
}
// Update rendered scene
renderer->GetRenderingManager()->RequestUpdateAll();
ok = true;
break;
}
case AcCHECKEQUALS1:
{
// NOTE: Action name is a bit misleading; this action checks whether
// the figure has already the minimum number of required points to
// be finished (by double-click)
const mitk::PositionEvent *positionEvent =
dynamic_cast< const mitk::PositionEvent * > ( stateEvent->GetEvent() );
if ( positionEvent == NULL )
{
ok = false;
break;
}
- if ( planarFigure->GetNumberOfControlPoints() >= planarFigure->GetMinimumNumberOfControlPoints() )
+ if ( m_LastPointWasValid && planarFigure->GetNumberOfControlPoints() > planarFigure->GetMinimumNumberOfControlPoints() )
{
// Initial placement finished: deselect control point and send an
// event to notify application listeners
planarFigure->Modified();
planarFigure->DeselectControlPoint();
- if ( planarFigure->GetNumberOfControlPoints()-1 >= planarFigure->GetMinimumNumberOfControlPoints() )
- {
- planarFigure->RemoveLastControlPoint();
- }
+ planarFigure->RemoveLastControlPoint();
planarFigure->InvokeEvent( EndPlacementPlanarFigureEvent() );
planarFigure->InvokeEvent( EndInteractionPlanarFigureEvent() );
planarFigure->SetProperty( "initiallyplaced", mitk::BoolProperty::New( true ) );
m_DataNode->Modified();
this->HandleEvent( new mitk::StateEvent( EIDYES, NULL ) );
}
else
{
this->HandleEvent( new mitk::StateEvent( EIDNO, NULL ) );
}
// Update rendered scene
renderer->GetRenderingManager()->RequestUpdateAll();
ok = true;
break;
}
case AcCHECKPOINT:
{
// Check if the distance of the current point to the previously set point in display coordinates
// is sufficient (if a previous point exists)
// Extract display position
const mitk::PositionEvent *positionEvent =
dynamic_cast< const mitk::PositionEvent * > ( stateEvent->GetEvent() );
if ( positionEvent == NULL )
{
ok = false;
break;
}
- bool tooClose = !IsMousePositionAcceptableAsNewControlPoint( positionEvent, planarFigure );
-
- if (tooClose)
+ m_LastPointWasValid = IsMousePositionAcceptableAsNewControlPoint( positionEvent, planarFigure );
+ if (m_LastPointWasValid)
{
- this->HandleEvent( new mitk::StateEvent( EIDNO, stateEvent->GetEvent() ) );
+ this->HandleEvent( new mitk::StateEvent( EIDYES, stateEvent->GetEvent() ) );
}
else
{
- this->HandleEvent( new mitk::StateEvent( EIDYES, stateEvent->GetEvent() ) );
+ this->HandleEvent( new mitk::StateEvent( EIDNO, stateEvent->GetEvent() ) );
}
ok = true;
break;
}
case AcADDPOINT:
{
bool selected = false;
bool isEditable = true;
m_DataNode->GetBoolProperty("selected", selected);
m_DataNode->GetBoolProperty( "planarfigure.iseditable", isEditable );
if ( !selected || !isEditable )
{
ok = false;
break;
}
// Extract point in 2D world coordinates (relative to Geometry2D of
// PlanarFigure)
Point2D point2D, projectedPoint;
if ( !this->TransformPositionEventToPoint2D( stateEvent, point2D,
planarFigureGeometry ) )
{
ok = false;
break;
}
// TODO: check segement of polyline we clicked in
int nextIndex = this->IsPositionOverFigure(
stateEvent, planarFigure,
planarFigureGeometry,
projectionPlane,
renderer->GetDisplayGeometry(),
projectedPoint
);
// Add point as new control point
renderer->GetDisplayGeometry()->DisplayToWorld( projectedPoint, projectedPoint );
if ( planarFigure->IsPreviewControlPointVisible() )
{
point2D = planarFigure->GetPreviewControlPoint();
}
planarFigure->AddControlPoint( point2D, nextIndex );
if ( planarFigure->IsPreviewControlPointVisible() )
{
planarFigure->SelectControlPoint( nextIndex );
planarFigure->ResetPreviewContolPoint();
}
// Re-evaluate features
planarFigure->EvaluateFeatures();
//this->LogPrintPlanarFigureQuantities( planarFigure );
// Update rendered scene
renderer->GetRenderingManager()->RequestUpdateAll();
ok = true;
break;
}
case AcDESELECTPOINT:
{
planarFigure->DeselectControlPoint();
// Issue event so that listeners may update themselves
planarFigure->Modified();
planarFigure->InvokeEvent( EndInteractionPlanarFigureEvent() );
m_DataNode->Modified();
// falls through
}
case AcCHECKHOVERING:
{
mitk::Point2D pointProjectedOntoLine;
int previousControlPoint = mitk::PlanarFigureInteractor::IsPositionOverFigure(
stateEvent, planarFigure,
planarFigureGeometry,
projectionPlane,
renderer->GetDisplayGeometry(),
pointProjectedOntoLine
);
bool isHovering = ( previousControlPoint != -1 );
int pointIndex = mitk::PlanarFigureInteractor::IsPositionInsideMarker(
stateEvent, planarFigure,
planarFigureGeometry,
projectionPlane,
renderer->GetDisplayGeometry() );
int initiallySelectedControlPoint = planarFigure->GetSelectedControlPoint();
if ( pointIndex >= 0 )
{
// If mouse is above control point, mark it as selected
planarFigure->SelectControlPoint( pointIndex );
// If mouse is hovering above a marker, it is also hovering above the figure
isHovering = true;
}
else
{
// Mouse in not above control point --> deselect point
planarFigure->DeselectControlPoint();
}
bool renderingUpdateNeeded = true;
if ( isHovering )
{
if ( !m_IsHovering )
{
// Invoke hover event once when the mouse is entering the figure area
m_IsHovering = true;
planarFigure->InvokeEvent( StartHoverPlanarFigureEvent() );
// Set bool property to indicate that planar figure is currently in "hovering" mode
m_DataNode->SetBoolProperty( "planarfigure.ishovering", true );
renderingUpdateNeeded = true;
}
bool selected = false;
bool isExtendable = false;
bool isEditable = true;
m_DataNode->GetBoolProperty("selected", selected);
m_DataNode->GetBoolProperty("planarfigure.isextendable", isExtendable);
m_DataNode->GetBoolProperty( "planarfigure.iseditable", isEditable );
if ( selected && isHovering && isExtendable && pointIndex == -1 && isEditable )
{
const mitk::PositionEvent *positionEvent =
dynamic_cast< const mitk::PositionEvent * > ( stateEvent->GetEvent() );
if ( positionEvent != NULL )
{
renderer->GetDisplayGeometry()->DisplayToWorld( pointProjectedOntoLine, pointProjectedOntoLine );
planarFigure->SetPreviewControlPoint( pointProjectedOntoLine );
renderingUpdateNeeded = true;
}
}
else
{
planarFigure->ResetPreviewContolPoint();
}
if ( planarFigure->GetSelectedControlPoint() != initiallySelectedControlPoint )
{
// the selected control point has changed -> rendering update necessary
renderingUpdateNeeded = true;
}
this->HandleEvent( new mitk::StateEvent( EIDYES, stateEvent->GetEvent() ) );
// Return true: only this interactor is eligible to react on this event
ok = true;
}
else
{
if ( m_IsHovering )
{
planarFigure->ResetPreviewContolPoint();
// Invoke end-hover event once the mouse is exiting the figure area
m_IsHovering = false;
planarFigure->InvokeEvent( EndHoverPlanarFigureEvent() );
// Set bool property to indicate that planar figure is no longer in "hovering" mode
m_DataNode->SetBoolProperty( "planarfigure.ishovering", false );
renderingUpdateNeeded = true;
}
this->HandleEvent( new mitk::StateEvent( EIDNO, NULL ) );
// Return false so that other (PlanarFigure) Interactors may react on this
// event as well
ok = false;
}
// Update rendered scene if necessray
if ( renderingUpdateNeeded )
{
renderer->GetRenderingManager()->RequestUpdateAll();
}
break;
}
case AcCHECKSELECTED:
{
bool selected = false;
m_DataNode->GetBoolProperty("selected", selected);
if ( selected )
{
this->HandleEvent( new mitk::StateEvent( EIDYES, stateEvent->GetEvent() ) );
}
else
{
// Invoke event to notify listeners that this planar figure should be selected
planarFigure->InvokeEvent( SelectPlanarFigureEvent() );
this->HandleEvent( new mitk::StateEvent( EIDNO, NULL ) );
}
}
case AcSELECTPICKEDOBJECT:
{
//// Invoke event to notify listeners that this planar figure should be selected
//planarFigure->InvokeEvent( SelectPlanarFigureEvent() );
// Check if planar figure is marked as "editable"
bool isEditable = true;
m_DataNode->GetBoolProperty( "planarfigure.iseditable", isEditable );
int pointIndex = -1;
if ( isEditable )
{
// If planar figure is editable, check if mouse is over a control point
pointIndex = mitk::PlanarFigureInteractor::IsPositionInsideMarker(
stateEvent, planarFigure,
planarFigureGeometry,
projectionPlane,
renderer->GetDisplayGeometry() );
}
// If editing is enabled and the mouse is currently over a control point, select it
if ( pointIndex >= 0 )
{
this->HandleEvent( new mitk::StateEvent( EIDYES, stateEvent->GetEvent() ) );
// Return true: only this interactor is eligible to react on this event
ok = true;
}
else
{
this->HandleEvent( new mitk::StateEvent( EIDNO, stateEvent->GetEvent() ) );
// Return false so that other (PlanarFigure) Interactors may react on this
// event as well
ok = false;
}
ok = true;
break;
}
case AcSELECTPOINT:
{
// Invoke event to notify listeners that interaction with this PF starts now
planarFigure->InvokeEvent( StartInteractionPlanarFigureEvent() );
// Reset the PlanarFigure if required
if ( planarFigure->ResetOnPointSelect() )
{
this->HandleEvent( new mitk::StateEvent( EIDYES, stateEvent->GetEvent() ) );
}
else
{
this->HandleEvent( new mitk::StateEvent( EIDNO, stateEvent->GetEvent() ) );
}
ok = true;
break;
}
case AcREMOVEPOINT:
{
bool isExtendable = false;
m_DataNode->GetBoolProperty("planarfigure.isextendable", isExtendable);
if ( isExtendable )
{
int selectedControlPoint = planarFigure->GetSelectedControlPoint();
planarFigure->RemoveControlPoint( selectedControlPoint );
// Re-evaluate features
planarFigure->EvaluateFeatures();
planarFigure->Modified();
planarFigure->InvokeEvent( EndInteractionPlanarFigureEvent() );
renderer->GetRenderingManager()->RequestUpdateAll();
this->HandleEvent( new mitk::StateEvent( EIDYES, NULL ) );
}
else
{
this->HandleEvent( new mitk::StateEvent( EIDNO, NULL ) );
}
}
//case AcMOVEPOINT:
//case AcMOVESELECTED:
// {
// // Update the display
// renderer->GetRenderingManager()->RequestUpdateAll();
// ok = true;
// break;
// }
//case AcFINISHMOVE:
// {
// ok = true;
// break;
// }
default:
return Superclass::ExecuteAction( action, stateEvent );
}
return ok;
}
bool mitk::PlanarFigureInteractor::TransformPositionEventToPoint2D(
const StateEvent *stateEvent, Point2D &point2D,
const Geometry2D *planarFigureGeometry )
{
// Extract world position, and from this position on geometry, if
// available
const mitk::PositionEvent *positionEvent =
dynamic_cast< const mitk::PositionEvent * > ( stateEvent->GetEvent() );
if ( positionEvent == NULL )
{
return false;
}
mitk::Point3D worldPoint3D = positionEvent->GetWorldPosition();
// TODO: proper handling of distance tolerance
if ( planarFigureGeometry->Distance( worldPoint3D ) > 0.1 )
{
return false;
}
// Project point onto plane of this PlanarFigure
planarFigureGeometry->Map( worldPoint3D, point2D );
return true;
}
bool mitk::PlanarFigureInteractor::TransformObjectToDisplay(
const mitk::Point2D &point2D,
mitk::Point2D &displayPoint,
const mitk::Geometry2D *objectGeometry,
const mitk::Geometry2D *rendererGeometry,
const mitk::DisplayGeometry *displayGeometry ) const
{
mitk::Point3D point3D;
// Map circle point from local 2D geometry into 3D world space
objectGeometry->Map( point2D, point3D );
// TODO: proper handling of distance tolerance
if ( displayGeometry->Distance( point3D ) < 0.1 )
{
// Project 3D world point onto display geometry
rendererGeometry->Map( point3D, displayPoint );
displayGeometry->WorldToDisplay( displayPoint, displayPoint );
return true;
}
return false;
}
bool mitk::PlanarFigureInteractor::IsPointNearLine(
const mitk::Point2D& point,
const mitk::Point2D& startPoint,
const mitk::Point2D& endPoint,
mitk::Point2D& projectedPoint
) const
{
mitk::Vector2D n1 = endPoint - startPoint;
n1.Normalize();
// Determine dot products between line vector and startpoint-point / endpoint-point vectors
double l1 = n1 * (point - startPoint);
double l2 = -n1 * (point - endPoint);
// Determine projection of specified point onto line defined by start / end point
mitk::Point2D crossPoint = startPoint + n1 * l1;
projectedPoint = crossPoint;
// Point is inside encompassing rectangle IF
// - its distance to its projected point is small enough
// - it is not further outside of the line than the defined tolerance
if ( (crossPoint.SquaredEuclideanDistanceTo( point ) < 20.0 )
&& ( l1 > 0.0 ) && ( l2 > 0.0 )
|| endPoint.SquaredEuclideanDistanceTo( point ) < 20.0
|| startPoint.SquaredEuclideanDistanceTo( point ) < 20.0 )
{
return true;
}
return false;
}
int mitk::PlanarFigureInteractor::IsPositionOverFigure(
const StateEvent *stateEvent, PlanarFigure *planarFigure,
const Geometry2D *planarFigureGeometry,
const Geometry2D *rendererGeometry,
const DisplayGeometry *displayGeometry,
Point2D& pointProjectedOntoLine ) const
{
// Extract display position
const mitk::PositionEvent *positionEvent =
dynamic_cast< const mitk::PositionEvent * > ( stateEvent->GetEvent() );
if ( positionEvent == NULL )
{
return -1;
}
mitk::Point2D displayPosition = positionEvent->GetDisplayPosition();
// Iterate over all polylines of planar figure, and check if
// any one is close to the current display position
typedef mitk::PlanarFigure::PolyLineType VertexContainerType;
mitk::Point2D worldPoint2D, displayControlPoint;
mitk::Point3D worldPoint3D;
int previousControlPoint = -1;
for ( unsigned short loop = 0; loop < planarFigure->GetPolyLinesSize(); ++loop )
{
const VertexContainerType polyLine = planarFigure->GetPolyLine( loop );
Point2D polyLinePoint;
Point2D firstPolyLinePoint;
Point2D previousPolyLinePoint;
bool firstPoint = true;
for ( VertexContainerType::const_iterator it = polyLine.begin(); it != polyLine.end(); ++it )
{
// Get plane coordinates of this point of polyline (if possible)
if ( !this->TransformObjectToDisplay( it->Point, polyLinePoint,
planarFigureGeometry, rendererGeometry, displayGeometry ) )
{
break; // Poly line invalid (not on current 2D plane) --> skip it
}
if ( firstPoint )
{
firstPolyLinePoint = polyLinePoint;
firstPoint = false;
}
else if ( this->IsPointNearLine( displayPosition, previousPolyLinePoint, polyLinePoint, pointProjectedOntoLine ) )
{
// Point is close enough to line segment --> Return index of the segment
return it->Index;
}
previousPolyLinePoint = polyLinePoint;
}
// For closed figures, also check last line segment
if ( planarFigure->IsClosed()
&& this->IsPointNearLine( displayPosition, polyLinePoint, firstPolyLinePoint, pointProjectedOntoLine ) )
{
return 0; // Return index of first control point
}
}
return -1;
}
int mitk::PlanarFigureInteractor::IsPositionInsideMarker(
const StateEvent *stateEvent, const PlanarFigure *planarFigure,
const Geometry2D *planarFigureGeometry,
const Geometry2D *rendererGeometry,
const DisplayGeometry *displayGeometry ) const
{
// Extract display position
const mitk::PositionEvent *positionEvent =
dynamic_cast< const mitk::PositionEvent * > ( stateEvent->GetEvent() );
if ( positionEvent == NULL )
{
return -1;
}
mitk::Point2D displayPosition = positionEvent->GetDisplayPosition();
// Iterate over all control points of planar figure, and check if
// any one is close to the current display position
mitk::Point2D worldPoint2D, displayControlPoint;
mitk::Point3D worldPoint3D;
int numberOfControlPoints = planarFigure->GetNumberOfControlPoints();
for ( int i=0; i<numberOfControlPoints; i++ )
{
Point2D displayControlPoint;
if ( this->TransformObjectToDisplay( planarFigure->GetControlPoint(i), displayControlPoint,
planarFigureGeometry, rendererGeometry, displayGeometry ) )
{
// TODO: variable size of markers
if ( displayPosition.SquaredEuclideanDistanceTo( displayControlPoint ) < 20.0 )
{
return i;
}
}
}
//for ( it = controlPoints.begin(); it != controlPoints.end(); ++it )
//{
// Point2D displayControlPoint;
// if ( this->TransformObjectToDisplay( it->Point, displayControlPoint,
// planarFigureGeometry, rendererGeometry, displayGeometry ) )
// {
// // TODO: variable size of markers
// if ( (abs(displayPosition[0] - displayControlPoint[0]) < 4 )
// && (abs(displayPosition[1] - displayControlPoint[1]) < 4 ) )
// {
// return index;
// }
// }
//}
return -1;
}
void mitk::PlanarFigureInteractor::LogPrintPlanarFigureQuantities(
const PlanarFigure *planarFigure )
{
MITK_INFO << "PlanarFigure: " << planarFigure->GetNameOfClass();
for ( unsigned int i = 0; i < planarFigure->GetNumberOfFeatures(); ++i )
{
MITK_INFO << "* " << planarFigure->GetFeatureName( i ) << ": "
<< planarFigure->GetQuantity( i ) << " " << planarFigure->GetFeatureUnit( i );
}
}
bool
mitk::PlanarFigureInteractor::IsMousePositionAcceptableAsNewControlPoint(
const PositionEvent* positionEvent,
const PlanarFigure* planarFigure )
{
assert(positionEvent && planarFigure);
BaseRenderer* renderer = positionEvent->GetSender();
assert(renderer);
// Get the timestep to support 3D+t
int timeStep( renderer->GetTimeStep( planarFigure ) );
// Get current display position of the mouse
Point2D currentDisplayPosition = positionEvent->GetDisplayPosition();
// Check if a previous point has been set
bool tooClose = false;
for( int i=0; i<planarFigure->GetNumberOfControlPoints(); i++ )
{
if ( i != planarFigure->GetSelectedControlPoint() )
{
// Try to convert previous point to current display coordinates
mitk::Geometry2D *planarFigureGeometry =
dynamic_cast< mitk::Geometry2D * >( planarFigure->GetGeometry( timeStep ) );
const Geometry2D *projectionPlane = renderer->GetCurrentWorldGeometry2D();
mitk::Point3D previousPoint3D;
planarFigureGeometry->Map( planarFigure->GetControlPoint( i ), previousPoint3D );
if ( renderer->GetDisplayGeometry()->Distance( previousPoint3D ) < 0.1 ) // ugly, but assert makes this work
{
mitk::Point2D previousDisplayPosition;
projectionPlane->Map( previousPoint3D, previousDisplayPosition );
renderer->GetDisplayGeometry()->WorldToDisplay( previousDisplayPosition, previousDisplayPosition );
double a = currentDisplayPosition[0] - previousDisplayPosition[0];
double b = currentDisplayPosition[1] - previousDisplayPosition[1];
// If point is to close, do not set a new point
tooClose = (a * a + b * b < 25.0);
}
if ( tooClose )
return false; // abort loop early
}
}
return !tooClose; // default
}
diff --git a/Modules/PlanarFigure/Interactions/mitkPlanarFigureInteractor.h b/Modules/PlanarFigure/Interactions/mitkPlanarFigureInteractor.h
index eba9581e2a..8357e62184 100644
--- a/Modules/PlanarFigure/Interactions/mitkPlanarFigureInteractor.h
+++ b/Modules/PlanarFigure/Interactions/mitkPlanarFigureInteractor.h
@@ -1,152 +1,154 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date: 2009-04-18 20:20:25 +0200 (Sa, 18 Apr 2009) $
Version: $Revision: 13129 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef MITKPLANARFIGUREINTERACTOR_H_HEADER_INCLUDED
#define MITKPLANARFIGUREINTERACTOR_H_HEADER_INCLUDED
#include "PlanarFigureExports.h"
#include "mitkCommon.h"
#include "mitkVector.h"
#include "mitkInteractor.h"
#include "mitkBaseRenderer.h"
#pragma GCC visibility push(default)
#include <itkEventObject.h>
#pragma GCC visibility pop
namespace mitk
{
class DataNode;
class Geometry2D;
class DisplayGeometry;
class PlanarFigure;
class PositionEvent;
#pragma GCC visibility push(default)
// Define events for PlanarFigure interaction notifications
itkEventMacro( PlanarFigureEvent, itk::AnyEvent );
itkEventMacro( StartPlacementPlanarFigureEvent, PlanarFigureEvent );
itkEventMacro( EndPlacementPlanarFigureEvent, PlanarFigureEvent );
itkEventMacro( SelectPlanarFigureEvent, PlanarFigureEvent );
itkEventMacro( StartInteractionPlanarFigureEvent, PlanarFigureEvent );
itkEventMacro( EndInteractionPlanarFigureEvent, PlanarFigureEvent );
itkEventMacro( StartHoverPlanarFigureEvent, PlanarFigureEvent );
itkEventMacro( EndHoverPlanarFigureEvent, PlanarFigureEvent );
#pragma GCC visibility pop
/**
* \brief Interaction with mitk::PlanarFigure objects via control-points
*
* \ingroup Interaction
*/
class PlanarFigure_EXPORT PlanarFigureInteractor : public Interactor
{
public:
mitkClassMacro(PlanarFigureInteractor, Interactor);
mitkNewMacro3Param(Self, const char *, DataNode *, int);
mitkNewMacro2Param(Self, const char *, DataNode *);
/** \brief Sets the amount of precision */
void SetPrecision( ScalarType precision );
/**
* \brief calculates how good the data, this statemachine handles, is hit
* by the event.
*
* overwritten, cause we don't look at the boundingbox, we look at each point
*/
virtual float CanHandleEvent(StateEvent const *stateEvent) const;
protected:
/**
* \brief Constructor with Param n for limited Set of Points
*
* if no n is set, then the number of points is unlimited*
*/
PlanarFigureInteractor(const char *type,
DataNode *dataNode, int n = -1);
/**
* \brief Default Destructor
**/
virtual ~PlanarFigureInteractor();
virtual bool ExecuteAction( Action *action,
mitk::StateEvent const *stateEvent );
/**
\brief Used when clicking to determine if a point is too close to the previous point.
*/
bool IsMousePositionAcceptableAsNewControlPoint( const PositionEvent*, const PlanarFigure* );
bool TransformPositionEventToPoint2D( const StateEvent *stateEvent,
Point2D &point2D,
const Geometry2D *planarFigureGeometry );
bool TransformObjectToDisplay( const mitk::Point2D &point2D,
mitk::Point2D &displayPoint,
const mitk::Geometry2D *objectGeometry,
const mitk::Geometry2D *rendererGeometry,
const mitk::DisplayGeometry *displayGeometry ) const;
/** \brief Returns true if the first specified point is in proximity of the line defined
* the other two point; false otherwise.
*
* Proximity is defined as the rectangle around the line with pre-defined distance
* from the line. */
bool IsPointNearLine( const mitk::Point2D& point,
const mitk::Point2D& startPoint, const mitk::Point2D& endPoint, mitk::Point2D& projectedPoint ) const;
/** \brief Returns true if the point contained in the passed event (in display coordinates)
* is over the planar figure (with a pre-defined tolerance range); false otherwise. */
int IsPositionOverFigure(
const StateEvent *StateEvent, PlanarFigure *planarFigure,
const Geometry2D *planarFigureGeometry,
const Geometry2D *rendererGeometry,
const DisplayGeometry *displayGeometry,
Point2D& pointProjectedOntoLine) const;
/** \brief Returns the index of the marker (control point) over which the point contained
* in the passed event (in display coordinates) currently is; -1 if the point is not over
* a marker. */
int IsPositionInsideMarker(
const StateEvent *StateEvent, const PlanarFigure *planarFigure,
const Geometry2D *planarFigureGeometry,
const Geometry2D *rendererGeometry,
const DisplayGeometry *displayGeometry ) const;
void LogPrintPlanarFigureQuantities( const PlanarFigure *planarFigure );
private:
/** \brief to store the value of precision to pick a point */
ScalarType m_Precision;
/** \brief True if the mouse is currently hovering over the image. */
bool m_IsHovering;
+
+ bool m_LastPointWasValid;
};
}
#endif // MITKPLANARFIGUREINTERACTOR_H_HEADER_INCLUDED
diff --git a/Modules/PlanarFigure/Rendering/mitkPlanarFigureMapper2D.cpp b/Modules/PlanarFigure/Rendering/mitkPlanarFigureMapper2D.cpp
index 410fa0bd05..cda930e2a5 100644
--- a/Modules/PlanarFigure/Rendering/mitkPlanarFigureMapper2D.cpp
+++ b/Modules/PlanarFigure/Rendering/mitkPlanarFigureMapper2D.cpp
@@ -1,675 +1,680 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date: 2009-04-23 13:50:34 +0200 (Do, 23 Apr 2009) $
Version: $Revision: 16947 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "mitkPlanarFigureMapper2D.h"
#include "mitkBaseRenderer.h"
#include "mitkPlaneGeometry.h"
#include "mitkColorProperty.h"
#include "mitkProperties.h"
#include "mitkGL.h"
#include "mitkVtkPropRenderer.h"
+// 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;
}
// Get PlanarFigure from input
mitk::PlanarFigure *planarFigure = const_cast< mitk::PlanarFigure * >(
static_cast< const mitk::PlanarFigure * >( this->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 );
// 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;
// draw name near the first point (if present)
std::string name = node->GetName();
if ( !name.empty() )
{
mitk::VtkPropRenderer* openGLrenderer = dynamic_cast<mitk::VtkPropRenderer*>( renderer );
if ( openGLrenderer )
{
if ( m_IsSelected || m_IsHovering )
{
openGLrenderer->WriteSimpleText( name,
firstPoint[0] + 6.0, firstPoint[1] + 4.0,
0,
0,
0); //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] );
}
// 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 << " / ";
}
quantityString << planarFigure->GetQuantity( i ) << " ";
quantityString << planarFigure->GetFeatureUnit( i );
firstActiveFeature = false;
}
}
mitk::VtkPropRenderer* openGLrenderer = dynamic_cast<mitk::VtkPropRenderer*>( renderer );
if ( openGLrenderer )
{
openGLrenderer->WriteSimpleText( quantityString.str().c_str(),
firstPoint[0] + 6.0, firstPoint[1] + 4.0 + annotationOffset,
0,
0,
0); //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] );
// 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 );
// 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;
}
}
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);
if ( closed )
{
glBegin( GL_LINE_LOOP );
}
else
{
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;
- glVertex2f( displayPoint[0], displayPoint[1] );
+ 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;
this->PaintPolyLine( polyline,
figure->IsClosed(),
shadow, 0.8, 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;
// paint shadow by painting the figure twice
// one in black with a slightly broader line-width ...
this->PaintPolyLine( helperPolyLine, false,
shadow, 0.8, 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;
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 );
- glVertex2f( displayPoint[0] - 4, displayPoint[1] - 4 );
- glVertex2f( displayPoint[0] - 4, displayPoint[1] + 4 );
- glVertex2f( displayPoint[0] + 4, displayPoint[1] + 4 );
- glVertex2f( displayPoint[0] + 4, displayPoint[1] - 4 );
+ 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 );
- glVertex2f(x,y);
+ 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 );
- glVertex2f(x,y);
+ 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_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;
}
node->GetBoolProperty( "selected", m_IsSelected );
node->GetBoolProperty( "planarfigure.ishovering", m_IsHovering );
node->GetBoolProperty( "planarfigure.drawoutline", m_DrawOutline );
node->GetBoolProperty( "planarfigure.drawquantities", m_DrawQuantities );
node->GetBoolProperty( "planarfigure.drawshadow", m_DrawShadow );
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();
}
node->GetColor( m_LineColor[PF_DEFAULT], NULL, "planarfigure.default.line.color" );
node->GetFloatProperty( "planarfigure.default.line.opacity", m_LineOpacity[PF_DEFAULT] );
node->GetColor( m_OutlineColor[PF_DEFAULT], NULL, "planarfigure.default.outline.color" );
node->GetFloatProperty( "planarfigure.default.outline.opacity", m_OutlineOpacity[PF_DEFAULT] );
node->GetColor( m_HelperlineColor[PF_DEFAULT], NULL, "planarfigure.default.helperline.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] );
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] );
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] );
}
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.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.color", mitk::ColorProperty::New(1.0,1.0,1.0) );
node->AddProperty( "planarfigure.default.line.opacity", mitk::FloatProperty::New(1.0) );
node->AddProperty( "planarfigure.default.outline.color", mitk::ColorProperty::New(1.0,1.0,1.0) );
node->AddProperty( "planarfigure.default.outline.opacity", mitk::FloatProperty::New(1.0) );
node->AddProperty( "planarfigure.default.helperline.color", mitk::ColorProperty::New(1.0,1.0,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/QmitkExt/QmitkBinaryThresholdToolGUI.cpp b/Modules/QmitkExt/QmitkBinaryThresholdToolGUI.cpp
index 1f928d3f46..03f74ba655 100644
--- a/Modules/QmitkExt/QmitkBinaryThresholdToolGUI.cpp
+++ b/Modules/QmitkExt/QmitkBinaryThresholdToolGUI.cpp
@@ -1,147 +1,148 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date$
Version: $Revision: 1.12 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "QmitkBinaryThresholdToolGUI.h"
#include "QmitkNewSegmentationDialog.h"
#include <qlabel.h>
#include <qslider.h>
#include <qpushbutton.h>
#include <qlayout.h>
MITK_TOOL_GUI_MACRO(QmitkExt_EXPORT, QmitkBinaryThresholdToolGUI, "")
QmitkBinaryThresholdToolGUI::QmitkBinaryThresholdToolGUI()
:QmitkToolGUI(),
m_Slider(NULL),
m_Spinner(NULL)
{
// create the visible widgets
QBoxLayout* mainLayout = new QVBoxLayout(this);
QLabel* label = new QLabel( "Threshold :", this );
QFont f = label->font();
f.setBold(false);
label->setFont( f );
mainLayout->addWidget(label);
QBoxLayout* layout = new QHBoxLayout();
m_Spinner = new QSpinBox();
m_Spinner->setMaximum(20);
m_Spinner->setMinimum(5);
m_Spinner->setValue(1);
connect(m_Spinner, SIGNAL(editingFinished()), this, SLOT(OnSpinnerValueChanged()) );
layout->addWidget(m_Spinner);
//m_Slider = new QSlider( 5, 20, 1, 1, Qt::Horizontal, this );
m_Slider = new QSlider( Qt::Horizontal, this );
m_Slider->setMinimum(5);
m_Slider->setMaximum(20);
m_Slider->setPageStep(1);
m_Slider->setValue(1);
connect( m_Slider, SIGNAL(valueChanged(int)), this, SLOT(OnSliderValueChanged(int)));
layout->addWidget( m_Slider );
QPushButton* okButton = new QPushButton("Ok", this);
connect( okButton, SIGNAL(clicked()), this, SLOT(OnAcceptThresholdPreview()));
okButton->setFont( f );
layout->addWidget( okButton );
mainLayout->addLayout(layout);
connect( this, SIGNAL(NewToolAssociated(mitk::Tool*)), this, SLOT(OnNewToolAssociated(mitk::Tool*)) );
}
QmitkBinaryThresholdToolGUI::~QmitkBinaryThresholdToolGUI()
{
// !!!
if (m_BinaryThresholdTool.IsNotNull())
{
m_BinaryThresholdTool->IntervalBordersChanged -= mitk::MessageDelegate2<QmitkBinaryThresholdToolGUI, int, int>( this, &QmitkBinaryThresholdToolGUI::OnThresholdingIntervalBordersChanged );
m_BinaryThresholdTool->ThresholdingValueChanged -= mitk::MessageDelegate1<QmitkBinaryThresholdToolGUI, int>( this, &QmitkBinaryThresholdToolGUI::OnThresholdingValueChanged );
}
}
void QmitkBinaryThresholdToolGUI::OnNewToolAssociated(mitk::Tool* tool)
{
if (m_BinaryThresholdTool.IsNotNull())
{
m_BinaryThresholdTool->IntervalBordersChanged -= mitk::MessageDelegate2<QmitkBinaryThresholdToolGUI, int, int>( this, &QmitkBinaryThresholdToolGUI::OnThresholdingIntervalBordersChanged );
m_BinaryThresholdTool->ThresholdingValueChanged -= mitk::MessageDelegate1<QmitkBinaryThresholdToolGUI, int>( this, &QmitkBinaryThresholdToolGUI::OnThresholdingValueChanged );
}
m_BinaryThresholdTool = dynamic_cast<mitk::BinaryThresholdTool*>( tool );
if (m_BinaryThresholdTool.IsNotNull())
{
m_BinaryThresholdTool->IntervalBordersChanged += mitk::MessageDelegate2<QmitkBinaryThresholdToolGUI, int, int>( this, &QmitkBinaryThresholdToolGUI::OnThresholdingIntervalBordersChanged );
m_BinaryThresholdTool->ThresholdingValueChanged += mitk::MessageDelegate1<QmitkBinaryThresholdToolGUI, int>( this, &QmitkBinaryThresholdToolGUI::OnThresholdingValueChanged );
}
}
void QmitkBinaryThresholdToolGUI::OnSliderValueChanged(int value)
{
if (m_BinaryThresholdTool.IsNotNull())
{
m_BinaryThresholdTool->SetThresholdValue( value );
}
m_Spinner->setValue(value);
}
+
void QmitkBinaryThresholdToolGUI::OnAcceptThresholdPreview()
{
if (m_BinaryThresholdTool.IsNotNull())
{
QmitkNewSegmentationDialog* dialog = new QmitkNewSegmentationDialog( this ); // needs a QWidget as parent, "this" is not QWidget
dialog->setPrompt("What did you just segment?");
int dialogReturnValue = dialog->exec();
std::string organName = dialog->GetSegmentationName().toStdString();
mitk::Color color = dialog->GetColor();
delete dialog;
if ( dialogReturnValue != QDialog::Rejected ) // user clicked cancel or pressed Esc or something similar
{
m_BinaryThresholdTool->AcceptCurrentThresholdValue( organName, color );
}
else
{
m_BinaryThresholdTool->CancelThresholding();
}
}
}
void QmitkBinaryThresholdToolGUI::OnThresholdingIntervalBordersChanged(int lower, int upper)
{
m_Slider->setRange(lower, upper);
m_Spinner->setRange(lower, upper);
}
void QmitkBinaryThresholdToolGUI::OnThresholdingValueChanged(int current)
{
m_Slider->setValue(current);
m_Spinner->setValue(current);
}
void QmitkBinaryThresholdToolGUI::OnSpinnerValueChanged()
{
m_Slider->setValue(m_Spinner->value());
}
diff --git a/Modules/QmitkExt/QmitkBinaryThresholdToolGUI.h b/Modules/QmitkExt/QmitkBinaryThresholdToolGUI.h
index f975cb5214..b59c56aca2 100644
--- a/Modules/QmitkExt/QmitkBinaryThresholdToolGUI.h
+++ b/Modules/QmitkExt/QmitkBinaryThresholdToolGUI.h
@@ -1,70 +1,72 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date$
Version: $Revision: 1.0 $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef QmitkBinaryThresholdToolGUI_h_Included
#define QmitkBinaryThresholdToolGUI_h_Included
#include "QmitkToolGUI.h"
#include "QmitkExtExports.h"
#include "mitkBinaryThresholdTool.h"
#include <QSpinBox>
class QSlider;
/**
\ingroup org_mitk_gui_qt_interactivesegmentation_internal
\brief GUI for mitk::BinaryThresholdTool.
This GUI shows a slider to change the tool's threshold and an OK button to accept a preview for actual thresholding.
Last contributor: $Author$
*/
class QmitkExt_EXPORT QmitkBinaryThresholdToolGUI : public QmitkToolGUI
{
Q_OBJECT
public:
mitkClassMacro(QmitkBinaryThresholdToolGUI, QmitkToolGUI);
itkNewMacro(QmitkBinaryThresholdToolGUI);
void OnThresholdingIntervalBordersChanged(int lower, int upper);
void OnThresholdingValueChanged(int current);
+ void OnThresholdingIntervalBordersChanged(double lower, double upper);
+ void OnThresholdingValueChanged(double current);
signals:
public slots:
protected slots:
void OnNewToolAssociated(mitk::Tool*);
void OnSliderValueChanged(int value);
void OnAcceptThresholdPreview();
void OnSpinnerValueChanged();
protected:
QmitkBinaryThresholdToolGUI();
virtual ~QmitkBinaryThresholdToolGUI();
QSlider* m_Slider;
QSpinBox* m_Spinner;
mitk::BinaryThresholdTool::Pointer m_BinaryThresholdTool;
};
#endif
diff --git a/Modules/ToFHardware/mitkToFCameraMESADevice.cpp b/Modules/ToFHardware/mitkToFCameraMESADevice.cpp
index b6fc0f4429..f98f6b35da 100644
--- a/Modules/ToFHardware/mitkToFCameraMESADevice.cpp
+++ b/Modules/ToFHardware/mitkToFCameraMESADevice.cpp
@@ -1,451 +1,448 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Module: $RCSfile$
Language: C++
Date: $Date: 2010-05-27 16:06:53 +0200 (Do, 27 Mai 2010) $
Version: $Revision: $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "mitkToFCameraMESADevice.h"
#include "mitkRealTimeClock.h"
#include "itkMultiThreader.h"
#include <itksys/SystemTools.hxx>
namespace mitk
{
ToFCameraMESADevice::ToFCameraMESADevice()
{
}
ToFCameraMESADevice::~ToFCameraMESADevice()
{
}
bool ToFCameraMESADevice::ConnectCamera()
{
bool ok = false;
if (m_Controller)
{
ok = m_Controller->OpenCameraConnection();
if (ok)
{
this->m_CaptureWidth = m_Controller->GetCaptureWidth();
this->m_CaptureHeight = m_Controller->GetCaptureHeight();
this->m_PixelNumber = this->m_CaptureWidth * this->m_CaptureHeight;
// allocate buffer
this->m_IntensityArray = new float[this->m_PixelNumber];
for(int i=0; i<this->m_PixelNumber; i++) {this->m_IntensityArray[i]=0.0;}
this->m_DistanceArray = new float[this->m_PixelNumber];
for(int i=0; i<this->m_PixelNumber; i++) {this->m_DistanceArray[i]=0.0;}
this->m_AmplitudeArray = new float[this->m_PixelNumber];
for(int i=0; i<this->m_PixelNumber; i++) {this->m_AmplitudeArray[i]=0.0;}
this->m_DistanceDataBuffer = new float*[this->m_MaxBufferSize];
for(int i=0; i<this->m_MaxBufferSize; i++)
{
this->m_DistanceDataBuffer[i] = new float[this->m_PixelNumber];
}
this->m_AmplitudeDataBuffer = new float*[this->m_MaxBufferSize];
for(int i=0; i<this->m_MaxBufferSize; i++)
{
this->m_AmplitudeDataBuffer[i] = new float[this->m_PixelNumber];
}
this->m_IntensityDataBuffer = new float*[this->m_MaxBufferSize];
for(int i=0; i<this->m_MaxBufferSize; i++)
{
this->m_IntensityDataBuffer[i] = new float[this->m_PixelNumber];
}
m_CameraConnected = true;
}
}
return ok;
}
bool ToFCameraMESADevice::DisconnectCamera()
{
bool ok = false;
if (m_Controller)
{
ok = m_Controller->CloseCameraConnection();
// clean-up only if camera was connected
if (m_CameraConnected)
{
delete [] m_IntensityArray;
delete [] m_DistanceArray;
delete [] m_AmplitudeArray;
for(int i=0; i<this->m_MaxBufferSize; i++)
{
delete[] this->m_DistanceDataBuffer[i];
}
delete[] this->m_DistanceDataBuffer;
for(int i=0; i<this->m_MaxBufferSize; i++)
{
delete[] this->m_AmplitudeDataBuffer[i];
}
delete[] this->m_AmplitudeDataBuffer;
for(int i=0; i<this->m_MaxBufferSize; i++)
{
delete[] this->m_IntensityDataBuffer[i];
}
delete[] this->m_IntensityDataBuffer;
m_CameraConnected = false;
}
}
return ok;
}
void ToFCameraMESADevice::StartCamera()
{
if (m_CameraConnected)
{
// get the first image
this->m_Controller->UpdateCamera();
this->m_ImageMutex->Lock();
this->m_Controller->GetDistances(this->m_DistanceDataBuffer[this->m_FreePos]);
this->m_Controller->GetAmplitudes(this->m_AmplitudeDataBuffer[this->m_FreePos]);
this->m_Controller->GetIntensities(this->m_IntensityDataBuffer[this->m_FreePos]);
this->m_FreePos = (this->m_FreePos+1) % this->m_BufferSize;
this->m_CurrentPos = (this->m_CurrentPos+1) % this->m_BufferSize;
this->m_ImageSequence++;
this->m_ImageMutex->Unlock();
this->m_CameraActiveMutex->Lock();
this->m_CameraActive = true;
this->m_CameraActiveMutex->Unlock();
this->m_ThreadID = this->m_MultiThreader->SpawnThread(this->Acquire, this);
// wait a little to make sure that the thread is started
itksys::SystemTools::Delay(10);
}
else
{
MITK_INFO<<"Camera not connected";
}
}
void ToFCameraMESADevice::StopCamera()
{
m_CameraActiveMutex->Lock();
m_CameraActive = false;
m_CameraActiveMutex->Unlock();
itksys::SystemTools::Delay(100);
if (m_MultiThreader.IsNotNull())
{
m_MultiThreader->TerminateThread(m_ThreadID);
}
// wait a little to make sure that the thread is terminated
itksys::SystemTools::Delay(10);
}
bool ToFCameraMESADevice::IsCameraActive()
{
m_CameraActiveMutex->Lock();
bool ok = m_CameraActive;
m_CameraActiveMutex->Unlock();
return ok;
}
void ToFCameraMESADevice::UpdateCamera()
{
if (m_Controller)
{
m_Controller->UpdateCamera();
}
}
ITK_THREAD_RETURN_TYPE ToFCameraMESADevice::Acquire(void* pInfoStruct)
{
/* extract this pointer from Thread Info structure */
struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct;
if (pInfo == NULL)
{
return ITK_THREAD_RETURN_VALUE;
}
if (pInfo->UserData == NULL)
{
return ITK_THREAD_RETURN_VALUE;
}
ToFCameraMESADevice* toFCameraDevice = (ToFCameraMESADevice*)pInfo->UserData;
if (toFCameraDevice!=NULL)
{
mitk::RealTimeClock::Pointer realTimeClock;
realTimeClock = mitk::RealTimeClock::New();
double t1, t2;
t1 = realTimeClock->GetCurrentStamp();
int n = 100;
bool overflow = false;
bool printStatus = false;
while (toFCameraDevice->IsCameraActive())
{
// update the ToF camera
toFCameraDevice->UpdateCamera();
// get the image data from the camera and write it at the next free position in the buffer
+ toFCameraDevice->m_ImageMutex->Lock();
toFCameraDevice->m_Controller->GetDistances(toFCameraDevice->m_DistanceDataBuffer[toFCameraDevice->m_FreePos]);
toFCameraDevice->m_Controller->GetAmplitudes(toFCameraDevice->m_AmplitudeDataBuffer[toFCameraDevice->m_FreePos]);
toFCameraDevice->m_Controller->GetIntensities(toFCameraDevice->m_IntensityDataBuffer[toFCameraDevice->m_FreePos]);
+ toFCameraDevice->m_ImageMutex->Unlock();
// call modified to indicate that cameraDevice was modified
toFCameraDevice->Modified();
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
TODO Buffer Handling currently only works for buffer size 1
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
- toFCameraDevice->m_ImageMutex->Lock();
//toFCameraDevice->m_ImageSequence++;
toFCameraDevice->m_FreePos = (toFCameraDevice->m_FreePos+1) % toFCameraDevice->m_BufferSize;
toFCameraDevice->m_CurrentPos = (toFCameraDevice->m_CurrentPos+1) % toFCameraDevice->m_BufferSize;
toFCameraDevice->m_ImageSequence++;
if (toFCameraDevice->m_FreePos == toFCameraDevice->m_CurrentPos)
{
// buffer overflow
//MITK_INFO << "Buffer overflow!! ";
//toFCameraDevice->m_CurrentPos = (toFCameraDevice->m_CurrentPos+1) % toFCameraDevice->m_BufferSize;
//toFCameraDevice->m_ImageSequence++;
overflow = true;
}
if (toFCameraDevice->m_ImageSequence % n == 0)
{
printStatus = true;
}
- toFCameraDevice->m_ImageMutex->Unlock();
if (overflow)
{
//itksys::SystemTools::Delay(10);
overflow = false;
}
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
END TODO Buffer Handling currently only works for buffer size 1
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
// print current framerate
if (printStatus)
{
t2 = realTimeClock->GetCurrentStamp() - t1;
//MITK_INFO << "t2: " << t2 <<" Time (s) for 1 image: " << (t2/1000) / n << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence;
MITK_INFO << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence;
t1 = realTimeClock->GetCurrentStamp();
printStatus = false;
}
} // end of while loop
}
return ITK_THREAD_RETURN_VALUE;
}
// TODO: Buffer size currently set to 1. Once Buffer handling is working correctly, method may be reactivated
// void ToFCameraMESADevice::ResetBuffer(int bufferSize)
// {
// this->m_BufferSize = bufferSize;
// this->m_CurrentPos = -1;
// this->m_FreePos = 0;
// }
void ToFCameraMESADevice::GetAmplitudes(float* amplitudeArray, int& imageSequence)
{
m_ImageMutex->Lock();
if (m_CameraActive)
{
// 1) copy the image buffer
// 2) Flip around y- axis (vertical axis)
/*
this->m_Controller->GetAmplitudes(this->m_SourceDataBuffer[this->m_CurrentPos], this->m_AmplitudeArray);
for (int i=0; i<this->m_CaptureHeight; i++)
{
for (int j=0; j<this->m_CaptureWidth; j++)
{
amplitudeArray[i*this->m_CaptureWidth+j] = this->m_AmplitudeArray[(i+1)*this->m_CaptureWidth-1-j];
}
}
*/
for (int i=0; i<this->m_PixelNumber; i++)
{
amplitudeArray[i] = this->m_AmplitudeDataBuffer[this->m_CurrentPos][i];
}
imageSequence = this->m_ImageSequence;
}
else
{
MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active.";
}
m_ImageMutex->Unlock();
}
void ToFCameraMESADevice::GetIntensities(float* intensityArray, int& imageSequence)
{
m_ImageMutex->Lock();
if (m_CameraActive)
{
// 1) copy the image buffer
// 2) Flip around y- axis (vertical axis)
/*
this->m_Controller->GetIntensities(this->m_SourceDataBuffer[this->m_CurrentPos], this->m_IntensityArray);
for (int i=0; i<this->m_CaptureHeight; i++)
{
for (int j=0; j<this->m_CaptureWidth; j++)
{
intensityArray[i*this->m_CaptureWidth+j] = this->m_IntensityArray[(i+1)*this->m_CaptureWidth-1-j];
}
}
*/
for (int i=0; i<this->m_PixelNumber; i++)
{
intensityArray[i] = this->m_IntensityDataBuffer[this->m_CurrentPos][i];
}
imageSequence = this->m_ImageSequence;
}
else
{
MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active.";
}
m_ImageMutex->Unlock();
}
void ToFCameraMESADevice::GetDistances(float* distanceArray, int& imageSequence)
{
m_ImageMutex->Lock();
if (m_CameraActive)
{
// 1) copy the image buffer
// 2) convert the distance values from m to mm
// 3) Flip around y- axis (vertical axis)
/*
this->m_Controller->GetDistances(this->m_SourceDataBuffer[this->m_CurrentPos], this->m_DistanceArray);
for (int i=0; i<this->m_CaptureHeight; i++)
{
for (int j=0; j<this->m_CaptureWidth; j++)
{
distanceArray[i*this->m_CaptureWidth+j] = 1000 * this->m_DistanceArray[(i+1)*this->m_CaptureWidth-1-j];
}
}
*/
for (int i=0; i<this->m_PixelNumber; i++)
{
distanceArray[i] = this->m_DistanceDataBuffer[this->m_CurrentPos][i]; // * 1000
}
imageSequence = this->m_ImageSequence;
}
else
{
MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active.";
}
m_ImageMutex->Unlock();
}
void ToFCameraMESADevice::GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray,
int requiredImageSequence, int& capturedImageSequence)
{
if (m_CameraActive)
{
- m_ImageMutex->Lock();
// 1) copy the image buffer
// 2) convert the distance values from m to mm
// 3) Flip around y- axis (vertical axis)
// check for empty buffer
if (this->m_ImageSequence < 0)
{
// buffer empty
MITK_INFO << "Buffer empty!! ";
capturedImageSequence = this->m_ImageSequence;
- m_ImageMutex->Unlock();
return;
}
// determine position of image in buffer
int pos = 0;
if ((requiredImageSequence < 0) || (requiredImageSequence > this->m_ImageSequence))
{
capturedImageSequence = this->m_ImageSequence;
pos = this->m_CurrentPos;
//MITK_INFO << "Required image not found! Required: " << requiredImageSequence << " delivered/current: " << this->m_ImageSequence;
}
else if (requiredImageSequence <= this->m_ImageSequence - this->m_BufferSize)
{
capturedImageSequence = (this->m_ImageSequence - this->m_BufferSize) + 1;
pos = (this->m_CurrentPos + 1) % this->m_BufferSize;
//MITK_INFO << "Out of buffer! Required: " << requiredImageSequence << " delivered: " << capturedImageSequence << " current: " << this->m_ImageSequence;
}
else // (requiredImageSequence > this->m_ImageSequence - this->m_BufferSize) && (requiredImageSequence <= this->m_ImageSequence)
{
capturedImageSequence = requiredImageSequence;
pos = (this->m_CurrentPos + (10-(this->m_ImageSequence - requiredImageSequence))) % this->m_BufferSize;
}
// write image data to float arrays
for (int i=0; i<this->m_PixelNumber; i++)
{
distanceArray[i] = this->m_DistanceDataBuffer[pos][i] /* * 1000 */;
amplitudeArray[i] = this->m_AmplitudeDataBuffer[pos][i];
intensityArray[i] = this->m_IntensityDataBuffer[pos][i];
}
- m_ImageMutex->Unlock();
/*
this->m_Controller->GetDistances(this->m_SourceDataBuffer[pos], this->m_DistanceArray);
this->m_Controller->GetAmplitudes(this->m_SourceDataBuffer[pos], this->m_AmplitudeArray);
this->m_Controller->GetIntensities(this->m_SourceDataBuffer[pos], this->m_IntensityArray);
int u, v;
for (int i=0; i<this->m_CaptureHeight; i++)
{
for (int j=0; j<this->m_CaptureWidth; j++)
{
u = i*this->m_CaptureWidth+j;
v = (i+1)*this->m_CaptureWidth-1-j;
distanceArray[u] = 1000 * this->m_DistanceArray[v]; // unit in mm
//distanceArray[u] = this->m_DistanceArray[v]; // unit in meter
amplitudeArray[u] = this->m_AmplitudeArray[v];
intensityArray[u] = this->m_IntensityArray[v];
}
}
memcpy(sourceDataArray, this->m_SourceDataBuffer[this->m_CurrentPos], this->m_SourceDataSize);
*/
}
else
{
MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active.";
}
}
ToFCameraMESAController::Pointer ToFCameraMESADevice::GetController()
{
return this->m_Controller;
}
void ToFCameraMESADevice::SetProperty( const char *propertyKey, BaseProperty* propertyValue )
{
ToFCameraDevice::SetProperty(propertyKey,propertyValue);
this->m_PropertyList->SetProperty(propertyKey, propertyValue);
if (strcmp(propertyKey, "ModulationFrequency") == 0)
{
int modulationFrequency = 0;
GetIntProperty(propertyValue, modulationFrequency);
m_Controller->SetModulationFrequency(modulationFrequency);
}
else if (strcmp(propertyKey, "IntegrationTime") == 0)
{
int integrationTime = 0;
GetIntProperty(propertyValue, integrationTime);
m_Controller->SetIntegrationTime(integrationTime);
}
}
}
diff --git a/Modules/ToFHardware/mitkToFCameraPMDDevice.cpp b/Modules/ToFHardware/mitkToFCameraPMDDevice.cpp
index 07c67c5180..2b0c48a992 100644
--- a/Modules/ToFHardware/mitkToFCameraPMDDevice.cpp
+++ b/Modules/ToFHardware/mitkToFCameraPMDDevice.cpp
@@ -1,414 +1,411 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Module: $RCSfile$
Language: C++
Date: $Date: 2010-05-27 16:06:53 +0200 (Do, 27 Mai 2010) $
Version: $Revision: $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "mitkToFCameraPMDDevice.h"
#include "mitkRealTimeClock.h"
#include "itkMultiThreader.h"
#include <itksys/SystemTools.hxx>
namespace mitk
{
ToFCameraPMDDevice::ToFCameraPMDDevice() :
m_SourceDataArray(NULL), m_SourceDataBuffer(NULL)
{
}
ToFCameraPMDDevice::~ToFCameraPMDDevice()
{
this->CleanUpSourceData();
}
bool ToFCameraPMDDevice::ConnectCamera()
{
bool ok = false;
if (m_Controller)
{
ok = m_Controller->OpenCameraConnection();
if (ok)
{
this->m_CaptureWidth = m_Controller->GetCaptureWidth();
this->m_CaptureHeight = m_Controller->GetCaptureHeight();
this->m_SourceDataSize = m_Controller->GetSourceDataStructSize();
this->m_PixelNumber = this->m_CaptureWidth * this->m_CaptureHeight;
// allocate buffers
AllocatePixelArrays();
this->AllocateSourceData();
m_CameraConnected = true;
}
}
return ok;
}
bool ToFCameraPMDDevice::DisconnectCamera()
{
bool ok = false;
if (m_Controller)
{
ok = m_Controller->CloseCameraConnection();
if (ok)
{
m_CameraConnected = false;
}
}
return ok;
}
void ToFCameraPMDDevice::StartCamera()
{
if (m_CameraConnected)
{
// get the first image
this->m_Controller->UpdateCamera();
this->m_ImageMutex->Lock();
//this->m_Controller->GetSourceData(this->m_SourceDataArray);
this->m_Controller->GetSourceData(this->m_SourceDataBuffer[this->m_FreePos]);
this->m_FreePos = (this->m_FreePos+1) % this->m_BufferSize;
this->m_CurrentPos = (this->m_CurrentPos+1) % this->m_BufferSize;
this->m_ImageSequence++;
this->m_ImageMutex->Unlock();
this->m_CameraActiveMutex->Lock();
this->m_CameraActive = true;
this->m_CameraActiveMutex->Unlock();
this->m_ThreadID = this->m_MultiThreader->SpawnThread(this->Acquire, this);
// wait a little to make sure that the thread is started
itksys::SystemTools::Delay(10);
}
else
{
MITK_INFO<<"Camera not connected";
}
}
void ToFCameraPMDDevice::StopCamera()
{
m_CameraActiveMutex->Lock();
m_CameraActive = false;
m_CameraActiveMutex->Unlock();
itksys::SystemTools::Delay(100);
if (m_MultiThreader.IsNotNull())
{
m_MultiThreader->TerminateThread(m_ThreadID);
}
// wait a little to make sure that the thread is terminated
itksys::SystemTools::Delay(10);
}
bool ToFCameraPMDDevice::IsCameraActive()
{
m_CameraActiveMutex->Lock();
bool ok = m_CameraActive;
m_CameraActiveMutex->Unlock();
return ok;
}
void ToFCameraPMDDevice::UpdateCamera()
{
if (m_Controller)
{
m_Controller->UpdateCamera();
}
}
ITK_THREAD_RETURN_TYPE ToFCameraPMDDevice::Acquire(void* pInfoStruct)
{
/* extract this pointer from Thread Info structure */
struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct;
if (pInfo == NULL)
{
return ITK_THREAD_RETURN_VALUE;
}
if (pInfo->UserData == NULL)
{
return ITK_THREAD_RETURN_VALUE;
}
ToFCameraPMDDevice* toFCameraDevice = (ToFCameraPMDDevice*)pInfo->UserData;
if (toFCameraDevice!=NULL)
{
mitk::RealTimeClock::Pointer realTimeClock;
realTimeClock = mitk::RealTimeClock::New();
double t1, t2;
t1 = realTimeClock->GetCurrentStamp();
int n = 100;
bool overflow = false;
bool printStatus = false;
while (toFCameraDevice->IsCameraActive())
{
// update the ToF camera
toFCameraDevice->UpdateCamera();
// get the source data from the camera and write it at the next free position in the buffer
toFCameraDevice->m_ImageMutex->Lock();
toFCameraDevice->m_Controller->GetSourceData(toFCameraDevice->m_SourceDataBuffer[toFCameraDevice->m_FreePos]);
toFCameraDevice->m_ImageMutex->Unlock();
// call modified to indicate that cameraDevice was modified
toFCameraDevice->Modified();
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
TODO Buffer Handling currently only works for buffer size 1
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
//toFCameraDevice->m_ImageSequence++;
toFCameraDevice->m_FreePos = (toFCameraDevice->m_FreePos+1) % toFCameraDevice->m_BufferSize;
toFCameraDevice->m_CurrentPos = (toFCameraDevice->m_CurrentPos+1) % toFCameraDevice->m_BufferSize;
toFCameraDevice->m_ImageSequence++;
if (toFCameraDevice->m_FreePos == toFCameraDevice->m_CurrentPos)
{
// buffer overflow
//MITK_INFO << "Buffer overflow!! ";
//toFCameraDevice->m_CurrentPos = (toFCameraDevice->m_CurrentPos+1) % toFCameraDevice->m_BufferSize;
//toFCameraDevice->m_ImageSequence++;
overflow = true;
}
if (toFCameraDevice->m_ImageSequence % n == 0)
{
printStatus = true;
}
if (overflow)
{
//itksys::SystemTools::Delay(10);
overflow = false;
}
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
END TODO Buffer Handling currently only works for buffer size 1
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
// print current framerate
if (printStatus)
{
t2 = realTimeClock->GetCurrentStamp() - t1;
//MITK_INFO << "t2: " << t2 <<" Time (s) for 1 image: " << (t2/1000) / n << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence;
MITK_INFO << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence;
t1 = realTimeClock->GetCurrentStamp();
printStatus = false;
}
} // end of while loop
}
return ITK_THREAD_RETURN_VALUE;
}
// TODO: Buffer size currently set to 1. Once Buffer handling is working correctly, method may be reactivated
// void ToFCameraPMDDevice::ResetBuffer(int bufferSize)
// {
// this->m_BufferSize = bufferSize;
// this->m_CurrentPos = -1;
// this->m_FreePos = 0;
// }
void ToFCameraPMDDevice::GetAmplitudes(float* amplitudeArray, int& imageSequence)
{
- m_ImageMutex->Lock();
if (m_CameraActive)
{
// 1) copy the image buffer
// 2) Flip around y- axis (vertical axis)
-
+ m_ImageMutex->Lock();
this->m_Controller->GetAmplitudes(this->m_SourceDataBuffer[this->m_CurrentPos], this->m_AmplitudeArray);
+ m_ImageMutex->Unlock();
for (int i=0; i<this->m_CaptureHeight; i++)
{
for (int j=0; j<this->m_CaptureWidth; j++)
{
amplitudeArray[i*this->m_CaptureWidth+j] = this->m_AmplitudeArray[(i+1)*this->m_CaptureWidth-1-j];
}
}
imageSequence = this->m_ImageSequence;
}
else
{
MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active.";
}
- m_ImageMutex->Unlock();
}
void ToFCameraPMDDevice::GetIntensities(float* intensityArray, int& imageSequence)
{
- m_ImageMutex->Lock();
if (m_CameraActive)
{
// 1) copy the image buffer
// 2) Flip around y- axis (vertical axis)
+ m_ImageMutex->Lock();
this->m_Controller->GetIntensities(this->m_SourceDataBuffer[this->m_CurrentPos], this->m_IntensityArray);
+ m_ImageMutex->Unlock();
for (int i=0; i<this->m_CaptureHeight; i++)
{
for (int j=0; j<this->m_CaptureWidth; j++)
{
intensityArray[i*this->m_CaptureWidth+j] = this->m_IntensityArray[(i+1)*this->m_CaptureWidth-1-j];
}
}
imageSequence = this->m_ImageSequence;
}
else
{
MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active.";
}
m_ImageMutex->Unlock();
}
void ToFCameraPMDDevice::GetDistances(float* distanceArray, int& imageSequence)
{
- m_ImageMutex->Lock();
if (m_CameraActive)
{
// 1) copy the image buffer
// 2) convert the distance values from m to mm
// 3) Flip around y- axis (vertical axis)
-
+ m_ImageMutex->Lock();
this->m_Controller->GetDistances(this->m_SourceDataBuffer[this->m_CurrentPos], this->m_DistanceArray);
+ m_ImageMutex->Unlock();
for (int i=0; i<this->m_CaptureHeight; i++)
{
for (int j=0; j<this->m_CaptureWidth; j++)
{
distanceArray[i*this->m_CaptureWidth+j] = 1000 * this->m_DistanceArray[(i+1)*this->m_CaptureWidth-1-j];
}
}
imageSequence = this->m_ImageSequence;
}
else
{
MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active.";
}
- m_ImageMutex->Unlock();
}
void ToFCameraPMDDevice::GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray,
int requiredImageSequence, int& capturedImageSequence)
{
if (m_CameraActive)
{
- m_ImageMutex->Lock();
// 1) copy the image buffer
// 2) convert the distance values from m to mm
// 3) Flip around y- axis (vertical axis)
// check for empty buffer
if (this->m_ImageSequence < 0)
{
// buffer empty
MITK_INFO << "Buffer empty!! ";
capturedImageSequence = this->m_ImageSequence;
- m_ImageMutex->Unlock();
return;
}
// determine position of image in buffer
int pos = 0;
if ((requiredImageSequence < 0) || (requiredImageSequence > this->m_ImageSequence))
{
capturedImageSequence = this->m_ImageSequence;
pos = this->m_CurrentPos;
//MITK_INFO << "Required image not found! Required: " << requiredImageSequence << " delivered/current: " << this->m_ImageSequence;
}
else if (requiredImageSequence <= this->m_ImageSequence - this->m_BufferSize)
{
capturedImageSequence = (this->m_ImageSequence - this->m_BufferSize) + 1;
pos = (this->m_CurrentPos + 1) % this->m_BufferSize;
//MITK_INFO << "Out of buffer! Required: " << requiredImageSequence << " delivered: " << capturedImageSequence << " current: " << this->m_ImageSequence;
}
else // (requiredImageSequence > this->m_ImageSequence - this->m_BufferSize) && (requiredImageSequence <= this->m_ImageSequence)
{
capturedImageSequence = requiredImageSequence;
pos = (this->m_CurrentPos + (10-(this->m_ImageSequence - requiredImageSequence))) % this->m_BufferSize;
}
+ m_ImageMutex->Lock();
this->m_Controller->GetDistances(this->m_SourceDataBuffer[pos], this->m_DistanceArray);
this->m_Controller->GetAmplitudes(this->m_SourceDataBuffer[pos], this->m_AmplitudeArray);
this->m_Controller->GetIntensities(this->m_SourceDataBuffer[pos], this->m_IntensityArray);
+ memcpy(sourceDataArray, this->m_SourceDataBuffer[this->m_CurrentPos], this->m_SourceDataSize);
+ m_ImageMutex->Unlock();
int u, v;
for (int i=0; i<this->m_CaptureHeight; i++)
{
for (int j=0; j<this->m_CaptureWidth; j++)
{
u = i*this->m_CaptureWidth+j;
v = (i+1)*this->m_CaptureWidth-1-j;
distanceArray[u] = 1000 * this->m_DistanceArray[v]; // unit in minimeter
//distanceArray[u] = this->m_DistanceArray[v]; // unit in meter
amplitudeArray[u] = this->m_AmplitudeArray[v];
intensityArray[u] = this->m_IntensityArray[v];
}
}
-
- memcpy(sourceDataArray, this->m_SourceDataBuffer[this->m_CurrentPos], this->m_SourceDataSize);
- m_ImageMutex->Unlock();
}
else
{
MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active.";
}
}
ToFCameraPMDController::Pointer ToFCameraPMDDevice::GetController()
{
return this->m_Controller;
}
void ToFCameraPMDDevice::SetProperty( const char *propertyKey, BaseProperty* propertyValue )
{
ToFCameraDevice::SetProperty(propertyKey,propertyValue);
this->m_PropertyList->SetProperty(propertyKey, propertyValue);
if (strcmp(propertyKey, "ModulationFrequency") == 0)
{
int modulationFrequency = 0;
GetIntProperty(propertyValue, modulationFrequency);
m_Controller->SetModulationFrequency(modulationFrequency);
}
else if (strcmp(propertyKey, "IntegrationTime") == 0)
{
int integrationTime = 0;
GetIntProperty(propertyValue, integrationTime);
m_Controller->SetIntegrationTime(integrationTime);
}
}
void ToFCameraPMDDevice::AllocateSourceData()
{
// clean up if array and data have already been allocated
CleanUpSourceData();
// (re-) allocate memory
this->m_SourceDataArray = new char[this->m_SourceDataSize];
for(int i=0; i<this->m_SourceDataSize; i++) {this->m_SourceDataArray[i]=0;}
this->m_SourceDataBuffer = new char*[this->m_MaxBufferSize];
for(int i=0; i<this->m_MaxBufferSize; i++)
{
this->m_SourceDataBuffer[i] = new char[this->m_SourceDataSize];
}
}
void ToFCameraPMDDevice::CleanUpSourceData()
{
if (m_SourceDataArray)
{
delete[] m_SourceDataArray;
}
if (m_SourceDataBuffer)
{
for(int i=0; i<this->m_MaxBufferSize; i++)
{
delete[] this->m_SourceDataBuffer[i];
}
delete[] this->m_SourceDataBuffer;
}
}
}
diff --git a/Modules/ToFHardware/mitkToFCameraPMDRawDataDevice.cpp b/Modules/ToFHardware/mitkToFCameraPMDRawDataDevice.cpp
index 4c67815343..77795a368d 100644
--- a/Modules/ToFHardware/mitkToFCameraPMDRawDataDevice.cpp
+++ b/Modules/ToFHardware/mitkToFCameraPMDRawDataDevice.cpp
@@ -1,491 +1,489 @@
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Module: $RCSfile$
Language: C++
Date: $Date: 2010-05-27 16:06:53 +0200 (Do, 27 Mai 2010) $
Version: $Revision: $
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "mitkToFCameraPMDRawDataDevice.h"
#include "mitkRealTimeClock.h"
#include "itkMultiThreader.h"
#include <itksys/SystemTools.hxx>
namespace mitk
{
ToFCameraPMDRawDataDevice::ToFCameraPMDRawDataDevice() :
m_SourceDataArray(NULL), m_SourceDataBuffer(NULL), m_ShortSourceData(NULL)
{
m_RawDataSource = ThreadedToFRawDataReconstruction::New();
}
ToFCameraPMDRawDataDevice::~ToFCameraPMDRawDataDevice()
{
this->CleanUpSourceData();
}
bool ToFCameraPMDRawDataDevice::ConnectCamera()
{
bool ok = false;
if (m_Controller.IsNotNull())
{
ok = m_Controller->OpenCameraConnection();
if (ok)
{
this->m_CaptureWidth = m_Controller->GetCaptureWidth();
this->m_CaptureHeight = m_Controller->GetCaptureHeight();
this->m_SourceDataSize = m_Controller->GetSourceDataStructSize();
this->m_PixelNumber = this->m_CaptureWidth * this->m_CaptureHeight;
// allocate buffers
this->AllocatePixelArrays();
this->AllocateSourceData();
m_CameraConnected = true;
}
}
return ok;
}
bool ToFCameraPMDRawDataDevice::DisconnectCamera()
{
bool ok = false;
if (m_Controller)
{
ok = m_Controller->CloseCameraConnection();
if (ok)
{
m_CameraConnected = false;
}
}
return ok;
}
void ToFCameraPMDRawDataDevice::StartCamera()
{
if (m_CameraConnected)
{
// get the first image
this->m_Controller->UpdateCamera();
this->m_ImageMutex->Lock();
this->m_Controller->GetSourceData(this->m_SourceDataBuffer[this->m_FreePos]);
this->m_FreePos = (this->m_FreePos+1) % this->m_BufferSize;
this->m_CurrentPos = (this->m_CurrentPos+1) % this->m_BufferSize;
this->m_ImageSequence++;
this->m_ImageMutex->Unlock();
this->m_CameraActiveMutex->Lock();
this->m_CameraActive = true;
this->m_CameraActiveMutex->Unlock();
this->m_ThreadID = this->m_MultiThreader->SpawnThread(this->Acquire, this);
// wait a little to make sure that the thread is started
itksys::SystemTools::Delay(100);
}
else
{
MITK_INFO<<"Camera not connected";
}
}
void ToFCameraPMDRawDataDevice::StopCamera()
{
m_CameraActiveMutex->Lock();
m_CameraActive = false;
m_CameraActiveMutex->Unlock();
itksys::SystemTools::Delay(100);
if (m_MultiThreader.IsNotNull())
{
m_MultiThreader->TerminateThread(m_ThreadID);
}
// wait a little to make sure that the thread is terminated
itksys::SystemTools::Delay(10);
}
bool ToFCameraPMDRawDataDevice::IsCameraActive()
{
m_CameraActiveMutex->Lock();
bool ok = m_CameraActive;
m_CameraActiveMutex->Unlock();
return ok;
}
void ToFCameraPMDRawDataDevice::UpdateCamera()
{
if (m_Controller)
{
m_Controller->UpdateCamera();
}
}
ITK_THREAD_RETURN_TYPE ToFCameraPMDRawDataDevice::Acquire(void* pInfoStruct)
{
/* extract this pointer from Thread Info structure */
struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct;
if (pInfo == NULL)
{
return ITK_THREAD_RETURN_VALUE;
}
if (pInfo->UserData == NULL)
{
return ITK_THREAD_RETURN_VALUE;
}
ToFCameraPMDRawDataDevice* toFCameraDevice = (ToFCameraPMDRawDataDevice*)pInfo->UserData;
if (toFCameraDevice!=NULL)
{
mitk::RealTimeClock::Pointer realTimeClock = mitk::RealTimeClock::New();
double t1, t2;
t1 = realTimeClock->GetCurrentStamp();
int n = 100;
bool overflow = false;
bool printStatus = false;
while (toFCameraDevice->IsCameraActive())
{
// update the ToF camera
toFCameraDevice->UpdateCamera();
// get the source data from the camera and write it at the next free position in the buffer
vtkShortArray* channelData = vtkShortArray::New();
toFCameraDevice->m_ImageMutex->Lock();
toFCameraDevice->m_Controller->GetSourceData(toFCameraDevice->m_SourceDataArray);
+ toFCameraDevice->m_ImageMutex->Unlock();
toFCameraDevice->m_Controller->GetShortSourceData(toFCameraDevice->m_ShortSourceData);
toFCameraDevice->GetChannelSourceData( toFCameraDevice->m_ShortSourceData, channelData );
- toFCameraDevice->m_ImageMutex->Unlock();
// call modified to indicate that cameraDevice was modified
toFCameraDevice->Modified();
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
TODO Buffer Handling currently only works for buffer size 1
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
if(!toFCameraDevice->m_RawDataSource->GetInit())
{
toFCameraDevice->m_RawDataSource->Initialize(toFCameraDevice->m_CaptureWidth, toFCameraDevice->m_CaptureHeight,
toFCameraDevice->m_Controller->GetModulationFrequency(), toFCameraDevice->GetChannelSize());
}
toFCameraDevice->m_RawDataSource->SetChannelData(channelData);
toFCameraDevice->m_RawDataSource->Update();
toFCameraDevice->m_ImageMutex->Lock();
toFCameraDevice->m_RawDataSource->GetAmplitudes(toFCameraDevice->m_AmplitudeArray);
toFCameraDevice->m_RawDataSource->GetIntensities(toFCameraDevice->m_IntensityArray);
toFCameraDevice->m_RawDataSource->GetDistances(toFCameraDevice->m_DistanceArray);
toFCameraDevice->m_ImageMutex->Unlock();
toFCameraDevice->m_FreePos = (toFCameraDevice->m_FreePos+1) % toFCameraDevice->m_BufferSize;
toFCameraDevice->m_CurrentPos = (toFCameraDevice->m_CurrentPos+1) % toFCameraDevice->m_BufferSize;
toFCameraDevice->m_ImageSequence++;
if (toFCameraDevice->m_FreePos == toFCameraDevice->m_CurrentPos)
{
overflow = true;
}
if (toFCameraDevice->m_ImageSequence % n == 0)
{
printStatus = true;
}
channelData->Delete();
if (overflow)
{
overflow = false;
}
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
END TODO Buffer Handling currently only works for buffer size 1
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
// print current framerate
if (printStatus)
{
t2 = realTimeClock->GetCurrentStamp() - t1;
//MITK_INFO << "t2: " << t2 <<" Time (s) for 1 image: " << (t2/1000) / n << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence;
MITK_INFO << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence;
t1 = realTimeClock->GetCurrentStamp();
printStatus = false;
}
} // end of while loop
}
return ITK_THREAD_RETURN_VALUE;
}
// TODO: Buffer size currently set to 1. Once Buffer handling is working correctly, method may be reactivated
// void ToFCameraPMDDevice::ResetBuffer(int bufferSize)
// {
// this->m_BufferSize = bufferSize;
// this->m_CurrentPos = -1;
// this->m_FreePos = 0;
// }
void ToFCameraPMDRawDataDevice::GetAmplitudes(float* amplitudeArray, int& imageSequence)
{
- m_ImageMutex->Lock();
if (m_CameraActive)
{
// Flip around y- axis (vertical axis)
+ m_ImageMutex->Lock();
this->XYAxisFlipImage(this->m_AmplitudeArray, amplitudeArray, 1, 0 );
+ m_ImageMutex->Unlock();
imageSequence = this->m_ImageSequence;
}
else
{
MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active.";
}
- m_ImageMutex->Unlock();
}
void ToFCameraPMDRawDataDevice::GetIntensities(float* intensityArray, int& imageSequence)
{
- m_ImageMutex->Lock();
if (m_CameraActive)
{
// Flip around y- axis (vertical axis)
+ m_ImageMutex->Lock();
this->XYAxisFlipImage(this->m_IntensityArray, intensityArray, 0, 1);
+ m_ImageMutex->Unlock();
imageSequence = this->m_ImageSequence;
}
else
{
MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active.";
}
- m_ImageMutex->Unlock();
}
void ToFCameraPMDRawDataDevice::GetDistances(float* distanceArray, int& imageSequence)
{
- m_ImageMutex->Lock();
if (m_CameraActive)
{
// Flip around y- axis (vertical axis)
+ m_ImageMutex->Lock();
this->XYAxisFlipImage(this->m_DistanceArray,distanceArray, 1, 1);
+ m_ImageMutex->Unlock();
imageSequence = this->m_ImageSequence;
}
else
{
MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active.";
}
- m_ImageMutex->Unlock();
}
void ToFCameraPMDRawDataDevice::GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray,
int requiredImageSequence, int& capturedImageSequence)
{
if (m_CameraActive)
{
- m_ImageMutex->Lock();
// 1) copy the image buffer
// 2) convert the distance values from m to mm
// 3) Flip around y- axis (vertical axis)
// check for empty buffer
if (this->m_ImageSequence < 0)
{
// buffer empty
MITK_INFO << "Buffer empty!! ";
capturedImageSequence = this->m_ImageSequence;
- m_ImageMutex->Unlock();
return;
}
// determine position of image in buffer
int pos = 0;
if ((requiredImageSequence < 0) || (requiredImageSequence > this->m_ImageSequence))
{
capturedImageSequence = this->m_ImageSequence;
pos = this->m_CurrentPos;
//MITK_INFO << "Required image not found! Required: " << requiredImageSequence << " delivered/current: " << this->m_ImageSequence;
}
else if (requiredImageSequence <= this->m_ImageSequence - this->m_BufferSize)
{
capturedImageSequence = (this->m_ImageSequence - this->m_BufferSize) + 1;
pos = (this->m_CurrentPos + 1) % this->m_BufferSize;
//MITK_INFO << "Out of buffer! Required: " << requiredImageSequence << " delivered: " << capturedImageSequence << " current: " << this->m_ImageSequence;
}
else // (requiredImageSequence > this->m_ImageSequence - this->m_BufferSize) && (requiredImageSequence <= this->m_ImageSequence)
{
capturedImageSequence = requiredImageSequence;
pos = (this->m_CurrentPos + (10-(this->m_ImageSequence - requiredImageSequence))) % this->m_BufferSize;
}
- m_ImageMutex->Unlock();
int u, v;
+ m_ImageMutex->Lock();
for (int i=0; i<this->m_CaptureHeight; i++)
{
for (int j=0; j<this->m_CaptureWidth; j++)
{
u = i*this->m_CaptureWidth+j;
v = (i+1)*this->m_CaptureWidth-1-j;
distanceArray[u] = this->m_DistanceArray[v]; // unit in millimeter
amplitudeArray[u] = this->m_AmplitudeArray[v];
intensityArray[u] = this->m_IntensityArray[v];
}
}
-
memcpy(sourceDataArray, this->m_SourceDataBuffer[this->m_CurrentPos], this->m_SourceDataSize);
+ m_ImageMutex->Unlock();
}
else
{
MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active.";
}
}
void ToFCameraPMDRawDataDevice::XYAxisFlipImage( float* imageData, float* &flippedData, int xAxis, int yAxis, int dimension )
{
int captureWidth = this->GetCaptureWidth();
int captureHeight = this->GetCaptureHeight();
//
//flips image around x- axis (horizontal axis)
//
if(xAxis == 1 && yAxis != 1)
{
for (int i=0; i<captureHeight; i++)
{
for (int j=0; j<captureWidth; j++)
{
for (int k=0; k<dimension; k++)
{
flippedData[i*captureWidth*dimension+j*dimension+k] = imageData[((captureHeight-1-i)*captureWidth*dimension)+((j)*dimension+k)];
}
}
}
}
//
// flips image around y- axis (vertical axis)
//
if(xAxis!=1 && yAxis == 1)
{
for (int i=0; i<captureHeight; i++)
{
for (int j=0; j<captureWidth; j++)
{
for (int k=0; k<dimension; k++)
{
flippedData[i*captureWidth*dimension+j*dimension+k] = imageData[(i+1)*captureWidth*dimension-1-j*dimension-k];
}
}
}
}
//
//flips image around x- and y- axis
//
else if(xAxis == 1 && yAxis == 1)
{
for (int i=0; i<captureHeight; i++)
{
for (int j=0; j<captureWidth; j++)
{
for (int k=0; k<dimension; k++)
{
flippedData[i*captureWidth*dimension+j*dimension+k] = imageData[((captureHeight-i)*(captureWidth)*dimension-1)-(j*dimension-k)];
}
}
}
}
}
ToFCameraPMDController::Pointer ToFCameraPMDRawDataDevice::GetController()
{
return this->m_Controller;
}
void ToFCameraPMDRawDataDevice::SetProperty( const char *propertyKey, BaseProperty* propertyValue )
{
ToFCameraDevice::SetProperty(propertyKey,propertyValue);
this->m_PropertyList->SetProperty(propertyKey, propertyValue);
if (strcmp(propertyKey, "ModulationFrequency") == 0)
{
int modulationFrequency = 0;
GetIntProperty(propertyValue, modulationFrequency);
m_Controller->SetModulationFrequency(modulationFrequency);
}
else if (strcmp(propertyKey, "IntegrationTime") == 0)
{
int integrationTime = 0;
GetIntProperty(propertyValue, integrationTime);
m_Controller->SetIntegrationTime(integrationTime);
}
}
void ToFCameraPMDRawDataDevice::CleanupPixelArrays()
{
if (m_IntensityArray)
{
delete [] m_IntensityArray;
}
if (m_DistanceArray)
{
delete [] m_DistanceArray;
}
if (m_AmplitudeArray)
{
delete [] m_AmplitudeArray;
}
if (m_ShortSourceData)
{
delete [] m_ShortSourceData;
}
}
void ToFCameraPMDRawDataDevice::AllocatePixelArrays()
{
// free memory if it was already allocated
CleanupPixelArrays();
// allocate buffer
this->m_IntensityArray = new float[this->m_PixelNumber];
for(int i=0; i<this->m_PixelNumber; i++) {this->m_IntensityArray[i]=0.0;}
this->m_DistanceArray = new float[this->m_PixelNumber];
for(int i=0; i<this->m_PixelNumber; i++) {this->m_DistanceArray[i]=0.0;}
this->m_AmplitudeArray = new float[this->m_PixelNumber];
for(int i=0; i<this->m_PixelNumber; i++) {this->m_AmplitudeArray[i]=0.0;}
this->m_ShortSourceData = new short[this->m_SourceDataSize];
for(int i=0; i<this->m_SourceDataSize; i++) {this->m_ShortSourceData[i]=0.0;}
}
void ToFCameraPMDRawDataDevice::AllocateSourceData()
{
// clean up if array and data have already been allocated
CleanUpSourceData();
// (re-) allocate memory
this->m_SourceDataArray = new char[this->m_SourceDataSize];
for(int i=0; i<this->m_SourceDataSize; i++) {this->m_SourceDataArray[i]=0;}
this->m_SourceDataBuffer = new char*[this->m_MaxBufferSize];
for(int i=0; i<this->m_MaxBufferSize; i++)
{
this->m_SourceDataBuffer[i] = new char[this->m_SourceDataSize];
}
}
void ToFCameraPMDRawDataDevice::CleanUpSourceData()
{
if (m_SourceDataArray)
{
delete[] m_SourceDataArray;
}
if (m_SourceDataBuffer)
{
for(int i=0; i<this->m_MaxBufferSize; i++)
{
delete[] this->m_SourceDataBuffer[i];
}
delete[] this->m_SourceDataBuffer;
}
}
}
diff --git a/mitkTestingConfig.h.in b/mitkTestingConfig.h.in
index 02b0b416ec..3a908f70f0 100644
--- a/mitkTestingConfig.h.in
+++ b/mitkTestingConfig.h.in
@@ -1,13 +1,18 @@
/*
mitkTestingConfig.h
this file is generated. Do not change!
*/
+#ifndef MITKTESTINGCONFIG_H
+#define MITKTESTINGCONFIG_H
+
#cmakedefine BUILD_TESTING
#cmakedefine MITK_FAST_TESTING
#define MITK_TEST_OUTPUT_DIR "@MITK_TEST_OUTPUT_DIR@"
#ifdef CMAKE_INTDIR
-#define MITK_RUNTIME_OUTPUT_DIR "@CMAKE_RUNTIME_OUTPUT_DIRECTORY@/" ## CMAKE_INTDIR
+#define MITK_RUNTIME_OUTPUT_DIR "@CMAKE_RUNTIME_OUTPUT_DIRECTORY@/" CMAKE_INTDIR
#else
#define MITK_RUNTIME_OUTPUT_DIR "@CMAKE_RUNTIME_OUTPUT_DIRECTORY@"
#endif
+
+#endif // MITKTESTINGCONFIG_H

File Metadata

Mime Type
application/octet-stream
Expires
Mon, Sep 30, 5:21 AM (1 d, 21 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
72/c2/fb69641b6831627f829300a0cbb1
Default Alt Text
(1 MB)

Event Timeline