diff --git a/Modules/Bundles/CMakeLists.txt b/Modules/Bundles/CMakeLists.txt index 2adfcf8006..6ff0566acf 100644 --- a/Modules/Bundles/CMakeLists.txt +++ b/Modules/Bundles/CMakeLists.txt @@ -1,40 +1,41 @@ IF(MITK_USE_BLUEBERRY) SET(MITK_DEFAULT_SUBPROJECTS MITK-Plugins) SET(_mitk_bundles_default ) IF(QT4_FOUND) LIST(APPEND _mitk_bundles_default "org.mitk.gui.qt.imagenavigator") # BlueBerry depends on CTK which depends on Qt, so we # need the Qt include direcotries INCLUDE(${QT_USE_FILE}) ENDIF() SET(PLUGIN_EXCLUDE_LIST org.mitk.core.ext org.mitk.gui.qt.volumetry org.mitk.core.jobs org.mitk.diffusionimaging org.mitk.gui.qt.diffusionimaging org.mitk.gui.qt.ext org.mitk.gui.qt.extapplication org.mitk.gui.qt.datamanager + org.mitk.gui.qt.segmentation org.mitk.planarfigure ) MACRO_COLLECT_PLUGINS(OUTPUT_DIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ExtBundles CACHE_PLUGIN_SOURCE_DIRS MITK_MODULES_PLUGIN_SOURCE_DIRS CACHE_PLUGIN_OUTPUT_DIRS MITK_MODULES_PLUGIN_OUTPUT_DIRS CACHE_PLUGIN_TARGETS MITK_MODULES_ENABLED_PLUGINS BUNDLE_LIST_PATH "${MITK_BINARY_DIR}/Bundles/MITKModulesBundleList.cmake" CMAKE_CACHE_PREFIX "MITK" PLUGIN_DEFAULT_ON ${_mitk_bundles_default} PLUGIN_EXCLUDES ${PLUGIN_EXCLUDE_LIST} ${MITK_BUILD_ALL_PLUGINS_OPTION}) ENDIF(MITK_USE_BLUEBERRY) diff --git a/Modules/Bundles/PluginList.cmake b/Modules/Bundles/PluginList.cmake index 66f20fe41d..26e4d630d5 100644 --- a/Modules/Bundles/PluginList.cmake +++ b/Modules/Bundles/PluginList.cmake @@ -1,10 +1,11 @@ SET(MITK_EXT_PLUGINS org.mitk.core.ext:ON org.mitk.core.jobs:OFF org.mitk.diffusionimaging:OFF org.mitk.gui.qt.diffusionimaging:OFF org.mitk.gui.qt.ext:ON org.mitk.gui.qt.extapplication:ON + org.mitk.gui.qt.segmentation:OFF org.mitk.planarfigure:ON org.mitk.gui.qt.datamanager:ON ) diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/CMakeLists.txt b/Modules/Bundles/org.mitk.gui.qt.segmentation/CMakeLists.txt index d1fae30ab7..9d9cf6f307 100644 --- a/Modules/Bundles/org.mitk.gui.qt.segmentation/CMakeLists.txt +++ b/Modules/Bundles/org.mitk.gui.qt.segmentation/CMakeLists.txt @@ -1 +1,7 @@ -MACRO_CREATE_MITK_PLUGIN(QmitkExt) +PROJECT(org_mitk_gui_qt_segmentation) + +MACRO_CREATE_MITK_CTK_PLUGIN( + EXPORT_DIRECTIVE MITK_QT_SEGMENTATION + EXPORTED_INCLUDE_SUFFIXES src + MODULE_DEPENDENCIES QmitkExt +) diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/META-INF/MANIFEST.MF b/Modules/Bundles/org.mitk.gui.qt.segmentation/META-INF/MANIFEST.MF deleted file mode 100644 index 1f5da077a9..0000000000 --- a/Modules/Bundles/org.mitk.gui.qt.segmentation/META-INF/MANIFEST.MF +++ /dev/null @@ -1,6 +0,0 @@ -Manifest-Version: 1.0 -Bundle-Name: Segmentation -Bundle-SymbolicName: org.mitk.gui.qt.segmentation -Bundle-Version: 1.0.0 -Bundle-Vendor: DKFZ, Medical and Biological Informatics -Require-Bundle: org.mitk.gui.qt.common, org.mitk.gui.qt.datamanager diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/files.cmake b/Modules/Bundles/org.mitk.gui.qt.segmentation/files.cmake index db62e6df58..439b3a9e35 100644 --- a/Modules/Bundles/org.mitk.gui.qt.segmentation/files.cmake +++ b/Modules/Bundles/org.mitk.gui.qt.segmentation/files.cmake @@ -1,45 +1,48 @@ SET(SRC_CPP_FILES QmitkSegmentationPreferencePage.cpp ) SET(INTERNAL_CPP_FILES + mitkPluginActivator.cpp QmitkSegmentationView.cpp QmitkSegmentationPostProcessing.cpp QmitkThresholdAction.cpp QmitkCreatePolygonModelAction.cpp QmitkStatisticsAction.cpp - QmitkAutocropAction.cpp + QmitkAutocropAction.cpp ) SET(UI_FILES src/internal/QmitkSegmentationControls.ui ) SET(MOC_H_FILES src/QmitkSegmentationPreferencePage.h + src/internal/mitkPluginActivator.h src/internal/QmitkSegmentationView.h src/internal/QmitkSegmentationPostProcessing.h src/internal/QmitkThresholdAction.h src/internal/QmitkCreatePolygonModelAction.h src/internal/QmitkStatisticsAction.h src/internal/QmitkAutocropAction.h ) -SET(RESOURCE_FILES +SET(CACHED_RESOURCE_FILES resources/segmentation.png + plugin.xml ) -SET(RES_FILES +SET(QRC_FILES resources/segmentation.qrc ) -SET(CPP_FILES manifest.cpp) +SET(CPP_FILES) foreach(file ${SRC_CPP_FILES}) SET(CPP_FILES ${CPP_FILES} src/${file}) endforeach(file ${SRC_CPP_FILES}) foreach(file ${INTERNAL_CPP_FILES}) SET(CPP_FILES ${CPP_FILES} src/internal/${file}) endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/manifest.cpp b/Modules/Bundles/org.mitk.gui.qt.segmentation/manifest.cpp deleted file mode 100644 index 522a7e6c9d..0000000000 --- a/Modules/Bundles/org.mitk.gui.qt.segmentation/manifest.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/*========================================================================= - -Program: Medical Imaging & Interaction Toolkit -Language: C++ -Date: $Date$ -Version: $Revision: 14645 $ - -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 "src/internal/QmitkSegmentationView.h" -#include "src/QmitkSegmentationPreferencePage.h" -#include "src/internal/QmitkThresholdAction.h" -#include "src/internal/QmitkCreatePolygonModelAction.h" -#include "src/internal/QmitkStatisticsAction.h" -#include "src/internal/QmitkAutocropAction.h" - - -POCO_BEGIN_NAMED_MANIFEST(berryIViewPart, berry::IViewPart) - POCO_EXPORT_CLASS(QmitkSegmentationView) -POCO_END_MANIFEST - -POCO_BEGIN_NAMED_MANIFEST(berryIPreferencePage, berry::IPreferencePage) - POCO_EXPORT_CLASS(QmitkSegmentationPreferencePage) -POCO_END_MANIFEST - -POCO_BEGIN_NAMED_MANIFEST(mitkIContextMenuAction, mitk::IContextMenuAction) - POCO_EXPORT_CLASS(QmitkThresholdAction) - POCO_EXPORT_CLASS(QmitkCreatePolygonModelAction) - POCO_EXPORT_CLASS(QmitkStatisticsAction) - POCO_EXPORT_CLASS(QmitkAutocropAction) -POCO_END_MANIFEST diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/manifest_headers.cmake b/Modules/Bundles/org.mitk.gui.qt.segmentation/manifest_headers.cmake new file mode 100644 index 0000000000..7372947673 --- /dev/null +++ b/Modules/Bundles/org.mitk.gui.qt.segmentation/manifest_headers.cmake @@ -0,0 +1,5 @@ +set(Plugin-Name "Segmentation") +set(Plugin-Version "1.0.0") +set(Plugin-Vendor "DKFZ, Medical and Biological Informatics") +set(Plugin-ContactAddress "http://www.mitk.org") +set(Require-Plugin org.mitk.gui.qt.common org.mitk.gui.qt.datamanager) diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/QmitkSegmentationPreferencePage.cpp b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/QmitkSegmentationPreferencePage.cpp index 33ca3c8301..c5e04c0193 100644 --- a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/QmitkSegmentationPreferencePage.cpp +++ b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/QmitkSegmentationPreferencePage.cpp @@ -1,115 +1,120 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: 18019 $ 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 "QmitkSegmentationPreferencePage.h" #include #include #include #include #include #include #include #include #include QmitkSegmentationPreferencePage::QmitkSegmentationPreferencePage() : m_MainControl(0) , m_Initializing(false) { } +QmitkSegmentationPreferencePage::~QmitkSegmentationPreferencePage() +{ + +} + void QmitkSegmentationPreferencePage::Init(berry::IWorkbench::Pointer ) { } void QmitkSegmentationPreferencePage::CreateQtControl(QWidget* parent) { m_Initializing = true; berry::IPreferencesService::Pointer prefService = berry::Platform::GetServiceRegistry() .GetServiceById(berry::IPreferencesService::ID); m_SegmentationPreferencesNode = prefService->GetSystemPreferences()->Node("/org.mitk.views.segmentation"); m_MainControl = new QWidget(parent); QVBoxLayout* displayOptionsLayout = new QVBoxLayout; m_RadioOutline = new QRadioButton( "Draw as outline", m_MainControl); displayOptionsLayout->addWidget( m_RadioOutline ); m_RadioOverlay = new QRadioButton( "Draw as transparent overlay", m_MainControl); displayOptionsLayout->addWidget( m_RadioOverlay ); QFormLayout *formLayout = new QFormLayout; formLayout->addRow( "2D display", displayOptionsLayout ); m_VolumeRenderingCheckBox = new QCheckBox( "Show as volume rendering", m_MainControl ); formLayout->addRow( "3D display", m_VolumeRenderingCheckBox ); connect( m_VolumeRenderingCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnVolumeRenderingCheckboxChecked(int)) ); m_MainControl->setLayout(formLayout); this->Update(); m_Initializing = false; } QWidget* QmitkSegmentationPreferencePage::GetQtControl() const { return m_MainControl; } bool QmitkSegmentationPreferencePage::PerformOk() { m_SegmentationPreferencesNode->PutBool("draw outline", m_RadioOutline->isChecked()); m_SegmentationPreferencesNode->PutBool("volume rendering", m_VolumeRenderingCheckBox->isChecked()); return true; } void QmitkSegmentationPreferencePage::PerformCancel() { } void QmitkSegmentationPreferencePage::Update() { //m_EnableSingleEditing->setChecked(m_SegmentationPreferencesNode->GetBool("Single click property editing", true)); if (m_SegmentationPreferencesNode->GetBool("draw outline", true) ) { m_RadioOutline->setChecked( true ); } else { m_RadioOverlay->setChecked( true ); } m_VolumeRenderingCheckBox->setChecked( m_SegmentationPreferencesNode->GetBool("volume rendering", false) ); } void QmitkSegmentationPreferencePage::OnVolumeRenderingCheckboxChecked(int state) { if (m_Initializing) return; if ( state != Qt::Unchecked ) { QMessageBox::information(NULL, "Memory warning", "Turning on volume rendering of segmentations will make the application more memory intensive (and potentially prone to crashes).\n\n" "If you encounter out-of-memory problems, try turning off volume rendering again."); } } diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/QmitkSegmentationPreferencePage.h b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/QmitkSegmentationPreferencePage.h index 2d3555cadd..c5c68f8aa5 100644 --- a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/QmitkSegmentationPreferencePage.h +++ b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/QmitkSegmentationPreferencePage.h @@ -1,76 +1,82 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: 16224 $ 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 QmitkSegmentationPreferencePage_h_included #define QmitkSegmentationPreferencePage_h_included #include "berryIQtPreferencePage.h" -#include "mitkQtSegmentationDll.h" +#include "org_mitk_gui_qt_segmentation_Export.h" #include class QWidget; class QCheckBox; class QRadioButton; class MITK_QT_SEGMENTATION QmitkSegmentationPreferencePage : public QObject, public berry::IQtPreferencePage { Q_OBJECT public: QmitkSegmentationPreferencePage(); + QmitkSegmentationPreferencePage(const QmitkSegmentationPreferencePage& other) + { + Q_UNUSED(other) + throw std::runtime_error("Copy constructor not implemented"); + } + ~QmitkSegmentationPreferencePage(); void Init(berry::IWorkbench::Pointer workbench); void CreateQtControl(QWidget* widget); QWidget* GetQtControl() const; /// /// \see IPreferencePage::PerformOk() /// virtual bool PerformOk(); /// /// \see IPreferencePage::PerformCancel() /// virtual void PerformCancel(); /// /// \see IPreferencePage::Update() /// virtual void Update(); protected slots: void OnVolumeRenderingCheckboxChecked(int); protected: QWidget* m_MainControl; QRadioButton* m_RadioOutline; QRadioButton* m_RadioOverlay; QCheckBox* m_VolumeRenderingCheckBox; bool m_Initializing; berry::IPreferences::Pointer m_SegmentationPreferencesNode; }; #endif /* QMITKDATAMANAGERPREFERENCEPAGE_H_ */ diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropAction.h b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropAction.h index 5c981278bd..b8908ce9ed 100644 --- a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropAction.h +++ b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropAction.h @@ -1,36 +1,43 @@ #ifndef QMITK_AUTOCROPACTION_H #define QMITK_AUTOCROPACTION_H #include "mitkIContextMenuAction.h" -#include "mitkQtSegmentationDll.h" +#include "org_mitk_gui_qt_segmentation_Export.h" #include "vector" #include "mitkDataNode.h" #include "mitkImage.h" -class MITK_QT_SEGMENTATION QmitkAutocropAction : public mitk::IContextMenuAction +class MITK_QT_SEGMENTATION QmitkAutocropAction : public QObject, public mitk::IContextMenuAction { + Q_OBJECT + public: QmitkAutocropAction(); + QmitkAutocropAction(const QmitkAutocropAction& other) + { + Q_UNUSED(other) + throw std::runtime_error("Copy constructor not implemented"); + } virtual ~QmitkAutocropAction(); //interface methods void Run( const std::vector& selectedNodes ); void SetDataStorage(mitk::DataStorage* dataStorage); void SetSmoothed(bool smoothed); void SetDecimated(bool decimated); void SetFunctionality(berry::QtViewPart* functionality); protected: mitk::Image::Pointer IncreaseCroppedImageSize( mitk::Image::Pointer image ); private: typedef std::vector NodeList; }; -#endif // QMITK_AUTOCROPACTION_H \ No newline at end of file +#endif // QMITK_AUTOCROPACTION_H diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkCreatePolygonModelAction.h b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkCreatePolygonModelAction.h index be145c3d7c..fd18f8b83b 100644 --- a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkCreatePolygonModelAction.h +++ b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkCreatePolygonModelAction.h @@ -1,38 +1,44 @@ #ifndef QMITK_CREATEPOLYGONMODELACTION_H #define QMITK_CREATEPOLYGONMODELACTION_H #include "berryQtViewPart.h" #include "mitkIContextMenuAction.h" -#include "mitkQtSegmentationDll.h" +#include "org_mitk_gui_qt_segmentation_Export.h" #include "mitkDataNode.h" -class MITK_QT_SEGMENTATION QmitkCreatePolygonModelAction: public mitk::IContextMenuAction +class MITK_QT_SEGMENTATION QmitkCreatePolygonModelAction: public QObject, public mitk::IContextMenuAction { + Q_OBJECT public: QmitkCreatePolygonModelAction(); + QmitkCreatePolygonModelAction(const QmitkCreatePolygonModelAction& other) + { + Q_UNUSED(other) + throw std::runtime_error("Copy constructor not implemented"); + } virtual ~QmitkCreatePolygonModelAction(); //interface methods void Run( const std::vector& selectedNodes ); void SetDataStorage(mitk::DataStorage* dataStorage); void SetSmoothed(bool smoothed); void SetDecimated(bool decimated); void SetFunctionality(berry::QtViewPart* functionality); // for receiving messages void OnSurfaceCalculationDone(); protected: typedef std::vector NodeList; mitk::DataStorage::Pointer m_DataStorage; bool m_IsSmoothed; bool m_IsDecimated; }; -#endif // QMITK_CREATEPOLYGONMODELACTION_H \ No newline at end of file +#endif // QMITK_CREATEPOLYGONMODELACTION_H diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp index 21252104bd..eaf2c40a52 100644 --- a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp +++ b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp @@ -1,925 +1,924 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: 1.12 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkDataNodeObject.h" #include "mitkProperties.h" #include "mitkSegTool2D.h" #include "mitkGlobalInteraction.h" #include "QmitkStdMultiWidget.h" #include "QmitkNewSegmentationDialog.h" #include #include #include "QmitkSegmentationView.h" #include "QmitkSegmentationPostProcessing.h" #include "QmitkSegmentationOrganNamesHandling.cpp" #include #include #include "mitkVtkResliceInterpolationProperty.h" // public methods QmitkSegmentationView::QmitkSegmentationView() :m_Parent(NULL) ,m_Controls(NULL) ,m_MultiWidget(NULL) -// ,m_PostProcessing(NULL) ,m_RenderingManagerObserverTag(0) { } QmitkSegmentationView::~QmitkSegmentationView() { // delete m_PostProcessing; delete m_Controls; } void QmitkSegmentationView::NewNodesGenerated() { // ForceDisplayPreferencesUponAllImages(); } void QmitkSegmentationView::NewNodeObjectsGenerated(mitk::ToolManager::DataVectorType* nodes) { if (!nodes) return; mitk::ToolManager* toolManager = m_Controls->m_ManualToolSelectionBox->GetToolManager(); if (!toolManager) return; for (mitk::ToolManager::DataVectorType::iterator iter = nodes->begin(); iter != nodes->end(); ++iter) { this->FireNodeSelected( *iter ); // only last iteration meaningful, multiple generated objects are not taken into account here } } void QmitkSegmentationView::Activated() { // should be moved to ::BecomesVisible() or similar if( m_Controls ) { m_Controls->m_ManualToolSelectionBox->setEnabled( true ); m_Controls->m_OrganToolSelectionBox->setEnabled( true ); m_Controls->m_LesionToolSelectionBox->setEnabled( true ); m_Controls->m_SlicesInterpolator->EnableInterpolation( m_Controls->widgetStack->currentWidget() == m_Controls->pageManual ); itk::ReceptorMemberCommand::Pointer command1 = itk::ReceptorMemberCommand::New(); command1->SetCallbackFunction( this, &QmitkSegmentationView::RenderingManagerReinitialized ); m_RenderingManagerObserverTag = mitk::RenderingManager::GetInstance()->AddObserver( mitk::RenderingManagerViewsInitializedEvent(), command1 ); } } void QmitkSegmentationView::Deactivated() { if( m_Controls ) { mitk::RenderingManager::GetInstance()->RemoveObserver( m_RenderingManagerObserverTag ); m_Controls->m_ManualToolSelectionBox->setEnabled( false ); //deactivate all tools m_Controls->m_ManualToolSelectionBox->GetToolManager()->ActivateTool(-1); m_Controls->m_OrganToolSelectionBox->setEnabled( false ); m_Controls->m_LesionToolSelectionBox->setEnabled( false ); m_Controls->m_SlicesInterpolator->EnableInterpolation( false ); } } void QmitkSegmentationView::StdMultiWidgetAvailable( QmitkStdMultiWidget& stdMultiWidget ) { SetMultiWidget(&stdMultiWidget); } void QmitkSegmentationView::StdMultiWidgetNotAvailable() { SetMultiWidget(NULL); } void QmitkSegmentationView::StdMultiWidgetClosed( QmitkStdMultiWidget& /*stdMultiWidget*/ ) { SetMultiWidget(NULL); } void QmitkSegmentationView::SetMultiWidget(QmitkStdMultiWidget* multiWidget) { if (m_MultiWidget) { mitk::SlicesCoordinator* coordinator = m_MultiWidget->GetSlicesRotator(); if (coordinator) { coordinator->RemoveObserver( m_SlicesRotationObserverTag1 ); } coordinator = m_MultiWidget->GetSlicesSwiveller(); if (coordinator) { coordinator->RemoveObserver( m_SlicesRotationObserverTag2 ); } } // save the current multiwidget as the working widget m_MultiWidget = multiWidget; if (m_MultiWidget) { mitk::SlicesCoordinator* coordinator = m_MultiWidget->GetSlicesRotator(); if (coordinator) { itk::ReceptorMemberCommand::Pointer command2 = itk::ReceptorMemberCommand::New(); command2->SetCallbackFunction( this, &QmitkSegmentationView::SliceRotation ); m_SlicesRotationObserverTag1 = coordinator->AddObserver( mitk::SliceRotationEvent(), command2 ); } coordinator = m_MultiWidget->GetSlicesSwiveller(); if (coordinator) { itk::ReceptorMemberCommand::Pointer command2 = itk::ReceptorMemberCommand::New(); command2->SetCallbackFunction( this, &QmitkSegmentationView::SliceRotation ); m_SlicesRotationObserverTag2 = coordinator->AddObserver( mitk::SliceRotationEvent(), command2 ); } } if (m_Parent) { m_Parent->setEnabled(m_MultiWidget); } // tell the interpolation about toolmanager and multiwidget (and data storage) if (m_Controls && m_MultiWidget) { mitk::ToolManager* toolManager = m_Controls->m_ManualToolSelectionBox->GetToolManager(); m_Controls->m_SlicesInterpolator->SetDataStorage( *(this->GetDefaultDataStorage())); m_Controls->m_SlicesInterpolator->Initialize( toolManager, m_MultiWidget ); } } void QmitkSegmentationView::OnPreferencesChanged(const berry::IBerryPreferences*) { ForceDisplayPreferencesUponAllImages(); } void QmitkSegmentationView::RenderingManagerReinitialized(const itk::EventObject&) { CheckImageAlignment(); } void QmitkSegmentationView::SliceRotation(const itk::EventObject&) { CheckImageAlignment(); } // protected slots void QmitkSegmentationView::CreateNewSegmentation() { mitk::DataNode::Pointer node = m_Controls->m_ManualToolSelectionBox->GetToolManager()->GetReferenceData(0); if (node.IsNotNull()) { mitk::Image::Pointer image = dynamic_cast( node->GetData() ); if (image.IsNotNull()) { if (image->GetDimension()>2) { // ask about the name and organ type of the new segmentation QmitkNewSegmentationDialog* dialog = new QmitkNewSegmentationDialog( m_Parent ); // needs a QWidget as parent, "this" is not QWidget QString storedList = QString::fromStdString( this->GetPreferences()->GetByteArray("Organ-Color-List","") ); QStringList organColors; if (storedList.isEmpty()) { organColors = GetDefaultOrganColorString(); } else { /* a couple of examples of how organ names are stored: a simple item is built up like 'name#AABBCC' where #AABBCC is the hexadecimal notation of a color as known from HTML items are stored separated by ';' this makes it necessary to escape occurrences of ';' in name. otherwise the string "hugo;ypsilon#AABBCC;eugen#AABBCC" could not be parsed as two organs but we would get "hugo" and "ypsilon#AABBCC" and "eugen#AABBCC" so the organ name "hugo;ypsilon" is stored as "hugo\;ypsilon" and must be unescaped after loading the following lines could be one split with Perl's negative lookbehind */ // recover string list from BlueBerry view's preferences QString storedString = QString::fromStdString( this->GetPreferences()->GetByteArray("Organ-Color-List","") ); MITK_DEBUG << "storedString: " << storedString.toStdString(); // match a string consisting of any number of repetitions of either "anything but ;" or "\;". This matches everything until the next unescaped ';' QRegExp onePart("(?:[^;]|\\\\;)*"); MITK_DEBUG << "matching " << onePart.pattern().toStdString(); int count = 0; int pos = 0; while( (pos = onePart.indexIn( storedString, pos )) != -1 ) { ++count; int length = onePart.matchedLength(); if (length == 0) break; QString matchedString = storedString.mid(pos, length); MITK_DEBUG << " Captured length " << length << ": " << matchedString.toStdString(); pos += length + 1; // skip separating ';' // unescape possible occurrences of '\;' in the string matchedString.replace("\\;", ";"); // add matched string part to output list organColors << matchedString; } MITK_DEBUG << "Captured " << count << " organ name/colors"; } dialog->SetSuggestionList( organColors ); int dialogReturnValue = dialog->exec(); if ( dialogReturnValue == QDialog::Rejected ) return; // user clicked cancel or pressed Esc or something similar // ask the user about an organ type and name, add this information to the image's (!) propertylist // create a new image of the same dimensions and smallest possible pixel type mitk::ToolManager* toolManager = m_Controls->m_ManualToolSelectionBox->GetToolManager(); mitk::Tool* firstTool = toolManager->GetToolById(0); if (firstTool) { try { mitk::DataNode::Pointer emptySegmentation = firstTool->CreateEmptySegmentationNode( image, dialog->GetSegmentationName().toStdString(), dialog->GetColor() ); //Here we change the reslice interpolation mode for a segmentation, so that contours in rotated slice can be shown correctly emptySegmentation->SetProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New(VTK_RESLICE_CUBIC) ); // initialize showVolume to false to prevent recalculating the volume while working on the segmentation emptySegmentation->SetProperty( "showVolume", mitk::BoolProperty::New( false ) ); if (!emptySegmentation) return; // could be aborted by user UpdateOrganList( organColors, dialog->GetSegmentationName(), dialog->GetColor() ); /* escape ';' here (replace by '\;'), see longer comment above */ std::string stringForStorage = organColors.replaceInStrings(";","\\;").join(";").toStdString(); MITK_DEBUG << "Will store: " << stringForStorage; this->GetPreferences()->PutByteArray("Organ-Color-List", stringForStorage ); this->GetPreferences()->Flush(); this->GetDefaultDataStorage()->Add( emptySegmentation, node ); // add as a child, because the segmentation "derives" from the original this->FireNodeSelected( emptySegmentation ); this->OnSelectionChanged( emptySegmentation ); } catch (std::bad_alloc) { QMessageBox::warning(NULL,"Create new segmentation","Could not allocate memory for new segmentation"); } } } else { QMessageBox::information(NULL,"Segmentation","Segmentation is currently not supported for 2D images"); } } } else { MITK_ERROR << "'Create new segmentation' button should never be clickable unless a patient image is selected..."; } } void QmitkSegmentationView::CreateSegmentationFromSurface() { mitk::DataNode::Pointer surfaceNode = m_Controls->MaskSurfaces->GetSelectedNode(); mitk::Surface::Pointer surface(0); if(surfaceNode.IsNotNull()) surface = dynamic_cast ( surfaceNode->GetData() ); if(surface.IsNull()) { this->HandleException( "No surface selected.", m_Parent, true); return; } mitk::DataNode::Pointer imageNode = m_Controls->m_ManualToolSelectionBox->GetToolManager()->GetReferenceData(0); mitk::Image::Pointer image(0); if (imageNode.IsNotNull()) image = dynamic_cast( imageNode->GetData() ); if(image.IsNull()) { this->HandleException( "No image selected.", m_Parent, true); return; } mitk::SurfaceToImageFilter::Pointer s2iFilter = mitk::SurfaceToImageFilter::New(); s2iFilter->MakeOutputBinaryOn(); s2iFilter->SetInput(surface); s2iFilter->SetImage(image); s2iFilter->Update(); mitk::DataNode::Pointer resultNode = mitk::DataNode::New(); std::string nameOfResultImage = imageNode->GetName(); nameOfResultImage.append(surfaceNode->GetName()); resultNode->SetProperty("name", mitk::StringProperty::New(nameOfResultImage) ); resultNode->SetProperty("binary", mitk::BoolProperty::New(true) ); resultNode->SetData( s2iFilter->GetOutput() ); this->GetDataStorage()->Add(resultNode, imageNode); } void QmitkSegmentationView::ManualToolSelected(int id) { // disable crosshair movement when a manual drawing tool is active (otherwise too much visual noise) if (m_MultiWidget) { if (id >= 0) { m_MultiWidget->DisableNavigationControllerEventListening(); m_MultiWidget->SetWidgetPlaneMode(0); } else { m_MultiWidget->EnableNavigationControllerEventListening(); } } } void QmitkSegmentationView::ToolboxStackPageChanged(int id) { // interpolation only with manual tools visible m_Controls->m_SlicesInterpolator->EnableInterpolation( id == 0 ); if( id == 0 ) { mitk::DataNode::Pointer workingData = m_Controls->m_ManualToolSelectionBox->GetToolManager()->GetWorkingData(0); if( workingData.IsNotNull() ) { m_Controls->lblSegmentation->setText( workingData->GetName().c_str() ); m_Controls->lblSegImage->show(); m_Controls->lblSegmentation->show(); } } else { m_Controls->lblSegImage->hide(); m_Controls->lblSegmentation->hide(); } // this is just a workaround, should be removed when all tools support 3D+t if (id==2) // lesions { mitk::DataNode::Pointer node = m_Controls->m_ManualToolSelectionBox->GetToolManager()->GetReferenceData(0); if (node.IsNotNull()) { mitk::Image::Pointer image = dynamic_cast( node->GetData() ); if (image.IsNotNull()) { if (image->GetDimension()>3) { m_Controls->widgetStack->setCurrentIndex(0); QMessageBox::information(NULL,"Segmentation","Lesion segmentation is currently not supported for 4D images"); } } } } } // protected void QmitkSegmentationView::OnComboBoxSelectionChanged( const mitk::DataNode* node ) { mitk::DataNode* selectedNode = const_cast(node); if( selectedNode != NULL ) { m_Controls->refImageSelector->show(); m_Controls->lblReferenceImageSelectionWarning->hide(); this->OnSelectionChanged( const_cast(node) ); } else { m_Controls->refImageSelector->hide(); m_Controls->lblReferenceImageSelectionWarning->show(); } } //to remember the contour positions void QmitkSegmentationView::CheckboxRememberContourPositionsStateChanged (int state) { if(state == Qt::Checked) { m_Controls->m_ManualToolSelectionBox->GetToolManager()->SetRememberContourPosition( true ); } else { m_Controls->m_ManualToolSelectionBox->GetToolManager()->SetRememberContourPosition( false ); } } void QmitkSegmentationView::OnSelectionChanged(mitk::DataNode* node) { std::vector nodes; nodes.push_back( node ); this->OnSelectionChanged( nodes ); } void QmitkSegmentationView::OnSurfaceSelectionChanged() { // if Image and Surface are selected, enable button if ( (m_Controls->refImageSelector->GetSelectedNode().IsNull()) || (m_Controls->MaskSurfaces->GetSelectedNode().IsNull())) m_Controls->CreateSegmentationFromSurface->setEnabled(false); else m_Controls->CreateSegmentationFromSurface->setEnabled(true); } void QmitkSegmentationView::OnSelectionChanged(std::vector nodes) { // if the selected node is a contourmarker if ( !nodes.empty() ) { std::string markerName = "Contourmarker"; unsigned int numberOfNodes = nodes.size(); std::string nodeName = nodes.at( 0 )->GetName(); if ( ( numberOfNodes == 1 ) && ( nodeName.find( markerName ) == 0) ) { this->OnContourMarkerSelected( nodes.at( 0 ) ); } } // if Image and Surface are selected, enable button if ( (m_Controls->refImageSelector->GetSelectedNode().IsNull()) || (m_Controls->MaskSurfaces->GetSelectedNode().IsNull())) m_Controls->CreateSegmentationFromSurface->setEnabled(false); else m_Controls->CreateSegmentationFromSurface->setEnabled(true); if (!m_Parent || !m_Parent->isVisible()) return; // reaction to BlueBerry selection events // this method will try to figure out if a relevant segmentation and its corresponding original image were selected // a warning is issued if the selection is invalid // appropriate reactions are triggered otherwise mitk::DataNode::Pointer referenceData = FindFirstRegularImage( nodes ); //m_Controls->refImageSelector->GetSelectedNode(); //FindFirstRegularImage( nodes ); mitk::DataNode::Pointer workingData = FindFirstSegmentation( nodes ); bool invalidSelection( !nodes.empty() && ( nodes.size() > 2 || // maximum 2 selected nodes (nodes.size() == 2 && (workingData.IsNull() || referenceData.IsNull()) ) || // with two nodes, one must be the original image, one the segmentation ( workingData.GetPointer() == referenceData.GetPointer() ) //one node is selected as reference and working image // one item is always ok (might be working or reference or nothing ) ); if (invalidSelection) { // TODO visible warning when two images are selected MITK_ERROR << "WARNING: No image, too many (>2) or two equal images were selected."; workingData = NULL; if( m_Controls->refImageSelector->GetSelectedNode().IsNull() ) referenceData = NULL; } if ( workingData.IsNotNull() && referenceData.IsNull() ) { // find the DataStorage parent of workingData // try to find a "normal image" parent, select this as reference image mitk::TNodePredicateDataType::Pointer isImage = mitk::TNodePredicateDataType::New(); mitk::NodePredicateProperty::Pointer isBinary = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); mitk::NodePredicateNot::Pointer isNotBinary = mitk::NodePredicateNot::New( isBinary ); mitk::NodePredicateAnd::Pointer isNormalImage = mitk::NodePredicateAnd::New( isImage, isNotBinary ); mitk::DataStorage::SetOfObjects::ConstPointer possibleParents = this->GetDefaultDataStorage()->GetSources( workingData, isNormalImage ); if (possibleParents->size() > 0) { if (possibleParents->size() > 1) { // TODO visible warning for this rare case MITK_ERROR << "Selected binary image has multiple parents. Using arbitrary first one for segmentation."; } referenceData = (*possibleParents)[0]; } } //set comboBox to reference image disconnect( m_Controls->refImageSelector, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ), this, SLOT( OnComboBoxSelectionChanged( const mitk::DataNode* ) ) ); m_Controls->refImageSelector->setCurrentIndex( m_Controls->refImageSelector->Find(referenceData) ); connect( m_Controls->refImageSelector, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ), this, SLOT( OnComboBoxSelectionChanged( const mitk::DataNode* ) ) ); // if Image and Surface are selected, enable button if ( (m_Controls->refImageSelector->GetSelectedNode().IsNull()) || (m_Controls->MaskSurfaces->GetSelectedNode().IsNull()) || (!referenceData)) m_Controls->CreateSegmentationFromSurface->setEnabled(false); else m_Controls->CreateSegmentationFromSurface->setEnabled(true); SetToolManagerSelection(referenceData, workingData); ForceDisplayPreferencesUponAllImages(); } //New since rotated contour drawing is allowed. Effects a reorientation of the plane of the affected widget to the marker`s position void QmitkSegmentationView::OnContourMarkerSelected(const mitk::DataNode *node) { const mitk::PlaneGeometry* markerGeometry = dynamic_cast ( node->GetData()->GetGeometry() ); QmitkRenderWindow* selectedRenderWindow = 0; QmitkRenderWindow* RenderWindow1 = this->GetActiveStdMultiWidget()->GetRenderWindow1(); QmitkRenderWindow* RenderWindow2 = this->GetActiveStdMultiWidget()->GetRenderWindow2(); QmitkRenderWindow* RenderWindow3 = this->GetActiveStdMultiWidget()->GetRenderWindow3(); QmitkRenderWindow* RenderWindow4 = this->GetActiveStdMultiWidget()->GetRenderWindow4(); bool PlanarFigureInitializedWindow = false; // find initialized renderwindow if (node->GetBoolProperty("PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, RenderWindow1->GetRenderer())) { selectedRenderWindow = RenderWindow1; } if (!selectedRenderWindow && node->GetBoolProperty( "PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, RenderWindow2->GetRenderer())) { selectedRenderWindow = RenderWindow2; } if (!selectedRenderWindow && node->GetBoolProperty( "PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, RenderWindow3->GetRenderer())) { selectedRenderWindow = RenderWindow3; } if (!selectedRenderWindow && node->GetBoolProperty( "PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, RenderWindow4->GetRenderer())) { selectedRenderWindow = RenderWindow4; } // make node visible if (selectedRenderWindow) { mitk::Point3D centerP = markerGeometry->GetOrigin(); selectedRenderWindow->GetSliceNavigationController()->SelectSliceByPoint( centerP); selectedRenderWindow->GetSliceNavigationController()->ReorientSlices( centerP, markerGeometry->GetNormal()); } } mitk::DataNode::Pointer QmitkSegmentationView::FindFirstRegularImage( std::vector nodes ) { if (nodes.empty()) return NULL; for(unsigned int i = 0; i < nodes.size(); ++i) { //mitk::DataNode::Pointer node = i.value() bool isImage(false); if (nodes.at(i)->GetData()) { isImage = dynamic_cast(nodes.at(i)->GetData()) != NULL; } // make sure this is not a binary image bool isSegmentation(false); nodes.at(i)->GetBoolProperty("binary", isSegmentation); // return first proper mitk::Image if (isImage && !isSegmentation) return nodes.at(i); } return NULL; } mitk::DataNode::Pointer QmitkSegmentationView::FindFirstSegmentation( std::vector nodes ) { if (nodes.empty()) return NULL; for(unsigned int i = 0; i < nodes.size(); ++i) { bool isImage(false); if (nodes.at(i)->GetData()) { isImage = dynamic_cast(nodes.at(i)->GetData()) != NULL; } bool isSegmentation(false); nodes.at(i)->GetBoolProperty("binary", isSegmentation); // return first proper binary mitk::Image if (isImage && isSegmentation) { return nodes.at(i); } } return NULL; } void QmitkSegmentationView::SetToolManagerSelection(const mitk::DataNode* referenceData, const mitk::DataNode* workingData) { // called as a result of new BlueBerry selections // tells the ToolManager for manual segmentation about new selections // updates GUI information about what the user should select mitk::ToolManager* toolManager = m_Controls->m_ManualToolSelectionBox->GetToolManager(); toolManager->SetReferenceData(const_cast(referenceData)); toolManager->SetWorkingData( const_cast(workingData)); // check original image m_Controls->btnNewSegmentation->setEnabled(referenceData != NULL); if (referenceData) { m_Controls->lblReferenceImageSelectionWarning->hide(); } else { m_Controls->lblReferenceImageSelectionWarning->show(); m_Controls->lblWorkingImageSelectionWarning->hide(); m_Controls->lblSegImage->hide(); m_Controls->lblSegmentation->hide(); } // check, wheter reference image is aligned like render windows. Otherwise display a visible warning (because 2D tools will probably not work) CheckImageAlignment(); // check segmentation if (referenceData) { if (!workingData) { m_Controls->lblWorkingImageSelectionWarning->show(); if( m_Controls->widgetStack->currentIndex() == 0 ) { m_Controls->lblSegImage->hide(); m_Controls->lblSegmentation->hide(); } } else { m_Controls->lblWorkingImageSelectionWarning->hide(); if( m_Controls->widgetStack->currentIndex() == 0 ) { m_Controls->lblSegmentation->setText( workingData->GetName().c_str() ); m_Controls->lblSegmentation->show(); m_Controls->lblSegImage->show(); } } } } void QmitkSegmentationView::CheckImageAlignment() { bool wrongAlignment(true); mitk::DataNode::Pointer node = m_Controls->m_ManualToolSelectionBox->GetToolManager()->GetReferenceData(0); if (node.IsNotNull()) { mitk::Image::Pointer image = dynamic_cast( node->GetData() ); if (image.IsNotNull() && m_MultiWidget) { wrongAlignment = !( IsRenderWindowAligned(m_MultiWidget->GetRenderWindow1(), image ) && IsRenderWindowAligned(m_MultiWidget->GetRenderWindow2(), image ) && IsRenderWindowAligned(m_MultiWidget->GetRenderWindow3(), image ) ); } if (wrongAlignment) { m_Controls->lblAlignmentWarning->show(); } } } bool QmitkSegmentationView::IsRenderWindowAligned(QmitkRenderWindow* renderWindow, mitk::Image* image) { if (!renderWindow) return false; // for all 2D renderwindows of m_MultiWidget check alignment mitk::PlaneGeometry::ConstPointer displayPlane = dynamic_cast( renderWindow->GetRenderer()->GetCurrentWorldGeometry2D() ); if (displayPlane.IsNull()) return false; int affectedDimension(-1); int affectedSlice(-1); return mitk::SegTool2D::DetermineAffectedImageSlice( image, displayPlane, affectedDimension, affectedSlice ); } void QmitkSegmentationView::ForceDisplayPreferencesUponAllImages() { if (!m_Parent || !m_Parent->isVisible()) return; // check all images and segmentations in DataStorage: // (items in brackets are implicitly done by previous steps) // 1. // if a reference image is selected, // show the reference image // and hide all other images (orignal and segmentation), // (and hide all segmentations of the other original images) // and show all the reference's segmentations // if no reference image is selected, do do nothing // // 2. // if a segmentation is selected, // show it // (and hide all all its siblings (childs of the same parent, incl, NULL parent)) // if no segmentation is selected, do nothing if (!m_Controls) return; // might happen on initialization (preferences loaded) mitk::DataNode::Pointer referenceData = m_Controls->m_ManualToolSelectionBox->GetToolManager()->GetReferenceData(0); mitk::DataNode::Pointer workingData = m_Controls->m_ManualToolSelectionBox->GetToolManager()->GetWorkingData(0); // 1. if (referenceData.IsNotNull()) { // iterate all images mitk::TNodePredicateDataType::Pointer isImage = mitk::TNodePredicateDataType::New(); mitk::DataStorage::SetOfObjects::ConstPointer allImages = this->GetDefaultDataStorage()->GetSubset( isImage ); for ( mitk::DataStorage::SetOfObjects::const_iterator iter = allImages->begin(); iter != allImages->end(); ++iter) { mitk::DataNode* node = *iter; // apply display preferences ApplyDisplayOptions(node); // set visibility node->SetVisibility(node == referenceData); } } // 2. if (workingData.IsNotNull()) { workingData->SetVisibility(true); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkSegmentationView::ApplyDisplayOptions(mitk::DataNode* node) { if (!node) return; bool isBinary(false); node->GetPropertyValue("binary", isBinary); if (isBinary) { node->SetProperty( "outline binary", mitk::BoolProperty::New( this->GetPreferences()->GetBool("draw outline", true)) ); node->SetProperty( "outline width", mitk::FloatProperty::New( 2.0 ) ); node->SetProperty( "opacity", mitk::FloatProperty::New( this->GetPreferences()->GetBool("draw outline", true) ? 1.0 : 0.3 ) ); node->SetProperty( "volumerendering", mitk::BoolProperty::New( this->GetPreferences()->GetBool("volume rendering", false) ) ); } } void QmitkSegmentationView::CreateQtPartControl(QWidget* parent) { // setup the basic GUI of this view m_Parent = parent; m_Controls = new Ui::QmitkSegmentationControls; m_Controls->setupUi(parent); m_Controls->lblWorkingImageSelectionWarning->hide(); m_Controls->lblAlignmentWarning->hide(); m_Controls->lblSegImage->hide(); m_Controls->lblSegmentation->hide(); m_Controls->refImageSelector->SetDataStorage(this->GetDefaultDataStorage()); m_Controls->refImageSelector->SetPredicate(mitk::NodePredicateDataType::New("Image")); if( m_Controls->refImageSelector->GetSelectedNode().IsNotNull() ) m_Controls->lblReferenceImageSelectionWarning->hide(); else m_Controls->refImageSelector->hide(); mitk::ToolManager* toolManager = m_Controls->m_ManualToolSelectionBox->GetToolManager(); toolManager->SetDataStorage( *(this->GetDefaultDataStorage()) ); assert ( toolManager ); // all part of open source MITK m_Controls->m_ManualToolSelectionBox->SetGenerateAccelerators(true); m_Controls->m_ManualToolSelectionBox->SetToolGUIArea( m_Controls->m_ManualToolGUIContainer ); m_Controls->m_ManualToolSelectionBox->SetDisplayedToolGroups("Add Subtract Paint Wipe 'Region Growing' Correction Fill Erase"); m_Controls->m_ManualToolSelectionBox->SetEnabledMode( QmitkToolSelectionBox::EnabledWithReferenceAndWorkingData ); // available only in the 3M application if ( !m_Controls->m_OrganToolSelectionBox->children().count() ) { m_Controls->widgetStack->setItemEnabled( 1, false ); } m_Controls->m_OrganToolSelectionBox->SetToolManager( *toolManager ); m_Controls->m_OrganToolSelectionBox->SetToolGUIArea( m_Controls->m_OrganToolGUIContainer ); m_Controls->m_OrganToolSelectionBox->SetDisplayedToolGroups("'Hippocampus left' 'Hippocampus right' 'Lung left' 'Lung right' 'Liver' 'Heart LV' 'Endocard LV' 'Epicard LV' 'Prostate'"); m_Controls->m_OrganToolSelectionBox->SetEnabledMode( QmitkToolSelectionBox::EnabledWithReferenceData ); // available only in the 3M application if ( !m_Controls->m_LesionToolSelectionBox->children().count() ) { m_Controls->widgetStack->setItemEnabled( 2, false ); } m_Controls->m_LesionToolSelectionBox->SetToolManager( *toolManager ); m_Controls->m_LesionToolSelectionBox->SetToolGUIArea( m_Controls->m_LesionToolGUIContainer ); m_Controls->m_LesionToolSelectionBox->SetDisplayedToolGroups("'Lymph Node'"); m_Controls->m_LesionToolSelectionBox->SetEnabledMode( QmitkToolSelectionBox::EnabledWithReferenceData ); toolManager->NewNodesGenerated += mitk::MessageDelegate( this, &QmitkSegmentationView::NewNodesGenerated ); // update the list of segmentations toolManager->NewNodeObjectsGenerated += mitk::MessageDelegate1( this, &QmitkSegmentationView::NewNodeObjectsGenerated ); // update the list of segmentations // create signal/slot connections connect( m_Controls->refImageSelector, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ), this, SLOT( OnComboBoxSelectionChanged( const mitk::DataNode* ) ) ); connect( m_Controls->btnNewSegmentation, SIGNAL(clicked()), this, SLOT(CreateNewSegmentation()) ); connect( m_Controls->CreateSegmentationFromSurface, SIGNAL(clicked()), this, SLOT(CreateSegmentationFromSurface()) ); connect( m_Controls->m_ManualToolSelectionBox, SIGNAL(ToolSelected(int)), this, SLOT(ManualToolSelected(int)) ); connect( m_Controls->widgetStack, SIGNAL(currentChanged(int)), this, SLOT(ToolboxStackPageChanged(int)) ); //To remember the position of each contour connect( m_Controls->cbRememberContourPositions, SIGNAL(stateChanged(int)), this, SLOT(CheckboxRememberContourPositionsStateChanged(int))); connect(m_Controls->MaskSurfaces, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ), this, SLOT( OnSurfaceSelectionChanged( ) ) ); m_Controls->MaskSurfaces->SetDataStorage(this->GetDefaultDataStorage()); m_Controls->MaskSurfaces->SetPredicate(mitk::NodePredicateDataType::New("Surface")); //// create helper class to provide context menus for segmentations in data manager // m_PostProcessing = new QmitkSegmentationPostProcessing(this->GetDefaultDataStorage(), this, m_Parent); } //void QmitkSegmentationView::OnPlaneModeChanged(int i) //{ // //if plane mode changes, disable all tools // if (m_MultiWidget) // { // mitk::ToolManager* toolManager = m_Controls->m_ManualToolSelectionBox->GetToolManager(); // // if (toolManager) // { // if (toolManager->GetActiveToolID() >= 0) // { // toolManager->ActivateTool(-1); // } // else // { // m_MultiWidget->EnableNavigationControllerEventListening(); // } // } // } //} // ATTENTION some methods for handling the known list of (organ names, colors) are defined in QmitkSegmentationOrganNamesHandling.cpp diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.h b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.h index ddb629241b..d3ec851433 100644 --- a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.h +++ b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.h @@ -1,155 +1,159 @@ -/*========================================================================= - +/*====================================================================== Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: 1.12 $ - + Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef QmitkSegmentationView_h #define QmitkSegmentationView_h #include "QmitkFunctionality.h" #include #include "ui_QmitkSegmentationControls.h" class QmitkRenderWindow; // class QmitkSegmentationPostProcessing; /** * \ingroup ToolManagerEtAl * \ingroup org_mitk_gui_qt_segmentation_internal * \warning Implementation of this class is split up into two .cpp files to make things more compact. Check both this file and QmitkSegmentationOrganNamesHandling.cpp */ class QmitkSegmentationView : public QmitkFunctionality { Q_OBJECT - - public: - - QmitkSegmentationView(); - virtual ~QmitkSegmentationView(); - - /*! + +public: + + QmitkSegmentationView(); + QmitkSegmentationView(const QmitkSegmentationView& other) + { + Q_UNUSED(other) + throw std::runtime_error("Copy constructor not implemented"); + } + virtual ~QmitkSegmentationView(); + + /*! \brief Invoked when the DataManager selection changed */ - virtual void OnSelectionChanged(mitk::DataNode* node); - virtual void OnSelectionChanged(std::vector nodes); - - // reaction to new segmentations being created by segmentation tools - void NewNodesGenerated(); - void NewNodeObjectsGenerated(mitk::ToolManager::DataVectorType*); - - // QmitkFunctionality's activate/deactivate - virtual void Activated(); - virtual void Deactivated(); - - // QmitkFunctionality's changes regarding THE QmitkStdMultiWidget - virtual void StdMultiWidgetAvailable(QmitkStdMultiWidget& stdMultiWidget); - virtual void StdMultiWidgetNotAvailable(); - virtual void StdMultiWidgetClosed(QmitkStdMultiWidget& stdMultiWidget); - - // BlueBerry's notification about preference changes (e.g. from a dialog) - virtual void OnPreferencesChanged(const berry::IBerryPreferences*); - - // observer to mitk::RenderingManager's RenderingManagerViewsInitializedEvent event - void RenderingManagerReinitialized(const itk::EventObject&); - - // observer to mitk::SliceController's SliceRotation event - void SliceRotation(const itk::EventObject&); - - protected slots: - - void OnComboBoxSelectionChanged(const mitk::DataNode* node); - - // reaction to the button "New segmentation" - void CreateNewSegmentation(); - - // reaction to the button "New segmentation" - void CreateSegmentationFromSurface(); - - // called when a segmentation tool is activated - void ManualToolSelected(int id); - - // called when one of "Manual", "Organ", "Lesion" pages of the QToolbox is selected - void ToolboxStackPageChanged(int id); - - void OnSurfaceSelectionChanged(); - - //called when the checkbox Remember Contour Positions is selected/deselected - void CheckboxRememberContourPositionsStateChanged(int state); - - protected: - - // a type for handling lists of DataNodes - typedef std::vector NodeList; - - // set available multiwidget - void SetMultiWidget(QmitkStdMultiWidget* multiWidget); - - // actively query the current selection of data manager - //void PullCurrentDataManagerSelection(); - - // reactions to selection events from data manager (and potential other senders) - //void BlueBerrySelectionChanged(berry::IWorkbenchPart::Pointer sourcepart, berry::ISelection::ConstPointer selection); - mitk::DataNode::Pointer FindFirstRegularImage( std::vector nodes ); - mitk::DataNode::Pointer FindFirstSegmentation( std::vector nodes ); - - // propagate BlueBerry selection to ToolManager for manual segmentation - void SetToolManagerSelection(const mitk::DataNode* referenceData, const mitk::DataNode* workingData); - - // checks if selected reference image is aligned with the slices stack orientation of the StdMultiWidget - void CheckImageAlignment(); - - // checks if given render window aligns with the slices of given image - bool IsRenderWindowAligned(QmitkRenderWindow* renderWindow, mitk::Image* image); - - // make sure all images/segmentations look as selected by the users in this view's preferences - void ForceDisplayPreferencesUponAllImages(); - - // decorates a DataNode according to the user preference settings - void ApplyDisplayOptions(mitk::DataNode* node); - - // GUI setup - void CreateQtPartControl(QWidget* parent); - - // handling of a list of known (organ name, organ color) combination - // ATTENTION these methods are defined in QmitkSegmentationOrganNamesHandling.cpp - QStringList GetDefaultOrganColorString(); - void UpdateOrganList(QStringList& organColors, const QString& organname, mitk::Color colorname); - void AppendToOrganList(QStringList& organColors, const QString& organname, int r, int g, int b); - - // If a contourmarker is selected, the plane in the related widget will be reoriented according to the marker`s geometry - void OnContourMarkerSelected (const mitk::DataNode* node); - - // the Qt parent of our GUI (NOT of this object) - QWidget* m_Parent; - - // our GUI - Ui::QmitkSegmentationControls * m_Controls; - - // THE currently existing QmitkStdMultiWidget - QmitkStdMultiWidget * m_MultiWidget; - - // QmitkSegmentationPostProcessing* m_PostProcessing; - - unsigned long m_RenderingManagerObserverTag; - unsigned long m_SlicesRotationObserverTag1; - unsigned long m_SlicesRotationObserverTag2; - - + virtual void OnSelectionChanged(mitk::DataNode* node); + virtual void OnSelectionChanged(std::vector nodes); + + // reaction to new segmentations being created by segmentation tools + void NewNodesGenerated(); + void NewNodeObjectsGenerated(mitk::ToolManager::DataVectorType*); + + // QmitkFunctionality's activate/deactivate + virtual void Activated(); + virtual void Deactivated(); + + // QmitkFunctionality's changes regarding THE QmitkStdMultiWidget + virtual void StdMultiWidgetAvailable(QmitkStdMultiWidget& stdMultiWidget); + virtual void StdMultiWidgetNotAvailable(); + virtual void StdMultiWidgetClosed(QmitkStdMultiWidget& stdMultiWidget); + + // BlueBerry's notification about preference changes (e.g. from a dialog) + virtual void OnPreferencesChanged(const berry::IBerryPreferences*); + + // observer to mitk::RenderingManager's RenderingManagerViewsInitializedEvent event + void RenderingManagerReinitialized(const itk::EventObject&); + + // observer to mitk::SliceController's SliceRotation event + void SliceRotation(const itk::EventObject&); + +protected slots: + + void OnComboBoxSelectionChanged(const mitk::DataNode* node); + + // reaction to the button "New segmentation" + void CreateNewSegmentation(); + + // reaction to the button "New segmentation" + void CreateSegmentationFromSurface(); + + // called when a segmentation tool is activated + void ManualToolSelected(int id); + + // called when one of "Manual", "Organ", "Lesion" pages of the QToolbox is selected + void ToolboxStackPageChanged(int id); + + void OnSurfaceSelectionChanged(); + + //called when the checkbox Remember Contour Positions is selected/deselected + void CheckboxRememberContourPositionsStateChanged(int state); + +protected: + + // a type for handling lists of DataNodes + typedef std::vector NodeList; + + // set available multiwidget + void SetMultiWidget(QmitkStdMultiWidget* multiWidget); + + // actively query the current selection of data manager + //void PullCurrentDataManagerSelection(); + + // reactions to selection events from data manager (and potential other senders) + //void BlueBerrySelectionChanged(berry::IWorkbenchPart::Pointer sourcepart, berry::ISelection::ConstPointer selection); + mitk::DataNode::Pointer FindFirstRegularImage( std::vector nodes ); + mitk::DataNode::Pointer FindFirstSegmentation( std::vector nodes ); + + // propagate BlueBerry selection to ToolManager for manual segmentation + void SetToolManagerSelection(const mitk::DataNode* referenceData, const mitk::DataNode* workingData); + + // checks if selected reference image is aligned with the slices stack orientation of the StdMultiWidget + void CheckImageAlignment(); + + // checks if given render window aligns with the slices of given image + bool IsRenderWindowAligned(QmitkRenderWindow* renderWindow, mitk::Image* image); + + // make sure all images/segmentations look as selected by the users in this view's preferences + void ForceDisplayPreferencesUponAllImages(); + + // decorates a DataNode according to the user preference settings + void ApplyDisplayOptions(mitk::DataNode* node); + + // GUI setup + void CreateQtPartControl(QWidget* parent); + + // handling of a list of known (organ name, organ color) combination + // ATTENTION these methods are defined in QmitkSegmentationOrganNamesHandling.cpp + QStringList GetDefaultOrganColorString(); + void UpdateOrganList(QStringList& organColors, const QString& organname, mitk::Color colorname); + void AppendToOrganList(QStringList& organColors, const QString& organname, int r, int g, int b); + + // If a contourmarker is selected, the plane in the related widget will be reoriented according to the marker`s geometry + void OnContourMarkerSelected (const mitk::DataNode* node); + + // the Qt parent of our GUI (NOT of this object) + QWidget* m_Parent; + + // our GUI + Ui::QmitkSegmentationControls * m_Controls; + + // THE currently existing QmitkStdMultiWidget + QmitkStdMultiWidget * m_MultiWidget; + + // QmitkSegmentationPostProcessing* m_PostProcessing; + + unsigned long m_RenderingManagerObserverTag; + unsigned long m_SlicesRotationObserverTag1; + unsigned long m_SlicesRotationObserverTag2; + + }; #endif /*QMITKsegmentationVIEW_H_*/ diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkStatisticsAction.h b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkStatisticsAction.h index 6c5e023f66..a88c637718 100644 --- a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkStatisticsAction.h +++ b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkStatisticsAction.h @@ -1,30 +1,37 @@ #ifndef QMITK_STATISTICSACTION_H #define QMITK_STATISTICSACTION_H #include #include "berryQtViewPart.h" #include "mitkIContextMenuAction.h" -#include "mitkQtSegmentationDll.h" +#include "org_mitk_gui_qt_segmentation_Export.h" -class MITK_QT_SEGMENTATION QmitkStatisticsAction: public mitk::IContextMenuAction +class MITK_QT_SEGMENTATION QmitkStatisticsAction: public QObject, public mitk::IContextMenuAction { + Q_OBJECT + public: QmitkStatisticsAction(); + QmitkStatisticsAction(const QmitkStatisticsAction& other) + { + Q_UNUSED(other) + throw std::runtime_error("Copy constructor not implemented"); + } virtual ~QmitkStatisticsAction(); //interface methods void Run( const std::vector& selectedNodes ); void SetDataStorage(mitk::DataStorage* dataStorage); void SetSmoothed(bool smoothed); void SetDecimated(bool decimated); void SetFunctionality(berry::QtViewPart* functionality); protected: //needs to be set over the IContextMenuAction (with this - QmitkDataManagerView - as parameter) berry::QtViewPart* m_BlueBerryView; }; -#endif // QMITK_STATISTICSACTION_H \ No newline at end of file +#endif // QMITK_STATISTICSACTION_H diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkThresholdAction.h b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkThresholdAction.h index 56e8e7f0f4..c9d4190ea6 100644 --- a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkThresholdAction.h +++ b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkThresholdAction.h @@ -1,51 +1,56 @@ #ifndef QMITK_THRESHOLDACTION_H #define QMITK_THRESHOLDACTION_H #include #include "berryQtViewPart.h" #include "mitkIContextMenuAction.h" #include "mitkDataStorage.h" #include "mitkToolManager.h" -#include "mitkQtSegmentationDll.h" +#include "org_mitk_gui_qt_segmentation_Export.h" #include #include class MITK_QT_SEGMENTATION QmitkThresholdAction: public QObject, public mitk::IContextMenuAction { Q_OBJECT - public: +public: - QmitkThresholdAction(); - virtual ~QmitkThresholdAction(); + QmitkThresholdAction(); + QmitkThresholdAction(const QmitkThresholdAction& other) + { + Q_UNUSED(other) + throw std::runtime_error("Copy constructor not implemented"); + } + virtual ~QmitkThresholdAction(); - //interface methods - void Run( const std::vector& selectedNodes ); - void SetDataStorage(mitk::DataStorage* dataStorage); - void SetSmoothed(bool smoothed); - void SetDecimated(bool decimated); - void SetFunctionality(berry::QtViewPart* functionality); + //interface methods + void Run( const std::vector& selectedNodes ); + void SetDataStorage(mitk::DataStorage* dataStorage); + void SetSmoothed(bool smoothed); + void SetDecimated(bool decimated); + void SetFunctionality(berry::QtViewPart* functionality); - // for receiving messages - void OnThresholdingToolManagerToolModified(); + // for receiving messages + void OnThresholdingToolManagerToolModified(); - protected: +protected: - typedef std::vector NodeList; + typedef std::vector NodeList; - mitk::DataStorage::Pointer m_DataStorage; - mitk::ToolManager::Pointer m_ThresholdingToolManager; + mitk::DataStorage::Pointer m_DataStorage; + mitk::ToolManager::Pointer m_ThresholdingToolManager; - QDialog* m_ThresholdingDialog; + QDialog* m_ThresholdingDialog; - protected slots: +protected slots: - // class internal slot - void ThresholdingDone(int); + // class internal slot + void ThresholdingDone(int); }; -#endif // QMITK_THRESHOLDACTION_H \ No newline at end of file +#endif // QMITK_THRESHOLDACTION_H diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.cpp b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.cpp new file mode 100644 index 0000000000..a731a4ffbc --- /dev/null +++ b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.cpp @@ -0,0 +1,30 @@ +#include "mitkPluginActivator.h" + +#include +#include "QmitkSegmentationView.h" +#include "QmitkThresholdAction.h" +#include "QmitkCreatePolygonModelAction.h" +#include "QmitkStatisticsAction.h" +#include "QmitkAutocropAction.h" +#include "QmitkSegmentationPreferencePage.h" + +namespace mitk { + +void PluginActivator::start(ctkPluginContext* context) +{ + BERRY_REGISTER_EXTENSION_CLASS(QmitkSegmentationView, context); + BERRY_REGISTER_EXTENSION_CLASS(QmitkThresholdAction, context); + BERRY_REGISTER_EXTENSION_CLASS(QmitkCreatePolygonModelAction, context); + BERRY_REGISTER_EXTENSION_CLASS(QmitkStatisticsAction, context); + BERRY_REGISTER_EXTENSION_CLASS(QmitkAutocropAction, context); + BERRY_REGISTER_EXTENSION_CLASS(QmitkSegmentationPreferencePage, context); +} + +void PluginActivator::stop(ctkPluginContext* context) +{ + Q_UNUSED(context) +} + +} + +Q_EXPORT_PLUGIN2(org_mitk_gui_qt_segmentation, mitk::PluginActivator) diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.h b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.h new file mode 100644 index 0000000000..a34be34be4 --- /dev/null +++ b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.h @@ -0,0 +1,23 @@ +#ifndef MITKPLUGINACTIVATOR_H +#define MITKPLUGINACTIVATOR_H + +#include + +namespace mitk { + +class PluginActivator : + public QObject, public ctkPluginActivator +{ + Q_OBJECT + Q_INTERFACES(ctkPluginActivator) + +public: + + void start(ctkPluginContext* context); + void stop(ctkPluginContext* context); + +}; // PluginActivator + +} + +#endif // MITKPLUGINACTIVATOR_H diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/mitkQtSegmentationDll.h b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/mitkQtSegmentationDll.h deleted file mode 100755 index 950ac91057..0000000000 --- a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/mitkQtSegmentationDll.h +++ /dev/null @@ -1,41 +0,0 @@ -/*========================================================================= - -Program: Medical Imaging & Interaction Toolkit -Language: C++ -Date: $Date$ -Version: $Revision: 16330 $ - -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 MITKQTSEGMENTATIONDLL_H_ -#define MITKQTSEGMENTATIONDLL_H_ - -// -// The following block is the standard way of creating macros which make exporting -// from a DLL simpler. All files within this DLL are compiled with the org_mitk_gui_qt_application_EXPORTS -// symbol defined on the command line. this symbol should not be defined on any project -// that uses this DLL. This way any other project whose source files include this file see -// MITK_QT_APP functions as being imported from a DLL, wheras this DLL sees symbols -// defined with this macro as being exported. -// -#if defined(_WIN32) && !defined(BERRY_STATIC) - #if defined(org_mitk_gui_qt_segmentation_EXPORTS) - #define MITK_QT_SEGMENTATION __declspec(dllexport) - #else - #define MITK_QT_SEGMENTATION __declspec(dllimport) - #endif -#endif - -#if !defined(MITK_QT_SEGMENTATION) - #define MITK_QT_SEGMENTATION -#endif - -#endif /*MITKQTSEGMENTATIONDLL_H_*/ diff --git a/Modules/MitkExt/Algorithms/mitkExtractDirectedPlaneImageFilter.cpp.orig b/Modules/MitkExt/Algorithms/mitkExtractDirectedPlaneImageFilter.cpp.orig new file mode 100644 index 0000000000..fdc10a7bf1 --- /dev/null +++ b/Modules/MitkExt/Algorithms/mitkExtractDirectedPlaneImageFilter.cpp.orig @@ -0,0 +1,504 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision: $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + + +#include "mitkExtractDirectedPlaneImageFilter.h" +#include "mitkAbstractTransformGeometry.h" + +#include +#include +#include +#include +#include + +#include "pic2vtk.h" +#include "picimage.h" + + + +mitk::ExtractDirectedPlaneImageFilter::ExtractDirectedPlaneImageFilter() +: m_WorldGeometry(NULL) +{ + m_Reslicer = vtkImageReslice::New(); + m_TargetTimestep = 0; + m_InPlaneResampleExtentByGeometry = false; +} + +mitk::ExtractDirectedPlaneImageFilter::~ExtractDirectedPlaneImageFilter() +{ + m_WorldGeometry = NULL; + m_Reslicer->Delete(); +} + +void mitk::ExtractDirectedPlaneImageFilter::GenerateData() +{ + // A world geometry must be set... + if ( m_WorldGeometry == NULL ) + { + itkWarningMacro(<<"No world geometry has been set. Returning."); + return; + } + + Image *input = const_cast< ImageToImageFilter::InputImageType* >( this->GetInput() ); + input->Update(); + + if ( input == NULL ) + { + itkWarningMacro(<<"No input set."); + return; + } + + const TimeSlicedGeometry *inputTimeGeometry = input->GetTimeSlicedGeometry(); + if ( ( inputTimeGeometry == NULL ) + || ( inputTimeGeometry->GetTimeSteps() == 0 ) ) + { + itkWarningMacro(<<"Error reading input image geometry."); + return; + } + + // Get the target timestep; if none is set, use the lowest given. + unsigned int timestep = 0; + if ( ! m_TargetTimestep ) + { + ScalarType time = m_WorldGeometry->GetTimeBounds()[0]; + if ( time > ScalarTypeNumericTraits::NonpositiveMin() ) + { + timestep = inputTimeGeometry->MSToTimeStep( time ); + } + } + else timestep = m_TargetTimestep; + + if ( inputTimeGeometry->IsValidTime( timestep ) == false ) + { + itkWarningMacro(<<"This is not a valid timestep: "<IsVolumeSet( timestep ) ) + { + itkWarningMacro(<<"No volume data existent at given timestep "<GetLargestPossibleRegion(); + requestedRegion.SetIndex( 3, timestep ); + requestedRegion.SetSize( 3, 1 ); + requestedRegion.SetSize( 4, 1 ); + input->SetRequestedRegion( &requestedRegion ); + input->Update(); + + vtkImageData* inputData = input->GetVtkImageData( timestep ); + + if ( inputData == NULL ) + { + itkWarningMacro(<<"Could not extract vtk image data for given timestep"<GetSpacing( spacing ); + + // how big the area is in physical coordinates: widthInMM x heightInMM pixels + mitk::ScalarType widthInMM, heightInMM; + + // where we want to sample + Point3D origin; + Vector3D right, bottom, normal; + Vector3D rightInIndex, bottomInIndex; + + assert( input->GetTimeSlicedGeometry() == inputTimeGeometry ); + + // take transform of input image into account + Geometry3D* inputGeometry = inputTimeGeometry->GetGeometry3D( timestep ); + if ( inputGeometry == NULL ) + { + itkWarningMacro(<<"There is no Geometry3D at given timestep "<( m_WorldGeometry ) != NULL ) + { + const PlaneGeometry *planeGeometry = + static_cast< const PlaneGeometry * >( m_WorldGeometry ); + origin = planeGeometry->GetOrigin(); + right = planeGeometry->GetAxisVector( 0 ); + bottom = planeGeometry->GetAxisVector( 1 ); + normal = planeGeometry->GetNormal(); + + if ( m_InPlaneResampleExtentByGeometry ) + { + // Resampling grid corresponds to the current world geometry. This + // means that the spacing of the output 2D image depends on the + // currently selected world geometry, and *not* on the image itself. + + extent[0] = m_WorldGeometry->GetExtent( 0 ); + extent[1] = m_WorldGeometry->GetExtent( 1 ); + } + else + { + // Resampling grid corresponds to the input geometry. This means that + // the spacing of the output 2D image is directly derived from the + // associated input image, regardless of the currently selected world + // geometry. + inputGeometry->WorldToIndex( origin, right, rightInIndex ); + inputGeometry->WorldToIndex( origin, bottom, bottomInIndex ); + extent[0] = rightInIndex.GetNorm(); + extent[1] = bottomInIndex.GetNorm(); + } + + // Get the extent of the current world geometry and calculate resampling + // spacing therefrom. + widthInMM = m_WorldGeometry->GetExtentInMM( 0 ); + heightInMM = m_WorldGeometry->GetExtentInMM( 1 ); + + mmPerPixel[0] = widthInMM / extent[0]; + mmPerPixel[1] = heightInMM / extent[1]; + + right.Normalize(); + bottom.Normalize(); + normal.Normalize(); + + //origin += right * ( mmPerPixel[0] * 0.5 ); + //origin += bottom * ( mmPerPixel[1] * 0.5 ); + + //widthInMM -= mmPerPixel[0]; + //heightInMM -= mmPerPixel[1]; + + // Use inverse transform of the input geometry for reslicing the 3D image + m_Reslicer->SetResliceTransform( + inputGeometry->GetVtkTransform()->GetLinearInverse() ); + + // Set background level to TRANSLUCENT (see Geometry2DDataVtkMapper3D) + m_Reslicer->SetBackgroundLevel( -32768 ); + + // Check if a reference geometry does exist (as would usually be the case for + // PlaneGeometry). + // Note: this is currently not strictly required, but could facilitate + // correct plane clipping. + if ( m_WorldGeometry->GetReferenceGeometry() ) + { + // Calculate the actual bounds of the transformed plane clipped by the + // dataset bounding box; this is required for drawing the texture at the + // correct position during 3D mapping. + boundsInitialized = this->CalculateClippedPlaneBounds( + m_WorldGeometry->GetReferenceGeometry(), planeGeometry, bounds ); + } + } + + // Do we have an AbstractTransformGeometry? + else if ( dynamic_cast< const AbstractTransformGeometry * >( m_WorldGeometry ) ) + { + const mitk::AbstractTransformGeometry* abstractGeometry = + dynamic_cast< const AbstractTransformGeometry * >(m_WorldGeometry); + + extent[0] = abstractGeometry->GetParametricExtent(0); + extent[1] = abstractGeometry->GetParametricExtent(1); + + widthInMM = abstractGeometry->GetParametricExtentInMM(0); + heightInMM = abstractGeometry->GetParametricExtentInMM(1); + + mmPerPixel[0] = widthInMM / extent[0]; + mmPerPixel[1] = heightInMM / extent[1]; + + origin = abstractGeometry->GetPlane()->GetOrigin(); + + right = abstractGeometry->GetPlane()->GetAxisVector(0); + right.Normalize(); + + bottom = abstractGeometry->GetPlane()->GetAxisVector(1); + bottom.Normalize(); + + normal = abstractGeometry->GetPlane()->GetNormal(); + normal.Normalize(); + + // Use a combination of the InputGeometry *and* the possible non-rigid + // AbstractTransformGeometry for reslicing the 3D Image + vtkGeneralTransform *composedResliceTransform = vtkGeneralTransform::New(); + composedResliceTransform->Identity(); + composedResliceTransform->Concatenate( + inputGeometry->GetVtkTransform()->GetLinearInverse() ); + composedResliceTransform->Concatenate( + abstractGeometry->GetVtkAbstractTransform() + ); + + m_Reslicer->SetResliceTransform( composedResliceTransform ); + + // Set background level to BLACK instead of translucent, to avoid + // boundary artifacts (see Geometry2DDataVtkMapper3D) + m_Reslicer->SetBackgroundLevel( -1023 ); + composedResliceTransform->Delete(); + } + else + { + itkWarningMacro(<<"World Geometry has to be a PlaneGeometry or an AbstractTransformGeometry."); + return; + } + + // Make sure that the image to be resliced has a certain minimum size. + if ( (extent[0] <= 2) && (extent[1] <= 2) ) + { + itkWarningMacro(<<"Image is too small to be resliced..."); + return; + } + + vtkImageChangeInformation * unitSpacingImageFilter = vtkImageChangeInformation::New() ; + unitSpacingImageFilter->SetOutputSpacing( 1.0, 1.0, 1.0 ); + unitSpacingImageFilter->SetInput( inputData ); + + m_Reslicer->SetInput( unitSpacingImageFilter->GetOutput() ); + unitSpacingImageFilter->Delete(); + + //m_Reslicer->SetInput( inputData ); + + m_Reslicer->SetOutputDimensionality( 2 ); + m_Reslicer->SetOutputOrigin( 0.0, 0.0, 0.0 ); + + Vector2D pixelsPerMM; + pixelsPerMM[0] = 1.0 / mmPerPixel[0]; + pixelsPerMM[1] = 1.0 / mmPerPixel[1]; + + //calulate the originArray and the orientations for the reslice-filter + double originArray[3]; + itk2vtk( origin, originArray ); + + m_Reslicer->SetResliceAxesOrigin( originArray ); + + double cosines[9]; + + // direction of the X-axis of the sampled result + vnl2vtk( right.Get_vnl_vector(), cosines ); + + // direction of the Y-axis of the sampled result + vnl2vtk( bottom.Get_vnl_vector(), cosines + 3 ); + + // normal of the plane + vnl2vtk( normal.Get_vnl_vector(), cosines + 6 ); + + m_Reslicer->SetResliceAxesDirectionCosines( cosines ); + + // Determine output extent for reslicing + ScalarType size[2]; + size[0] = (bounds[1] - bounds[0]) / mmPerPixel[0]; + size[1] = (bounds[3] - bounds[2]) / mmPerPixel[1]; + + int xMin, xMax, yMin, yMax; + if ( boundsInitialized ) + { + xMin = static_cast< int >( bounds[0] / mmPerPixel[0] );//+ 0.5 ); + xMax = static_cast< int >( bounds[1] / mmPerPixel[0] );//+ 0.5 ); + yMin = static_cast< int >( bounds[2] / mmPerPixel[1] );//+ 0.5); + yMax = static_cast< int >( bounds[3] / mmPerPixel[1] );//+ 0.5 ); + } + else + { + // If no reference geometry is available, we also don't know about the + // maximum plane size; so the overlap is just ignored + + xMin = yMin = 0; + xMax = static_cast< int >( extent[0] - pixelsPerMM[0] );//+ 0.5 ); + yMax = static_cast< int >( extent[1] - pixelsPerMM[1] );//+ 0.5 ); + } + + m_Reslicer->SetOutputSpacing( mmPerPixel[0], mmPerPixel[1], 1.0 ); + // xMax and yMax are meant exclusive until now, whereas + // SetOutputExtent wants an inclusive bound. Thus, we need + // to subtract 1. + m_Reslicer->SetOutputExtent( xMin, xMax-1, yMin, yMax-1, 0, 1 ); + + // Do the reslicing. Modified() is called to make sure that the reslicer is + // executed even though the input geometry information did not change; this + // is necessary when the input /em data, but not the /em geometry changes. + m_Reslicer->Modified(); + m_Reslicer->ReleaseDataFlagOn(); + + m_Reslicer->Update(); + + // 1. Check the result + vtkImageData* reslicedImage = m_Reslicer->GetOutput(); + + mitkIpPicDescriptor *pic = Pic2vtk::convert( reslicedImage ); + + if((reslicedImage == NULL) || (reslicedImage->GetDataDimension() < 1)) + { + itkWarningMacro(<<"Reslicer returned empty image"); + return; + } + + unsigned int dimensions[2]; + dimensions[0] = (unsigned int)extent[0]; dimensions[1] = (unsigned int)extent[1]; + Vector3D spacingVector; + FillVector3D(spacingVector, mmPerPixel[0], mmPerPixel[1], 1.0); + + mitk::Image::Pointer resultImage = this->GetOutput(); + resultImage->Initialize( pic ); + resultImage->SetSpacing( spacingVector ); + resultImage->SetPicVolume( pic ); + + mitkIpPicFree(pic); + + /*unsigned int dimensions[2]; + dimensions[0] = (unsigned int)extent[0]; dimensions[1] = (unsigned int)extent[1]; + Vector3D spacingVector; + FillVector3D(spacingVector, mmPerPixel[0], mmPerPixel[1], 1.0); + + mitk::Image::Pointer resultImage = this->GetOutput(); + resultImage->Initialize(m_Reslicer->GetOutput()); + resultImage->Initialize(inputImage->GetPixelType(), 2, dimensions); + resultImage->SetSpacing(spacingVector); + resultImage->SetSlice(m_Reslicer->GetOutput());*/ +} + + +void mitk::ExtractDirectedPlaneImageFilter::GenerateOutputInformation() +{ + Superclass::GenerateOutputInformation(); +} + + +bool mitk::ExtractDirectedPlaneImageFilter +::CalculateClippedPlaneBounds( const Geometry3D *boundingGeometry, + const PlaneGeometry *planeGeometry, vtkFloatingPointType *bounds ) +{ + // Clip the plane with the bounding geometry. To do so, the corner points + // of the bounding box are transformed by the inverse transformation + // matrix, and the transformed bounding box edges derived therefrom are + // clipped with the plane z=0. The resulting min/max values are taken as + // bounds for the image reslicer. + const BoundingBox *boundingBox = boundingGeometry->GetBoundingBox(); + + BoundingBox::PointType bbMin = boundingBox->GetMinimum(); + BoundingBox::PointType bbMax = boundingBox->GetMaximum(); + BoundingBox::PointType bbCenter = boundingBox->GetCenter(); + + vtkPoints *points = vtkPoints::New(); + if(boundingGeometry->GetImageGeometry()) + { + points->InsertPoint( 0, bbMin[0]-0.5, bbMin[1]-0.5, bbMin[2]-0.5 ); + points->InsertPoint( 1, bbMin[0]-0.5, bbMin[1]-0.5, bbMax[2]-0.5 ); + points->InsertPoint( 2, bbMin[0]-0.5, bbMax[1]-0.5, bbMax[2]-0.5 ); + points->InsertPoint( 3, bbMin[0]-0.5, bbMax[1]-0.5, bbMin[2]-0.5 ); + points->InsertPoint( 4, bbMax[0]-0.5, bbMin[1]-0.5, bbMin[2]-0.5 ); + points->InsertPoint( 5, bbMax[0]-0.5, bbMin[1]-0.5, bbMax[2]-0.5 ); + points->InsertPoint( 6, bbMax[0]-0.5, bbMax[1]-0.5, bbMax[2]-0.5 ); + points->InsertPoint( 7, bbMax[0]-0.5, bbMax[1]-0.5, bbMin[2]-0.5 ); + } + else + { + points->InsertPoint( 0, bbMin[0], bbMin[1], bbMin[2] ); + points->InsertPoint( 1, bbMin[0], bbMin[1], bbMax[2] ); + points->InsertPoint( 2, bbMin[0], bbMax[1], bbMax[2] ); + points->InsertPoint( 3, bbMin[0], bbMax[1], bbMin[2] ); + points->InsertPoint( 4, bbMax[0], bbMin[1], bbMin[2] ); + points->InsertPoint( 5, bbMax[0], bbMin[1], bbMax[2] ); + points->InsertPoint( 6, bbMax[0], bbMax[1], bbMax[2] ); + points->InsertPoint( 7, bbMax[0], bbMax[1], bbMin[2] ); + } + + vtkPoints *newPoints = vtkPoints::New(); + + vtkTransform *transform = vtkTransform::New(); + transform->Identity(); + transform->Concatenate( + planeGeometry->GetVtkTransform()->GetLinearInverse() + ); + + transform->Concatenate( boundingGeometry->GetVtkTransform() ); + + transform->TransformPoints( points, newPoints ); + transform->Delete(); + + bounds[0] = bounds[2] = 10000000.0; + bounds[1] = bounds[3] = -10000000.0; + bounds[4] = bounds[5] = 0.0; + + this->LineIntersectZero( newPoints, 0, 1, bounds ); + this->LineIntersectZero( newPoints, 1, 2, bounds ); + this->LineIntersectZero( newPoints, 2, 3, bounds ); + this->LineIntersectZero( newPoints, 3, 0, bounds ); + this->LineIntersectZero( newPoints, 0, 4, bounds ); + this->LineIntersectZero( newPoints, 1, 5, bounds ); + this->LineIntersectZero( newPoints, 2, 6, bounds ); + this->LineIntersectZero( newPoints, 3, 7, bounds ); + this->LineIntersectZero( newPoints, 4, 5, bounds ); + this->LineIntersectZero( newPoints, 5, 6, bounds ); + this->LineIntersectZero( newPoints, 6, 7, bounds ); + this->LineIntersectZero( newPoints, 7, 4, bounds ); + + // clean up vtk data + points->Delete(); + newPoints->Delete(); + + if ( (bounds[0] > 9999999.0) || (bounds[2] > 9999999.0) + || (bounds[1] < -9999999.0) || (bounds[3] < -9999999.0) ) + { + return false; + } + else + { + // The resulting bounds must be adjusted by the plane spacing, since we + // we have so far dealt with index coordinates + const float *planeSpacing = planeGeometry->GetFloatSpacing(); + bounds[0] *= planeSpacing[0]; + bounds[1] *= planeSpacing[0]; + bounds[2] *= planeSpacing[1]; + bounds[3] *= planeSpacing[1]; + bounds[4] *= planeSpacing[2]; + bounds[5] *= planeSpacing[2]; + return true; + } +} + +bool mitk::ExtractDirectedPlaneImageFilter +::LineIntersectZero( vtkPoints *points, int p1, int p2, + vtkFloatingPointType *bounds ) +{ + vtkFloatingPointType point1[3]; + vtkFloatingPointType point2[3]; + points->GetPoint( p1, point1 ); + points->GetPoint( p2, point2 ); + + if ( (point1[2] * point2[2] <= 0.0) && (point1[2] != point2[2]) ) + { + double x, y; + x = ( point1[0] * point2[2] - point1[2] * point2[0] ) / ( point2[2] - point1[2] ); + y = ( point1[1] * point2[2] - point1[2] * point2[1] ) / ( point2[2] - point1[2] ); + + if ( x < bounds[0] ) { bounds[0] = x; } + if ( x > bounds[1] ) { bounds[1] = x; } + if ( y < bounds[2] ) { bounds[2] = y; } + if ( y > bounds[3] ) { bounds[3] = y; } + bounds[4] = bounds[5] = 0.0; + return true; + } + return false; +}