diff --git a/CMake/MITKDashboardDriverScript.cmake b/CMake/MITKDashboardDriverScript.cmake index 68e9b60d63..841d39870b 100644 --- a/CMake/MITKDashboardDriverScript.cmake +++ b/CMake/MITKDashboardDriverScript.cmake @@ -1,466 +1,473 @@ # # Included from a dashboard script, this cmake file will drive the configure and build # steps of MITK # #----------------------------------------------------------------------------- # The following variable are expected to be define in the top-level script: set(expected_variables CTEST_NOTES_FILES CTEST_SITE CTEST_DASHBOARD_ROOT CTEST_CMAKE_COMMAND CTEST_CMAKE_GENERATOR WITH_MEMCHECK WITH_COVERAGE WITH_DOCUMENTATION CTEST_BUILD_CONFIGURATION CTEST_TEST_TIMEOUT CTEST_BUILD_FLAGS TEST_TO_EXCLUDE_REGEX CTEST_SOURCE_DIRECTORY CTEST_BINARY_DIRECTORY CTEST_BUILD_NAME SCRIPT_MODE CTEST_COVERAGE_COMMAND CTEST_MEMORYCHECK_COMMAND CTEST_GIT_COMMAND QT_QMAKE_EXECUTABLE PROJECT_BUILD_DIR SUPERBUILD_TARGETS ) foreach(var ${expected_variables}) if(NOT DEFINED ${var}) message(FATAL_ERROR "Variable ${var} should be defined in top-level script !") endif() endforeach() if (NOT DEFINED GIT_BRANCH OR GIT_BRANCH STREQUAL "") set(GIT_BRANCH "") else() set(GIT_BRANCH "-b ${GIT_BRANCH}") endif() # Should binary directory be cleaned? set(empty_binary_directory FALSE) # Attempt to build and test also if 'ctest_update' returned an error set(initial_force_build FALSE) # Set model options set(model "") if (SCRIPT_MODE STREQUAL "experimental") set(empty_binary_directory FALSE) set(initial_force_build TRUE) set(model Experimental) elseif (SCRIPT_MODE STREQUAL "continuous") set(empty_binary_directory FALSE) set(initial_force_build FALSE) set(model Continuous) elseif (SCRIPT_MODE STREQUAL "nightly") set(empty_binary_directory TRUE) set(initial_force_build TRUE) set(model Nightly) else() message(FATAL_ERROR "Unknown script mode: '${SCRIPT_MODE}'. Script mode should be either 'experimental', 'continuous' or 'nightly'") endif() #message("script_mode:${SCRIPT_MODE}") #message("model:${model}") #message("empty_binary_directory:${empty_binary_directory}") #message("force_build:${initial_force_build}") set(CTEST_CONFIGURATION_TYPE ${CTEST_BUILD_CONFIGURATION}) if(empty_binary_directory) message("Directory ${CTEST_BINARY_DIRECTORY} cleaned !") ctest_empty_binary_directory(${CTEST_BINARY_DIRECTORY}) endif() if(NOT DEFINED CTEST_CHECKOUT_DIR) set(CTEST_CHECKOUT_DIR ${CTEST_SOURCE_DIRECTORY}) endif() if(NOT EXISTS "${CTEST_CHECKOUT_DIR}") set(CTEST_CHECKOUT_COMMAND "\"${CTEST_GIT_COMMAND}\" clone ${GIT_BRANCH} ${GIT_REPOSITORY} \"${CTEST_CHECKOUT_DIR}\"") endif() set(CTEST_UPDATE_TYPE "git") set(CTEST_UPDATE_COMMAND "${CTEST_GIT_COMMAND}") #---------------------------------------------------------------------- # Utility macros #---------------------------------------------------------------------- function(func_build_target target build_dir) set(CTEST_BUILD_TARGET ${target}) ctest_build(BUILD "${build_dir}" APPEND RETURN_VALUE res NUMBER_ERRORS num_errors NUMBER_WARNINGS num_warnings) ctest_submit(PARTS Build) if(num_errors) math(EXPR build_errors "${build_errors} + ${num_errors}") set(build_errors ${build_errors} PARENT_SCOPE) endif() if(num_warnings) math(EXPR build_warnings "${build_warnings} + ${num_warnings}") set(build_warnings ${build_warnings} PARENT_SCOPE) endif() endfunction() function(func_test label build_dir) if (NOT TESTING_PARALLEL_LEVEL) set(TESTING_PARALLEL_LEVEL 8) endif() if(label MATCHES "Unlabeled") set(_include_label EXCLUDE_LABEL .*) else() set(_include_label INCLUDE_LABEL ${label}) endif() ctest_test(BUILD "${build_dir}" ${_include_label} PARALLEL_LEVEL ${TESTING_PARALLEL_LEVEL} EXCLUDE ${TEST_TO_EXCLUDE_REGEX} RETURN_VALUE res ) ctest_submit(PARTS Test) if(res) math(EXPR test_errors "${test_errors} + 1") set(test_errors ${test_errors} PARENT_SCOPE) endif() if(ARG3) set(WITH_COVERAGE ${ARG3}) endif() if(ARG4) set(WITH_MEMCHECK ${ARG4}) endif() if(WITH_COVERAGE AND CTEST_COVERAGE_COMMAND) message("----------- [ Coverage ${label} ] -----------") ctest_coverage(BUILD "${build_dir}" LABELS ${label}) ctest_submit(PARTS Coverage) endif () if(WITH_MEMCHECK AND CTEST_MEMORYCHECK_COMMAND) if(NOT CTEST_MEMORYCHECK_SUPPRESSIONS_FILE) if(EXISTS "${CTEST_SOURCE_DIRECTORY}/CMake/valgrind.supp") set(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE "${CTEST_SOURCE_DIRECTORY}/CMake/valgrind.supp") endif() endif() if(NOT CTEST_MEMORYCHECK_COMMAND_OPTIONS) set(CTEST_MEMORYCHECK_COMMAND_OPTIONS "-q --tool=memcheck --leak-check=yes --show-reachable=no --show-possibly-lost=no --workaround-gcc296-bugs=yes --num-callers=50") endif() ctest_memcheck(BUILD "${build_dir}" INCLUDE_LABEL ${label}) ctest_submit(PARTS MemCheck) endif () endfunction() #--------------------------------------------------------------------- # run_ctest macro #--------------------------------------------------------------------- MACRO(run_ctest) set(build_warnings 0) set(build_errors 0) set(test_errors 0) ctest_start(${model}) ctest_update(SOURCE "${CTEST_CHECKOUT_DIR}" RETURN_VALUE res) if(res LESS 0) # update error math(EXPR build_errors "${build_errors} + 1") endif() set(force_build ${initial_force_build}) # Check if a forced run was requested set(cdash_remove_rerun_url ) if(NOT MITK_NO_CDASH_WEBADMIN) set(cdash_rerun_url "http://mbits/rerun/${CTEST_BUILD_NAME}") set(cdash_remove_rerun_url "http://mbits/rerun/rerun.php?name=${CTEST_BUILD_NAME}&remove=1") file(DOWNLOAD "${cdash_rerun_url}" "${CTEST_BINARY_DIRECTORY}/tmp.txt" STATUS status ) list(GET status 0 error_code) file(READ "${CTEST_BINARY_DIRECTORY}/tmp.txt" rerun_content LIMIT 1) if(NOT error_code AND NOT rerun_content) set(force_build 1) endif() endif() if(COMMAND MITK_OVERRIDE_FORCE_BUILD) MITK_OVERRIDE_FORCE_BUILD(force_build) endif() # force a build if this is the first run and the build dir is empty if(NOT EXISTS "${CTEST_BINARY_DIRECTORY}/CMakeCache.txt") message("First time build - Initialize CMakeCache.txt") set(res 1) # Write initial cache. if (NOT DEFINED BUILD_TESTING) set(BUILD_TESTING ON) endif() # Write initial cache. file(WRITE "${CTEST_BINARY_DIRECTORY}/CMakeCache.txt" " CTEST_USE_LAUNCHERS:BOOL=${CTEST_USE_LAUNCHERS} CTEST_PROJECT_ADDITIONAL_TARGETS:INTERNAL=${CTEST_PROJECT_ADDITIONAL_TARGETS} BUILD_TESTING:BOOL=${BUILD_TESTING} MITK_CTEST_SCRIPT_MODE:STRING=${SCRIPT_MODE} CMAKE_BUILD_TYPE:STRING=${CTEST_BUILD_CONFIGURATION} QT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} WITH_COVERAGE:BOOL=${WITH_COVERAGE} ${INITIAL_CMAKECACHE_OPTIONS} ") endif() if(res GREATER 0 OR force_build) # Clear the forced rerun request if(NOT MITK_NO_CDASH_WEBADMIN AND cdash_remove_rerun_url) file(DOWNLOAD "${cdash_remove_rerun_url}" "${CTEST_BINARY_DIRECTORY}/tmp.txt") file(REMOVE "${CTEST_BINARY_DIRECTORY}/tmp.txt") endif() if(CTEST_PROJECT_NAME_SUPERBUILD) set(ctest_project_name_orig ${CTEST_PROJECT_NAME}) set(CTEST_PROJECT_NAME ${CTEST_PROJECT_NAME_SUPERBUILD}) endif() message("----------- [ Configure SuperBuild ] -----------") set_property(GLOBAL PROPERTY SubProject SuperBuild) set_property(GLOBAL PROPERTY Label SuperBuild) ctest_configure(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res) if(res) math(EXPR build_errors "${build_errors} + 1") endif() # Project.xml is generated during the superbuild configure step ctest_submit(FILES "${CTEST_BINARY_DIRECTORY}/Project.xml") ctest_read_custom_files("${CTEST_BINARY_DIRECTORY}") ctest_submit(PARTS Configure) # submit the update results *after* the submitting the Configure info, # otherwise CDash is somehow confused and cannot add the update info # to the superbuild project ctest_submit(PARTS Update) # To get CTEST_PROJECT_SUBPROJECTS and CTEST_PROJECT_EXTERNALS definition include("${CTEST_BINARY_DIRECTORY}/CTestConfigSubProject.cmake") # Build top level (either all or the supplied targets at # superbuild level if(SUPERBUILD_TARGETS) foreach(superbuild_target ${SUPERBUILD_TARGETS}) message("----------- [ Build ${superbuild_target} - SuperBuild ] -----------") func_build_target(${superbuild_target} "${CTEST_BINARY_DIRECTORY}") # runs only tests that have a LABELS property matching "SuperBuild" func_test("SuperBuild" "${CTEST_BINARY_DIRECTORY}") endforeach() # HACK Unfortunately ctest_coverage ignores the build argument, back-up the original dirs file(READ "${CTEST_BINARY_DIRECTORY}/CMakeFiles/TargetDirectories.txt" old_coverage_dirs) # explicitly build requested external projects as subprojects foreach(external_project_with_build_dir ${CTEST_PROJECT_EXTERNALS}) string(REPLACE "^^" ";" external_project_with_build_dir_list "${external_project_with_build_dir}") - list(GET external_project_with_build_dir_list 0 external_project) - list(GET external_project_with_build_dir_list 1 external_project_test_dir) - list(GET external_project_with_build_dir_list 2 external_project_build_dir) - list(GET external_project_with_build_dir_list 3 external_project_extra_target) + list(GET external_project_with_build_dir_list 0 external_project_name) + list(GET external_project_with_build_dir_list 1 external_project_builddir) + list(GET external_project_with_build_dir_list 2 external_project_superbuilddir) + list(GET external_project_with_build_dir_list 3 external_project_buildtarget) + + set_property(GLOBAL PROPERTY SubProject ${external_project_name}) + set_property(GLOBAL PROPERTY Label ${external_project_name}) - if (NOT external_project_build_dir) - set(external_project_build_dir ${external_project_test_dir}) + message("----------- [ Build ${external_project_name} ] -----------") + + func_build_target("${external_project_name}" "${CTEST_BINARY_DIRECTORY}") + + # The next func_build_target calls are for continuous clients, to make sure + # the external project is completely build (targets added with ExternalProject_Add + # are not rebuild automatically if their sources changed + if(NOT build_errors AND external_project_superbuilddir) + func_build_target("" "${CTEST_BINARY_DIRECTORY}/${external_project_superbuilddir}") endif() - - set_property(GLOBAL PROPERTY SubProject ${external_project}) - set_property(GLOBAL PROPERTY Label ${external_project}) - message("----------- [ Build ${external_project} ] -----------") + if(NOT build_errors AND external_project_buildtarget) + func_build_target("${external_project_buildtarget}" "${CTEST_BINARY_DIRECTORY}/${external_project_superbuilddir}") + endif() - # Build the "all" target for the external project - func_build_target("" "${CTEST_BINARY_DIRECTORY}/${external_project_build_dir}") - if(external_project_extra_target) - func_build_target("${external_project_extra_target}" "${CTEST_BINARY_DIRECTORY}/${external_project_build_dir}") + if(NOT build_errors) + func_build_target("" "${CTEST_BINARY_DIRECTORY}/${external_project_builddir}") endif() # HACK Unfortunately ctest_coverage ignores the build argument, try to force it... - file(READ "${CTEST_BINARY_DIRECTORY}/${external_project_test_dir}/CMakeFiles/TargetDirectories.txt" mitk_build_coverage_dirs) + file(READ "${CTEST_BINARY_DIRECTORY}/${external_project_builddir}/CMakeFiles/TargetDirectories.txt" mitk_build_coverage_dirs) file(APPEND "${CTEST_BINARY_DIRECTORY}/CMakeFiles/TargetDirectories.txt" "${mitk_build_coverage_dirs}") - message("----------- [ Test ${external_project} ] -----------") + message("----------- [ Test ${external_project_name} ] -----------") - # runs only tests that have a LABELS property matching "${external_project}" - func_test(${external_project} "${CTEST_BINARY_DIRECTORY}/${external_project_test_dir}") + # runs only tests that have a LABELS property matching "${external_project_name}" + func_test(${external_project_name} "${CTEST_BINARY_DIRECTORY}/${external_project_builddir}") # restore old coverage dirs file(WRITE "${CTEST_BINARY_DIRECTORY}/CMakeFiles/TargetDirectories.txt" "${old_coverage_dirs}") endforeach() # switch back to SuperBuild label set_property(GLOBAL PROPERTY SubProject SuperBuild) set_property(GLOBAL PROPERTY Label SuperBuild) message("----------- [ Finish SuperBuild ] -----------") else() message("----------- [ Build SuperBuild ] -----------") endif() # build everything at superbuild level which has not yet been built func_build_target("" "${CTEST_BINARY_DIRECTORY}") # runs only tests that have a LABELS property matching "SuperBuild" #func_test("SuperBuild" "${CTEST_BINARY_DIRECTORY}") set(build_dir "${CTEST_BINARY_DIRECTORY}/${PROJECT_BUILD_DIR}") if(CTEST_PROJECT_NAME_SUPERBUILD) set(CTEST_PROJECT_NAME ${ctest_project_name_orig}) endif() message("----------- [ Configure ${build_dir} ] -----------") # Configure target ctest_configure(BUILD "${build_dir}" OPTIONS "-DCTEST_USE_LAUNCHERS=${CTEST_USE_LAUNCHERS}" RETURN_VALUE res ) ctest_read_custom_files("${CTEST_BINARY_DIRECTORY}") ctest_submit(PARTS Configure) if(res) math(EXPR build_errors "${build_errors} + 1") endif() foreach(subproject ${CTEST_PROJECT_SUBPROJECTS}) set_property(GLOBAL PROPERTY SubProject ${subproject}) set_property(GLOBAL PROPERTY Label ${subproject}) if(subproject MATCHES "Unlabeled") message("----------- [ Build All (Unlabeled) ] -----------") # Build target func_build_target("" "${build_dir}") else() message("----------- [ Build ${subproject} ] -----------") # Build target func_build_target(${subproject} "${build_dir}") endif() endforeach() # HACK Unfortunately ctest_coverage ignores the build argument, try to force it... file(READ ${build_dir}/CMakeFiles/TargetDirectories.txt mitk_build_coverage_dirs) file(APPEND "${CTEST_BINARY_DIRECTORY}/CMakeFiles/TargetDirectories.txt" "${mitk_build_coverage_dirs}") foreach(subproject ${CTEST_PROJECT_SUBPROJECTS}) set_property(GLOBAL PROPERTY SubProject ${subproject}) set_property(GLOBAL PROPERTY Label ${subproject}) message("----------- [ Test ${subproject} ] -----------") # runs only tests that have a LABELS property matching "${subproject}" func_test(${subproject} "${build_dir}") endforeach() # Build any additional target which is not build by "all" # i.e. the "package" target if(CTEST_PROJECT_ADDITIONAL_TARGETS) foreach(additional_target ${CTEST_PROJECT_ADDITIONAL_TARGETS}) set_property(GLOBAL PROPERTY SubProject ${additional_target}) set_property(GLOBAL PROPERTY Label ${additional_target}) message("----------- [ Build ${additional_target} ] -----------") func_build_target(${additional_target} "${build_dir}") message("----------- [ Test ${additional_target} ] -----------") # runs only tests that have a LABELS property matching "${subproject}" func_test(${additional_target} "${build_dir}") endforeach() endif() if (WITH_DOCUMENTATION) message("----------- [ Build Documentation ] -----------") set(ctest_use_launchers_orig ${CTEST_USE_LAUNCHERS}) set(CTEST_USE_LAUNCHERS 0) # Build Documentation target set_property(GLOBAL PROPERTY SubProject Documentation) set_property(GLOBAL PROPERTY Label Documentation) func_build_target("doc" "${build_dir}") set(CTEST_USE_LAUNCHERS ${ctest_use_launchers_orig}) endif() set_property(GLOBAL PROPERTY SubProject SuperBuild) set_property(GLOBAL PROPERTY Label SuperBuild) # Global coverage ... if (WITH_COVERAGE AND CTEST_COVERAGE_COMMAND) message("----------- [ Global coverage ] -----------") ctest_coverage(BUILD "${build_dir}" APPEND) ctest_submit(PARTS Coverage) endif () # Global dynamic analysis ... if (WITH_MEMCHECK AND CTEST_MEMORYCHECK_COMMAND) message("----------- [ Global memcheck ] -----------") ctest_memcheck(BUILD "${build_dir}") ctest_submit(PARTS MemCheck) endif () # Note should be at the end ctest_submit(PARTS Notes) # Send status to the "CDash Web Admin" if(NOT MITK_NO_CDASH_WEBADMIN) set(cdash_admin_url "http://mbits/cdashadmin-web/index.php?pw=4da12ca9c06d46d3171d7f73974c900f") string(REGEX REPLACE ".*\\?project=(.*)&?" "\\1" _ctest_project "${CTEST_DROP_LOCATION}") file(DOWNLOAD "${cdash_admin_url}&action=submit&name=${CTEST_BUILD_NAME}&hasTestErrors=${test_errors}&hasBuildErrors=${build_errors}&hasBuildWarnings=${build_warnings}&ctestDropSite=${CTEST_DROP_SITE}&ctestProject=${_ctest_project}" "${CTEST_BINARY_DIRECTORY}/cdashadmin.txt" STATUS status ) list(GET status 0 error_code) list(GET status 1 error_msg) if(error_code) message(FATAL_ERROR "error: Failed to communicate with cdashadmin-web - ${error_msg}") endif() endif() endif() # Clear the CTEST_CHECKOUT_COMMAND variable to prevent continuous clients # to try to checkout again set(CTEST_CHECKOUT_COMMAND "") endmacro() if(SCRIPT_MODE STREQUAL "continuous") while(1) run_ctest() # Loop no faster than once every 5 minutes message("Wait for 5 minutes ...") ctest_sleep(300) endwhile() else() run_ctest() endif() 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 6f347b9e47..481983a691 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,534 +1,703 @@ /*========================================================================= 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 application and interaction service #include #include // Qmitk #include "QmitkFiberBundleDeveloperView.h" #include +// Qt +#include // MITK -#include //for fiberStructure +//#include //for fiberStructure //===needed when timeSlicedGeometry is null to invoke rendering mechansims ==== #include #include // VTK #include //for randomized FiberStructure #include //for fiberStructure #include //for fiberStructure #include //for geometry //ITK #include + +/*=================================================================================== + * THIS METHOD IMPLEMENTS THE ACTIONS WHICH SHALL BE EXECUTED by the according THREAD + */ +QmitkFiberIDWorker::QmitkFiberIDWorker(QThread* hostingThread, Package4WorkingThread itemPackage) +: m_itemPackage(itemPackage), +m_hostingThread(hostingThread) +{ + +} +void QmitkFiberIDWorker::run() +{ + + //accurate time measurement using ITK timeProbe + itk::TimeProbe clock; + clock.Start(); + + m_itemPackage.st_FBX->DoGenerateFiberIds(); + m_itemPackage.st_idGenerateTimer->stop(); //stop fancy Qt-timer in GUI + + clock.Stop(); + m_itemPackage.st_Controls->infoTimerGenerateFiberIds->setText( QString::number(clock.GetTotal()) ); + MITK_INFO << "==== Generate idSet ====\n Mean: " << clock.GetMean() << "\n Total: " << clock.GetTotal() ; + // m_hostingThread->quit(); + +} + + + + + + + + +// ========= HERE STARTS THE ACTUAL FIBERBUNDLE 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_hostThread = new QThread; + m_threadInProgress = false; } // Destructor QmitkFiberBundleDeveloperView::~QmitkFiberBundleDeveloperView() { + m_FiberBundleX->Delete(); + delete m_hostThread; + delete m_FiberIDGenerator; + + // m_idGenerateTimer no need to delete, is not initialized using "new" } 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 ); - //disabled due to incomplete implementation of these options + /*=========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); 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)) ); + } // 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::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::const_iterator i; for (i = m_DirectionRadios.begin(); i != m_DirectionRadios.end(); ++i) { QRadioButton* rdbtn = *i; if (rdbtn->isChecked()) fibDirection = rdbtn->objectName(); } - vtkSmartPointer output; // FiberPD stores the generated PolyData + vtkPolyData* output; // FiberPD stores the generated PolyData 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(); + //output = GenerateVtkFibersDirectionX(); } else if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_Y ) { // build polydata with YDirection fibers - output = GenerateVtkFibersDirectionY(); + // output = GenerateVtkFibersDirectionY(); } else if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_Z ) { // build polydata with ZDirection fibers - output = GenerateVtkFibersDirectionZ(); + // output = GenerateVtkFibersDirectionZ(); } mitk::FiberBundleX::Pointer FB = mitk::FiberBundleX::New(); FB->SetFibers(output); 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(); //necessary?? m_MultiWidget->RequestUpdate(); //necessary?? } } /* * Generate polydata of random fibers */ -vtkSmartPointer QmitkFiberBundleDeveloperView::GenerateVtkFibersRandom() +vtkPolyData* QmitkFiberBundleDeveloperView::GenerateVtkFibersRandom() { int numOfFibers = m_Controls->boxFiberNumbers->value(); int distrRadius = m_Controls->boxDistributionRadius->value(); int numOfPoints = numOfFibers * distrRadius; std::vector< std::vector > fiberStorage; for (int i=0; i a; fiberStorage.push_back( a ); } //get number of items in fiberStorage MITK_INFO << "Fibers in fiberstorage: " << fiberStorage.size(); /* Generate Point Cloud */ vtkSmartPointer randomPoints = vtkSmartPointer::New(); randomPoints->SetCenter(0.0, 0.0, 0.0); randomPoints->SetNumberOfPoints(numOfPoints); randomPoints->SetRadius(distrRadius); randomPoints->Update(); vtkPoints* pnts = randomPoints->GetOutput()->GetPoints(); /*====== checkpoint: compare initialized and required points =============================*/ if (numOfPoints != pnts->GetNumberOfPoints()) { MITK_INFO << "VTK POINT ERROR, WRONG AMOUNT OF GENRERATED POINTS... COULD BE VTK BUG OR BITFLIP DUE TO COSMIC RADIATION!"; return NULL; }/* ================================= */ /* ASSIGN EACH POINT TO A RANDOM FIBER */ srand((unsigned)time(0)); // init randomizer for (int i=0; iGetNumberOfPoints(); ++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; + // MITK_INFO << "point" << i << " |" << pnts->GetPoint(random_integer)[0] << "|" << pnts->GetPoint(random_integer)[1]<< "|" << pnts->GetPoint(random_integer)[2] << "| into fiber" << random_integer; } //=====timer measurement==== itk::TimeProbe clock; clock.Start(); //========================== - + /* GENERATE VTK POLYLINES OUT OF FIBERSTORAGE */ vtkSmartPointer linesCell = vtkSmartPointer::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 singleFiber = fiberStorage.at(i); vtkSmartPointer fiber = vtkSmartPointer::New(); fiber->GetPointIds()->SetNumberOfIds((int)singleFiber.size()); for (unsigned long si=0; siGetPointIds()->SetId( si, singleFiber.at(si) ); } linesCell->InsertNextCell(fiber); } /* =======checkpoint for cellarray allocation ==========*/ if ( (linesCell->GetSize()/pnts->GetNumberOfPoints()) != 2 ) { 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."; }/* ====================================================*/ // MITK_INFO << "CellSize: " << linesCell->GetSize() << " NumberOfCells: " << linesCell->GetNumberOfCells(); /* HOSTING POLYDATA FOR RANDOM FIBERSTRUCTURE */ - vtkSmartPointer PDRandom = vtkSmartPointer::New(); + vtkPolyData* PDRandom = vtkPolyData::New(); PDRandom->SetPoints(pnts); PDRandom->SetLines(linesCell); //====timer measurement======== clock.Stop(); MITK_INFO << "=====Assambling random Fibers to Polydata======\nMean: " << clock.GetMean() << std::endl; MITK_INFO << "Total: " << clock.GetTotal() << std::endl; //============================= return PDRandom; } vtkSmartPointer QmitkFiberBundleDeveloperView::GenerateVtkFibersDirectionX() { int numOfFibers = m_Controls->boxFiberNumbers->value(); vtkSmartPointer linesCell = vtkSmartPointer::New(); vtkSmartPointer points = vtkSmartPointer::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 newFiber = vtkSmartPointer::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 PDX = vtkSmartPointer::New(); PDX->SetPoints(points); PDX->SetLines(linesCell); return PDX; } vtkSmartPointer QmitkFiberBundleDeveloperView::GenerateVtkFibersDirectionY() { vtkSmartPointer PDY = vtkSmartPointer::New(); //todo return PDY; } vtkSmartPointer QmitkFiberBundleDeveloperView::GenerateVtkFibersDirectionZ() { vtkSmartPointer PDZ = vtkSmartPointer::New(); //todo return PDZ; } -/* === THIS METHOD GENERATES ESSENTIAL GEOMETRY PARAMETERS FOR THE MITK FRAMEWORK === +/* === 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::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() +{ + + struct Package4WorkingThread FiberIdPackage; + FiberIdPackage.st_FBX = m_FiberBundleX; + FiberIdPackage.st_idGenerateTimer = &m_idGenerateTimer; + FiberIdPackage.st_Controls = m_Controls; + + /* ===== TIMER CONFIGURATIONS for visual effect ====== + * start and stop is called in Thread pre- and postprocessing methods */ + m_idGenerateTimer.setInterval( 10 ); + connect( &m_idGenerateTimer, SIGNAL(timeout()), this, SLOT(UpdateFiberIDTimer()) ); + + // 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_Controls->infoTimerGenerateFiberIds->setText(QString::number(0)); //set GUI representation of timer to 0 + m_threadInProgress = true; + m_idGenerateTimer.start(); + +} + +void QmitkFiberBundleDeveloperView::AfterThread_IdGenerate() +{ + // m_idGenerateTimer.stop(); //not smart to set timer.stop here, cuz this will override the actual measurements of ITK:PROBE in GUI + m_threadInProgress = false; + + +} + +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::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 nodes ) { - for( std::vector::iterator it = nodes.begin(); - it != nodes.end(); ++it ) + /* ==== 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 - + //==================================================== + + + if (nodes.empty()) + return; + + + for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { - //flags needed for algorithm execution logic - mitk::DataNode::Pointer node = *it; + + /* CHECKPOINT: FIBERBUNDLE*/ if( node.IsNotNull() && dynamic_cast(node->GetData()) ) { - MITK_INFO << node->GetData()->GetNameOfClass(); + m_FiberBundleX = dynamic_cast(node->GetData()); + if (m_FiberBundleX == NULL) + MITK_INFO << "========ATTENTION=========\n unable to load selected FiberBundleX to FiberBundleDeveloper-plugin \n"; - MITK_INFO << "FBX"; - mitk::FiberBundleX::Pointer serwas = dynamic_cast(node->GetData()); - if (serwas.GetPointer() != NULL){ - vtkSmartPointer pdfb = serwas->GetFibers(); - - MITK_INFO << pdfb->GetNumberOfLines(); - MITK_INFO << pdfb->GetNumberOfPoints(); - }else{ - MITK_INFO << "what happend in datastorage?"; - MITK_INFO << node->GetData()->GetNameOfClass(); - } + // ==== FIBERBUNDLE_INFO ELEMENTS ==== + if ( m_Controls->page_FiberInfo->isVisible() ) + FeedFiberInfoWidget(); - } else { - MITK_INFO << node->GetData()->GetNameOfClass(); + // 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 158258cbb2..9dd8ab3826 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,117 +1,184 @@ /*========================================================================= 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 #include #include #include "ui_QmitkFiberBundleDeveloperViewControls.h" #include #include // Qt #include #include #include // VTK #include #include +#include +#include +#include +#include +/* ==== THIS STRUCT CONTAINS ALL NECESSARY VARIABLES + * TO EXECUTE AND UPDATE GUI ELEMENTS DURING PROCESSING OF A THREAD + */ +struct Package4WorkingThread +{ + mitk::FiberBundleX* st_FBX; + QTimer* st_idGenerateTimer; + Ui::QmitkFiberBundleDeveloperViewControls* st_Controls; +}; + + +// ==================================================================== +// ============= WORKER WHICH IS PASSED TO THREAD ===================== +// ==================================================================== +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; + + +}; + + + + + +// ========= 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 */ 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 UpdateFiberIDTimer(); + void SelectionChangedToolBox(int); + + //SLOTS FOR THREADS + void BeforeThread_IdGenerate(); + void AfterThread_IdGenerate(); + protected: /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged( std::vector nodes ); Ui::QmitkFiberBundleDeveloperViewControls* m_Controls; QmitkStdMultiWidget* m_MultiWidget; private: /* METHODS GENERATING FIBERSTRUCTURES */ - vtkSmartPointer GenerateVtkFibersRandom(); + vtkPolyData* GenerateVtkFibersRandom(); vtkSmartPointer GenerateVtkFibersDirectionX(); vtkSmartPointer GenerateVtkFibersDirectionY(); vtkSmartPointer GenerateVtkFibersDirectionZ(); - /* MITK RELEVANT HELPERMETHODS */ + /* METHODS FOR FIBER PROCESSING OR PREPROCESSING */ + + + /* HELPERMETHODS */ mitk::Geometry3D::Pointer GenerateStandardGeometryForMITK(); + void ResetFiberInfoWidget(); + void FeedFiberInfoWidget(); + void FBXDependendGUIElementsConfigurator(bool); //contains the selected FiberBundle - mitk::DataNode::Pointer m_FiberBundleNode; + mitk::FiberBundleX* m_FiberBundleX; // radiobutton groups QVector< QRadioButton* > m_DirectionRadios; QVector< QRadioButton* > m_FARadios; QVector< QRadioButton* > m_GARadios; + + // timer for updating fiber id generation + QTimer m_idGenerateTimer; + + QmitkFiberIDWorker * m_FiberIDGenerator; + QThread * m_hostThread; + bool m_threadInProgress; + }; #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 8e9abb471a..1e3f883b98 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,660 +1,793 @@ QmitkFiberBundleDeveloperViewControls 0 0 382 691 Form 12 50 false - 0 + 1 - + 0 0 355 395 Fiber Generator 0 Fiber Bundles Generate Fiberbundle Fiber Parameters 11 Total number of Fibers 10 999999999 100 Qt::Horizontal 40 20 11 Distribution Radius 10 99 11 Fiber Length Max (points) 10 50 11 Fiber Length Min (points) 10 10 labelFibersTotal boxFiberNumbers horizontalSpacer_3 labelDistrRadius boxDistributionRadius labelFiberMaxLength boxFiberMaxLength labelFiberMinLength boxFiberMinLength 11 Fiber Orientation along Z Axis along X Axis random true along Y Axis Qt::Horizontal 40 20 Qt::Vertical 20 40 DWI Values GA Values no values true nothing yet implemented 11 FA Values const value false 10 1.000000000000000 0.100000000000000 1.000000000000000 random range false 10 1.000000000000000 0.100000000000000 no values true false 10 1.000000000000000 0.100000000000000 Qt::Vertical 20 40 Page Select a FiberBundle in Datamanager Qt::Vertical 20 40 - + 0 0 343 403 Fiber Processor - + 2 Colors Fiber Coloring Color Fibers Qt::Vertical 20 40 Shape Qt::Vertical 20 40 Fiber Smoothing Smooth Fibers QFrame::StyledPanel QFrame::Raised static value relative in% false 10 none true false 10 9999 Qt::Horizontal 40 20 vtkFilters Tubes vtkDecimatePro vtkSmoothPolyDataFilter Cutting + + + + + Step1: Generate Fibers IDs in FBX + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + QFormLayout::FieldsStayAtSizeHint + + + + + + 10 + + + + Timer: + + + + + + + + 10 + + + + - + + + + + + + + + + Execute Step1 + + + + + + + + 0 + 0 + 185 + 116 + + + + FiberInfo + + + + + + General Information + + + + + + Number of Fibers: + + + + + + + - + + + + + + + Number of Points: + + + + + + + - + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + Qt::Vertical 20 40 diff --git a/Modules/CameraCalibration/mitkEndoDebug.h b/Modules/CameraCalibration/mitkEndoDebug.h index d05723ad1a..801658632e 100644 --- a/Modules/CameraCalibration/mitkEndoDebug.h +++ b/Modules/CameraCalibration/mitkEndoDebug.h @@ -1,166 +1,179 @@ #ifndef mitkEndoDebug_h #define mitkEndoDebug_h #include #include #include #include namespace mitk { /// /// again d pointer impl /// struct EndoDebugData; /// /// class responsible for handling debug matters /// in endotracking /// struct mitkCameraCalibration_EXPORT EndoDebug { /// /// singleton class /// static EndoDebug& GetInstance(); /// /// set if debug is enabled at all /// void SetDebugEnabled(bool _DebugEnabled); /// /// \return true if debug should be enabled /// bool GetDebugEnabled(); /// /// set if debug is enabled at all /// void SetShowImagesInDebug(bool _ShowImagesInDebug); /// /// \return true if debug should be enabled /// bool GetShowImagesInDebug(); /// /// set if debug is enabled at all /// void SetShowImagesTimeOut(size_t _ShowImagesTimeOut); /// /// \return true if debug should be enabled /// bool GetShowImagesTimeOut(); /// /// \return the basename of a file without path /// std::string GetFilenameWithoutExtension(const std::string& s); /// /// add a file to debug ( if one or more files are set ) /// only those files will be debugged when using the macros /// below. e.g. call AddFileToDebug("MyClass.cpp"), then /// statements like endodebug(...) will be evaluated in /// MyClass.cpp and nowhere else /// void AddFileToDebug(const std::string& fileToDebug); /// /// same as files to debug, but the user can provide /// any symbol string. if one or more symbols /// are set only for these symbols Debug() will return true /// void AddSymbolToDebug(const std::string& symbolToDebug); /// /// \return true if file should be debugged /// bool DebugFile( const std::string& fileToDebug ); /// /// \return true if symbol should be debugged /// bool DebugSymbol( const std::string& symbolToDebug ); /// /// \return the all in all status if debug output /// should be generated /// bool Debug( const std::string& fileToDebug, const std::string& symbol="" ); /// /// init defaults /// EndoDebug(); /// /// delete d pointer /// virtual ~EndoDebug(); private: /// /// d pointer /// EndoDebugData* d; }; } /// /// macro for debugging purposes /// #define endodebugmarker\ if( mitk::EndoDebug::GetInstance().Debug(__FILE__) ) \ { \ std::cout << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " << __LINE__\ << ": " << __FUNCTION__ << std::endl;\ } /// /// macro for debugging purposes /// #define endodebug(msg)\ if( mitk::EndoDebug::GetInstance().Debug(__FILE__) ) \ { \ std::cout << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " << __LINE__\ << ": " << msg << std::endl;\ } /// /// macro for debugging variables /// #define endodebugvar(var)\ if( mitk::EndoDebug::GetInstance().Debug(__FILE__) ) \ { \ std::cout << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " << __LINE__\ << ": " #var " = " << var << std::endl;\ } /// /// macro for debugging a variable as symbol /// #define endodebugsymbol(var, mSymbol)\ if( mitk::EndoDebug::GetInstance().Debug(__FILE__, mSymbol) ) \ { \ std::cout << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " << __LINE__\ << ": " #var " = " << var << std::endl;\ } /// /// macro for showing cv image if in debug mode /// highgui.h must be included before /// #define endodebugimg(imgVariableName)\ if( mitk::EndoDebug::GetInstance().Debug(__FILE__) \ && mitk::EndoDebug::GetInstance().GetShowImagesInDebug()) \ { \ std::cout << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " << __LINE__\ << ": Showing " #imgVariableName << std::endl; \ cv::imshow( "Debug", imgVariableName ); \ cv::waitKey( mitk::EndoDebug::GetInstance().GetShowImagesTimeOut() ); \ } +/// +/// macro for a section that should only be executed if debugging is enabled +/// +#define endodebugbegin \ + if( mitk::EndoDebug::GetInstance().Debug(__FILE__) ) \ + { \ + +/// +/// macro for a section that should only be executed if debugging is enabled +/// +#define endodebugend \ + } + #endif // mitkEndoDebug_h diff --git a/Modules/CameraCalibration/mitkTransform.cpp b/Modules/CameraCalibration/mitkTransform.cpp index 856e58d2c9..17783e6838 100644 --- a/Modules/CameraCalibration/mitkTransform.cpp +++ b/Modules/CameraCalibration/mitkTransform.cpp @@ -1,688 +1,700 @@ #include "mitkTransform.h" #include #include #include #include #include #include namespace mitk { + // DO NOT CHANGE THE VALUES OF THESE CONSTANTS!! + const std::string Transform::UNKNOWN_TYPE = "Unknown type"; + const std::string Transform::ENDOSCOPE_SCOPE_TOOL = "Endoscope scope tool"; + const std::string Transform::ENDOSCOPE_CAM_TOOL = "Endoscope camera tool"; + const std::string Transform::CHESSBOARD_TOOL = "Chessboard tool"; + const std::string Transform::POINTER_TOOL = "Pointer tool"; + const std::string Transform::BOARD_TO_BOARD_TOOL = "Board to board tool"; Transform::Transform() - : m_NavData(mitk::NavigationData::New()) + : m_NavData(mitk::NavigationData::New()), m_Type( UNKNOWN_TYPE ) { vnl_matrix_fixed rot; rot.set_identity(); this->SetRotation( rot ); } Transform::Transform(const mitk::NavigationData* nd) - : m_NavData(mitk::NavigationData::New()) + : m_NavData(mitk::NavigationData::New()), m_Type( UNKNOWN_TYPE ) { m_NavData->Graft(nd); } void Transform::Copy(const mitk::NavigationData* nd) { (const_cast(m_NavData.GetPointer()))->Graft(nd); } void Transform::Concatenate( mitk::Transform* transform ) { vnl_matrix_fixed mat = transform->GetMatrix(); mat = mat * this->GetMatrix(); // this->SetMatrix( mat ); } void Transform::Concatenate( const vnl_matrix_fixed& transform ) { Transform::Pointer t = Transform::New(); t->SetMatrix( transform ); this->Concatenate( t ); } void Transform::Concatenate( const vtkMatrix4x4* transform ) { Transform::Pointer t = Transform::New(); t->SetMatrix( transform ); this->Concatenate( t ); } void Transform::SetOrientation( const vnl_quaternion& orientation) { m_NavData->SetOrientation(orientation); this->Modified(); } void Transform::SetTranslation( const vnl_vector_fixed& transl) { mitk::Point3D p; for(unsigned int i=0; i<3; ++i) p[i] = transl[i]; m_NavData->SetPosition(p); this->Modified(); } void Transform::SetTranslation( float* array ) { vnl_vector_fixed vec; for(unsigned int i=0; iSetTranslation( vec ); } void Transform::SetRotation( float* array ) { vnl_matrix_fixed mat; unsigned int row = 0; unsigned int col = 0; for(unsigned int i=0; i 0 && i % 3 == 0 ) { ++row; col = 0; } mat(row,col) = array[i]; ++col; } this->SetRotation( mat ); } void Transform::SetOrientation( const vnl_quaternion& orientation) { vnl_vector_fixed qvec; VnlVectorFixedCaster caster( &orientation, &qvec ); caster.Update(); mitk::Quaternion p( qvec ); this->SetOrientation( p ); } vnl_vector_fixed Transform::GetVnlDoubleTranslation() const { vnl_vector_fixed vecFloat = this->GetVnlTranslation(); vnl_vector_fixed vecDouble; VnlVectorFixedCaster caster( &vecFloat, &vecDouble ); caster.Update(); return vecDouble; } void Transform::SetTranslation( const vnl_vector& transl) { vnl_vector_fixed dTransl(transl); vnl_vector_fixed fTransl; VnlVectorFixedCaster caster( &dTransl, &fTransl ); caster.Update(); this->SetTranslation( fTransl ); } vnl_quaternion Transform::GetVnlDoubleQuaternion() const { mitk::Quaternion fOrientation = this->GetOrientation(); vnl_quaternion dOrientation; VnlVectorFixedCaster caster( &fOrientation, &dOrientation ); caster.Update(); return dOrientation; } void Transform::FromCSVFile(const std::string& file) { std::ifstream csvFile (file.c_str()); endoAssert ( csvFile.fail() == false ); mitk::Transform::Pointer transform = mitk::Transform::New(); vnl_matrix_fixed mat; std::string line; mitk::ScalarType d = 0.0f; int row=0,column = 0; while (std::getline (csvFile, line)) { std::istringstream linestream(line); std::string item; column = 0; while (std::getline (linestream, item, ',')) { std::istringstream number; number.str(item); number >> d; mat(row, column) = d; ++column; } ++row; } endoAssert( row == 4 && column == 4 ); transform->SetMatrix( mat ); this->SetNavigationData( transform->GetNavigationData() ); // modified is called in SetNavigationData } std::string Transform::ToCSVString() const { std::ostringstream s; s.precision(12); vnl_matrix_fixed mat = this->GetMatrix(); for( unsigned int j=0; j mat = this->GetMatrix(); s << varname << " = ["; for( unsigned int j=0; jGraft(transform->GetNavigationData()); } mitk::Transform::Pointer Transform::Clone() const { Transform::Pointer copy = Transform::New(); copy->Copy( this ); return copy; } void Transform::SetMatrix( const vtkMatrix4x4* mat) { vnl_matrix_fixed vnlMat; for(unsigned int i=0; i<4; ++i) for(unsigned int j=0; j<4; ++j) vnlMat(i,j) = mat->GetElement(i, j); this->SetMatrix( vnlMat ); } void Transform::ToCSVFile(const std::string& file) const { std::ofstream csvFile; csvFile.open(file.c_str()); endoAssert ( csvFile.fail() == false ); csvFile << this->ToCSVString(); csvFile.close(); } void Transform::ToMatlabFile(const std::string& file , const std::string& varname) const { std::ofstream csvFile; csvFile.open(file.c_str()); endoAssert ( csvFile.fail() == false ); csvFile << this->ToMatlabString(varname); csvFile.close(); } void Transform::SetNavigationData( const mitk::NavigationData* naviData ) { endoAssert( naviData != 0 ); m_NavData->Graft( naviData ); this->Modified(); } void Transform::SetRotation( vnl_matrix_fixed& mat) { this->m_NavData->SetOrientation( mitk::Quaternion(mat) ); this->Modified(); } void Transform::SetRotation( vnl_matrix& mat) { vnl_matrix_fixed tmp(mat); this->SetRotation( tmp ); } void Transform::SetPosition( const mitk::Point3D& transl) { this->SetTranslation( transl.GetVnlVector() ); } void Transform::SetTranslation( double array[3] ) { mitk::Point3D p; for(unsigned int i = 0; i < 3; ++i) p.SetElement(i, array[i]); this->SetTranslation( p.GetVnlVector() ); } void Transform::SetRotation( double array[3][3] ) { vnl_matrix_fixed mat; for(unsigned int i = 0; i < 3; ++i) for(unsigned int j = 0; j < 3; ++j) mat(i, j) = array[i][j]; this->SetRotation( mat ); } void Transform::Invert() { vnl_matrix_fixed tmp(this->GetMatrix()); this->SetMatrix( vnl_inverse( tmp ) ); } void Transform::SetMatrix( const vnl_matrix_fixed& mat) { // set translation first vnl_vector transl = mat.get_column(3); mitk::Point3D p; for(unsigned int i=0; i<3; ++i) p[i] = transl[i]; m_NavData->SetPosition(p); // set rotation vnl_matrix_fixed rotMatFixed( mat.extract(3,3)); this->SetRotation(rotMatFixed); } bool Transform::IsValid() const { return m_NavData->IsDataValid(); } void Transform::SetTranslation( const cv::Mat& transl) { vnl_vector vec(3); VnlVectorFromCvMat _VnlVectorFromCvMat( &transl, &vec ); _VnlVectorFromCvMat.Update(); this->SetTranslation( vnl_vector_fixed( vec ) ); } void Transform::SetRotation( const cv::Mat& mat ) { vnl_matrix vnlMat(3, 3); VnlMatrixFromCvMat _VnlMatrixFromCvMat( &mat, &vnlMat ); _VnlMatrixFromCvMat.Update(); vnl_matrix_fixed vnlMatFixed(vnlMat); this->SetRotation(vnlMatFixed); } void Transform::SetRotationVector( const cv::Mat& rotVec ) { cv::Mat rotMat; cv::Rodrigues( rotVec, rotMat ); vnl_matrix vnlMat(3, 3); VnlMatrixFromCvMat _VnlMatrixFromCvMat( &rotMat, &vnlMat ); _VnlMatrixFromCvMat.Update(); vnl_matrix_fixed vnlMatFixed(vnlMat); this->SetRotation( vnlMatFixed ); } //# getter mitk::NavigationData::Pointer Transform::GetNavigationData() const { return m_NavData; } mitk::Point3D Transform::GetTranslation() const { return m_NavData->GetPosition(); } mitk::Point3D Transform::GetPosition() const { return m_NavData->GetPosition(); } mitk::Quaternion Transform::GetOrientation() const { return m_NavData->GetOrientation(); } void Transform::GetMatrix(vtkMatrix4x4* matrix) const { vnl_matrix_fixed vnlMat = this->GetMatrix(); for(unsigned int i=0; iSetElement(i,j, vnlMat(i,j)); } void Transform::GetVtkOpenGlMatrix(vtkMatrix4x4* matrix) const { vnl_matrix vnlRotation = this->GetVnlRotationMatrix().as_matrix(); // normalize rows of rotation matrix vnlRotation.normalize_rows(); vnl_matrix vnlInverseRotation(3,3); // invert rotation vnlInverseRotation = vnl_matrix_inverse(vnlRotation); vnl_vector vnlTranslation = this->GetPosition().GetVnlVector(); // rotate translation vector by inverse rotation P = P' vnlTranslation = vnlInverseRotation * vnlTranslation; vnlTranslation *= -1; // save -P' // set position mitk::Transform::Pointer tmp = mitk::Transform::New(); tmp->SetTranslation( vnlTranslation ); tmp->SetRotation( vnlRotation ); tmp->GetMatrix(matrix); } //# cv getter cv::Mat Transform::GetCvTranslation() const { cv::Mat mat; vnl_vector vec = this->GetVnlTranslation().as_vector(); endodebugvar( vec ) CvMatFromVnlVector _CvMatFromVnlVector(&vec, &mat); _CvMatFromVnlVector.Update(); return mat; } cv::Mat Transform::GetCvRotationMatrix() const { cv::Mat mat; vnl_matrix vec = this->GetVnlRotationMatrix().as_matrix(); endodebugvar( vec ) CvMatFromVnlMatrix _CvMatFromVnlMatrix(&vec, &mat); _CvMatFromVnlMatrix.Update(); return mat; } cv::Mat Transform::GetCvMatrix() const { cv::Mat mat; vnl_matrix vec = this->GetMatrix().as_matrix(); CvMatFromVnlMatrix _CvMatFromVnlMatrix(&vec, &mat); _CvMatFromVnlMatrix.Update(); return mat; } cv::Mat Transform::GetCvRotationVector() const { cv::Mat rotVec(3,1,cv::DataType::type); cv::Rodrigues( this->GetCvRotationMatrix(), rotVec ); return rotVec; } //# vnl getter vnl_vector_fixed Transform::GetVnlTranslation() const { vnl_vector_fixed vec(m_NavData->GetPosition() .GetVnlVector()); return vec; } vnl_matrix_fixed Transform::GetVnlRotationMatrix() const { return m_NavData->GetOrientation().rotation_matrix_transpose(); } vnl_matrix_fixed Transform::GetVnlDoubleMatrix() const { vnl_matrix_fixed mat = this->GetMatrix(); vnl_matrix_fixed doubleMat; for(unsigned int i=0; i( mat(i,j) ); return doubleMat; } vnl_matrix_fixed Transform::GetMatrix() const { vnl_vector_fixed transl = this->GetVnlTranslation(); vnl_matrix_fixed rot = this->GetVnlRotationMatrix(); vnl_matrix_fixed homMat; homMat.set_identity(); //std::cout << homMat << std::endl; for(unsigned int i=0; i rotMat = this->GetVnlRotationMatrix().transpose(); this->SetRotation( rotMat ); } void Transform::SetValid( bool valid ) { if( m_NavData->IsDataValid() == valid ) return; m_NavData->SetDataValid( valid ); this->Modified(); } std::string mitk::Transform::ToString() const { std::ostringstream s; s.precision(12); mitk::NavigationData::PositionType position; position.Fill(0.0); position = m_NavData->GetPosition(); mitk::NavigationData::OrientationType orientation(0.0, 0.0, 0.0, 0.0); orientation = m_NavData->GetOrientation(); s << "Translation: [" << position[0] << ", " << position[1] << ", " << position[2] << "]"; s << ", orientation: [" << orientation[0] << ", " << orientation[1] << ", " << orientation[2] << ", " << orientation[3] << "]"; s << ", valid: [" << (this->IsValid()? "true": "false") << "]"; return s.str(); } void mitk::Transform::ToXML(TiXmlElement* elem) const { std::string value = elem->ValueStr(); if(value.empty()) elem->SetValue(this->GetNameOfClass()); mitk::NavigationData::PositionType position; position.Fill(0.0); position = m_NavData->GetPosition(); mitk::NavigationData::OrientationType orientation(0.0, 0.0, 0.0, 0.0); orientation = m_NavData->GetOrientation(); mitk::NavigationData::CovarianceMatrixType matrix; matrix.SetIdentity(); matrix = m_NavData->GetCovErrorMatrix(); bool hasPosition = true; hasPosition = m_NavData->GetHasPosition(); bool hasOrientation = true; hasOrientation = m_NavData->GetHasOrientation(); bool dataValid = false; dataValid = m_NavData->IsDataValid(); mitk::NavigationData::TimeStampType timestamp=0.0; + elem->SetAttribute("Type", m_Type); elem->SetDoubleAttribute("Time", timestamp); elem->SetDoubleAttribute("X", position[0]); elem->SetDoubleAttribute("Y", position[1]); elem->SetDoubleAttribute("Z", position[2]); elem->SetDoubleAttribute("QX", orientation[0]); elem->SetDoubleAttribute("QY", orientation[1]); elem->SetDoubleAttribute("QZ", orientation[2]); elem->SetDoubleAttribute("QR", orientation[3]); elem->SetDoubleAttribute("C00", matrix[0][0]); elem->SetDoubleAttribute("C01", matrix[0][1]); elem->SetDoubleAttribute("C02", matrix[0][2]); elem->SetDoubleAttribute("C03", matrix[0][3]); elem->SetDoubleAttribute("C04", matrix[0][4]); elem->SetDoubleAttribute("C05", matrix[0][5]); elem->SetDoubleAttribute("C10", matrix[1][0]); elem->SetDoubleAttribute("C11", matrix[1][1]); elem->SetDoubleAttribute("C12", matrix[1][2]); elem->SetDoubleAttribute("C13", matrix[1][3]); elem->SetDoubleAttribute("C14", matrix[1][4]); elem->SetDoubleAttribute("C15", matrix[1][5]); if (dataValid) elem->SetAttribute("Valid",1); else elem->SetAttribute("Valid",0); if (hasOrientation) elem->SetAttribute("hO",1); else elem->SetAttribute("hO",0); if (hasPosition) elem->SetAttribute("hP",1); else elem->SetAttribute("hP",0); } void mitk::Transform::FromXML(TiXmlElement* elem) { assert(elem); mitk::NavigationData::Pointer nd = mitk::NavigationData::New(); mitk::NavigationData::PositionType position; mitk::NavigationData::OrientationType orientation(0.0,0.0,0.0,0.0); mitk::NavigationData::TimeStampType timestamp = -1; mitk::NavigationData::CovarianceMatrixType matrix; bool hasPosition = true; bool hasOrientation = true; bool dataValid = false; position.Fill(0.0); matrix.SetIdentity(); + std::string type = Transform::UNKNOWN_TYPE; + elem->QueryStringAttribute("Type", &type); elem->QueryDoubleAttribute("Time",×tamp); // position and orientation is mandatory! if(elem->QueryFloatAttribute("X", &position[0]) != TIXML_SUCCESS) throw std::invalid_argument("No X position found in xml"); if(elem->QueryFloatAttribute("Y", &position[1]) != TIXML_SUCCESS) throw std::invalid_argument("No Y position found in xml"); if(elem->QueryFloatAttribute("Z", &position[2]) != TIXML_SUCCESS) throw std::invalid_argument("No Z position found in xml"); if(elem->QueryFloatAttribute("QX", &orientation[0]) != TIXML_SUCCESS) throw std::invalid_argument("No QX orientation found in xml"); if(elem->QueryFloatAttribute("QY", &orientation[1]) != TIXML_SUCCESS) throw std::invalid_argument("No QY orientation found in xml"); if(elem->QueryFloatAttribute("QZ", &orientation[2]) != TIXML_SUCCESS) throw std::invalid_argument("No QZ orientation found in xml"); if(elem->QueryFloatAttribute("QR", &orientation[3]) != TIXML_SUCCESS) throw std::invalid_argument("No QR orientation found in xml"); elem->QueryFloatAttribute("C00", &matrix[0][0]); elem->QueryFloatAttribute("C01", &matrix[0][1]); elem->QueryFloatAttribute("C02", &matrix[0][2]); elem->QueryFloatAttribute("C03", &matrix[0][3]); elem->QueryFloatAttribute("C04", &matrix[0][4]); elem->QueryFloatAttribute("C05", &matrix[0][5]); elem->QueryFloatAttribute("C10", &matrix[1][0]); elem->QueryFloatAttribute("C11", &matrix[1][1]); elem->QueryFloatAttribute("C12", &matrix[1][2]); elem->QueryFloatAttribute("C13", &matrix[1][3]); elem->QueryFloatAttribute("C14", &matrix[1][4]); elem->QueryFloatAttribute("C15", &matrix[1][5]); int tmpval = 0; elem->QueryIntAttribute("Valid", &tmpval); if (tmpval == 0) dataValid = false; else dataValid = true; tmpval = 0; elem->QueryIntAttribute("hO", &tmpval); if (tmpval == 0) hasOrientation = false; else hasOrientation = true; tmpval = 0; elem->QueryIntAttribute("hP", &tmpval); if (tmpval == 0) hasPosition = false; else hasPosition = true; nd->SetTimeStamp(timestamp); nd->SetPosition(position); nd->SetOrientation(orientation); nd->SetCovErrorMatrix(matrix); nd->SetDataValid(dataValid); nd->SetHasOrientation(hasOrientation); nd->SetHasPosition(hasPosition); m_NavData = nd; + m_Type = type; + this->Modified(); } } // namespace mitk std::ostream& operator<< (std::ostream& os, mitk::Transform::Pointer p) { os << p->ToString(); return os; } diff --git a/Modules/CameraCalibration/mitkTransform.h b/Modules/CameraCalibration/mitkTransform.h index 798d53ebc7..c2d2abbe6f 100644 --- a/Modules/CameraCalibration/mitkTransform.h +++ b/Modules/CameraCalibration/mitkTransform.h @@ -1,257 +1,276 @@ #ifndef MITKTRANSFORM_H #define MITKTRANSFORM_H #include #include #include #include #include #include #include #include #include #include namespace mitk { /// /// \brief class representing a transfrom in 3D /// /// internally it stores a mitk navigation data. this is more /// or less a wrapper for navigation data for easy casting /// between opencv/vnl/mitk/xml representations of transform /// data /// class mitkCameraCalibration_EXPORT Transform: public itk::Object, public XMLSerializable { public: mitkClassMacro(Transform, itk::Object); itkFactorylessNewMacro(Transform); mitkNewMacro1Param(Transform, const mitk::NavigationData*); + /// + /// constants describing the type of transform + /// represented here + /// + static const std::string UNKNOWN_TYPE; + static const std::string ENDOSCOPE_SCOPE_TOOL; + static const std::string ENDOSCOPE_CAM_TOOL; + static const std::string CHESSBOARD_TOOL; + static const std::string POINTER_TOOL; + static const std::string BOARD_TO_BOARD_TOOL; + + + itkGetConstMacro(Type, std::string); + itkSetMacro(Type, std::string&); /// /// Copies the content of transform to this /// instance /// void Copy( const mitk::Transform* transform ); /// /// Copies the content of transform to this /// instance /// void Copy( const mitk::NavigationData* transform ); /// /// Inverts the rotation of this transform /// (Polaris navigation Data have inverted rotation /// so you may want to call this function when using /// polaris data) /// void TransposeRotation(); /// /// get a copy of this transform /// mitk::Transform::Pointer Clone() const; /// /// concatenate this transform with the given one, /// i.e. this transform is done first, then transform /// ( if x is this transform, y is transform, then this will be y*x) /// post multiply semantics! /// \see vtkTransform /// void Concatenate( mitk::Transform* transform ); /// /// same as above with vnl mat argument /// void Concatenate( const vnl_matrix_fixed& transform ); /// /// same as above with vtk mat argument /// void Concatenate( const vtkMatrix4x4* transform ); /// /// invert this transform /// void Invert(); /// /// read from xml /// void FromXML(TiXmlElement* elem); /// /// read csv file /// void FromCSVFile(const std::string& file); /// /// grafts the data from naviData to this transform /// void SetNavigationData( const mitk::NavigationData* naviData ); /// /// method to set orientation quat /// void SetOrientation( const vnl_quaternion& orientation); /// /// method to set double valued orientation quat /// void SetOrientation( const vnl_quaternion& orientation); /// /// method to set translation /// void SetTranslation( const vnl_vector_fixed& transl); /// /// method to set a vector of doubles as translation /// void SetTranslation( const vnl_vector& transl); /// /// method to set a mitk::Point3D as position /// void SetPosition( const mitk::Point3D& transl); /// /// sets rotation with a rotation matrix /// void SetRotation( vnl_matrix_fixed& mat); /// /// sets rotation with a non fixed rotation matrix /// void SetRotation( vnl_matrix& mat); /// /// sets rotation and translation with a transformation matrix /// void SetMatrix( const vnl_matrix_fixed& mat); /// /// sets rotation and translation with a vtk transformation matrix /// void SetMatrix( const vtkMatrix4x4* mat); /// /// sets translation from a POD vector /// void SetTranslation( float* array ); /// /// sets translation from a POD vector. this must be a /// 3x3=9 sized vector in row major format (first row = first /// three elements) /// void SetRotation( float* array ); /// /// sets translation from a POD vector /// void SetTranslation( double array[3] ); /// /// sets translation from a POD vector /// void SetRotation( double array[3][3] ); /// /// method to set translation by cv vector /// void SetTranslation( const cv::Mat& transl); /// /// sets rotation with a rotation matrix /// void SetRotation( const cv::Mat& mat ); /// /// sets rotation with a rodrigues rotation vector /// void SetRotationVector( const cv::Mat& rotVec); /// /// \return the navigation data that stores all information /// mitk::NavigationData::Pointer GetNavigationData() const; /// /// calls navigationdata::GetPosition() /// mitk::Point3D GetPosition() const; /// /// same as GetPosition /// mitk::Point3D GetTranslation() const; /// /// calls navigationdata::IsValid() /// bool IsValid() const; /// /// calls navigationdata::SetValid() /// void SetValid(bool valid); /// /// calls navigationdata::GetOrientation() /// mitk::Quaternion GetOrientation() const; /// /// \return the homogeneous matrix representing this transform /// vnl_matrix_fixed GetMatrix() const; /// /// \return the homogeneous vtk matrix representing this transform /// void GetMatrix(vtkMatrix4x4* matrix) const; /// /// \return the homogeneous vtk matrix representing this transform /// in !OpenGL! left handed coordinate system /// void GetVtkOpenGlMatrix(vtkMatrix4x4* matrix) const; /// /// create xml representation /// void ToXML(TiXmlElement* elem) const; /// /// create string representation /// std::string ToString() const; /// /// create string csv representation (only the transformation values!!!!) /// std::string ToCSVString() const; /// /// create matlab representation /// std::string ToMatlabString(const std::string& varname="transform", bool printLastRow=true) const; /// /// write csv representation to file (only the transformation values!!!!) /// void ToCSVFile(const std::string& file) const; /// /// write matlab representation to file /// void ToMatlabFile(const std::string& file , const std::string& varname="transform") const; /// /// conversion to cv types /// cv::Mat GetCvTranslation() const; cv::Mat GetCvRotationVector() const; cv::Mat GetCvRotationMatrix() const; cv::Mat GetCvMatrix() const; /// /// conversion to vnl types /// vnl_vector_fixed GetVnlTranslation() const; vnl_vector_fixed GetVnlDoubleTranslation() const; vnl_quaternion GetVnlDoubleQuaternion() const; vnl_matrix_fixed GetVnlRotationMatrix() const; vnl_matrix_fixed GetVnlDoubleMatrix() const; protected: Transform(); Transform(const mitk::NavigationData* nd); // everything is stored here mitk::NavigationData::Pointer m_NavData; + + /// + /// saves the type of the transform (Default is UNKNOWN_TYPE) + /// + std::string m_Type; }; } // namespace mitk mitkCameraCalibration_EXPORT std::ostream& operator<< (std::ostream& os, mitk::Transform::Pointer p); #endif // MITKTRANSFORM_H diff --git a/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp b/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp index 40fec9e9b6..2d9eefa7d7 100644 --- a/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp +++ b/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp @@ -1,283 +1,308 @@ /*========================================================================= 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 "mitkFiberBundleX.h" /* musthave */ #include // without geometry, fibers are not rendered #include #include #include #include - +#include // baptize array names const char* mitk::FiberBundleX::COLORCODING_ORIENTATION_BASED = "Color_Orient"; const char* mitk::FiberBundleX::COLORCODING_FA_BASED = "Color_FA"; +const char* mitk::FiberBundleX::FIBER_ID_ARRAY = "Fiber_IDs"; mitk::FiberBundleX::FiberBundleX() { /* ====== GEOMETRY IS ESSENTIAL ======= * by default set a standard geometry, usually geometry is * set by the user on initializing a mitkFiberBundle Object */ // mitk::Geometry3D::Pointer fbgeometry = mitk::Geometry3D::New(); // fbgeometry->SetIdentity(); // this->SetGeometry(fbgeometry); /* ==================================== */ } mitk::FiberBundleX::~FiberBundleX() { - + // Memory Management + m_FiberStructureData->Delete(); } /* === main input method ==== * set computed fibers from tractography algorithms */ -void mitk::FiberBundleX::SetFibers(vtkSmartPointer fiberPD) +void mitk::FiberBundleX::SetFibers(vtkPolyData* fiberPD) { - if (fiberPD.GetPointer() == NULL){ + if (fiberPD == NULL){ MITK_INFO << "passed FiberBundleX is NULL, exit!"; return; } m_FiberStructureData = fiberPD; } /* === main output method === * return fiberbundle as vtkPolyData * Depending on processing of input fibers, this method returns * the latest processed fibers. */ - vtkSmartPointer mitk::FiberBundleX::GetFibers() + vtkPolyData* mitk::FiberBundleX::GetFibers() { return m_FiberStructureData; } /*============================================== *++++ PROCESSING WITH FIBER INFORMATION +++++++ =============================================*/ void mitk::FiberBundleX::DoColorCodingOrientationbased() { //===== FOR WRITING A TEST ======================== // colorT size == tupelComponents * tupelElements // compare color results // to cover this code 100% also polydata needed, where colorarray already exists // + one fiber with exactly 1 point // + one fiber with 0 points //================================================= /* make sure that processing colorcoding is only called when necessary */ if ( m_FiberStructureData->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED) && m_FiberStructureData->GetNumberOfPoints() == m_FiberStructureData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)->GetNumberOfTuples() ) { // fiberstructure is already colorcoded MITK_INFO << " NO NEED TO REGENERATE COLORCODING!"; return; } /* Finally, execute color calculation */ vtkPoints* extrPoints = m_FiberStructureData->GetPoints(); int numOfPoints = extrPoints->GetNumberOfPoints(); //colors and alpha value for each single point, RGBA = 4 components unsigned char rgba[4] = {0,0,0,0}; int componentSize = sizeof(rgba); vtkUnsignedCharArray *colorsT = vtkUnsignedCharArray::New(); colorsT->Allocate(numOfPoints * componentSize); colorsT->SetNumberOfComponents(componentSize); colorsT->SetName(COLORCODING_ORIENTATION_BASED); /* checkpoint: does polydata contain any fibers */ int numOfFibers = m_FiberStructureData->GetNumberOfLines(); if (numOfFibers < 1) { MITK_INFO << "\n ========= Number of Fibers is below 1 ========= \n"; return; } /* extract single fibers of fiberBundle */ vtkCellArray* fiberList = m_FiberStructureData->GetLines(); for (int fi=0; fiGetNextCell(numOfPoints, idList); /* single fiber checkpoints: is number of points valid */ if (numOfPoints > 1) { /* operate on points of single fiber */ for (int i=0; i 0) { /* The color value of the current point is influenced by the previous point and next point. */ vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); vnl_vector_fixed< double, 3 > nextPntvtk(extrPoints->GetPoint(idList[i+1])[0], extrPoints->GetPoint(idList[i+1])[1], extrPoints->GetPoint(idList[i+1])[2]); vnl_vector_fixed< double, 3 > prevPntvtk(extrPoints->GetPoint(idList[i-1])[0], extrPoints->GetPoint(idList[i-1])[1], extrPoints->GetPoint(idList[i-1])[2]); vnl_vector_fixed< double, 3 > diff1; diff1 = currentPntvtk - nextPntvtk; diff1.normalize(); vnl_vector_fixed< double, 3 > diff2; diff2 = currentPntvtk - prevPntvtk; diff2.normalize(); vnl_vector_fixed< double, 3 > diff; diff = (diff1 - diff2) / 2.0; rgba[0] = (unsigned char) (255.0 * std::abs(diff[0])); rgba[1] = (unsigned char) (255.0 * std::abs(diff[1])); rgba[2] = (unsigned char) (255.0 * std::abs(diff[2])); rgba[3] = (unsigned char) (255.0); } else if (i==0) { /* First point has no previous point, therefore only diff1 is taken */ vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); vnl_vector_fixed< double, 3 > nextPntvtk(extrPoints->GetPoint(idList[i+1])[0], extrPoints->GetPoint(idList[i+1])[1], extrPoints->GetPoint(idList[i+1])[2]); vnl_vector_fixed< double, 3 > diff1; diff1 = currentPntvtk - nextPntvtk; diff1.normalize(); rgba[0] = (unsigned char) (255.0 * std::abs(diff1[0])); rgba[1] = (unsigned char) (255.0 * std::abs(diff1[1])); rgba[2] = (unsigned char) (255.0 * std::abs(diff1[2])); rgba[3] = (unsigned char) (255.0); } else if (i==numOfPoints-1) { /* Last point has no next point, therefore only diff2 is taken */ vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); vnl_vector_fixed< double, 3 > prevPntvtk(extrPoints->GetPoint(idList[i-1])[0], extrPoints->GetPoint(idList[i-1])[1], extrPoints->GetPoint(idList[i-1])[2]); vnl_vector_fixed< double, 3 > diff2; diff2 = currentPntvtk - prevPntvtk; diff2.normalize(); rgba[0] = (unsigned char) (255.0 * std::abs(diff2[0])); rgba[1] = (unsigned char) (255.0 * std::abs(diff2[1])); rgba[2] = (unsigned char) (255.0 * std::abs(diff2[2])); rgba[3] = (unsigned char) (255.0); } colorsT->InsertTupleValue(idList[i], rgba); } //end for loop } else if (numOfPoints == 1) { /* a single point does not define a fiber (use vertex mechanisms instead */ continue; // colorsT->InsertTupleValue(0, rgba); } else { MITK_INFO << "Fiber with 0 points detected... please check your tractography algorithm!" ; continue; } }//end for loop m_FiberStructureData->GetPointData()->AddArray(colorsT); //mini test, shall be ported to MITK TESTINGS! if (colorsT->GetSize() != numOfPoints*componentSize) { MITK_INFO << "ALLOCATION ERROR IN INITIATING COLOR ARRAY"; } //===== clean memory ===== colorsT->Delete(); //======================== } +void mitk::FiberBundleX::DoGenerateFiberIds() +{ + if (m_FiberStructureData == NULL) + return; + +// for (int i=0; i<10000000; ++i) +// { +// if(i%500 == 0) +// MITK_INFO << i; +// } + + vtkSmartPointer idFiberFilter = vtkSmartPointer::New(); + idFiberFilter->SetInput(m_FiberStructureData); + idFiberFilter->CellIdsOn(); +// idFiberFilter->PointIdsOn(); // point id's are not needed + idFiberFilter->SetIdsArrayName(FIBER_ID_ARRAY); + idFiberFilter->FieldDataOn(); + idFiberFilter->Update(); + + m_FiberIdDataSet = idFiberFilter->GetOutput(); + +} -double* mitk::FiberBundleX::DoComputeFiberStructureBoundingBox(vtkSmartPointer fiberStructure) +/* COMPUTE BOUND OF FiberBundle */ +double* mitk::FiberBundleX::DoComputeFiberStructureBoundingBox() { - fiberStructure->ComputeBounds(); - double* bounds = fiberStructure->GetBounds(); + m_FiberStructureData->ComputeBounds(); + double* bounds = m_FiberStructureData->GetBounds(); return bounds; } ////private repairMechanism for orientationbased colorcoding //bool mitk::FiberBundleX::doSelfHealingColorOrient(vtkPolyData* healMe) //{ // bool hasHealingSucceeded = false; // MITK_INFO << "FiberBundleX self repair mechanism is called, but not yet implemented"; //// check type of healMe // if (healMe == m_ImportedFiberData) // { // //todo // } // // return hasHealingSucceeded; //} /* ESSENTIAL IMPLEMENTATION OF SUPERCLASS METHODS */ void mitk::FiberBundleX::UpdateOutputInformation() { } void mitk::FiberBundleX::SetRequestedRegionToLargestPossibleRegion() { } bool mitk::FiberBundleX::RequestedRegionIsOutsideOfTheBufferedRegion() { return false; } bool mitk::FiberBundleX::VerifyRequestedRegion() { return true; } void mitk::FiberBundleX::SetRequestedRegion( itk::DataObject *data ) { } \ No newline at end of file diff --git a/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.h b/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.h index 21a59fe45a..806c62dcba 100644 --- a/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.h +++ b/Modules/DiffusionImaging/IODataStructures/FiberBundleX/mitkFiberBundleX.h @@ -1,113 +1,121 @@ /*========================================================================= 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. =========================================================================*/ +/* =============== IMPORTANT TODO =================== + * ==== USE vtkSmartPointer<> when necessary ONLY!!!! + */ #ifndef _MITK_FiberBundleX_H #define _MITK_FiberBundleX_H //includes for MITK datastructure #include "mitkBaseData.h" #include "MitkDiffusionImagingExports.h" //includes storing fiberdata #include //may be replaced by class precompile argument #include // may be replaced by class #include // my be replaced by class - +#include namespace mitk { /** * \brief Base Class for Fiber Bundles; */ class MitkDiffusionImaging_EXPORT FiberBundleX : public BaseData { public: // names of certain arrays (e.g colorcodings, etc.) static const char* COLORCODING_ORIENTATION_BASED; static const char* COLORCODING_FA_BASED; + static const char* FIBER_ID_ARRAY; /* friend classes wanna access typedefs ContainerPointType, ContainerTractType, ContainerType */ friend class FiberBundleXWriter; friend class FiberBundleXReader; // ======virtual methods must have====== virtual void UpdateOutputInformation(); virtual void SetRequestedRegionToLargestPossibleRegion(); virtual bool RequestedRegionIsOutsideOfTheBufferedRegion(); virtual bool VerifyRequestedRegion(); virtual void SetRequestedRegion( itk::DataObject *data ); //======================================= mitkClassMacro( FiberBundleX, BaseData ); itkNewMacro( Self ); /*====FIBERBUNDLE I/O METHODS====*/ - void SetFibers(vtkSmartPointer); //set result of tractography algorithm in vtkPolyData format using vtkPolyLines - vtkSmartPointer GetFibers(); + void SetFibers(vtkPolyData*); //set result of tractography algorithm in vtkPolyData format using vtkPolyLines + vtkPolyData* GetFibers(); vtkSmartPointer GetVertices(); /*===FIBERBUNDLE PROCESSING METHODS====*/ void DoColorCodingOrientationbased(); - + void DoGenerateFiberIds(); /*===FIBERBUNDLE ASSESSMENT METHODS====*/ - // Compute Bounding Box for FiberStructure; needed for MITK Geometry - double* DoComputeFiberStructureBoundingBox(vtkSmartPointer); + // Compute Bounding Box of FiberStructure; needed for MITK Geometry + double* DoComputeFiberStructureBoundingBox(); protected: FiberBundleX(); virtual ~FiberBundleX(); private: //// ====TODO==================================== // bool doSelfHealingColorOrient( vtkPolyData* ); //// ============================================ // The following polydata variables are used for fiber- and pointbased representation of the tractography results. As VTK suggests, one vtkPolyData is used to manage vertices and the other for polylines. // FiberPolyData stores all brain fibers using polylines (in world coordinates) // this variable hosts the smoothed fiber data, this data we generate, therefore a smartpointer structure is recommended // vtkSmartPointer m_FiberPolyData; is depricated // // this variable hosts the original fiber data, no smartpointer needed because who or whatever passes this data to FiberBundleX should use vtkSmartPointer structure - vtkSmartPointer m_FiberStructureData; + vtkPolyData* m_FiberStructureData; //this is a common pointer because fiberDataStructure gets passed to this class. m_FiberStructureData is destroyed in the destructor then. // VertexPolyData stores all original points as vertices computed by tracking algorithms vtkSmartPointer m_VertexPolyData; + // this variable contains all additional IDs of Fibers which are needed for efficient fiber manipulation such as extracting etc. + vtkSmartPointer m_FiberIdDataSet; + + }; } // namespace mitk #endif /* _MITK_FiberBundleX_H */ diff --git a/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper3D.cpp b/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper3D.cpp index 9b2c9fc6c3..002a9aebad 100644 --- a/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper3D.cpp +++ b/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper3D.cpp @@ -1,187 +1,187 @@ /*========================================================================= 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 "mitkFiberBundleXMapper3D.h" #include //#include //#include #include #include #include //not essential for mapper #include mitk::FiberBundleXMapper3D::FiberBundleXMapper3D() :m_FiberMapperGLSP(vtkSmartPointer::New()), m_FiberMapperGLWP(vtkOpenGLPolyDataMapper::New()), m_FiberActorSP(vtkSmartPointer::New()), m_FiberActorWP(vtkOpenGLActor::New()), m_FiberAssembly(vtkPropAssembly::New()) { } mitk::FiberBundleXMapper3D::~FiberBundleXMapper3D() { m_FiberAssembly->Delete(); } const mitk::FiberBundleX* mitk::FiberBundleXMapper3D::GetInput() { MITK_INFO << "FiberBundleXxXXMapper3D() GetInput()"; return static_cast ( GetData() ); } /* This method is called once the mapper gets new input, for UI rotation or changes in colorcoding this method is NOT called */ void mitk::FiberBundleXMapper3D::GenerateData() { //MITK_INFO << "GENERATE DATA FOR FBX :)"; //=====timer measurement==== QTime myTimer; myTimer.start(); //========================== // mitk::FiberBundleX::Pointer FBX = dynamic_cast< mitk::FiberBundleX* > (this->GetData()); - mitk::FiberBundleX::Pointer FBX = dynamic_cast (this->GetData()); - if (FBX.GetPointer() == NULL) { - MITK_INFO << "FBX==NULL"; - } - vtkSmartPointer FiberData = FBX->GetFibers(); + mitk::FiberBundleX* FBX = dynamic_cast (this->GetData()); +// if (FBX == NULL) { +// MITK_INFO << "FBX==NULL"; not allowed to be null ;-) +// } + vtkPolyData* FiberData = FBX->GetFibers(); MITK_INFO << "NumOfFibs: " << FiberData->GetNumberOfLines(); MITK_INFO << "NumOfPoints: " << FiberData->GetNumberOfPoints(); m_FiberMapperGLSP->SetInput(FiberData); // m_FiberMapperGLWP->SetInput(FiberData); if ( FiberData->GetPointData()->GetNumberOfArrays() > 0 ) { if ( FiberData->GetPointData()->HasArray(FiberBundleX::COLORCODING_ORIENTATION_BASED) ) { m_FiberMapperGLSP->SelectColorArray(FiberBundleX::COLORCODING_ORIENTATION_BASED); // m_FiberMapperGLWP->SelectColorArray(FiberBundleX::COLORCODING_ORIENTATION_BASED); } else { // iterate through polydata array and take the first best -but valid- array //===ToDo=== //check of componentsize as well, if it is not RGB or RGBA (ie. size 3 or 4), then check if it is a scalar // if scalar then create lookuptable for that. } m_FiberMapperGLSP->ScalarVisibilityOn(); // m_FiberMapperGLWP->ScalarVisibilityOn(); m_FiberMapperGLSP->SetScalarModeToUsePointFieldData(); // m_FiberMapperGLWP->SetScalarModeToUsePointFieldData(); } m_FiberActorSP->SetMapper(m_FiberMapperGLSP); // m_FiberActorWP->SetMapper(m_FiberMapperGLWP); m_FiberActorSP->GetProperty()->SetOpacity(1.0); // m_FiberActorWP->GetProperty()->SetOpacity(1.0); m_FiberAssembly->AddPart(m_FiberActorSP); //====timer measurement======== MITK_INFO << "Execution Time GenerateData() (nmiliseconds): " << myTimer.elapsed(); //============================= } void mitk::FiberBundleXMapper3D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { //MITK_INFO << "FiberBundleXxXXMapper3D()DataForRenderer"; //ToDo do update checks } void mitk::FiberBundleXMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { // MITK_INFO << "FiberBundleXxXXMapper3D()SetDefaultProperties"; //MITK_INFO << "FiberBundleMapperX3D SetDefault Properties(...)"; // node->AddProperty( "DisplayChannel", mitk::IntProperty::New( true ), renderer, overwrite ); // node->AddProperty( "LineWidth", mitk::IntProperty::New( true ), renderer, overwrite ); // node->AddProperty( "ColorCoding", mitk::IntProperty::New( 0 ), renderer, overwrite); // node->AddProperty( "VertexOpacity_1", mitk::BoolProperty::New( false ), renderer, overwrite); // node->AddProperty( "Set_FA_VertexAlpha", mitk::BoolProperty::New( false ), renderer, overwrite); // node->AddProperty( "pointSize", mitk::FloatProperty::New(0.5), renderer, overwrite); // node->AddProperty( "setShading", mitk::IntProperty::New(1), renderer, overwrite); // node->AddProperty( "Xmove", mitk::IntProperty::New( 0 ), renderer, overwrite); // node->AddProperty( "Ymove", mitk::IntProperty::New( 0 ), renderer, overwrite); // node->AddProperty( "Zmove", mitk::IntProperty::New( 0 ), renderer, overwrite); // node->AddProperty( "RepPoints", mitk::BoolProperty::New( false ), renderer, overwrite); // node->AddProperty( "TubeSides", mitk::IntProperty::New( 8 ), renderer, overwrite); // node->AddProperty( "TubeRadius", mitk::FloatProperty::New( 0.15 ), renderer, overwrite); // node->AddProperty( "TubeOpacity", mitk::FloatProperty::New( 1.0 ), renderer, overwrite); node->AddProperty( "pickable", mitk::BoolProperty::New( true ), renderer, overwrite); Superclass::SetDefaultProperties(node, renderer, overwrite); } vtkProp* mitk::FiberBundleXMapper3D::GetVtkProp(mitk::BaseRenderer *renderer) { //MITK_INFO << "FiberBundleXxXXMapper3D()GetVTKProp"; //this->GenerateData(); return m_FiberAssembly; } void mitk::FiberBundleXMapper3D::ApplyProperties(mitk::BaseRenderer* renderer) { // MITK_INFO << "FiberBundleXXXXMapper3D ApplyProperties(renderer)"; } void mitk::FiberBundleXMapper3D::UpdateVtkObjects() { // MITK_INFO << "FiberBundleXxxXMapper3D UpdateVtkObjects()"; } void mitk::FiberBundleXMapper3D::SetVtkMapperImmediateModeRendering(vtkMapper *) { } diff --git a/Modules/IGT/IGTFilters/mitkNavigationDataSequentialPlayer.cpp b/Modules/IGT/IGTFilters/mitkNavigationDataSequentialPlayer.cpp index 81241543fa..0acf753561 100644 --- a/Modules/IGT/IGTFilters/mitkNavigationDataSequentialPlayer.cpp +++ b/Modules/IGT/IGTFilters/mitkNavigationDataSequentialPlayer.cpp @@ -1,198 +1,200 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2009-02-10 18:08:54 +0100 (Di, 10 Feb 2009) $ Version: $Revision: 16228 $ 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 "mitkNavigationDataSequentialPlayer.h" //for the pause #include #include #include #include mitk::NavigationDataSequentialPlayer::NavigationDataSequentialPlayer() : mitk::NavigationDataPlayerBase() , m_Doc(new TiXmlDocument) , m_DataElem(0) , m_CurrentElem(0) , m_Repeat(false) , m_NumberOfSnapshots(0) , m_LastGoTo(0) { } mitk::NavigationDataSequentialPlayer::~NavigationDataSequentialPlayer() { delete m_Doc; } void mitk::NavigationDataSequentialPlayer::ReinitXML() { m_DataElem = m_Doc->FirstChildElement("Data"); int toolcount; if(!m_DataElem) MITK_WARN << "Data element not found"; else { m_DataElem->QueryIntAttribute("ToolCount", &toolcount); this->SetNumberOfOutputs(toolcount); mitk::NavigationData::Pointer emptyNd = mitk::NavigationData::New(); mitk::NavigationData::PositionType position; mitk::NavigationData::OrientationType orientation(0.0,0.0,0.0,0.0); position.Fill(0.0); emptyNd->SetPosition(position); emptyNd->SetOrientation(orientation); emptyNd->SetDataValid(false); mitk::NavigationData::Pointer tmp; for (unsigned int index = 0; index < this->GetNumberOfOutputs(); index++) { tmp = mitk::NavigationData::New(); tmp->Graft(emptyNd); this->SetNthOutput(index, tmp); } // find out _NumberOfSnapshots m_NumberOfSnapshots = 0; - TiXmlElement* nextND = m_DataElem->FirstChildElement("ND"); + TiXmlElement* nextND = m_DataElem->FirstChildElement("NavigationData"); while(nextND) { ++m_NumberOfSnapshots; - nextND = nextND->NextSiblingElement("ND"); + nextND = nextND->NextSiblingElement("NavigationData"); } // e.g. 12 nd found and 2 tools used => number of snapshots is 12:2=6 m_NumberOfSnapshots = m_NumberOfSnapshots/toolcount; } } void mitk::NavigationDataSequentialPlayer::GoToSnapshot(int i) { assert(m_DataElem); int numOfUpdateCalls = 0; // i.e. number of snapshots 10 // goto(7), m_LastGoTo=3 => numOfUpdateCalls = 4 if(m_LastGoTo <= i) numOfUpdateCalls = i - m_LastGoTo; // goto(4), m_LastGoTo=7 => numOfUpdateCalls = 7 else { if(!m_Repeat) { MITK_WARN << "cannot go back to snapshot " << i << " because the " << this->GetNameOfClass() << " is configured to not repeat the" << " navigation data"; } else { numOfUpdateCalls = (m_NumberOfSnapshots - m_LastGoTo) + i; } } for(int j=0; jUpdate(); m_LastGoTo = i; } void mitk::NavigationDataSequentialPlayer:: SetFileName(const std::string& _FileName) { m_FileName = _FileName; if(!m_Doc->LoadFile(m_FileName)) { this->SetNumberOfOutputs(0); std::ostringstream s; s << "File " << _FileName << " could not be loaded"; throw std::invalid_argument(s.str()); } else this->ReinitXML(); this->Modified(); } void mitk::NavigationDataSequentialPlayer:: SetXMLString(const std::string& _XMLString) { m_XMLString = _XMLString; m_Doc->Parse( m_XMLString.c_str() ); this->ReinitXML(); this->Modified(); } void mitk::NavigationDataSequentialPlayer::GenerateData() { assert(m_DataElem); // very important: go through the tools (there could be more then one) mitk::NavigationData::Pointer tmp; + //MITK_INFO << "this->GetNumberOfOutputs()" << this->GetNumberOfOutputs(); for (unsigned int index = 0; index < this->GetNumberOfOutputs(); index++) { + //MITK_INFO << "index" << index; // go to the first element if(!m_CurrentElem) - m_CurrentElem = m_DataElem->FirstChildElement("ND"); + m_CurrentElem = m_DataElem->FirstChildElement("NavigationData"); // go to the next element else m_CurrentElem = m_CurrentElem->NextSiblingElement(); // if repeat is on: go back to the first element (prior calls delivered NULL // elem) if(!m_CurrentElem && m_Repeat) - m_CurrentElem = m_DataElem->FirstChildElement("ND"); + m_CurrentElem = m_DataElem->FirstChildElement("NavigationData"); mitk::NavigationData* output = this->GetOutput(index); tmp = this->ReadVersion1(); if(tmp.IsNotNull()) { output->Graft(tmp); m_StreamValid = true; } else // no valid output { output->SetDataValid(false); m_StreamValid = false; m_ErrorMessage = "Error: Cannot parse input file."; } } } mitk::NavigationData::Pointer mitk::NavigationDataSequentialPlayer::ReadVersion1() { TiXmlElement* elem = m_CurrentElem; if(!elem) return NULL; return this->ReadNavigationData(elem); } void mitk::NavigationDataSequentialPlayer::UpdateOutputInformation() { this->Modified(); // make sure that we need to be updated Superclass::UpdateOutputInformation(); } diff --git a/Modules/IGT/IGTFilters/mitkNavigationDataToPointSetPlayer.cpp b/Modules/IGT/IGTFilters/mitkNavigationDataToPointSetPlayer.cpp index 1ea2dbc3b2..4b09e5eff0 100644 --- a/Modules/IGT/IGTFilters/mitkNavigationDataToPointSetPlayer.cpp +++ b/Modules/IGT/IGTFilters/mitkNavigationDataToPointSetPlayer.cpp @@ -1,193 +1,193 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2009-02-10 18:08:54 +0100 (Di, 10 Feb 2009) $ Version: $Revision: 16228 $ 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 "mitkNavigationDataToPointSetPlayer.h" //for the pause #include #include #include #include #include mitk::NavigationDataToPointSetPlayer::NavigationDataToPointSetPlayer() : m_Doc(new TiXmlDocument) , m_DataElem(0) , m_CurrentElem(0) , m_Repeat(false) , m_NumberOfSnapshots(0) , m_LastGoTo(0) { } mitk::NavigationDataToPointSetPlayer::~NavigationDataToPointSetPlayer() { delete m_Doc; } void mitk::NavigationDataToPointSetPlayer::ReinitXML() { m_NDPointSet.clear(); m_PointSetFilter = mitk::NavigationDataToPointSetFilter::New(); m_DataElem = m_Doc->FirstChildElement("Data"); int toolcount; if(!m_DataElem) MITK_WARN << "Data element not found"; else { m_DataElem->QueryIntAttribute("ToolCount", &toolcount); this->SetNumberOfOutputs(toolcount); mitk::NavigationData::Pointer emptyNd = mitk::NavigationData::New(); mitk::NavigationData::PositionType position; mitk::NavigationData::OrientationType orientation(0.0,0.0,0.0,0.0); position.Fill(0.0); emptyNd->SetPosition(position); emptyNd->SetOrientation(orientation); emptyNd->SetDataValid(false); mitk::NavigationData::Pointer tmp; for (unsigned int index = 0; index < this->GetNumberOfOutputs(); index++) { tmp = mitk::NavigationData::New(); tmp->Graft(emptyNd); this->SetNthOutput(index, tmp); } // find out _NumberOfSnapshots NavigationData::Pointer nd; m_NumberOfSnapshots = 0; - TiXmlElement* nextND = m_DataElem->FirstChildElement("ND"); + TiXmlElement* nextND = m_DataElem->FirstChildElement("NavigationData"); while(nextND) { ++m_NumberOfSnapshots; - nextND = nextND->NextSiblingElement("ND"); + nextND = nextND->NextSiblingElement("NavigationData"); } // e.g. 12 nd found and 2 tools used => number of snapshots is 12:2=6 m_NumberOfSnapshots = m_NumberOfSnapshots/toolcount; /*NavigationData::TimeStampType recordedTime = (lastTimestamp-firstTimestamp) / 1000; int frameRate = static_cast(floor(1000 / (float) (m_NumberOfSnapshots/recordedTime) + 0.5));*/ } } void mitk::NavigationDataToPointSetPlayer:: SetFileName(const std::string& _FileName) { m_FileName = _FileName; if(!m_Doc->LoadFile(m_FileName)) { this->SetNumberOfOutputs(0); std::ostringstream s; s << "File " << _FileName << " could not be loaded"; throw std::invalid_argument(s.str()); } else { this->ReinitXML(); } this->Modified(); } void mitk::NavigationDataToPointSetPlayer::GenerateData() { assert(m_DataElem); // very important: go through the tools (there could be more then one) mitk::NavigationData::Pointer tmp; for (unsigned int index = 0; index < this->GetNumberOfOutputs(); index++) { // go to the first element if(!m_CurrentElem) - m_CurrentElem = m_DataElem->FirstChildElement("ND"); + m_CurrentElem = m_DataElem->FirstChildElement("NavigationData"); // go to the next element else m_CurrentElem = m_CurrentElem->NextSiblingElement(); // if repeat is on: go back to the first element (prior calls delivered NULL // elem) if(!m_CurrentElem && m_Repeat) - m_CurrentElem = m_DataElem->FirstChildElement("ND"); + m_CurrentElem = m_DataElem->FirstChildElement("NavigationData"); mitk::NavigationData* output = this->GetOutput(index); tmp = this->ReadVersion1(); if(tmp.IsNotNull()) output->Graft(tmp); else // no valid output output->SetDataValid(false); } } void mitk::NavigationDataToPointSetPlayer::StartPlaying() { //TODO } void mitk::NavigationDataToPointSetPlayer::StopPlaying() { //TODO } void mitk::NavigationDataToPointSetPlayer::Pause() { //TODO } void mitk::NavigationDataToPointSetPlayer::Resume() { //TODO } //TODO const bool mitk::NavigationDataToPointSetPlayer::IsAtEnd() { bool result = false; return result; } mitk::NavigationData::Pointer mitk::NavigationDataToPointSetPlayer::ReadVersion1() { TiXmlElement* elem = m_CurrentElem; if(!elem) return NULL; return this->ReadNavigationData(elem); } void mitk::NavigationDataToPointSetPlayer::UpdateOutputInformation() { this->Modified(); // make sure that we need to be updated Superclass::UpdateOutputInformation(); } diff --git a/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp b/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp index cb733a9957..e0e2e43f3a 100644 --- a/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp @@ -1,136 +1,136 @@ /*========================================================================= 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 #include #include "mitkTestingMacros.h" #include #include const char* XML_STRING = "" - "" - "" - "" - "" - "" - "" + "" + "" + "" + "" + "" + "" ""; vnl_vector tTool0Snapshot1(3); vnl_vector tTool1Snapshot2(3); mitk::Quaternion qTool0Snapshot0; mitk::Quaternion qTool1Snapshot1; mitk::NavigationDataSequentialPlayer::Pointer player( mitk::NavigationDataSequentialPlayer::New()); void runLoop() { mitk::NavigationData::Pointer nd0; mitk::NavigationData::Pointer nd1; for(unsigned int i=0; iGetNumberOfSnapshots();++i) { player->Update(); nd0 = player->GetOutput(); nd1 = player->GetOutput(1); // test some values MITK_TEST_CONDITION_REQUIRED(nd0.IsNotNull(), "nd0.IsNotNull()"); MITK_TEST_CONDITION_REQUIRED(nd1.IsNotNull(), "nd1.IsNotNull()"); if(i==0) { MITK_TEST_CONDITION(qTool0Snapshot0.as_vector() == nd0->GetOrientation().as_vector(), "qTool0Snapshot0.as_vector() == nd0->GetOrientation().as_vector()"); } else if(i==1) { MITK_TEST_CONDITION(tTool0Snapshot1 == nd0->GetPosition().GetVnlVector(), "tTool0Snapshot1 == nd0->GetPosition().GetVnlVector()"); MITK_TEST_CONDITION(qTool1Snapshot1.as_vector() == nd1->GetOrientation().as_vector(), "qTool1Snapshot1.as_vector() == nd1->GetOrientation().as_vector()"); } else if(i==2) // should be repeated { MITK_TEST_CONDITION(tTool1Snapshot2 == nd1->GetPosition().GetVnlVector(), "tTool1Snapshot2 == nd1->GetPosition().GetVnlVector()"); } } } /**Documentation * test for the class "NavigationDataRecorder". */ int mitkNavigationDataSequentialPlayerTest(int /* argc */, char* /*argv*/[]) { MITK_TEST_BEGIN("NavigationDataSequentialPlayer"); // create test values valid for the xml data above tTool0Snapshot1[0] = -336.65; tTool0Snapshot1[1] = 138.5; tTool0Snapshot1[2]= -2061.07; tTool1Snapshot2[0] = -56.93; tTool1Snapshot2[1] = 233.79; tTool1Snapshot2[2]= -2042.6; vnl_vector_fixed qVec; qVec[0] = 0.0085; qVec[1] = -0.0576; qVec[2]= -0.0022; qVec[3]= 0.9982; qTool0Snapshot0 = mitk::Quaternion(qVec); qVec[0] = 0.4683; qVec[1] = 0.0188; qVec[2]= -0.8805; qVec[3]= 0.0696; qTool1Snapshot1 = mitk::Quaternion(qVec); player ->SetXMLString(XML_STRING); MITK_TEST_CONDITION_REQUIRED(player->GetNumberOfSnapshots() == 3, "player->GetNumberOfSnapshots() == 3"); player ->SetRepeat(true); runLoop(); // repeat is on should work a second time runLoop(); // now test the go to snapshot function player->GoToSnapshot(3); mitk::NavigationData::Pointer nd1 = player->GetOutput(1); MITK_TEST_CONDITION(tTool1Snapshot2 == nd1->GetPosition().GetVnlVector(), "tTool1Snapshot2 == nd1->GetPosition().GetVnlVector()"); player->GoToSnapshot(1); mitk::NavigationData::Pointer nd0 = player->GetOutput(0); MITK_TEST_CONDITION(qTool0Snapshot0.as_vector() == nd0->GetOrientation().as_vector(), "qTool0Snapshot0.as_vector() == nd0->GetOrientation().as_vector()"); player->GoToSnapshot(3); // and a third time runLoop(); // always end with this! MITK_TEST_END(); } diff --git a/Modules/ToFProcessing/mitkToFCompositeFilter.cpp b/Modules/ToFProcessing/mitkToFCompositeFilter.cpp index 2eceead661..1d04c2e697 100644 --- a/Modules/ToFProcessing/mitkToFCompositeFilter.cpp +++ b/Modules/ToFProcessing/mitkToFCompositeFilter.cpp @@ -1,419 +1,419 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Module: $RCSfile$ 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 #include //#include #include mitk::ToFCompositeFilter::ToFCompositeFilter() : m_ImageWidth(0), m_ImageHeight(0), m_ImageSize(0), m_IplDistanceImage(NULL), m_IplOutputImage(NULL), m_ItkInputImage(NULL), m_ApplyTemporalMedianFilter(false), m_ApplyAverageFilter(false), m_ApplyMedianFilter(false), m_ApplyThresholdFilter(false), m_ApplyBilateralFilter(false), m_DataBuffer(NULL), m_DataBufferCurrentIndex(0), m_DataBufferMaxSize(0), m_TemporalMedianFilterNumOfFrames(10), m_ThresholdFilterMin(1), m_ThresholdFilterMax(7000), m_BilateralFilterDomainSigma(2), m_BilateralFilterRangeSigma(60), m_BilateralFilterKernelRadius(0) { } mitk::ToFCompositeFilter::~ToFCompositeFilter() { cvReleaseImage(&(this->m_IplDistanceImage)); cvReleaseImage(&(this->m_IplOutputImage)); if (m_DataBuffer!=NULL) { delete [] m_DataBuffer; } } void mitk::ToFCompositeFilter::SetInput( mitk::Image* distanceImage ) { this->SetInput(0, distanceImage); } void mitk::ToFCompositeFilter::SetInput( unsigned int idx, mitk::Image* distanceImage ) { if ((distanceImage == NULL) && (idx == this->GetNumberOfInputs() - 1)) // if the last input is set to NULL, reduce the number of inputs by one { this->SetNumberOfInputs(this->GetNumberOfInputs() - 1); } else { if (idx==0) //create IPL image holding distance data { if (distanceImage->GetData()) { this->m_ImageWidth = distanceImage->GetDimension(0); this->m_ImageHeight = distanceImage->GetDimension(1); this->m_ImageSize = this->m_ImageWidth * this->m_ImageHeight * sizeof(float); if (this->m_IplDistanceImage != NULL) { cvReleaseImage(&(this->m_IplDistanceImage)); } float* distanceFloatData = (float*)distanceImage->GetSliceData(0, 0, 0)->GetData(); this->m_IplDistanceImage = cvCreateImage(cvSize(this->m_ImageWidth, this->m_ImageHeight), IPL_DEPTH_32F, 1); memcpy(this->m_IplDistanceImage->imageData, (void*)distanceFloatData, this->m_ImageSize); if (this->m_IplOutputImage != NULL) { cvReleaseImage(&(this->m_IplOutputImage)); } this->m_IplOutputImage = cvCreateImage(cvSize(this->m_ImageWidth, this->m_ImageHeight), IPL_DEPTH_32F, 1); CreateItkImage(this->m_ItkInputImage); } } this->ProcessObject::SetNthInput(idx, distanceImage); // Process object is not const-correct so the const_cast is required here } this->CreateOutputsForAllInputs(); } mitk::Image* mitk::ToFCompositeFilter::GetInput() { return this->GetInput(0); } mitk::Image* mitk::ToFCompositeFilter::GetInput( unsigned int idx ) { if (this->GetNumberOfInputs() < 1) return NULL; //TODO: geeignete exception werfen return static_cast< mitk::Image*>(this->ProcessObject::GetInput(idx)); } void mitk::ToFCompositeFilter::GenerateData() { // copy input 1...n to output 1...n for (unsigned int idx=0; idxGetNumberOfOutputs(); idx++) { mitk::Image::Pointer outputImage = this->GetOutput(idx); mitk::Image::Pointer inputImage = this->GetInput(idx); if (outputImage.IsNotNull()&&inputImage.IsNotNull()) { outputImage->CopyInformation(inputImage); outputImage->Initialize(inputImage); outputImage->SetSlice(inputImage->GetSliceData()->GetData()); } } mitk::Image::Pointer outputDistanceImage = this->GetOutput(0); float* outputDistanceFloatData = (float*)outputDistanceImage->GetSliceData(0, 0, 0)->GetData(); mitk::Image::Pointer inputDistanceImage = this->GetInput(); // copy initial distance image to ipl image float* distanceFloatData = (float*)inputDistanceImage->GetSliceData(0, 0, 0)->GetData(); memcpy(this->m_IplDistanceImage->imageData, (void*)distanceFloatData, this->m_ImageSize); if (m_ApplyThresholdFilter) { ProcessThresholdFilter(this->m_IplDistanceImage, this->m_ThresholdFilterMin, this->m_ThresholdFilterMax); } if (this->m_ApplyTemporalMedianFilter||this->m_ApplyAverageFilter) { ProcessStreamedQuickSelectMedianImageFilter(this->m_IplDistanceImage, this->m_TemporalMedianFilterNumOfFrames); } if (this->m_ApplyMedianFilter) { ProcessCVMedianFilter(this->m_IplDistanceImage, this->m_IplOutputImage); memcpy( this->m_IplDistanceImage->imageData, this->m_IplOutputImage->imageData, this->m_ImageSize ); } if (this->m_ApplyBilateralFilter) { float* itkFloatData = this->m_ItkInputImage->GetBufferPointer(); memcpy(itkFloatData, this->m_IplDistanceImage->imageData, this->m_ImageSize ); ItkImageType2D::Pointer itkOutputImage = ProcessItkBilateralFilter(this->m_ItkInputImage, this->m_BilateralFilterDomainSigma, this->m_BilateralFilterRangeSigma, this->m_BilateralFilterKernelRadius); memcpy( this->m_IplDistanceImage->imageData, itkOutputImage->GetBufferPointer(), this->m_ImageSize ); //ProcessCVBilateralFilter(this->m_IplDistanceImage, this->m_OutputIplImage, domainSigma, rangeSigma, kernelRadius); //memcpy( distanceFloatData, this->m_OutputIplImage->imageData, distanceImageSize ); } memcpy( outputDistanceFloatData, this->m_IplDistanceImage->imageData, this->m_ImageSize ); } void mitk::ToFCompositeFilter::CreateOutputsForAllInputs() { this->SetNumberOfOutputs(this->GetNumberOfInputs()); // create outputs for all inputs for (unsigned int idx = 0; idx < this->GetNumberOfOutputs(); ++idx) if (this->GetOutput(idx) == NULL) { DataObjectPointer newOutput = this->MakeOutput(idx); this->SetNthOutput(idx, newOutput); } this->Modified(); } void mitk::ToFCompositeFilter::GenerateOutputInformation() { mitk::Image::ConstPointer input = this->GetInput(); mitk::Image::Pointer output = this->GetOutput(); if (output->IsInitialized()) return; itkDebugMacro(<<"GenerateOutputInformation()"); output->Initialize(input->GetPixelType(), *input->GetTimeSlicedGeometry()); output->SetPropertyList(input->GetPropertyList()->Clone()); } void mitk::ToFCompositeFilter::ProcessThresholdFilter(IplImage* inputIplImage, int min, int max) { for(int i=0; im_ImageWidth*this->m_ImageHeight; i++) { float *f = (float*)inputIplImage->imageData; if (f[i]<=min) { f[i] = 0.0; } else if (f[i]>=max) { f[i] = 0.0; } } } ItkImageType2D::Pointer mitk::ToFCompositeFilter::ProcessItkBilateralFilter(ItkImageType2D::Pointer inputItkImage, int domainSigma, int rangeSigma, int kernelRadius) { ItkImageType2D::Pointer outputItkImage; BilateralFilterType::Pointer bilateralFilter = BilateralFilterType::New(); bilateralFilter->SetInput(inputItkImage); bilateralFilter->SetDomainSigma(domainSigma); bilateralFilter->SetRangeSigma(rangeSigma); //bilateralFilter->SetRadius(kernelRadius); outputItkImage = bilateralFilter->GetOutput(); outputItkImage->Update(); return outputItkImage; } void mitk::ToFCompositeFilter::ProcessCVBilateralFilter(IplImage* inputIplImage, IplImage* outputIplImage, int domainSigma, int rangeSigma, int kernelRadius) { int diameter = kernelRadius; double sigmaColor = rangeSigma; double sigmaSpace = domainSigma; cvSmooth(inputIplImage, outputIplImage, CV_BILATERAL, diameter, 0, sigmaColor, sigmaSpace); } void mitk::ToFCompositeFilter::ProcessCVMedianFilter(IplImage* inputIplImage, IplImage* outputIplImage, int radius) { cvSmooth(inputIplImage, outputIplImage, CV_MEDIAN, radius, 0, 0, 0); } void mitk::ToFCompositeFilter::ProcessStreamedQuickSelectMedianImageFilter(IplImage* inputIplImage, int numOfImages) { float* data = (float*)inputIplImage->imageData; int imageSize = inputIplImage->width * inputIplImage->height; float* tmpArray; if (numOfImages == 0) { return; } if (numOfImages != this->m_DataBufferMaxSize) // reset { //delete current buffer for( int i=0; im_DataBufferMaxSize; i++ ) { delete[] this->m_DataBuffer[i]; } if (this->m_DataBuffer != NULL) { delete[] this->m_DataBuffer; } this->m_DataBufferMaxSize = numOfImages; // create new buffer with current size this->m_DataBuffer = new float*[this->m_DataBufferMaxSize]; for(int i=0; im_DataBufferMaxSize; i++) { this->m_DataBuffer[i] = NULL; } this->m_DataBufferCurrentIndex = 0; } int currentBufferSize = this->m_DataBufferMaxSize; tmpArray = new float[this->m_DataBufferMaxSize]; // copy data to buffer if (this->m_DataBuffer[this->m_DataBufferCurrentIndex] == NULL) { this->m_DataBuffer[this->m_DataBufferCurrentIndex] = new float[imageSize]; currentBufferSize = this->m_DataBufferCurrentIndex + 1; } for(int j=0; jm_DataBuffer[this->m_DataBufferCurrentIndex][j] = data[j]; } float tmpValue = 0.0f; for(int i=0; im_DataBuffer[j][i]; } - data[i] = tmpValue/numOfImages; + data[i] = tmpValue/currentBufferSize; } else if (m_ApplyTemporalMedianFilter) { for(int j=0; jm_DataBuffer[j][i]; } data[i] = quick_select(tmpArray, currentBufferSize); } } this->m_DataBufferCurrentIndex = (this->m_DataBufferCurrentIndex + 1) % this->m_DataBufferMaxSize; delete[] tmpArray; } #define ELEM_SWAP(a,b) { register float t=(a);(a)=(b);(b)=t; } float mitk::ToFCompositeFilter::quick_select(float arr[], int n) { int low = 0; int high = n-1; int median = (low + high)/2; int middle = 0; int ll = 0; int hh = 0; for (;;) { if (high <= low) /* One element only */ return arr[median] ; if (high == low + 1) { /* Two elements only */ if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]) ; return arr[median] ; } /* Find median of low, middle and high items; swap into position low */ middle = (low + high) / 2; if (arr[middle] > arr[high]) ELEM_SWAP(arr[middle], arr[high]) ; if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]) ; if (arr[middle] > arr[low]) ELEM_SWAP(arr[middle], arr[low]) ; /* Swap low item (now in position middle) into position (low+1) */ ELEM_SWAP(arr[middle], arr[low+1]) ; /* Nibble from each end towards middle, swapping items when stuck */ ll = low + 1; hh = high; for (;;) { do ll++; while (arr[low] > arr[ll]) ; do hh--; while (arr[hh] > arr[low]) ; if (hh < ll) break; ELEM_SWAP(arr[ll], arr[hh]) ; } /* Swap middle item (in position low) back into correct position */ ELEM_SWAP(arr[low], arr[hh]) ; /* Re-set active partition */ if (hh <= median) low = ll; if (hh >= median) high = hh - 1; } } #undef ELEM_SWAP bool mitk::ToFCompositeFilter::GetApplyTemporalMedianFilter() { return this->m_ApplyTemporalMedianFilter; } bool mitk::ToFCompositeFilter::GetApplyMedianFilter() { return this->m_ApplyMedianFilter; } bool mitk::ToFCompositeFilter::GetApplyThresholdFilter() { return this->m_ApplyThresholdFilter; } bool mitk::ToFCompositeFilter::GetApplyBilateralFilter() { return this->m_ApplyBilateralFilter; } void mitk::ToFCompositeFilter::SetApplyTemporalMedianFilter(bool flag) { this->m_ApplyTemporalMedianFilter = flag; } void mitk::ToFCompositeFilter::SetApplyAverageFilter(bool flag) { this->m_ApplyAverageFilter = flag; } void mitk::ToFCompositeFilter::SetApplyMedianFilter(bool flag) { this->m_ApplyMedianFilter = flag; } void mitk::ToFCompositeFilter::SetApplyThresholdFilter(bool flag) { this->m_ApplyThresholdFilter = flag; } void mitk::ToFCompositeFilter::SetApplyBilateralFilter(bool flag) { this->m_ApplyBilateralFilter = flag; } void mitk::ToFCompositeFilter::SetTemporalMedianFilterParameter(int tmporalMedianFilterNumOfFrames) { this->m_TemporalMedianFilterNumOfFrames = tmporalMedianFilterNumOfFrames; } void mitk::ToFCompositeFilter::SetThresholdFilterParameter(int min, int max) { if (min > max) { min = max; } this->m_ThresholdFilterMin = min; this->m_ThresholdFilterMax = max; } void mitk::ToFCompositeFilter::SetBilateralFilterParameter(int domainSigma, int rangeSigma, int kernelRadius = 0) { this->m_BilateralFilterDomainSigma = domainSigma; this->m_BilateralFilterRangeSigma = rangeSigma; this->m_BilateralFilterKernelRadius = kernelRadius; } void mitk::ToFCompositeFilter::CreateItkImage(ItkImageType2D::Pointer &itkInputImage) { itkInputImage = ItkImageType2D::New(); ItkImageType2D::IndexType startIndex; startIndex[0] = 0; // first index on X startIndex[1] = 0; // first index on Y ItkImageType2D::SizeType size; size[0] = this->m_ImageWidth; // size along X size[1] = this->m_ImageHeight; // size along Y ItkImageType2D::RegionType region; region.SetSize( size ); region.SetIndex( startIndex ); itkInputImage->SetRegions( region ); itkInputImage->Allocate(); }