diff --git a/Core/Code/DataManagement/mitkApplicationCursor.cpp b/Core/Code/DataManagement/mitkApplicationCursor.cpp index 3286df2125..a4de3a11aa 100644 --- a/Core/Code/DataManagement/mitkApplicationCursor.cpp +++ b/Core/Code/DataManagement/mitkApplicationCursor.cpp @@ -1,112 +1,115 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkApplicationCursor.h" #include #include +//us +#include "mitkModuleResource.h" + mitk::ApplicationCursorImplementation* mitk::ApplicationCursor::m_Implementation = NULL; namespace mitk { ApplicationCursor::ApplicationCursor() { } ApplicationCursor* ApplicationCursor::GetInstance() { static ApplicationCursor* m_Instance = NULL; if (!m_Instance) { m_Instance = new ApplicationCursor(); } return m_Instance; } void ApplicationCursor::RegisterImplementation(ApplicationCursorImplementation* implementation) { m_Implementation = implementation; } -void ApplicationCursor::PushCursor(const std::string& path, int hotspotX, int hotspotY) +void ApplicationCursor::PushCursor(const ModuleResource resource, int hotspotX, int hotspotY) { if (m_Implementation) { - m_Implementation->PushCursor(path, hotspotX, hotspotY); + m_Implementation->PushCursor(resource, hotspotX, hotspotY); } else { MITK_ERROR << "in mitk::ApplicationCursor::PushCursor(): no implementation registered." << std::endl; throw std::logic_error("No implementation registered for mitk::ApplicationCursor."); } } void ApplicationCursor::PushCursor(const char* XPM[], int hotspotX, int hotspotY) { if (m_Implementation) { m_Implementation->PushCursor(XPM, hotspotX, hotspotY); } else { MITK_ERROR << "in mitk::ApplicationCursor::PushCursor(): no implementation registered." << std::endl; throw std::logic_error("No implementation registered for mitk::ApplicationCursor."); } } void ApplicationCursor::PopCursor() { if (m_Implementation) { m_Implementation->PopCursor(); } else { MITK_ERROR << "in mitk::ApplicationCursor::PopCursor(): no implementation registered." << std::endl; throw std::logic_error("No implementation registered for mitk::ApplicationCursor."); } } const Point2I ApplicationCursor::GetCursorPosition() { if (m_Implementation) { return m_Implementation->GetCursorPosition(); } else { MITK_ERROR << "in mitk::ApplicationCursor::GetCursorPosition(): no implementation registered." << std::endl; throw std::logic_error("No implementation registered for mitk::ApplicationCursor."); } } void ApplicationCursor::SetCursorPosition(const Point2I& p) { if (m_Implementation) { m_Implementation->SetCursorPosition(p); } else { MITK_ERROR << "in mitk::ApplicationCursor::SetCursorPosition(): no implementation registered." << std::endl; throw std::logic_error("No implementation registered for mitk::ApplicationCursor."); } } } // namespace diff --git a/Core/Code/DataManagement/mitkApplicationCursor.h b/Core/Code/DataManagement/mitkApplicationCursor.h index 5b3d93195d..341a93ad22 100644 --- a/Core/Code/DataManagement/mitkApplicationCursor.h +++ b/Core/Code/DataManagement/mitkApplicationCursor.h @@ -1,109 +1,111 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITK_APPLICATION_CURSOR_H_DEFINED_AND_ALL_IS_GOOD #define MITK_APPLICATION_CURSOR_H_DEFINED_AND_ALL_IS_GOOD #include #include "mitkVector.h" namespace mitk { +class ModuleResource; + /*! \brief Toolkit specific implementation of mitk::ApplicationCursor For any toolkit, this class has to be sub-classed. One instance of that sub-class has to be registered with mitk::ApplicationCursor. See the (very simple) implmentation of QmitkApplicationCursor for an example. */ class MITK_CORE_EXPORT ApplicationCursorImplementation { public: /// Change the current application cursor virtual void PushCursor(const char* XPM[], int hotspotX, int hotspotY) = 0; /// Change the current application cursor - virtual void PushCursor(const std::string& path, int hotspotX, int hotspotY) = 0; + virtual void PushCursor(const ModuleResource, int hotspotX, int hotspotY) = 0; /// Restore the previous cursor virtual void PopCursor() = 0; /// Get absolute mouse position on screen virtual const Point2I GetCursorPosition() = 0; /// Set absolute mouse position on screen virtual void SetCursorPosition(const Point2I&) = 0; virtual ~ApplicationCursorImplementation() {}; protected: private: }; /*! \brief Allows to override the application's cursor. Base class for classes that allow to override the applications cursor with context dependent cursors. Accepts cursors in the XPM format. The behaviour is stack-like. You can push your cursor on top of the stack and later pop it to reset the cursor to its former state. This is mimicking Qt's Application::setOverrideCuror() behaviour, but should be ok for most cases where you want to switch a cursor. */ class MITK_CORE_EXPORT ApplicationCursor { public: /// This class is a singleton. static ApplicationCursor* GetInstance(); /// To be called by a toolkit specific ApplicationCursorImplementation. static void RegisterImplementation(ApplicationCursorImplementation* implementation); /// Change the current application cursor void PushCursor(const char* XPM[], int hotspotX = -1, int hotspotY = -1); /// Change the current application cursor - void PushCursor(const std::string& path, int hotspotX = -1, int hotspotY = -1); + void PushCursor(const ModuleResource, int hotspotX = -1, int hotspotY = -1); /// Restore the previous cursor void PopCursor(); /// Get absolute mouse position on screen /// \return (-1, -1) if querying mouse position is not possible const Point2I GetCursorPosition(); /// Set absolute mouse position on screen void SetCursorPosition(const Point2I&); protected: /// Purposely hidden - singleton ApplicationCursor(); private: static ApplicationCursorImplementation* m_Implementation; }; } // namespace #endif diff --git a/Modules/MitkExt/Interactions/mitkTool.cpp b/Modules/MitkExt/Interactions/mitkTool.cpp index 19e67a1a60..2e48f71efa 100644 --- a/Modules/MitkExt/Interactions/mitkTool.cpp +++ b/Modules/MitkExt/Interactions/mitkTool.cpp @@ -1,193 +1,201 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkTool.h" #include "mitkDataNodeFactory.h" #include "mitkProperties.h" #include "mitkLevelWindowProperty.h" #include "mitkVtkResliceInterpolationProperty.h" // us #include "mitkModule.h" #include "mitkModuleResource.h" #include #include #include mitk::Tool::Tool(const char* type) : StateMachine(type), m_SupportRoi(false), // for reference images m_PredicateImages(NodePredicateDataType::New("Image")), m_PredicateDim3(NodePredicateDimension::New(3, 1)), m_PredicateDim4(NodePredicateDimension::New(4, 1)), m_PredicateDimension( mitk::NodePredicateOr::New(m_PredicateDim3, m_PredicateDim4) ), m_PredicateImage3D( NodePredicateAnd::New(m_PredicateImages, m_PredicateDimension) ), m_PredicateBinary(NodePredicateProperty::New("binary", BoolProperty::New(true))), m_PredicateNotBinary( NodePredicateNot::New(m_PredicateBinary) ), m_PredicateSegmentation(NodePredicateProperty::New("segmentation", BoolProperty::New(true))), m_PredicateNotSegmentation( NodePredicateNot::New(m_PredicateSegmentation) ), m_PredicateHelper(NodePredicateProperty::New("helper object", BoolProperty::New(true))), m_PredicateNotHelper( NodePredicateNot::New(m_PredicateHelper) ), m_PredicateImageColorful( NodePredicateAnd::New(m_PredicateNotBinary, m_PredicateNotSegmentation) ), m_PredicateImageColorfulNotHelper( NodePredicateAnd::New(m_PredicateImageColorful, m_PredicateNotHelper) ), m_PredicateReference( NodePredicateAnd::New(m_PredicateImage3D, m_PredicateImageColorfulNotHelper) ), // for working image m_IsSegmentationPredicate(NodePredicateAnd::New(NodePredicateOr::New(m_PredicateBinary, m_PredicateSegmentation), m_PredicateNotHelper)) { } mitk::Tool::~Tool() { } const char* mitk::Tool::GetGroup() const { return "default"; } void mitk::Tool::SetToolManager(ToolManager* manager) { m_ToolManager = manager; } void mitk::Tool::Activated() { } void mitk::Tool::Deactivated() { StateMachine::ResetStatemachineToStartState(); // forget about the past } itk::Object::Pointer mitk::Tool::GetGUI(const std::string& toolkitPrefix, const std::string& toolkitPostfix) { itk::Object::Pointer object; std::string classname = this->GetNameOfClass(); std::string guiClassname = toolkitPrefix + classname + toolkitPostfix; std::list allGUIs = itk::ObjectFactoryBase::CreateAllInstance(guiClassname.c_str()); for( std::list::iterator iter = allGUIs.begin(); iter != allGUIs.end(); ++iter ) { if (object.IsNull()) { object = dynamic_cast( iter->GetPointer() ); } else { MITK_ERROR << "There is more than one GUI for " << classname << " (several factories claim ability to produce a " << guiClassname << " ) " << std::endl; return NULL; // people should see and fix this error } } return object; } mitk::NodePredicateBase::ConstPointer mitk::Tool::GetReferenceDataPreference() const { return m_PredicateReference.GetPointer(); } mitk::NodePredicateBase::ConstPointer mitk::Tool::GetWorkingDataPreference() const { return m_IsSegmentationPredicate.GetPointer(); } mitk::DataNode::Pointer mitk::Tool::CreateEmptySegmentationNode( Image* original, const std::string& organName, const mitk::Color& color ) { // we NEED a reference image for size etc. if (!original) return NULL; // actually create a new empty segmentation PixelType pixelType(mitk::MakeScalarPixelType() ); Image::Pointer segmentation = Image::New(); if (original->GetDimension() == 2) { const unsigned int dimensions[] = { original->GetDimension(0), original->GetDimension(1), 1 }; segmentation->Initialize(pixelType, 3, dimensions); } else { segmentation->Initialize(pixelType, original->GetDimension(), original->GetDimensions()); } unsigned int byteSize = sizeof(DefaultSegmentationDataType); for (unsigned int dim = 0; dim < segmentation->GetDimension(); ++dim) { byteSize *= segmentation->GetDimension(dim); } memset( segmentation->GetData(), 0, byteSize ); if (original->GetTimeSlicedGeometry() ) { TimeSlicedGeometry::Pointer originalGeometry = original->GetTimeSlicedGeometry()->Clone(); segmentation->SetGeometry( originalGeometry ); } else { Tool::ErrorMessage("Original image does not have a 'Time sliced geometry'! Cannot create a segmentation."); return NULL; } return CreateSegmentationNode( segmentation, organName, color ); } mitk::DataNode::Pointer mitk::Tool::CreateSegmentationNode( Image* image, const std::string& organName, const mitk::Color& color ) { if (!image) return NULL; // decorate the datatreenode with some properties DataNode::Pointer segmentationNode = DataNode::New(); segmentationNode->SetData( image ); // name segmentationNode->SetProperty( "name", StringProperty::New( organName ) ); // visualization properties segmentationNode->SetProperty( "binary", BoolProperty::New(true) ); segmentationNode->SetProperty( "color", ColorProperty::New(color) ); segmentationNode->SetProperty( "texture interpolation", BoolProperty::New(false) ); segmentationNode->SetProperty( "layer", IntProperty::New(10) ); segmentationNode->SetProperty( "levelwindow", LevelWindowProperty::New( LevelWindow(0.5, 1) ) ); segmentationNode->SetProperty( "opacity", FloatProperty::New(0.3) ); segmentationNode->SetProperty( "segmentation", BoolProperty::New(true) ); segmentationNode->SetProperty( "reslice interpolation", VtkResliceInterpolationProperty::New() ); // otherwise -> segmentation appears in 2 slices sometimes (only visual effect, not different data) // For MITK-3M3 release, the volume of all segmentations should be shown segmentationNode->SetProperty( "showVolume", BoolProperty::New( true ) ); return segmentationNode; } mitk::ModuleResource mitk::Tool::GetIconResource() const { Module* module = GetModuleContext()->GetModule(); // Each specific tool should load its own resource. This one will be invalid ModuleResource resource = module->GetResource("dummy.resource"); return resource; } + +mitk::ModuleResource mitk::Tool::GetCursorIconResource() const +{ + Module* module = GetModuleContext()->GetModule(); + // Each specific tool should load its own resource. This one will be invalid + ModuleResource resource = module->GetResource("dummy.resource"); + return resource; +} diff --git a/Modules/MitkExt/Interactions/mitkTool.h b/Modules/MitkExt/Interactions/mitkTool.h index b2cbe68469..df65a4c7a3 100644 --- a/Modules/MitkExt/Interactions/mitkTool.h +++ b/Modules/MitkExt/Interactions/mitkTool.h @@ -1,241 +1,241 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkTool_h_Included #define mitkTool_h_Included #include "mitkCommon.h" #include "MitkExtExports.h" #include "mitkStateMachine.h" #include "mitkToolEvents.h" #include "itkObjectFactoryBase.h" #include "itkVersion.h" #include "mitkToolFactoryMacro.h" #include "mitkMessage.h" #include "mitkDataNode.h" #include "mitkNodePredicateProperty.h" #include "mitkNodePredicateDataType.h" #include "mitkNodePredicateDimension.h" #include "mitkNodePredicateAnd.h" #include "mitkNodePredicateOr.h" #include "mitkNodePredicateNot.h" #include #include #include namespace mitk { class ModuleResource; class ToolManager; /** \brief Base class of all tools used by mitk::ToolManager. \sa ToolManager \sa SegTool2D \ingroup Interaction \ingroup ToolManagerEtAl There is a separate page describing the \ref QmitkInteractiveSegmentationTechnicalPage. Every tool is a mitk::StateMachine, which can follow any transition pattern that it likes. One important thing to know is, that every derived tool should always call SuperClass::Deactivated() in its own implementation of Deactivated, because mitk::Tool resets the StateMachine in this method. Only if you are very sure that you covered all possible things that might happen to your own tool, you should consider not to reset the StateMachine from time to time. To learn about the MITK implementation of state machines in general, have a look at \ref InteractionPage. To derive a non-abstract tool, you inherit from mitk::Tool (or some other base class further down the inheritance tree), and in your own parameterless constructor (that is called from the itkNewMacro that you use) you pass a StateMachine pattern name to the superclass. Names for valid patterns can be found in StateMachine.xml (which might be enhanced by you). You have to implement at least GetXPM() and GetName() to provide some identification. Each Tool knows its ToolManager, which can provide the data that the tool should work on. \warning Only to be instantiated by mitk::ToolManager (because SetToolManager has to be called). All other uses are unsupported. $Author$ */ class MitkExt_EXPORT Tool : public StateMachine { public: typedef unsigned char DefaultSegmentationDataType; /** * \brief To let GUI process new events (e.g. qApp->processEvents() ) */ Message<> GUIProcessEventsMessage; /** * \brief To send error messages (to be shown by some GUI) */ Message1 ErrorMessage; /** * \brief To send whether the tool is busy (to be shown by some GUI) */ Message1 CurrentlyBusy; /** * \brief To send general messages (to be shown by some GUI) */ Message1 GeneralMessage; mitkClassMacro(Tool, StateMachine); // no New(), there should only be subclasses /** \brief Returns an icon in the XPM format. This icon has to fit into some kind of button in most applications, so make it smaller than 25x25 pixels. XPM is e.g. supported by The Gimp. But if you open any XPM file in your text editor, you will see that you could also "draw" it with an editor. */ virtual const char** GetXPM() const = 0; /** * \brief Returns the path of an icon. * * This icon is preferred to the XPM icon. */ virtual std::string GetIconPath() const { return ""; } /** * \brief Returns the path of a cursor icon. * */ - virtual std::string GetCursorIconPath() const { return ""; } + virtual ModuleResource GetCursorIconResource() const; /** * @brief Returns the tool button icon of the tool wrapped by a usModuleResource * @return a valid ModuleResource or an invalid if this function * is not reimplemented */ virtual ModuleResource GetIconResource() const; /** \brief Returns the name of this tool. Make it short! This name has to fit into some kind of button in most applications, so take some time to think of a good name! */ virtual const char* GetName() const = 0; /** \brief Name of a group. You can group several tools by assigning a group name. Graphical tool selectors might use this information to group tools. (What other reason could there be?) */ virtual const char* GetGroup() const; /** * \brief Interface for GUI creation. * * This is the basic interface for creation of a GUI object belonging to one tool. * * Tools that support a GUI (e.g. for display/editing of parameters) should follow some rules: * * - A Tool and its GUI are two separate classes * - There may be several instances of a GUI at the same time. * - mitk::Tool is toolkit (Qt, wxWidgets, etc.) independent, the GUI part is of course dependent * - The GUI part inherits both from itk::Object and some GUI toolkit class * - The GUI class name HAS to be constructed like "toolkitPrefix" tool->GetClassName() + "toolkitPostfix", e.g. MyTool -> wxMyToolGUI * - For each supported toolkit there is a base class for tool GUIs, which contains some convenience methods * - Tools notify the GUI about changes using ITK events. The GUI must observe interesting events. * - The GUI base class may convert all ITK events to the GUI toolkit's favoured messaging system (Qt -> signals) * - Calling methods of a tool by its GUI is done directly. * In some cases GUIs don't want to be notified by the tool when they cause a change in a tool. * There is a macro CALL_WITHOUT_NOTICE(method()), which will temporarily disable all notifications during a method call. */ virtual itk::Object::Pointer GetGUI(const std::string& toolkitPrefix, const std::string& toolkitPostfix); virtual NodePredicateBase::ConstPointer GetReferenceDataPreference() const; virtual NodePredicateBase::ConstPointer GetWorkingDataPreference() const; DataNode::Pointer CreateEmptySegmentationNode( Image* original, const std::string& organName, const mitk::Color& color ); DataNode::Pointer CreateSegmentationNode( Image* image, const std::string& organName, const mitk::Color& color ); itkGetMacro(SupportRoi, bool); itkSetMacro(SupportRoi, bool); itkBooleanMacro(SupportRoi); protected: friend class ToolManager; virtual void SetToolManager(ToolManager*); /** \brief Called when the tool gets activated (registered to mitk::GlobalInteraction). Derived tools should call their parents implementation. */ virtual void Activated(); /** \brief Called when the tool gets deactivated (unregistered from mitk::GlobalInteraction). Derived tools should call their parents implementation. */ virtual void Deactivated(); Tool(); // purposely hidden Tool( const char*); // purposely hidden virtual ~Tool(); ToolManager* m_ToolManager; bool m_SupportRoi; private: // for reference data NodePredicateDataType::Pointer m_PredicateImages; NodePredicateDimension::Pointer m_PredicateDim3; NodePredicateDimension::Pointer m_PredicateDim4; NodePredicateOr::Pointer m_PredicateDimension; NodePredicateAnd::Pointer m_PredicateImage3D; NodePredicateProperty::Pointer m_PredicateBinary; NodePredicateNot::Pointer m_PredicateNotBinary; NodePredicateProperty::Pointer m_PredicateSegmentation; NodePredicateNot::Pointer m_PredicateNotSegmentation; NodePredicateProperty::Pointer m_PredicateHelper; NodePredicateNot::Pointer m_PredicateNotHelper; NodePredicateAnd::Pointer m_PredicateImageColorful; NodePredicateAnd::Pointer m_PredicateImageColorfulNotHelper; NodePredicateAnd::Pointer m_PredicateReference; // for working data NodePredicateAnd::Pointer m_IsSegmentationPredicate; }; } // namespace #endif diff --git a/Modules/Qmitk/QmitkApplicationCursor.cpp b/Modules/Qmitk/QmitkApplicationCursor.cpp index 19b6bfd0d4..5a99950711 100644 --- a/Modules/Qmitk/QmitkApplicationCursor.cpp +++ b/Modules/Qmitk/QmitkApplicationCursor.cpp @@ -1,67 +1,84 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkApplicationCursor.h" #include #include #include #include +// us +#include "mitkModuleResource.h" +#include "mitkModuleResourceStream.h" + QmitkApplicationCursor::QmitkApplicationCursor() { mitk::ApplicationCursor::RegisterImplementation(this); } -void QmitkApplicationCursor::PushCursor(const std::string& path, int hotspotX, int hotspotY) +void QmitkApplicationCursor::PushCursor(const mitk::ModuleResource resource, int hotspotX, int hotspotY) { - QPixmap pixmap( path.c_str() ); - QCursor cursor( pixmap, hotspotX, hotspotY ); // no test for validity in QPixmap(xpm)! - QApplication::setOverrideCursor( cursor ); + if (resource.IsValid()) + { + mitk::ModuleResourceStream resourceStream(resource); + resourceStream.seekg(0, std::ios::end); + std::ios::pos_type length = resourceStream.tellg(); + resourceStream.seekg(0, std::ios::beg); + + char* data = new char[length]; + resourceStream.read(data, length); + QPixmap pixmap; + pixmap.loadFromData(QByteArray::fromRawData(data, length)); + QCursor cursor( pixmap, hotspotX, hotspotY ); // no test for validity in QPixmap(xpm)! + QApplication::setOverrideCursor( cursor ); + delete[] data; + + } } void QmitkApplicationCursor::PushCursor(const char* XPM[], int hotspotX, int hotspotY) { QPixmap pixmap( XPM ); QCursor cursor( pixmap, hotspotX, hotspotY ); // no test for validity in QPixmap(xpm)! QApplication::setOverrideCursor( cursor ); } void QmitkApplicationCursor::PopCursor() { QApplication::restoreOverrideCursor(); } const mitk::Point2I QmitkApplicationCursor::GetCursorPosition() { mitk::Point2I mp; QPoint qp = QCursor::pos(); mp[0] = qp.x(); mp[1] = qp.y(); return mp; } void QmitkApplicationCursor::SetCursorPosition(const mitk::Point2I& p) { static bool selfCall = false; if (selfCall) return; // this is to avoid recursive calls selfCall = true; QCursor::setPos( p[0], p[1] ); selfCall = false; } diff --git a/Modules/Qmitk/QmitkApplicationCursor.h b/Modules/Qmitk/QmitkApplicationCursor.h index 1b82ca8d0e..8cdba027bc 100644 --- a/Modules/Qmitk/QmitkApplicationCursor.h +++ b/Modules/Qmitk/QmitkApplicationCursor.h @@ -1,49 +1,53 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITK_APPLICATION_CURSOR_H_INCLUDED #define QMITK_APPLICATION_CURSOR_H_INCLUDED #include #include "mitkApplicationCursor.h" +namespace mitk { +class ModuleResource; +} + /*! \ingroup QmitkModule \brief Qt specific implementation of ApplicationCursorImplementation This class very simply calls the QApplication's methods setOverrideCursor() and restoreOverrideCursor(). */ class QMITK_EXPORT QmitkApplicationCursor : public mitk::ApplicationCursorImplementation { public: // Will be instantiated automatically from QmitkApplicationCursor.cpp once QmitkApplicationCursor(); virtual void PushCursor(const char* XPM[], int hotspotX, int hotspotY); - virtual void PushCursor(const std::string& path, int hotspotX, int hotspotY); + virtual void PushCursor(const mitk::ModuleResource, int hotspotX, int hotspotY); virtual void PopCursor(); virtual const mitk::Point2I GetCursorPosition(); virtual void SetCursorPosition(const mitk::Point2I&); protected: private: }; #endif diff --git a/Modules/QmitkExt/files.cmake b/Modules/QmitkExt/files.cmake index 95ba54d22c..f4667c71f3 100644 --- a/Modules/QmitkExt/files.cmake +++ b/Modules/QmitkExt/files.cmake @@ -1,224 +1,223 @@ set(CPP_FILES QmitkApplicationBase/QmitkCommonFunctionality.cpp QmitkApplicationBase/QmitkIOUtil.cpp #QmitkModels/QmitkDataStorageListModel.cpp #QmitkModels/QmitkPropertiesTableModel.cpp #QmitkModels/QmitkDataStorageTreeModel.cpp #QmitkModels/QmitkDataStorageTableModel.cpp #QmitkModels/QmitkPropertyDelegate.cpp #QmitkModels/QmitkPointListModel.cpp #QmitkAlgorithmFunctionalityComponent.cpp #QmitkBaseAlgorithmComponent.cpp QmitkAboutDialog/QmitkAboutDialog.cpp #QmitkFunctionalityComponents/QmitkSurfaceCreatorComponent.cpp #QmitkFunctionalityComponents/QmitkPixelGreyValueManipulatorComponent.cpp #QmitkFunctionalityComponents/QmitkConnectivityFilterComponent.cpp #QmitkFunctionalityComponents/QmitkImageCropperComponent.cpp #QmitkFunctionalityComponents/QmitkSeedPointSetComponent.cpp #QmitkFunctionalityComponents/QmitkSurfaceTransformerComponent.cpp QmitkPropertyObservers/QmitkBasePropertyView.cpp QmitkPropertyObservers/QmitkBoolPropertyWidget.cpp QmitkPropertyObservers/QmitkColorPropertyEditor.cpp QmitkPropertyObservers/QmitkColorPropertyView.cpp QmitkPropertyObservers/QmitkEnumerationPropertyWidget.cpp QmitkPropertyObservers/QmitkNumberPropertyEditor.cpp QmitkPropertyObservers/QmitkNumberPropertyView.cpp QmitkPropertyObservers/QmitkPropertyViewFactory.cpp QmitkPropertyObservers/QmitkStringPropertyEditor.cpp QmitkPropertyObservers/QmitkStringPropertyOnDemandEdit.cpp QmitkPropertyObservers/QmitkStringPropertyView.cpp QmitkPropertyObservers/QmitkNumberPropertySlider.cpp QmitkPropertyObservers/QmitkUGCombinedRepresentationPropertyWidget.cpp qclickablelabel.cpp #QmitkAbortEventFilter.cpp # QmitkApplicationCursor.cpp QmitkCallbackFromGUIThread.cpp QmitkEditPointDialog.cpp QmitkExtRegisterClasses.cpp QmitkFileChooser.cpp # QmitkRenderingManager.cpp # QmitkRenderingManagerFactory.cpp # QmitkRenderWindow.cpp # QmitkEventAdapter.cpp QmitkFloatingPointSpanSlider.cpp QmitkColorTransferFunctionCanvas.cpp QmitkStandardViews.cpp QmitkStepperAdapter.cpp # QmitkLineEditLevelWindowWidget.cpp # mitkSliderLevelWindowWidget.cpp # QmitkLevelWindowWidget.cpp # QmitkPointListWidget.cpp # QmitkPointListView.cpp QmitkPiecewiseFunctionCanvas.cpp QmitkSliderNavigatorWidget.cpp QmitkTransferFunctionCanvas.cpp QmitkCrossWidget.cpp #QmitkLevelWindowRangeChangeDialog.cpp #QmitkLevelWindowPresetDefinitionDialog.cpp # QmitkLevelWindowWidgetContextMenu.cpp QmitkSliceWidget.cpp # QmitkStdMultiWidget.cpp QmitkTransferFunctionWidget.cpp QmitkTransferFunctionGeneratorWidget.cpp QmitkSelectableGLWidget.cpp # QmitkPropertyListPopup.cpp # QmitkMaterialEditor.cpp # QmitkMaterialShowcase.cpp # QmitkPropertiesTableEditor.cpp QmitkPrimitiveMovieNavigatorWidget.cpp # QmitkDataStorageComboBox.cpp QmitkHistogram.cpp QmitkHistogramWidget.cpp QmitkPlotWidget.cpp QmitkPlotDialog.cpp QmitkPointListModel.cpp QmitkPointListView.cpp QmitkPointListWidget.cpp QmitkPointListViewWidget.cpp QmitkCorrespondingPointSetsView.cpp QmitkCorrespondingPointSetsModel.cpp QmitkCorrespondingPointSetsWidget.cpp QmitkVideoBackground.cpp QmitkHotkeyLineEdit.cpp QmitkBoundingObjectWidget.cpp QmitkModuleTableModel.cpp QmitkModulesDialog.cpp QmitkHistogramJSWidget.cpp QmitkLineEdit.cpp ) if( NOT ${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}.${VTK_BUILD_VERSION} VERSION_LESS 5.4.0 ) set(CPP_FILES ${CPP_FILES} QmitkVtkHistogramWidget.cpp QmitkVtkLineProfileWidget.cpp ) endif() if(NOT APPLE) set(CPP_FILES ${CPP_FILES} QmitkBaseComponent.cpp QmitkBaseFunctionalityComponent.cpp QmitkFunctionalityComponentContainer.cpp QmitkFunctionalityComponents/QmitkThresholdComponent.cpp ) endif() QT4_ADD_RESOURCES(CPP_FILES resources/QmitkResources.qrc) set(MOC_H_FILES QmitkPropertyObservers/QmitkBasePropertyView.h QmitkPropertyObservers/QmitkBoolPropertyWidget.h QmitkPropertyObservers/QmitkColorPropertyEditor.h QmitkPropertyObservers/QmitkColorPropertyView.h QmitkPropertyObservers/QmitkEnumerationPropertyWidget.h QmitkPropertyObservers/QmitkNumberPropertyEditor.h QmitkPropertyObservers/QmitkNumberPropertyView.h QmitkPropertyObservers/QmitkStringPropertyEditor.h QmitkPropertyObservers/QmitkStringPropertyOnDemandEdit.h QmitkPropertyObservers/QmitkStringPropertyView.h QmitkPropertyObservers/QmitkNumberPropertySlider.h QmitkPropertyObservers/QmitkUGCombinedRepresentationPropertyWidget.h # QmitkFunctionalityComponents/QmitkSurfaceCreatorComponent.h #QmitkFunctionalityComponents/QmitkPixelGreyValueManipulatorComponent.h # QmitkFunctionalityComponents/QmitkConnectivityFilterComponent.h # QmitkFunctionalityComponents/QmitkImageCropperComponent.h # QmitkFunctionalityComponents/QmitkSeedPointSetComponent.h # QmitkFunctionalityComponents/QmitkSurfaceTransformerComponent.h qclickablelabel.h QmitkCallbackFromGUIThread.h QmitkEditPointDialog.h #QmitkAlgorithmFunctionalityComponent.h #QmitkBaseAlgorithmComponent.h QmitkStandardViews.h QmitkStepperAdapter.h QmitkSliderNavigatorWidget.h QmitkSliceWidget.h QmitkColorTransferFunctionCanvas.h QmitkPiecewiseFunctionCanvas.h QmitkTransferFunctionCanvas.h QmitkFloatingPointSpanSlider.h QmitkCrossWidget.h QmitkTransferFunctionWidget.h QmitkTransferFunctionGeneratorWidget.h # QmitkPropertyListPopup.h #QmitkSelectableGLWidget.h QmitkPrimitiveMovieNavigatorWidget.h QmitkPlotWidget.h QmitkPointListModel.h QmitkPointListView.h QmitkPointListWidget.h QmitkPointListViewWidget.h QmitkCorrespondingPointSetsView.h QmitkCorrespondingPointSetsModel.h QmitkCorrespondingPointSetsWidget.h QmitkHistogramWidget.h QmitkVideoBackground.h QmitkFileChooser.h QmitkHotkeyLineEdit.h QmitkAboutDialog/QmitkAboutDialog.h QmitkBoundingObjectWidget.h QmitkPlotWidget.h QmitkHistogramJSWidget.h QmitkLineEdit.h ) if( NOT ${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}.${VTK_BUILD_VERSION} VERSION_LESS 5.4.0 ) set(MOC_H_FILES ${MOC_H_FILES} QmitkVtkHistogramWidget.h QmitkVtkLineProfileWidget.h ) endif() if(NOT APPLE) set(MOC_H_FILES ${MOC_H_FILES} QmitkBaseComponent.h QmitkBaseFunctionalityComponent.h QmitkFunctionalityComponentContainer.h QmitkFunctionalityComponents/QmitkThresholdComponent.h ) endif() set(UI_FILES QmitkSliderNavigator.ui # QmitkLevelWindowRangeChange.ui # QmitkLevelWindowPresetDefinition.ui # QmitkLevelWindowWidget.ui QmitkSliceWidget.ui QmitkTransferFunctionWidget.ui QmitkTransferFunctionGeneratorWidget.ui QmitkSelectableGLWidget.ui - QmitkOtsuToolWidgetControls.ui QmitkPrimitiveMovieNavigatorWidget.ui QmitkFunctionalityComponentContainerControls.ui QmitkFunctionalityComponents/QmitkThresholdComponentControls.ui QmitkAboutDialog/QmitkAboutDialogGUI.ui ) set(QRC_FILES QmitkExt.qrc ) diff --git a/Modules/Segmentation/Interactions/mitkAddContourTool.cpp b/Modules/Segmentation/Interactions/mitkAddContourTool.cpp index 7cf1096204..b326e47134 100644 --- a/Modules/Segmentation/Interactions/mitkAddContourTool.cpp +++ b/Modules/Segmentation/Interactions/mitkAddContourTool.cpp @@ -1,60 +1,62 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkAddContourTool.h" #include "mitkAddContourTool.xpm" // us #include "mitkModule.h" #include "mitkModuleResource.h" #include namespace mitk { MITK_TOOL_MACRO(Segmentation_EXPORT, AddContourTool, "Add tool"); } mitk::AddContourTool::AddContourTool() :ContourTool(1) { } mitk::AddContourTool::~AddContourTool() { } const char** mitk::AddContourTool::GetXPM() const { return mitkAddContourTool_xpm; } mitk::ModuleResource mitk::AddContourTool::GetIconResource() const { Module* module = GetModuleContext()->GetModule(); ModuleResource resource = module->GetResource("Add_48x48.png"); return resource; } -std::string mitk::AddContourTool::GetCursorIconPath() const +mitk::ModuleResource mitk::AddContourTool::GetCursorIconResource() const { - return ":/Segmentation/Add_Cursor_48x48.png"; + Module* module = GetModuleContext()->GetModule(); + ModuleResource resource = module->GetResource("Add_Cursor_48x48.png"); + return resource; } const char* mitk::AddContourTool::GetName() const { return "Add"; } diff --git a/Modules/Segmentation/Interactions/mitkAddContourTool.h b/Modules/Segmentation/Interactions/mitkAddContourTool.h index 2ff7cbe4d6..bdd637de1c 100644 --- a/Modules/Segmentation/Interactions/mitkAddContourTool.h +++ b/Modules/Segmentation/Interactions/mitkAddContourTool.h @@ -1,71 +1,71 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkAddContourTool_h_Included #define mitkAddContourTool_h_Included #include "mitkContourTool.h" #include "SegmentationExports.h" class ModuleResource; namespace mitk { /** \brief Fill the inside of a contour with 1 \sa ContourTool \ingroup Interaction \ingroup ToolManagerEtAl Fills a visible contour (from FeedbackContourTool) during mouse dragging. When the mouse button is released, AddContourTool tries to extract a slice from the working image and fill in the (filled) contour as a binary image. All inside pixels are set to 1. While holding the CTRL key, the contour changes color and the pixels on the inside would be filled with 0. \warning Only to be instantiated by mitk::ToolManager. $Author$ */ class Segmentation_EXPORT AddContourTool : public ContourTool { public: mitkClassMacro(AddContourTool, ContourTool); itkNewMacro(AddContourTool); virtual const char** GetXPM() const; - virtual std::string GetCursorIconPath() const; + virtual ModuleResource GetCursorIconResource() const; ModuleResource GetIconResource() const; virtual const char* GetName() const; protected: AddContourTool(); // purposely hidden virtual ~AddContourTool(); }; } // namespace #endif diff --git a/Modules/Segmentation/Interactions/mitkCorrectorTool2D.cpp b/Modules/Segmentation/Interactions/mitkCorrectorTool2D.cpp index e7a7cfa782..17ed328144 100644 --- a/Modules/Segmentation/Interactions/mitkCorrectorTool2D.cpp +++ b/Modules/Segmentation/Interactions/mitkCorrectorTool2D.cpp @@ -1,167 +1,169 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkCorrectorTool2D.h" #include "mitkCorrectorAlgorithm.h" #include "mitkToolManager.h" #include "mitkBaseRenderer.h" #include "mitkRenderingManager.h" #include "mitkCorrectorTool2D.xpm" // us #include "mitkModule.h" #include "mitkModuleResource.h" #include namespace mitk { MITK_TOOL_MACRO(Segmentation_EXPORT, CorrectorTool2D, "Correction tool"); } mitk::CorrectorTool2D::CorrectorTool2D(int paintingPixelValue) :FeedbackContourTool("PressMoveRelease"), m_PaintingPixelValue(paintingPixelValue) { // great magic numbers CONNECT_ACTION( 80, OnMousePressed ); CONNECT_ACTION( 90, OnMouseMoved ); CONNECT_ACTION( 42, OnMouseReleased ); GetFeedbackContour()->SetClosed( false ); // don't close the contour to a polygon } mitk::CorrectorTool2D::~CorrectorTool2D() { } const char** mitk::CorrectorTool2D::GetXPM() const { return mitkCorrectorTool2D_xpm; } mitk::ModuleResource mitk::CorrectorTool2D::GetIconResource() const { Module* module = GetModuleContext()->GetModule(); ModuleResource resource = module->GetResource("Correction_48x48.png"); return resource; } -std::string mitk::CorrectorTool2D::GetCursorIconPath() const +mitk::ModuleResource mitk::CorrectorTool2D::GetCursorIconResource() const { - return ":/Segmentation/Correction_Cursor_48x48.png"; + Module* module = GetModuleContext()->GetModule(); + ModuleResource resource = module->GetResource("Correction_Cursor_48x48.png"); + return resource; } const char* mitk::CorrectorTool2D::GetName() const { return "Correction"; } void mitk::CorrectorTool2D::Activated() { Superclass::Activated(); } void mitk::CorrectorTool2D::Deactivated() { Superclass::Deactivated(); } bool mitk::CorrectorTool2D::OnMousePressed (Action* action, const StateEvent* stateEvent) { const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; m_LastEventSender = positionEvent->GetSender(); m_LastEventSlice = m_LastEventSender->GetSlice(); if ( FeedbackContourTool::CanHandleEvent(stateEvent) < 1.0 ) return false; Contour* contour = FeedbackContourTool::GetFeedbackContour(); contour->Initialize(); contour->AddVertex( positionEvent->GetWorldPosition() ); FeedbackContourTool::SetFeedbackContourVisible(true); return true; } bool mitk::CorrectorTool2D::OnMouseMoved (Action* action, const StateEvent* stateEvent) { if ( FeedbackContourTool::CanHandleEvent(stateEvent) < 1.0 ) return false; const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; Contour* contour = FeedbackContourTool::GetFeedbackContour(); contour->AddVertex( positionEvent->GetWorldPosition() ); assert( positionEvent->GetSender()->GetRenderWindow() ); mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); return true; } bool mitk::CorrectorTool2D::OnMouseReleased(Action* action, const StateEvent* stateEvent) { // 1. Hide the feedback contour, find out which slice the user clicked, find out which slice of the toolmanager's working image corresponds to that FeedbackContourTool::SetFeedbackContourVisible(false); const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; assert( positionEvent->GetSender()->GetRenderWindow() ); mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); if ( FeedbackContourTool::CanHandleEvent(stateEvent) < 1.0 ) return false; DataNode* workingNode( m_ToolManager->GetWorkingData(0) ); if (!workingNode) return false; Image* image = dynamic_cast(workingNode->GetData()); const PlaneGeometry* planeGeometry( dynamic_cast (positionEvent->GetSender()->GetCurrentWorldGeometry2D() ) ); if ( !image || !planeGeometry ) return false; // 2. Slice is known, now we try to get it as a 2D image and project the contour into index coordinates of this slice m_WorkingSlice = FeedbackContourTool::GetAffectedImageSliceAs2DImage( positionEvent, image ); if ( m_WorkingSlice.IsNull() ) { MITK_ERROR << "Unable to extract slice." << std::endl; return false; } CorrectorAlgorithm::Pointer algorithm = CorrectorAlgorithm::New(); algorithm->SetInput( m_WorkingSlice ); algorithm->SetContour( FeedbackContourTool::GetFeedbackContour() ); try { algorithm->UpdateLargestPossibleRegion(); } catch ( std::exception& e ) { MITK_ERROR << "Caught exception '" << e.what() << "'" << std::endl; } mitk::Image::Pointer resultSlice = mitk::Image::New(); resultSlice->Initialize(algorithm->GetOutput()); resultSlice->SetVolume(algorithm->GetOutput()->GetData()); this->WriteBackSegmentationResult(positionEvent, resultSlice); return true; } diff --git a/Modules/Segmentation/Interactions/mitkCorrectorTool2D.h b/Modules/Segmentation/Interactions/mitkCorrectorTool2D.h index 84ccb5c427..0ba2cb2eea 100644 --- a/Modules/Segmentation/Interactions/mitkCorrectorTool2D.h +++ b/Modules/Segmentation/Interactions/mitkCorrectorTool2D.h @@ -1,85 +1,85 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkCorrectorTool2D_h_Included #define mitkCorrectorTool2D_h_Included #include "mitkCommon.h" #include "SegmentationExports.h" #include "mitkFeedbackContourTool.h" class ModuleResource; namespace mitk { class Image; /** \brief Corrector tool for 2D binary segmentations \sa FeedbackContourTool \sa ExtractImageFilter \sa OverwriteSliceImageFilter \ingroup Interaction \ingroup ToolManagerEtAl Lets the user draw a (multi-point) line and intelligently decides what to do. The underlying algorithm tests if the line begins and ends inside or outside a segmentation and either adds or subtracts a piece of segmentation. Algorithm is implemented in CorrectorAlgorithm (so that it could be reimplemented in a more modern fashion some time). \warning Only to be instantiated by mitk::ToolManager. $Author$ */ class Segmentation_EXPORT CorrectorTool2D : public FeedbackContourTool { public: mitkClassMacro(CorrectorTool2D, FeedbackContourTool); itkNewMacro(CorrectorTool2D); virtual const char** GetXPM() const; - virtual std::string GetCursorIconPath() const; + virtual ModuleResource GetCursorIconResource() const; ModuleResource GetIconResource() const; virtual const char* GetName() const; protected: CorrectorTool2D(int paintingPixelValue = 1); // purposely hidden virtual ~CorrectorTool2D(); virtual void Activated(); virtual void Deactivated(); virtual bool OnMousePressed (Action*, const StateEvent*); virtual bool OnMouseMoved (Action*, const StateEvent*); virtual bool OnMouseReleased(Action*, const StateEvent*); int m_PaintingPixelValue; Image::Pointer m_WorkingSlice; }; } // namespace #endif diff --git a/Modules/Segmentation/Interactions/mitkDrawPaintbrushTool.cpp b/Modules/Segmentation/Interactions/mitkDrawPaintbrushTool.cpp index d9eac46deb..f626d6f4d5 100644 --- a/Modules/Segmentation/Interactions/mitkDrawPaintbrushTool.cpp +++ b/Modules/Segmentation/Interactions/mitkDrawPaintbrushTool.cpp @@ -1,60 +1,62 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkDrawPaintbrushTool.h" #include "mitkDrawPaintbrushTool.xpm" // us #include "mitkModule.h" #include "mitkModuleResource.h" #include namespace mitk { MITK_TOOL_MACRO(Segmentation_EXPORT, DrawPaintbrushTool, "Paintbrush drawing tool"); } mitk::DrawPaintbrushTool::DrawPaintbrushTool() :PaintbrushTool(1) { } mitk::DrawPaintbrushTool::~DrawPaintbrushTool() { } const char** mitk::DrawPaintbrushTool::GetXPM() const { return mitkDrawPaintbrushTool_xpm; } mitk::ModuleResource mitk::DrawPaintbrushTool::GetIconResource() const { Module* module = GetModuleContext()->GetModule(); ModuleResource resource = module->GetResource("Paint_48x48.png"); return resource; } -std::string mitk::DrawPaintbrushTool::GetCursorIconPath() const +mitk::ModuleResource mitk::DrawPaintbrushTool::GetCursorIconResource() const { - return ":/Segmentation/Paint_Cursor_48x48.png"; + Module* module = GetModuleContext()->GetModule(); + ModuleResource resource = module->GetResource("Paint_Cursor_48x48.png"); + return resource; } const char* mitk::DrawPaintbrushTool::GetName() const { return "Paint"; } diff --git a/Modules/Segmentation/Interactions/mitkDrawPaintbrushTool.h b/Modules/Segmentation/Interactions/mitkDrawPaintbrushTool.h index c0e7b35f85..0b71f8d98b 100644 --- a/Modules/Segmentation/Interactions/mitkDrawPaintbrushTool.h +++ b/Modules/Segmentation/Interactions/mitkDrawPaintbrushTool.h @@ -1,68 +1,68 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkPaintContourTool_h_Included #define mitkPaintContourTool_h_Included #include "mitkPaintbrushTool.h" #include "SegmentationExports.h" class ModuleResource; namespace mitk { /** \brief Paintbrush tool for InteractiveSegmentation \sa FeedbackContourTool \sa ExtractImageFilter \sa OverwriteSliceImageFilter \ingroup Interaction \ingroup ToolManagerEtAl Simple paintbrush drawing tool. Right now there are only circular pens of varying size. This class specified only the drawing "color" for the super class PaintbrushTool. \warning Only to be instantiated by mitk::ToolManager. $Author: maleike $ */ class Segmentation_EXPORT DrawPaintbrushTool : public PaintbrushTool { public: mitkClassMacro(DrawPaintbrushTool, PaintbrushTool); itkNewMacro(DrawPaintbrushTool); virtual const char** GetXPM() const; - virtual std::string GetCursorIconPath() const; + virtual ModuleResource GetCursorIconResource() const; ModuleResource GetIconResource() const; virtual const char* GetName() const; protected: DrawPaintbrushTool(); // purposely hidden virtual ~DrawPaintbrushTool(); }; } // namespace #endif diff --git a/Modules/Segmentation/Interactions/mitkErasePaintbrushTool.cpp b/Modules/Segmentation/Interactions/mitkErasePaintbrushTool.cpp index 52093f3a89..5e18893423 100644 --- a/Modules/Segmentation/Interactions/mitkErasePaintbrushTool.cpp +++ b/Modules/Segmentation/Interactions/mitkErasePaintbrushTool.cpp @@ -1,61 +1,63 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkErasePaintbrushTool.h" #include "mitkErasePaintbrushTool.xpm" // us #include "mitkModule.h" #include "mitkModuleResource.h" #include namespace mitk { MITK_TOOL_MACRO(Segmentation_EXPORT, ErasePaintbrushTool, "Paintbrush erasing tool"); } mitk::ErasePaintbrushTool::ErasePaintbrushTool() :PaintbrushTool(0) { FeedbackContourTool::SetFeedbackContourColor( 1.0, 0.0, 0.0 ); } mitk::ErasePaintbrushTool::~ErasePaintbrushTool() { } const char** mitk::ErasePaintbrushTool::GetXPM() const { return mitkErasePaintbrushTool_xpm; } mitk::ModuleResource mitk::ErasePaintbrushTool::GetIconResource() const { Module* module = GetModuleContext()->GetModule(); ModuleResource resource = module->GetResource("Wipe_48x48.png"); return resource; } -std::string mitk::ErasePaintbrushTool::GetCursorIconPath() const +mitk::ModuleResource mitk::ErasePaintbrushTool::GetCursorIconResource() const { - return ":/Segmentation/Wipe_Cursor_48x48.png"; + Module* module = GetModuleContext()->GetModule(); + ModuleResource resource = module->GetResource("Wipe_Cursor_48x48.png"); + return resource; } const char* mitk::ErasePaintbrushTool::GetName() const { return "Wipe"; } diff --git a/Modules/Segmentation/Interactions/mitkErasePaintbrushTool.h b/Modules/Segmentation/Interactions/mitkErasePaintbrushTool.h index 23c40f826c..a9bafbf0a9 100644 --- a/Modules/Segmentation/Interactions/mitkErasePaintbrushTool.h +++ b/Modules/Segmentation/Interactions/mitkErasePaintbrushTool.h @@ -1,68 +1,68 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkErasePaintbrushTool_h_Included #define mitkErasePaintbrushTool_h_Included #include "mitkPaintbrushTool.h" #include "SegmentationExports.h" class ModuleResource; namespace mitk { /** \brief Paintbrush tool for InteractiveSegmentation \sa FeedbackContourTool \sa ExtractImageFilter \sa OverwriteSliceImageFilter \ingroup Interaction \ingroup ToolManagerEtAl Simple paintbrush drawing tool. Right now there are only circular pens of varying size. This class specified only the drawing "color" for the super class PaintbrushTool. \warning Only to be instantiated by mitk::ToolManager. $Author: maleike $ */ class Segmentation_EXPORT ErasePaintbrushTool : public PaintbrushTool { public: mitkClassMacro(ErasePaintbrushTool, PaintbrushTool); itkNewMacro(ErasePaintbrushTool); virtual const char** GetXPM() const; - virtual std::string GetCursorIconPath() const; + virtual ModuleResource GetCursorIconResource() const; ModuleResource GetIconResource() const; virtual const char* GetName() const; protected: ErasePaintbrushTool(); // purposely hidden virtual ~ErasePaintbrushTool(); }; } // namespace #endif diff --git a/Modules/Segmentation/Interactions/mitkEraseRegionTool.cpp b/Modules/Segmentation/Interactions/mitkEraseRegionTool.cpp index 6d9c1d54fc..18efeccced 100644 --- a/Modules/Segmentation/Interactions/mitkEraseRegionTool.cpp +++ b/Modules/Segmentation/Interactions/mitkEraseRegionTool.cpp @@ -1,61 +1,63 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkEraseRegionTool.h" #include "mitkEraseRegionTool.xpm" // us #include "mitkModule.h" #include "mitkModuleResource.h" #include namespace mitk { MITK_TOOL_MACRO(Segmentation_EXPORT, EraseRegionTool, "Erase tool"); } mitk::EraseRegionTool::EraseRegionTool() :SetRegionTool(0) { FeedbackContourTool::SetFeedbackContourColor( 1.0, 0.0, 0.0 ); } mitk::EraseRegionTool::~EraseRegionTool() { } const char** mitk::EraseRegionTool::GetXPM() const { return mitkEraseRegionTool_xpm; } mitk::ModuleResource mitk::EraseRegionTool::GetIconResource() const { Module* module = GetModuleContext()->GetModule(); ModuleResource resource = module->GetResource("Erase_48x48.png"); return resource; } -std::string mitk::EraseRegionTool::GetCursorIconPath() const +mitk::ModuleResource mitk::EraseRegionTool::GetCursorIconResource() const { - return ":/Segmentation/Erase_Cursor_48x48.png"; + Module* module = GetModuleContext()->GetModule(); + ModuleResource resource = module->GetResource("Erase_Cursor_48x48.png"); + return resource; } const char* mitk::EraseRegionTool::GetName() const { return "Erase"; } diff --git a/Modules/Segmentation/Interactions/mitkEraseRegionTool.h b/Modules/Segmentation/Interactions/mitkEraseRegionTool.h index 99feed3429..9fe310aabf 100644 --- a/Modules/Segmentation/Interactions/mitkEraseRegionTool.h +++ b/Modules/Segmentation/Interactions/mitkEraseRegionTool.h @@ -1,67 +1,67 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkEraseRegionTool_h_Included #define mitkEraseRegionTool_h_Included #include "mitkSetRegionTool.h" #include "SegmentationExports.h" class ModuleResource; namespace mitk { /** \brief Fill the inside of a contour with 1 \sa SetRegionTool \ingroup Interaction \ingroup ToolManagerEtAl Finds the outer contour of a shape in 2D (possibly including holes) and sets all the inside pixels to 0 (erasing a segmentation). \warning Only to be instantiated by mitk::ToolManager. $Author$ */ class Segmentation_EXPORT EraseRegionTool : public SetRegionTool { public: mitkClassMacro(EraseRegionTool, SetRegionTool); itkNewMacro(EraseRegionTool); virtual const char** GetXPM() const; - virtual std::string GetCursorIconPath() const; + virtual ModuleResource GetCursorIconResource() const; ModuleResource GetIconResource() const; virtual const char* GetName() const; protected: EraseRegionTool(); // purposely hidden virtual ~EraseRegionTool(); }; } // namespace #endif diff --git a/Modules/Segmentation/Interactions/mitkFastMarchingTool.cpp b/Modules/Segmentation/Interactions/mitkFastMarchingTool.cpp index 6954240f79..112fa17dc9 100644 --- a/Modules/Segmentation/Interactions/mitkFastMarchingTool.cpp +++ b/Modules/Segmentation/Interactions/mitkFastMarchingTool.cpp @@ -1,424 +1,426 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkFastMarchingTool.h" #include "mitkToolManager.h" #include "mitkBaseRenderer.h" #include "mitkRenderingManager.h" #include "mitkApplicationCursor.h" #include "mitkFastMarchingTool.xpm" #include "mitkInteractionConst.h" #include "itkOrImageFilter.h" // us #include "mitkModule.h" #include "mitkModuleResource.h" #include namespace mitk { MITK_TOOL_MACRO(Segmentation_EXPORT, FastMarchingTool, "FastMarching tool"); } mitk::FastMarchingTool::FastMarchingTool() :FeedbackContourTool("PressMoveReleaseAndPointSetting"), m_IsLivePreviewEnabled(false), m_LowerThreshold(0.0), m_UpperThreshold(200.0), m_StoppingValue(100), sigma(1.0), alpha(-0.5), beta(3.0) { /* Connect UI events */ CONNECT_ACTION( AcADDPOINTRMB, OnAddPoint ); CONNECT_ACTION( AcADDPOINT, OnAddPoint ); CONNECT_ACTION( AcREMOVEPOINT, OnDelete ); /*setup ITK filters */ m_SliceInITK = InternalImageType::New(); thresholder = ThresholdingFilterType::New(); thresholder->SetLowerThreshold( m_LowerThreshold ); thresholder->SetUpperThreshold( m_UpperThreshold ); thresholder->SetOutsideValue( 0 ); thresholder->SetInsideValue( 1.0 ); smoothing = SmoothingFilterType::New(); smoothing->SetTimeStep( 0.125 ); smoothing->SetNumberOfIterations( 5 ); smoothing->SetConductanceParameter( 9.0 ); gradientMagnitude = GradientFilterType::New(); gradientMagnitude->SetSigma( sigma ); sigmoid = SigmoidFilterType::New(); sigmoid->SetAlpha( alpha ); sigmoid->SetBeta( beta ); sigmoid->SetOutputMinimum( 0.0 ); sigmoid->SetOutputMaximum( 1.0 ); fastMarching = FastMarchingFilterType::New(); fastMarching->SetStoppingValue( m_StoppingValue ); seeds = NodeContainer::New(); seeds->Initialize(); fastMarching->SetTrialPoints( seeds ); //set up pipeline smoothing->SetInput( m_SliceInITK ); gradientMagnitude->SetInput( smoothing->GetOutput() ); sigmoid->SetInput( gradientMagnitude->GetOutput() ); fastMarching->SetInput( sigmoid->GetOutput() ); thresholder->SetInput( fastMarching->GetOutput() ); } mitk::FastMarchingTool::~FastMarchingTool() { m_ReferenceSlice = NULL; m_WorkingSlice = NULL; m_PositionEvent = NULL; } float mitk::FastMarchingTool::CanHandleEvent( StateEvent const *stateEvent) const { float returnValue = Superclass::CanHandleEvent(stateEvent); //we can handle delete if(stateEvent->GetId() == 12 ) { returnValue = 1.0; } return returnValue; } const char** mitk::FastMarchingTool::GetXPM() const { return NULL;// mitkFastMarchingTool_xpm; } mitk::ModuleResource mitk::FastMarchingTool::GetIconResource() const { Module* module = GetModuleContext()->GetModule(); ModuleResource resource = module->GetResource("FastMarching_48x48.png"); return resource; } -std::string mitk::FastMarchingTool::GetCursorIconPath() const +mitk::ModuleResource mitk::FastMarchingTool::GetCursorIconResource() const { - return ":/Segmentation/FastMarching_Cursor_48x48.png"; + Module* module = GetModuleContext()->GetModule(); + ModuleResource resource = module->GetResource("FastMarching_Cursor_48x48.png"); + return resource; } const char* mitk::FastMarchingTool::GetName() const { return "Fast Marching"; } void mitk::FastMarchingTool::SetUpperThreshold(float value) { m_UpperThreshold = value; thresholder->SetUpperThreshold( m_UpperThreshold ); if(m_IsLivePreviewEnabled) this->UpdatePreviewImage(); } void mitk::FastMarchingTool::SetLowerThreshold(float value) { m_LowerThreshold = value; thresholder->SetLowerThreshold( m_LowerThreshold ); if(m_IsLivePreviewEnabled) this->UpdatePreviewImage(); } void mitk::FastMarchingTool::SetMu(float value) { beta = value; sigmoid->SetBeta( beta ); if(m_IsLivePreviewEnabled) this->UpdatePreviewImage(); } void mitk::FastMarchingTool::SetStandardDeviation(float value) { alpha = value; sigmoid->SetAlpha( alpha ); if(m_IsLivePreviewEnabled) this->UpdatePreviewImage(); } void mitk::FastMarchingTool::SetStoppingValue(float value) { m_StoppingValue = value; fastMarching->SetStoppingValue( m_StoppingValue ); if(m_IsLivePreviewEnabled) this->UpdatePreviewImage(); } void mitk::FastMarchingTool::SetLivePreviewEnabled(bool enabled) { m_IsLivePreviewEnabled = enabled; if(enabled)//an update may be needed this->UpdatePreviewImage(); } void mitk::FastMarchingTool::Activated() { Superclass::Activated(); m_ResultImageNode = mitk::DataNode::New(); m_ResultImageNode->SetName("FastMarching_Preview"); m_ResultImageNode->SetBoolProperty("helper object", true); m_ResultImageNode->SetColor(0.0, 1.0, 0.0); m_ResultImageNode->SetVisibility(true); m_ToolManager->GetDataStorage()->Add( this->m_ResultImageNode); m_SeedsAsPointSet = mitk::PointSet::New(); m_SeedsAsPointSetNode = mitk::DataNode::New(); m_SeedsAsPointSetNode->SetData(m_SeedsAsPointSet); m_SeedsAsPointSetNode->SetName("Seeds_Preview"); m_SeedsAsPointSetNode->SetBoolProperty("helper object", true); m_SeedsAsPointSetNode->SetColor(0.0, 1.0, 0.0); m_SeedsAsPointSetNode->SetVisibility(true); m_ToolManager->GetDataStorage()->Add( this->m_SeedsAsPointSetNode); } void mitk::FastMarchingTool::Deactivated() { Superclass::Deactivated(); m_ToolManager->GetDataStorage()->Remove( this->m_ResultImageNode ); m_ToolManager->GetDataStorage()->Remove( this->m_SeedsAsPointSetNode ); m_ResultImageNode = NULL; } void mitk::FastMarchingTool::ConfirmSegmentation() { /*+++++++combine preview image with already performed segmentation++++++*/ if (m_PositionEvent) { // remember parameters for next time if (dynamic_cast(m_ResultImageNode->GetData())) { //logical or combination of preview and segmentation slice OutputImageType::Pointer segmentationSlice = OutputImageType::New(); mitk::Image::Pointer workingSlice = GetAffectedWorkingSlice( m_PositionEvent ); CastToItkImage( workingSlice, segmentationSlice ); typedef itk::OrImageFilter OrImageFilterType; OrImageFilterType::Pointer orFilter = OrImageFilterType::New(); orFilter->SetInput(0, thresholder->GetOutput()); orFilter->SetInput(1, segmentationSlice); orFilter->Update(); mitk::Image::Pointer segmentationResult = mitk::Image::New(); mitk::CastToMitkImage(orFilter->GetOutput(), segmentationResult); segmentationResult->GetGeometry()->SetOrigin(workingSlice->GetGeometry()->GetOrigin()); segmentationResult->GetGeometry()->SetIndexToWorldTransform(workingSlice->GetGeometry()->GetIndexToWorldTransform()); //write to segmentation volume and hide preview image this->WriteBackSegmentationResult(m_PositionEvent, segmentationResult ); this->m_ResultImageNode->SetVisibility(false); this->ClearSeeds(); } mitk::RenderingManager::GetInstance()->RequestUpdate( m_PositionEvent->GetSender()->GetRenderWindow() ); } } bool mitk::FastMarchingTool::OnAddPoint(Action* action, const StateEvent* stateEvent) { /*++++++++++++Add a new seed point for FastMarching algorithm+++++++++++*/ const mitk::PositionEvent* p = dynamic_cast(stateEvent->GetEvent()); if (!p) return false; m_PositionEvent = new PositionEvent(p->GetSender(), p->GetType(), p->GetButton(), p->GetButtonState(), p->GetKey(), p->GetDisplayPosition(), p->GetWorldPosition()); //if click happpened in another renderwindow or slice then reset pipeline and preview if( (m_LastEventSender != m_PositionEvent->GetSender()) || (m_LastEventSlice != m_PositionEvent->GetSender()->GetSlice()) ) { this->ResetFastMarching(m_PositionEvent); } m_LastEventSender = m_PositionEvent->GetSender(); m_LastEventSlice = m_LastEventSender->GetSlice(); mitk::Point3D clickInIndex; m_ReferenceSlice->GetGeometry()->WorldToIndex(m_PositionEvent->GetWorldPosition(), clickInIndex); itk::Index<2> seedPosition; seedPosition[0] = clickInIndex[0]; seedPosition[1] = clickInIndex[1]; NodeType node; const double seedValue = 0.0; node.SetValue( seedValue ); node.SetIndex( seedPosition ); this->seeds->InsertElement(this->seeds->Size(), node); fastMarching->Modified(); m_SeedsAsPointSet->InsertPoint(m_SeedsAsPointSet->GetSize(), m_PositionEvent->GetWorldPosition()); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); //preview result by updating the pipeline - this is not done automatically for changing seeds if(m_IsLivePreviewEnabled) this->UpdatePreviewImage(); return true; } bool mitk::FastMarchingTool::OnDelete(Action* action, const StateEvent* stateEvent) { /*++++++++++delete last seed point++++++++*/ if(!(this->seeds->empty())) { //delete last element of seeds container this->seeds->pop_back(); fastMarching->Modified(); //delete last point in pointset - somehow ugly m_SeedsAsPointSet->GetPointSet()->GetPoints()->DeleteIndex(m_SeedsAsPointSet->GetSize() - 1); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); //preview result by updating the pipeline - this is not done automatically for changing seeds if(m_IsLivePreviewEnabled) this->UpdatePreviewImage(); } return true; } void mitk::FastMarchingTool::UpdatePreviewImage() { /*++++++++update FastMarching pipeline and show result++++++++*/ if(m_ReferenceSlice.IsNotNull()) { try{ thresholder->UpdateLargestPossibleRegion(); } catch( itk::ExceptionObject & excep ) { std::cerr << "Exception caught !" << std::endl; std::cerr << excep << std::endl; std::cerr << "Reseting step." << std::endl; this->ResetToInitialState(); return; } //make output visible mitk::Image::Pointer result = mitk::Image::New(); CastToMitkImage( thresholder->GetOutput(), result); result->GetGeometry()->SetOrigin(m_ReferenceSlice->GetGeometry()->GetOrigin() ); result->GetGeometry()->SetIndexToWorldTransform(m_ReferenceSlice->GetGeometry()->GetIndexToWorldTransform() ); m_ResultImageNode->SetData(result); m_ResultImageNode->SetVisibility(true); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void mitk::FastMarchingTool::ClearSeeds() { /*++++++++clear seeds for FastMarching as well as the PointSet for visualization++++++++*/ this->seeds->clear(); fastMarching->Modified(); m_SeedsAsPointSet->Clear(); m_ResultImageNode->SetVisibility(false); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void mitk::FastMarchingTool::ResetFastMarching(const PositionEvent* positionEvent) { /*++++++++reset all relevant inputs for FastMarching++++++++*/ //reset reference slice according to the plane where the click happened m_ReferenceSlice = FeedbackContourTool::GetAffectedReferenceSlice( positionEvent ); //reset input of FastMarching pipeline CastToItkImage(m_ReferenceSlice, m_SliceInITK); smoothing->SetInput( m_SliceInITK ); //clear all seeds and preview empty result this->ClearSeeds(); this->UpdatePreviewImage(); } void mitk::FastMarchingTool::ResetToInitialState() { m_SeedsAsPointSet->Clear(); m_ResultImageNode->SetVisibility(false); m_SliceInITK = InternalImageType::New(); thresholder = ThresholdingFilterType::New(); thresholder->SetLowerThreshold( m_LowerThreshold ); thresholder->SetUpperThreshold( m_UpperThreshold ); thresholder->SetOutsideValue( 0 ); thresholder->SetInsideValue( 1.0 ); smoothing = SmoothingFilterType::New(); smoothing->SetTimeStep( 0.125 ); smoothing->SetNumberOfIterations( 5 ); smoothing->SetConductanceParameter( 9.0 ); gradientMagnitude = GradientFilterType::New(); gradientMagnitude->SetSigma( sigma ); sigmoid = SigmoidFilterType::New(); sigmoid->SetAlpha( alpha ); sigmoid->SetBeta( beta ); sigmoid->SetOutputMinimum( 0.0 ); sigmoid->SetOutputMaximum( 1.0 ); fastMarching = FastMarchingFilterType::New(); fastMarching->SetStoppingValue( m_StoppingValue ); seeds = NodeContainer::New(); seeds->Initialize(); fastMarching->SetTrialPoints( seeds ); //set up pipeline smoothing->SetInput( m_SliceInITK ); gradientMagnitude->SetInput( smoothing->GetOutput() ); sigmoid->SetInput( gradientMagnitude->GetOutput() ); fastMarching->SetInput( sigmoid->GetOutput() ); thresholder->SetInput( fastMarching->GetOutput() ); } diff --git a/Modules/Segmentation/Interactions/mitkFastMarchingTool.h b/Modules/Segmentation/Interactions/mitkFastMarchingTool.h index 7e4933caf2..b3c69e1249 100644 --- a/Modules/Segmentation/Interactions/mitkFastMarchingTool.h +++ b/Modules/Segmentation/Interactions/mitkFastMarchingTool.h @@ -1,158 +1,158 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkFastMarchingTool_h_Included #define mitkFastMarchingTool_h_Included #include "mitkFeedbackContourTool.h" #include "mitkLegacyAdaptors.h" #include "SegmentationExports.h" #include "mitkDataNode.h" #include "mitkPointSet.h" #include "mitkPositionEvent.h" #include "itkImage.h" //itk filter #include "itkFastMarchingImageFilter.h" #include "itkBinaryThresholdImageFilter.h" #include "itkGradientMagnitudeRecursiveGaussianImageFilter.h" #include "itkSigmoidImageFilter.h" #include "itkCurvatureAnisotropicDiffusionImageFilter.h" class ModuleResource; namespace mitk { /** \brief FastMarching semgentation tool. The segmentation is done by setting one or more seed point within the image and adapting time range plus threshold. The pipeline is: Smoothing->GradientMagnitude->SigmoidFunction->FastMarching->Threshold The resulting binary image is seen as a segmentation of an object. For detailed documentation see ITK Software Guide section 9.3.1 Fast Marching Segmentation. */ class Segmentation_EXPORT FastMarchingTool : public FeedbackContourTool { public: mitkClassMacro(FastMarchingTool, FeedbackContourTool); itkNewMacro(FastMarchingTool); /* typedefs for itk pipeline */ typedef float InternalPixelType; typedef itk::Image< InternalPixelType, 2 > InternalImageType; typedef unsigned char OutputPixelType; typedef itk::Image< OutputPixelType, 2 > OutputImageType; typedef itk::BinaryThresholdImageFilter< InternalImageType, OutputImageType > ThresholdingFilterType; typedef itk::CurvatureAnisotropicDiffusionImageFilter< InternalImageType, InternalImageType > SmoothingFilterType; typedef itk::GradientMagnitudeRecursiveGaussianImageFilter< InternalImageType, InternalImageType > GradientFilterType; typedef itk::SigmoidImageFilter< InternalImageType, InternalImageType > SigmoidFilterType; typedef itk::FastMarchingImageFilter< InternalImageType, InternalImageType > FastMarchingFilterType; typedef FastMarchingFilterType::NodeContainer NodeContainer; typedef FastMarchingFilterType::NodeType NodeType; /* icon stuff */ virtual const char** GetXPM() const; virtual const char* GetName() const; - virtual std::string GetCursorIconPath() const; + virtual ModuleResource GetCursorIconResource() const; ModuleResource GetIconResource() const; /* parameters of itk filters */ void SetUpperThreshold(float value); void SetLowerThreshold(float value); void SetMu(float value); void SetStoppingValue(float value); void SetStandardDeviation(float value); /// \brief Fill preview in segmentation image. virtual void ConfirmSegmentation(); /// \brief Select update preview image. virtual void SetLivePreviewEnabled(bool enabled); /// \brief Clear all seed point. void ClearSeeds(); protected: FastMarchingTool(); virtual ~FastMarchingTool(); virtual float CanHandleEvent( StateEvent const *stateEvent) const; virtual void Activated(); virtual void Deactivated(); /*Actions of StateMachine pattern*/ virtual bool OnAddPoint (Action*, const StateEvent*); virtual bool OnDelete (Action*, const StateEvent*); /// \brief Updates the itk pipeline and shows the result of FastMarching. void UpdatePreviewImage(); /// \brief Reset all relevant inputs of the itk pipeline. void ResetFastMarching(const PositionEvent* positionEvent); /// \brief Reinit filters. void ResetToInitialState(); mitk::BaseRenderer* m_LastEventSender; unsigned int m_LastEventSlice; mitk::PositionEvent* m_PositionEvent; Image::Pointer m_ReferenceSlice; Image::Pointer m_WorkingSlice; ScalarType m_LowerThreshold; ScalarType m_UpperThreshold; ScalarType m_StoppingValue; bool m_IsLivePreviewEnabled;//update preview image or not float sigma;//used for GradientFilter float alpha;//used for SigmoidFilter float beta;//used for SigmoidFilter NodeContainer::Pointer seeds;//seed point for FastMarching InternalImageType::Pointer m_SliceInITK;//the reference slice as itk::Image mitk::DataNode::Pointer m_ResultImageNode;//holds the result as a preview image mitk::DataNode::Pointer m_SeedsAsPointSetNode;//used to visualize the seed points mitk::PointSet::Pointer m_SeedsAsPointSet;//seed points as PointSet /* ITK filters */ ThresholdingFilterType::Pointer thresholder; SmoothingFilterType::Pointer smoothing; GradientFilterType::Pointer gradientMagnitude; SigmoidFilterType::Pointer sigmoid; FastMarchingFilterType::Pointer fastMarching; }; } // namespace #endif diff --git a/Modules/Segmentation/Interactions/mitkFillRegionTool.cpp b/Modules/Segmentation/Interactions/mitkFillRegionTool.cpp index 9aabf2c3ba..347e125298 100644 --- a/Modules/Segmentation/Interactions/mitkFillRegionTool.cpp +++ b/Modules/Segmentation/Interactions/mitkFillRegionTool.cpp @@ -1,60 +1,62 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkFillRegionTool.h" #include "mitkFillRegionTool.xpm" // us #include "mitkModule.h" #include "mitkModuleResource.h" #include namespace mitk { MITK_TOOL_MACRO(Segmentation_EXPORT, FillRegionTool, "Fill tool"); } mitk::FillRegionTool::FillRegionTool() :SetRegionTool(1) { } mitk::FillRegionTool::~FillRegionTool() { } const char** mitk::FillRegionTool::GetXPM() const { return mitkFillRegionTool_xpm; } mitk::ModuleResource mitk::FillRegionTool::GetIconResource() const { Module* module = GetModuleContext()->GetModule(); ModuleResource resource = module->GetResource("Fill_48x48.png"); return resource; } -std::string mitk::FillRegionTool::GetCursorIconPath() const +mitk::ModuleResource mitk::FillRegionTool::GetCursorIconResource() const { - return ":/Segmentation/Fill_Cursor_48x48.png"; + Module* module = GetModuleContext()->GetModule(); + ModuleResource resource = module->GetResource("Fill_Cursor_48x48.png"); + return resource; } const char* mitk::FillRegionTool::GetName() const { return "Fill"; } diff --git a/Modules/Segmentation/Interactions/mitkFillRegionTool.h b/Modules/Segmentation/Interactions/mitkFillRegionTool.h index 2f560a3df6..6de5e3b29c 100644 --- a/Modules/Segmentation/Interactions/mitkFillRegionTool.h +++ b/Modules/Segmentation/Interactions/mitkFillRegionTool.h @@ -1,66 +1,66 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkFillRegionTool_h_Included #define mitkFillRegionTool_h_Included #include "mitkSetRegionTool.h" #include "SegmentationExports.h" class ModuleResource; namespace mitk { /** \brief Fill the inside of a contour with 1 \sa SetRegionTool \ingroup Interaction \ingroup ToolManagerEtAl Finds the outer contour of a shape in 2D (possibly including holes) and sets all the inside pixels to 1, filling holes in a segmentation. \warning Only to be instantiated by mitk::ToolManager. $Author$ */ class Segmentation_EXPORT FillRegionTool : public SetRegionTool { public: mitkClassMacro(FillRegionTool, SetRegionTool); itkNewMacro(FillRegionTool); virtual const char** GetXPM() const; - virtual std::string GetCursorIconPath() const; + virtual ModuleResource GetCursorIconResource() const; ModuleResource GetIconResource() const; virtual const char* GetName() const; protected: FillRegionTool(); // purposely hidden virtual ~FillRegionTool(); }; } // namespace #endif diff --git a/Modules/Segmentation/Interactions/mitkLiveWireTool2D.cpp b/Modules/Segmentation/Interactions/mitkLiveWireTool2D.cpp index af82b7a441..40dd9c31fe 100644 --- a/Modules/Segmentation/Interactions/mitkLiveWireTool2D.cpp +++ b/Modules/Segmentation/Interactions/mitkLiveWireTool2D.cpp @@ -1,661 +1,663 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkLiveWireTool2D.h" #include "mitkToolManager.h" #include "mitkBaseRenderer.h" #include "mitkRenderingManager.h" #include "mitkLiveWireTool2D.xpm" #include #include #include #include "mitkContourUtils.h" #include "mitkContour.h" #include // us #include "mitkModule.h" #include "mitkModuleResource.h" #include namespace mitk { MITK_TOOL_MACRO(Segmentation_EXPORT, LiveWireTool2D, "LiveWire tool"); } mitk::LiveWireTool2D::LiveWireTool2D() :SegTool2D("LiveWireTool") { m_Contour = mitk::ContourModel::New(); m_ContourModelNode = mitk::DataNode::New(); m_ContourModelNode->SetData( m_Contour ); m_ContourModelNode->SetProperty("name", StringProperty::New("working contour node")); m_ContourModelNode->SetProperty("visible", BoolProperty::New(true)); m_ContourModelNode->AddProperty( "contour.color", ColorProperty::New(0.9, 1.0, 0.1), NULL, true ); m_ContourModelNode->AddProperty( "selectedcolor", ColorProperty::New(1.0, 0.0, 0.1), NULL, true ); m_LiveWireContour = mitk::ContourModel::New(); m_LiveWireContourNode = mitk::DataNode::New(); //m_LiveWireContourNode->SetData( m_LiveWireContour ); m_LiveWireContourNode->SetProperty("name", StringProperty::New("active livewire node")); m_LiveWireContourNode->SetProperty("visible", BoolProperty::New(true)); m_LiveWireContourNode->AddProperty( "contour.color", ColorProperty::New(0.1, 1.0, 0.1), NULL, true ); m_LiveWireContourNode->AddProperty( "selectedcolor", ColorProperty::New(0.5, 0.5, 0.1), NULL, true ); m_LiveWireFilter = mitk::ImageLiveWireContourModelFilter::New(); // great magic numbers CONNECT_ACTION( AcINITNEWOBJECT, OnInitLiveWire ); CONNECT_ACTION( AcADDPOINT, OnAddPoint ); CONNECT_ACTION( AcMOVE, OnMouseMoveNoDynamicCosts ); CONNECT_ACTION( AcCHECKPOINT, OnCheckPoint ); CONNECT_ACTION( AcFINISH, OnFinish ); CONNECT_ACTION( AcDELETEPOINT, OnLastSegmentDelete ); CONNECT_ACTION( AcADDLINE, OnMouseMoved ); } mitk::LiveWireTool2D::~LiveWireTool2D() { m_Contours.clear(); } float mitk::LiveWireTool2D::CanHandleEvent( StateEvent const *stateEvent) const { mitk::PositionEvent const *positionEvent = dynamic_cast (stateEvent->GetEvent()); //Key event handling: if (positionEvent == NULL) { //check for delete and escape event if(stateEvent->GetId() == 12 || stateEvent->GetId() == 14) { return 1.0; } //check, if the current state has a transition waiting for that key event. else if (this->GetCurrentState()->GetTransition(stateEvent->GetId())!=NULL) { return 0.5; } else { return 0.0; } } else { if ( positionEvent->GetSender()->GetMapperID() != BaseRenderer::Standard2D ) return 0.0; // we don't want anything but 2D return 1.0; } } const char** mitk::LiveWireTool2D::GetXPM() const { return mitkLiveWireTool2D_xpm; } mitk::ModuleResource mitk::LiveWireTool2D::GetIconResource() const { Module* module = GetModuleContext()->GetModule(); ModuleResource resource = module->GetResource("LiveWire_48x48.png"); return resource; } -std::string mitk::LiveWireTool2D::GetCursorIconPath() const +mitk::ModuleResource mitk::LiveWireTool2D::GetCursorIconResource() const { - return ":/Segmentation/LiveWire_Cursor_48x48.png"; + Module* module = GetModuleContext()->GetModule(); + ModuleResource resource = module->GetResource("LiveWire_Cursor_48x48.png"); + return resource; } const char* mitk::LiveWireTool2D::GetName() const { return "Live Wire"; } void mitk::LiveWireTool2D::Activated() { Superclass::Activated(); } void mitk::LiveWireTool2D::Deactivated() { this->FinishTool(); Superclass::Deactivated(); } void mitk::LiveWireTool2D::ConfirmSegmentation() { DataNode* workingNode( m_ToolManager->GetWorkingData(0) ); if ( !workingNode ) return; Image* workingImage = dynamic_cast(workingNode->GetData()); if ( !workingImage ) return; ContourUtils::Pointer contourUtils = mitk::ContourUtils::New(); /*+++++++++++++++++++++++ for all contours in list (currently created by tool) ++++++++++++++++++++++++++++++++++++*/ std::vector< std::pair >::iterator it = m_Contours.begin(); while(it != m_Contours.end() ) { //++++++++++if node contains data if( it->first->GetData() ) { //+++++++++++++++if this is a contourModel mitk::ContourModel* contourModel = dynamic_cast(it->first->GetData()); if( contourModel ) { //++++++++++++++++++++++ for each timestep of this contourModel for( int currentTimestep = 0; currentTimestep < contourModel->GetTimeSlicedGeometry()->GetTimeSteps(); currentTimestep++) { //get the segmentation image slice at current timestep mitk::Image::Pointer workingSlice = this->GetAffectedImageSliceAs2DImage(it->second, workingImage, currentTimestep); /*++++++++++++++++++++++ transfer to plain old contour to use contour util functionality +++++++++++++++++++++++*/ mitk::Contour::Pointer plainOldContour = mitk::Contour::New(); mitk::ContourModel::VertexIterator iter = contourModel->IteratorBegin(currentTimestep); while(iter != contourModel->IteratorEnd(currentTimestep) ) { plainOldContour->AddVertex( (*iter)->Coordinates ); iter++; } /*-------------------------------------------------------------------------------*/ mitk::Contour::Pointer projectedContour = contourUtils->ProjectContourTo2DSlice(workingSlice, plainOldContour, true, false); contourUtils->FillContourInSlice(projectedContour, workingSlice, 1.0); //write back to image volume this->WriteBackSegmentationResult(it->second, workingSlice, currentTimestep); } //remove contour node from datastorage m_ToolManager->GetDataStorage()->Remove( it->first ); } } ++it; } m_Contours.clear(); } bool mitk::LiveWireTool2D::OnInitLiveWire (Action* action, const StateEvent* stateEvent) { const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; m_LastEventSender = positionEvent->GetSender(); m_LastEventSlice = m_LastEventSender->GetSlice(); if ( Superclass::CanHandleEvent(stateEvent) < 1.0 ) return false; int timestep = positionEvent->GetSender()->GetTimeStep(); m_Contour->Expand(timestep+1); m_ToolManager->GetDataStorage()->Add( m_ContourModelNode ); m_ToolManager->GetDataStorage()->Add( m_LiveWireContourNode ); //set current slice as input for ImageToLiveWireContourFilter m_WorkingSlice = this->GetAffectedReferenceSlice(positionEvent); m_LiveWireFilter->SetInput(m_WorkingSlice); //map click to pixel coordinates mitk::Point3D click = const_cast(positionEvent->GetWorldPosition()); itk::Index<3> idx; m_WorkingSlice->GetGeometry()->WorldToIndex(click, idx); /*+++++++++++++++++++++++ get the pixel the gradient in region of 5x5 ++++++++++++++++++++++++++*/ itk::Index<3> indexWithHighestGradient; AccessFixedDimensionByItk_2(m_WorkingSlice, FindHighestGradientMagnitudeByITK, 2, idx, indexWithHighestGradient); /*----------------------------------------------------------------------------------------------------------------*/ //itk::Index to mitk::Point3D click[0] = indexWithHighestGradient[0]; click[1] = indexWithHighestGradient[1]; click[2] = indexWithHighestGradient[2]; m_WorkingSlice->GetGeometry()->IndexToWorld(click, click); //set initial start point m_Contour->AddVertex( click, true, timestep ); m_LiveWireFilter->SetStartPoint(click); m_CreateAndUseDynamicCosts = true; //render assert( positionEvent->GetSender()->GetRenderWindow() ); mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); return true; } bool mitk::LiveWireTool2D::OnAddPoint (Action* action, const StateEvent* stateEvent) { //complete LiveWire interaction for last segment //add current LiveWire contour to the finished contour and reset //to start new segment and computation /* check if event can be handled */ const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; if ( Superclass::CanHandleEvent(stateEvent) < 1.0 ) return false; /* END check if event can be handled */ int timestep = positionEvent->GetSender()->GetTimeStep(); //remove duplicate first vertex, it's already contained in m_Contour m_LiveWireContour->RemoveVertexAt(0, timestep); /* TODO fix this hack*/ //set last to active added point if( m_LiveWireContour->GetNumberOfVertices(timestep) > 0) { const_cast( m_LiveWireContour->GetVertexAt(m_LiveWireContour->GetNumberOfVertices(timestep)-1, timestep) )->IsControlPoint = true; } //merge contours m_Contour->Concatenate(m_LiveWireContour, timestep); //clear the livewire contour and reset the corresponding datanode m_LiveWireContour->Clear(timestep); //set new start point m_LiveWireFilter->SetStartPoint(const_cast(positionEvent->GetWorldPosition())); if( m_CreateAndUseDynamicCosts ) { //use dynamic cost map for next update m_LiveWireFilter->CreateDynamicCostMap(m_Contour); m_LiveWireFilter->SetUseDynamicCostMap(true); //m_CreateAndUseDynamicCosts = false; } //render assert( positionEvent->GetSender()->GetRenderWindow() ); mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); return true; } bool mitk::LiveWireTool2D::OnMouseMoved( Action* action, const StateEvent* stateEvent) { //compute LiveWire segment from last control point to current mouse position /* check if event can be handled */ if ( Superclass::CanHandleEvent(stateEvent) < 1.0 ) return false; const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; /* END check if event can be handled */ /* actual LiveWire computation */ int timestep = positionEvent->GetSender()->GetTimeStep(); m_LiveWireFilter->SetEndPoint(const_cast(positionEvent->GetWorldPosition())); m_LiveWireFilter->SetTimestep(timestep); m_LiveWireFilter->Update(); //ContourModel::VertexType* currentVertex = const_cast(m_LiveWireContour->GetVertexAt(0)); this->m_LiveWireContour = this->m_LiveWireFilter->GetOutput(); this->m_LiveWireContourNode->SetData(this->m_LiveWireFilter->GetOutput()); /* END actual LiveWire computation */ //render assert( positionEvent->GetSender()->GetRenderWindow() ); mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); return true; } bool mitk::LiveWireTool2D::OnMouseMoveNoDynamicCosts(Action* action, const StateEvent* stateEvent) { //do not use dynamic cost map m_LiveWireFilter->SetUseDynamicCostMap(false); OnMouseMoved(action, stateEvent); m_LiveWireFilter->SetUseDynamicCostMap(true); return true; } bool mitk::LiveWireTool2D::OnCheckPoint( Action* action, const StateEvent* stateEvent) { //check double click on first control point to finish the LiveWire tool // //Check distance to first point. //Transition YES if click close to first control point // mitk::StateEvent* newStateEvent = NULL; const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) { //stay in current state newStateEvent = new mitk::StateEvent(EIDNO, stateEvent->GetEvent()); } else { int timestep = positionEvent->GetSender()->GetTimeStep(); mitk::Point3D click = positionEvent->GetWorldPosition(); mitk::Point3D first = this->m_Contour->GetVertexAt(0, timestep)->Coordinates; if (first.EuclideanDistanceTo(click) < 1.5) { //finish newStateEvent = new mitk::StateEvent(EIDYES, stateEvent->GetEvent()); }else { //stay active newStateEvent = new mitk::StateEvent(EIDNO, stateEvent->GetEvent()); } } this->HandleEvent( newStateEvent ); return true; } bool mitk::LiveWireTool2D::OnFinish( Action* action, const StateEvent* stateEvent) { // finish livewire tool interaction /* check if event can be handled */ if ( Superclass::CanHandleEvent(stateEvent) < 1.0 ) return false; const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; /* END check if event can be handled */ //actual timestep int timestep = positionEvent->GetSender()->GetTimeStep(); //remove last control point being added by double click m_Contour->RemoveVertexAt(m_Contour->GetNumberOfVertices(timestep) - 1, timestep); //save contour and corresponding plane geometry to list std::pair contourPair(m_ContourModelNode.GetPointer(), dynamic_cast(positionEvent->GetSender()->GetCurrentWorldGeometry2D()->Clone().GetPointer()) ); m_Contours.push_back(contourPair); m_LiveWireFilter->SetUseDynamicCostMap(false); this->FinishTool(); return true; } void mitk::LiveWireTool2D::FinishTool() { unsigned int numberOfTimesteps = m_Contour->GetTimeSlicedGeometry()->GetTimeSteps(); //close contour in each timestep for( int i = 0; i <= numberOfTimesteps; i++) { m_Contour->Close(i); } //clear LiveWire node m_ToolManager->GetDataStorage()->Remove( m_LiveWireContourNode ); m_LiveWireContourNode = NULL; m_LiveWireContour = NULL; //TODO visual feedback for completing livewire tool m_ContourModelNode->AddProperty( "contour.color", ColorProperty::New(1.0, 1.0, 0.1), NULL, true ); m_ContourModelNode->SetProperty("name", StringProperty::New("contour node")); //set the livewire interactor to edit control points mitk::ContourModelLiveWireInteractor::Pointer interactor = mitk::ContourModelLiveWireInteractor::New(m_ContourModelNode); interactor->SetWorkingImage(this->m_WorkingSlice); m_ContourModelNode->SetInteractor(interactor); //add interactor to globalInteraction instance mitk::GlobalInteraction::GetInstance()->AddInteractor(interactor); /* END complete livewire tool interaction */ /* reset contours and datanodes */ m_Contour = mitk::ContourModel::New(); m_ContourModelNode = mitk::DataNode::New(); m_ContourModelNode->SetData( m_Contour ); m_ContourModelNode->SetProperty("name", StringProperty::New("working contour node")); m_ContourModelNode->SetProperty("visible", BoolProperty::New(true)); m_ContourModelNode->AddProperty( "contour.color", ColorProperty::New(0.9, 1.0, 0.1), NULL, true ); m_ContourModelNode->AddProperty( "points.color", ColorProperty::New(1.0, 0.0, 0.1), NULL, true ); m_LiveWireContour = mitk::ContourModel::New(); m_LiveWireContourNode = mitk::DataNode::New(); //m_LiveWireContourNode->SetData( m_LiveWireContour ); m_LiveWireContourNode->SetProperty("name", StringProperty::New("active livewire node")); m_LiveWireContourNode->SetProperty("visible", BoolProperty::New(true)); m_LiveWireContourNode->AddProperty( "contour.color", ColorProperty::New(0.1, 1.0, 0.1), NULL, true ); m_LiveWireContourNode->AddProperty( "points.color", ColorProperty::New(0.5, 0.5, 0.1), NULL, true ); /* END reset contours and datanodes */ } bool mitk::LiveWireTool2D::OnLastSegmentDelete( Action* action, const StateEvent* stateEvent) { int timestep = stateEvent->GetEvent()->GetSender()->GetTimeStep(); //if last point of current contour will be removed go to start state and remove nodes if( m_Contour->GetNumberOfVertices(timestep) <= 1 ) { m_ToolManager->GetDataStorage()->Remove( m_LiveWireContourNode ); m_ToolManager->GetDataStorage()->Remove( m_ContourModelNode ); m_LiveWireContour = mitk::ContourModel::New(); m_Contour = mitk::ContourModel::New(); m_ContourModelNode->SetData( m_Contour ); m_LiveWireContourNode->SetData( m_LiveWireContour ); Superclass::Deactivated(); //go to start state } else //remove last segment from contour and reset livewire contour { m_LiveWireContour = mitk::ContourModel::New(); m_LiveWireContourNode->SetData(m_LiveWireContour); mitk::ContourModel::Pointer newContour = mitk::ContourModel::New(); newContour->Expand(m_Contour->GetTimeSteps()); mitk::ContourModel::VertexIterator begin = m_Contour->IteratorBegin(); //iterate from last point to next active point mitk::ContourModel::VertexIterator newLast = m_Contour->IteratorBegin() + (m_Contour->GetNumberOfVertices() - 1); //go at least one down if(newLast != begin) { newLast--; } //search next active control point while(newLast != begin && !((*newLast)->IsControlPoint) ) { newLast--; } //set position of start point for livewire filter to coordinates of the new last point m_LiveWireFilter->SetStartPoint((*newLast)->Coordinates); mitk::ContourModel::VertexIterator it = m_Contour->IteratorBegin(); //fill new Contour while(it <= newLast) { newContour->AddVertex((*it)->Coordinates, (*it)->IsControlPoint, timestep); it++; } newContour->SetIsClosed(m_Contour->IsClosed()); //set new contour visible m_ContourModelNode->SetData(newContour); m_Contour = newContour; assert( stateEvent->GetEvent()->GetSender()->GetRenderWindow() ); mitk::RenderingManager::GetInstance()->RequestUpdate( stateEvent->GetEvent()->GetSender()->GetRenderWindow() ); } return true; } template void mitk::LiveWireTool2D::FindHighestGradientMagnitudeByITK(itk::Image* inputImage, itk::Index<3> &index, itk::Index<3> &returnIndex) { typedef itk::Image InputImageType; typedef typename InputImageType::IndexType IndexType; unsigned long xMAX = inputImage->GetLargestPossibleRegion().GetSize()[0]; unsigned long yMAX = inputImage->GetLargestPossibleRegion().GetSize()[1]; returnIndex[0] = index[0]; returnIndex[1] = index[1]; returnIndex[2] = 0.0; double gradientMagnitude = 0.0; double maxGradientMagnitude = 0.0; /* the size and thus the region of 7x7 is only used to calculate the gradient magnitude in that region not for searching the maximum value */ //maximum value in each direction for size typename InputImageType::SizeType size; size[0] = 7; size[1] = 7; //minimum value in each direction for startRegion IndexType startRegion; startRegion[0] = index[0] - 3; startRegion[1] = index[1] - 3; if(startRegion[0] < 0) startRegion[0] = 0; if(startRegion[1] < 0) startRegion[1] = 0; if(xMAX - index[0] < 7) startRegion[0] = xMAX - 7; if(yMAX - index[1] < 7) startRegion[1] = yMAX - 7; index[0] = startRegion[0] + 3; index[1] = startRegion[1] + 3; typename InputImageType::RegionType region; region.SetSize( size ); region.SetIndex( startRegion ); typedef typename itk::GradientMagnitudeImageFilter< InputImageType, InputImageType> GradientMagnitudeFilterType; typename GradientMagnitudeFilterType::Pointer gradientFilter = GradientMagnitudeFilterType::New(); gradientFilter->SetInput(inputImage); gradientFilter->GetOutput()->SetRequestedRegion(region); gradientFilter->Update(); typename InputImageType::Pointer gradientMagnImage; gradientMagnImage = gradientFilter->GetOutput(); IndexType currentIndex; currentIndex[0] = 0; currentIndex[1] = 0; // search max (approximate) gradient magnitude for( int x = -1; x <= 1; ++x) { currentIndex[0] = index[0] + x; for( int y = -1; y <= 1; ++y) { currentIndex[1] = index[1] + y; gradientMagnitude = gradientMagnImage->GetPixel(currentIndex); //check for new max if(maxGradientMagnitude < gradientMagnitude) { maxGradientMagnitude = gradientMagnitude; returnIndex[0] = currentIndex[0]; returnIndex[1] = currentIndex[1]; returnIndex[2] = 0.0; }//end if }//end for y currentIndex[1] = index[1]; }//end for x } diff --git a/Modules/Segmentation/Interactions/mitkLiveWireTool2D.h b/Modules/Segmentation/Interactions/mitkLiveWireTool2D.h index a2109b1fd9..ececd960d3 100644 --- a/Modules/Segmentation/Interactions/mitkLiveWireTool2D.h +++ b/Modules/Segmentation/Interactions/mitkLiveWireTool2D.h @@ -1,129 +1,129 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkCorrectorTool2D_h_Included #define mitkCorrectorTool2D_h_Included #include "mitkCommon.h" #include "SegmentationExports.h" #include "mitkSegTool2D.h" #include #include #include class ModuleResource; namespace mitk { /** \brief A 2D segmentation tool based on LiveWire approach. The contour between the last user added point and the current mouse position is computed by searching the shortest path according to specific features of the image. The contour thus snappest to the boundary of objects. \sa SegTool2D \sa ImageLiveWireContourModelFilter \ingroup Interaction \ingroup ToolManagerEtAl \warning Only to be instantiated by mitk::ToolManager. */ class Segmentation_EXPORT LiveWireTool2D : public SegTool2D { public: mitkClassMacro(LiveWireTool2D, SegTool2D); itkNewMacro(LiveWireTool2D); virtual const char** GetXPM() const; - virtual std::string GetCursorIconPath() const; + virtual ModuleResource GetCursorIconResource() const; ModuleResource GetIconResource() const; virtual const char* GetName() const; /// \brief Convert all current contour objects to binary segmentation image. void ConfirmSegmentation(); protected: LiveWireTool2D(); virtual ~LiveWireTool2D(); /** * \brief Calculates how good the data, this statemachine handles, is hit by the event. * */ virtual float CanHandleEvent( StateEvent const *stateEvent) const; virtual void Activated(); virtual void Deactivated(); /// \brief Initialize tool virtual bool OnInitLiveWire (Action*, const StateEvent*); /// \brief Add a control point and finish current segment virtual bool OnAddPoint (Action*, const StateEvent*); /// \breif Actual LiveWire computation virtual bool OnMouseMoved(Action*, const StateEvent*); /// \brief Check double click on first control point to finish the LiveWire tool virtual bool OnCheckPoint(Action*, const StateEvent*); /// \brief Finish LiveWire tool virtual bool OnFinish(Action*, const StateEvent*); /// \brief Close the contour virtual bool OnLastSegmentDelete(Action*, const StateEvent*); /// \brief Don't use dynamic cost map for LiveWire calculation virtual bool OnMouseMoveNoDynamicCosts(Action*, const StateEvent*); /// \brief Finish contour interaction. void FinishTool(); //the contour already set by the user mitk::ContourModel::Pointer m_Contour; //the corresponding datanode mitk::DataNode::Pointer m_ContourModelNode; //the current LiveWire computed contour mitk::ContourModel::Pointer m_LiveWireContour; //the corresponding datanode mitk::DataNode::Pointer m_LiveWireContourNode; //the current reference image mitk::Image::Pointer m_WorkingSlice; mitk::ImageLiveWireContourModelFilter::Pointer m_LiveWireFilter; bool m_CreateAndUseDynamicCosts; std::vector< std::pair > m_Contours; template void FindHighestGradientMagnitudeByITK(itk::Image* inputImage, itk::Index<3> &index, itk::Index<3> &returnIndex); }; } // namespace #endif diff --git a/Modules/Segmentation/Interactions/mitkRegionGrowingTool.cpp b/Modules/Segmentation/Interactions/mitkRegionGrowingTool.cpp index 4a21e703c9..ed2cb74681 100644 --- a/Modules/Segmentation/Interactions/mitkRegionGrowingTool.cpp +++ b/Modules/Segmentation/Interactions/mitkRegionGrowingTool.cpp @@ -1,687 +1,689 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkRegionGrowingTool.h" #include "mitkToolManager.h" #include "mitkOverwriteSliceImageFilter.h" #include "mitkImageDataItem.h" #include "mitkBaseRenderer.h" #include "mitkRenderingManager.h" #include "mitkApplicationCursor.h" #include "ipSegmentation.h" #include "mitkRegionGrowingTool.xpm" #include "mitkOverwriteDirectedPlaneImageFilter.h" #include "mitkExtractDirectedPlaneImageFilterNew.h" // us #include "mitkModule.h" #include "mitkModuleResource.h" #include namespace mitk { MITK_TOOL_MACRO(Segmentation_EXPORT, RegionGrowingTool, "Region growing tool"); } #define ROUND(a) ((a)>0 ? (int)((a)+0.5) : -(int)(0.5-(a))) mitk::RegionGrowingTool::RegionGrowingTool() :FeedbackContourTool("PressMoveRelease"), m_LowerThreshold(200), m_UpperThreshold(200), m_InitialLowerThreshold(200), m_InitialUpperThreshold(200), m_ScreenYDifference(0), m_OriginalPicSlice(NULL), m_SeedPointMemoryOffset(0), m_VisibleWindow(0), m_DefaultWindow(0), m_MouseDistanceScaleFactor(0.5), m_LastWorkingSeed(-1), m_FillFeedbackContour(true) { // great magic numbers CONNECT_ACTION( 80, OnMousePressed ); CONNECT_ACTION( 90, OnMouseMoved ); CONNECT_ACTION( 42, OnMouseReleased ); } mitk::RegionGrowingTool::~RegionGrowingTool() { } const char** mitk::RegionGrowingTool::GetXPM() const { return mitkRegionGrowingTool_xpm; } mitk::ModuleResource mitk::RegionGrowingTool::GetIconResource() const { Module* module = GetModuleContext()->GetModule(); ModuleResource resource = module->GetResource("RegionGrowing_48x48.png"); return resource; } -std::string mitk::RegionGrowingTool::GetCursorIconPath() const +mitk::ModuleResource mitk::RegionGrowingTool::GetCursorIconResource() const { - return ":/Segmentation/RegionGrowing_Cursor_48x48.png"; + Module* module = GetModuleContext()->GetModule(); + ModuleResource resource = module->GetResource("RegionGrowing_Cursor_48x48.png"); + return resource; } const char* mitk::RegionGrowingTool::GetName() const { return "Region Growing"; } void mitk::RegionGrowingTool::Activated() { Superclass::Activated(); } void mitk::RegionGrowingTool::Deactivated() { Superclass::Deactivated(); } /** 1 Determine which slice is clicked into 2 Determine if the user clicked inside or outside of the segmentation 3 Depending on the pixel value under the mouse click position, two different things happen: (separated out into OnMousePressedInside and OnMousePressedOutside) 3.1 Create a skeletonization of the segmentation and try to find a nice cut 3.1.1 Call a ipSegmentation algorithm to create a nice cut 3.1.2 Set the result of this algorithm as the feedback contour 3.2 Initialize region growing 3.2.1 Determine memory offset inside the original image 3.2.2 Determine initial region growing parameters from the level window settings of the image 3.2.3 Perform a region growing (which generates a new feedback contour) */ bool mitk::RegionGrowingTool::OnMousePressed (Action* action, const StateEvent* stateEvent) { const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; m_LastEventSender = positionEvent->GetSender(); m_LastEventSlice = m_LastEventSender->GetSlice(); //ToolLogger::SetVerboseness(3); MITK_DEBUG << "OnMousePressed" << std::endl; if ( FeedbackContourTool::CanHandleEvent(stateEvent) > 0.0 ) { MITK_DEBUG << "OnMousePressed: FeedbackContourTool says ok" << std::endl; // 1. Find out which slice the user clicked, find out which slice of the toolmanager's reference and working image corresponds to that if (positionEvent) { MITK_DEBUG << "OnMousePressed: got positionEvent" << std::endl; m_ReferenceSlice = FeedbackContourTool::GetAffectedReferenceSlice( positionEvent ); m_WorkingSlice = FeedbackContourTool::GetAffectedWorkingSlice( positionEvent ); if ( m_WorkingSlice.IsNotNull() ) // can't do anything without the segmentation { MITK_DEBUG << "OnMousePressed: got working slice" << std::endl; // 2. Determine if the user clicked inside or outside of the segmentation const Geometry3D* workingSliceGeometry = m_WorkingSlice->GetGeometry(); Point3D mprojectedPointIn2D; workingSliceGeometry->WorldToIndex( positionEvent->GetWorldPosition(), mprojectedPointIn2D); itk::Index<2> projectedPointInWorkingSlice2D; projectedPointInWorkingSlice2D[0] = static_cast( mprojectedPointIn2D[0] - 0.5 ); projectedPointInWorkingSlice2D[1] = static_cast( mprojectedPointIn2D[1] - 0.5 ); if ( workingSliceGeometry->IsIndexInside( projectedPointInWorkingSlice2D ) ) { MITK_DEBUG << "OnMousePressed: point " << positionEvent->GetWorldPosition() << " (index coordinates " << projectedPointInWorkingSlice2D << ") IS in working slice" << std::endl; // Convert to ipMITKSegmentationTYPE (because getting pixels relys on that data type) itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer correctPixelTypeImage; CastToItkImage( m_WorkingSlice, correctPixelTypeImage ); assert (correctPixelTypeImage.IsNotNull() ); // possible bug in CastToItkImage ? // direction maxtrix is wrong/broken/not working after CastToItkImage, leading to a failed assertion in // mitk/Core/DataStructures/mitkSlicedGeometry3D.cpp, 479: // virtual void mitk::SlicedGeometry3D::SetSpacing(const mitk::Vector3D&): Assertion `aSpacing[0]>0 && aSpacing[1]>0 && aSpacing[2]>0' failed // solution here: we overwrite it with an unity matrix itk::Image< ipMITKSegmentationTYPE, 2 >::DirectionType imageDirection; imageDirection.SetIdentity(); correctPixelTypeImage->SetDirection(imageDirection); Image::Pointer temporarySlice = Image::New(); // temporarySlice = ImportItkImage( correctPixelTypeImage ); CastToMitkImage( correctPixelTypeImage, temporarySlice ); mitkIpPicDescriptor* workingPicSlice = mitkIpPicNew(); CastToIpPicDescriptor(temporarySlice, workingPicSlice); int initialWorkingOffset = projectedPointInWorkingSlice2D[1] * workingPicSlice->n[0] + projectedPointInWorkingSlice2D[0]; if ( initialWorkingOffset < static_cast( workingPicSlice->n[0] * workingPicSlice->n[1] ) && initialWorkingOffset >= 0 ) { // 3. determine the pixel value under the last click bool inside = static_cast(workingPicSlice->data)[initialWorkingOffset] != 0; m_PaintingPixelValue = inside ? 0 : 1; // if inside, we want to remove a part, otherwise we want to add something if ( m_LastWorkingSeed >= static_cast( workingPicSlice->n[0] * workingPicSlice->n[1] ) || m_LastWorkingSeed < 0 ) { inside = false; } if ( m_ReferenceSlice.IsNotNull() ) { MITK_DEBUG << "OnMousePressed: got reference slice" << std::endl; m_OriginalPicSlice = mitkIpPicNew(); CastToIpPicDescriptor(m_ReferenceSlice, m_OriginalPicSlice); // 3.1. Switch depending on the pixel value if (inside) { OnMousePressedInside(action, stateEvent, workingPicSlice, initialWorkingOffset); } else { OnMousePressedOutside(action, stateEvent); } } } } } } } MITK_DEBUG << "end OnMousePressed" << std::endl; return true; } /** 3.1 Create a skeletonization of the segmentation and try to find a nice cut 3.1.1 Call a ipSegmentation algorithm to create a nice cut 3.1.2 Set the result of this algorithm as the feedback contour */ bool mitk::RegionGrowingTool::OnMousePressedInside(Action* itkNotUsed( action ), const StateEvent* stateEvent, mitkIpPicDescriptor* workingPicSlice, int initialWorkingOffset) { const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); // checked in OnMousePressed // 3.1.1. Create a skeletonization of the segmentation and try to find a nice cut // apply the skeletonization-and-cut algorithm // generate contour to remove // set m_ReferenceSlice = NULL so nothing will happen during mouse move // remember to fill the contour with 0 in mouserelease mitkIpPicDescriptor* segmentationHistory = ipMITKSegmentationCreateGrowerHistory( workingPicSlice, m_LastWorkingSeed, NULL ); // free again if (segmentationHistory) { tCutResult cutContour = ipMITKSegmentationGetCutPoints( workingPicSlice, segmentationHistory, initialWorkingOffset ); // tCutResult is a ipSegmentation type mitkIpPicFree( segmentationHistory ); if (cutContour.cutIt) { // 3.1.2 copy point from float* to mitk::Contour Contour::Pointer contourInImageIndexCoordinates = Contour::New(); contourInImageIndexCoordinates->Initialize(); Point3D newPoint; for (int index = 0; index < cutContour.deleteSize; ++index) { newPoint[0] = cutContour.deleteCurve[ 2 * index + 0 ]; newPoint[1] = cutContour.deleteCurve[ 2 * index + 1 ]; newPoint[2] = 0.0; contourInImageIndexCoordinates->AddVertex( newPoint - mitk::Point3D::VectorType(0.5) ); } free(cutContour.traceline); free(cutContour.deleteCurve); // perhaps visualize this for fun? free(cutContour.onGradient); Contour::Pointer contourInWorldCoordinates = FeedbackContourTool::BackProjectContourFrom2DSlice( m_WorkingSlice->GetGeometry(), contourInImageIndexCoordinates, true ); // true: sub 0.5 for ipSegmentation correction FeedbackContourTool::SetFeedbackContour( *contourInWorldCoordinates ); FeedbackContourTool::SetFeedbackContourVisible(true); mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); m_FillFeedbackContour = true; } else { m_FillFeedbackContour = false; } } else { m_FillFeedbackContour = false; } m_ReferenceSlice = NULL; return true; } /** 3.2 Initialize region growing 3.2.1 Determine memory offset inside the original image 3.2.2 Determine initial region growing parameters from the level window settings of the image 3.2.3 Perform a region growing (which generates a new feedback contour) */ bool mitk::RegionGrowingTool::OnMousePressedOutside(Action* itkNotUsed( action ), const StateEvent* stateEvent) { const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); // checked in OnMousePressed // 3.2 If we have a reference image, then perform an initial region growing, considering the reference image's level window // if click was outside the image, don't continue const Geometry3D* sliceGeometry = m_ReferenceSlice->GetGeometry(); Point3D mprojectedPointIn2D; sliceGeometry->WorldToIndex( positionEvent->GetWorldPosition(), mprojectedPointIn2D ); itk::Index<2> projectedPointIn2D; projectedPointIn2D[0] = static_cast( mprojectedPointIn2D[0] - 0.5 ); projectedPointIn2D[1] = static_cast( mprojectedPointIn2D[1] - 0.5 ); if ( sliceGeometry->IsIndexInside( mprojectedPointIn2D ) ) { MITK_DEBUG << "OnMousePressed: point " << positionEvent->GetWorldPosition() << " (index coordinates " << mprojectedPointIn2D << ") IS in reference slice" << std::endl; // 3.2.1 Remember Y cursor position and initial seed point //m_ScreenYPositionAtStart = static_cast(positionEvent->GetDisplayPosition()[1]); m_LastScreenPosition = ApplicationCursor::GetInstance()->GetCursorPosition(); m_ScreenYDifference = 0; m_SeedPointMemoryOffset = projectedPointIn2D[1] * m_OriginalPicSlice->n[0] + projectedPointIn2D[0]; m_LastWorkingSeed = m_SeedPointMemoryOffset; // remember for skeletonization if ( m_SeedPointMemoryOffset < static_cast( m_OriginalPicSlice->n[0] * m_OriginalPicSlice->n[1] ) && m_SeedPointMemoryOffset >= 0 ) { // 3.2.2 Get level window from reference DataNode // Use some logic to determine initial gray value bounds LevelWindow lw(0, 500); m_ToolManager->GetReferenceData(0)->GetLevelWindow(lw); // will fill lw if levelwindow property is present, otherwise won't touch it. ScalarType currentVisibleWindow = lw.GetWindow(); if (!mitk::Equal(currentVisibleWindow, m_VisibleWindow)) { m_InitialLowerThreshold = currentVisibleWindow / 20.0; m_InitialUpperThreshold = currentVisibleWindow / 20.0; m_LowerThreshold = m_InitialLowerThreshold; m_UpperThreshold = m_InitialUpperThreshold; // 3.2.3. Actually perform region growing mitkIpPicDescriptor* result = PerformRegionGrowingAndUpdateContour(); ipMITKSegmentationFree( result); // display the contour FeedbackContourTool::SetFeedbackContourVisible(true); mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow()); m_FillFeedbackContour = true; } } return true; } return false; } /** If in region growing mode (m_ReferenceSlice != NULL), then 1. Calculate the new thresholds from mouse position (relative to first position) 2. Perform a new region growing and update the feedback contour */ bool mitk::RegionGrowingTool::OnMouseMoved(Action* action, const StateEvent* stateEvent) { if ( FeedbackContourTool::CanHandleEvent(stateEvent) > 0.0 ) { if ( m_ReferenceSlice.IsNotNull() && m_OriginalPicSlice ) { const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (positionEvent) { ApplicationCursor* cursor = ApplicationCursor::GetInstance(); if (!cursor) return false; m_ScreenYDifference += cursor->GetCursorPosition()[1] - m_LastScreenPosition[1]; cursor->SetCursorPosition( m_LastScreenPosition ); m_LowerThreshold = std::max(0.0, m_InitialLowerThreshold - m_ScreenYDifference * m_MouseDistanceScaleFactor); m_UpperThreshold = std::max(0.0, m_InitialUpperThreshold - m_ScreenYDifference * m_MouseDistanceScaleFactor); // 2. Perform region growing again and show the result mitkIpPicDescriptor* result = PerformRegionGrowingAndUpdateContour(); ipMITKSegmentationFree( result ); // 3. Update the contour mitk::RenderingManager::GetInstance()->ForceImmediateUpdate(positionEvent->GetSender()->GetRenderWindow()); } } } return true; } /** If the feedback contour should be filled, then it is done here. (Contour is NOT filled, when skeletonization is done but no nice cut was found) */ bool mitk::RegionGrowingTool::OnMouseReleased(Action* action, const StateEvent* stateEvent) { if ( FeedbackContourTool::CanHandleEvent(stateEvent) > 0.0 ) { // 1. If we have a working slice, use the contour to fill a new piece on segmentation on it (or erase a piece that was selected by ipMITKSegmentationGetCutPoints) if ( m_WorkingSlice.IsNotNull() && m_OriginalPicSlice ) { const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (positionEvent) { // remember parameters for next time m_InitialLowerThreshold = m_LowerThreshold; m_InitialUpperThreshold = m_UpperThreshold; if (m_FillFeedbackContour) { // 3. use contour to fill a region in our working slice Contour* feedbackContour( FeedbackContourTool::GetFeedbackContour() ); if (feedbackContour) { Contour::Pointer projectedContour = FeedbackContourTool::ProjectContourTo2DSlice( m_WorkingSlice, feedbackContour, false, false ); // false: don't add any 0.5 // false: don't constrain the contour to the image's inside if (projectedContour.IsNotNull()) { FeedbackContourTool::FillContourInSlice( projectedContour, m_WorkingSlice, m_PaintingPixelValue ); const PlaneGeometry* planeGeometry( dynamic_cast (positionEvent->GetSender()->GetCurrentWorldGeometry2D() ) ); //MITK_DEBUG << "OnMouseReleased: writing back to dimension " << affectedDimension << ", slice " << affectedSlice << " in working image" << std::endl; // 4. write working slice back into image volume this->WriteBackSegmentationResult(positionEvent, m_WorkingSlice); } } } FeedbackContourTool::SetFeedbackContourVisible(false); mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); } } } m_ReferenceSlice = NULL; // don't leak m_WorkingSlice = NULL; m_OriginalPicSlice = NULL; return true; } /** Uses ipSegmentation algorithms to do the actual region growing. The result (binary image) is first smoothed by a 5x5 circle mask, then its contour is extracted and converted to MITK coordinates. */ mitkIpPicDescriptor* mitk::RegionGrowingTool::PerformRegionGrowingAndUpdateContour() { // 1. m_OriginalPicSlice and m_SeedPointMemoryOffset are set to sensitive values, as well as m_LowerThreshold and m_UpperThreshold assert (m_OriginalPicSlice); if (m_OriginalPicSlice->n[0] != 256 || m_OriginalPicSlice->n[1] != 256) // ??? assert( (m_SeedPointMemoryOffset < static_cast( m_OriginalPicSlice->n[0] * m_OriginalPicSlice->n[1] )) && (m_SeedPointMemoryOffset >= 0) ); // inside the image // 2. ipSegmentation is used to perform region growing float ignored; int oneContourOffset( 0 ); mitkIpPicDescriptor* regionGrowerResult = ipMITKSegmentationGrowRegion4N( m_OriginalPicSlice, m_SeedPointMemoryOffset, // seed point true, // grayvalue interval relative to seed point gray value? m_LowerThreshold, m_UpperThreshold, 0, // continue until done (maxIterations == 0) NULL, // allocate new memory (only this time, on mouse move we'll reuse the old buffer) oneContourOffset, // a pixel that is near the resulting contour ignored // ignored by us ); if (!regionGrowerResult || oneContourOffset == -1) { Contour::Pointer dummyContour = Contour::New(); dummyContour->Initialize(); FeedbackContourTool::SetFeedbackContour( *dummyContour ); if (regionGrowerResult) ipMITKSegmentationFree(regionGrowerResult); return NULL; } // 3. We smooth the result a little to reduce contour complexity bool smoothResult( true ); // currently fixed, perhaps remove else block mitkIpPicDescriptor* smoothedRegionGrowerResult; if (smoothResult) { // Smooth the result (otherwise very detailed contour) smoothedRegionGrowerResult = SmoothIPPicBinaryImage( regionGrowerResult, oneContourOffset ); ipMITKSegmentationFree( regionGrowerResult ); } else { smoothedRegionGrowerResult = regionGrowerResult; } // 4. convert the result of region growing into a mitk::Contour // At this point oneContourOffset could be useless, if smoothing destroyed a thin bridge. In these // cases, we have two or more unconnected segmentation regions, and we don't know, which one is touched by oneContourOffset. // In the bad case, the contour is not the one around our seedpoint, so the result looks very strange to the user. // -> we remove the point where the contour started so far. Then we look from the bottom of the image for the first segmentation pixel // and start another contour extraction from there. This is done, until the seedpoint is inside the contour int numberOfContourPoints( 0 ); int newBufferSize( 0 ); float* contourPoints = ipMITKSegmentationGetContour8N( smoothedRegionGrowerResult, oneContourOffset, numberOfContourPoints, newBufferSize ); // memory allocated with malloc if (contourPoints) { while ( !ipMITKSegmentationIsInsideContour( contourPoints, // contour numberOfContourPoints, // points in contour m_SeedPointMemoryOffset % smoothedRegionGrowerResult->n[0], // test point x m_SeedPointMemoryOffset / smoothedRegionGrowerResult->n[0] // test point y ) ) { // we decide that this cannot be part of the segmentation because the seedpoint is not contained in the contour (fill the 4-neighborhood with 0) ipMITKSegmentationReplaceRegion4N( smoothedRegionGrowerResult, oneContourOffset, 0 ); // move the contour offset to the last row (x position of the seed point) int rowLength = smoothedRegionGrowerResult->n[0]; // number of pixels in a row oneContourOffset = m_SeedPointMemoryOffset % smoothedRegionGrowerResult->n[0] // x of seed point + rowLength*(smoothedRegionGrowerResult->n[1]-1); // y of last row while ( oneContourOffset >=0 && (*(static_cast(smoothedRegionGrowerResult->data) + oneContourOffset) == 0) ) { oneContourOffset -= rowLength; // if pixel at data+oneContourOffset is 0, then move up one row } if ( oneContourOffset < 0 ) { break; // just use the last contour we found } free(contourPoints); // release contour memory contourPoints = ipMITKSegmentationGetContour8N( smoothedRegionGrowerResult, oneContourOffset, numberOfContourPoints, newBufferSize ); // memory allocated with malloc } // copy point from float* to mitk::Contour Contour::Pointer contourInImageIndexCoordinates = Contour::New(); contourInImageIndexCoordinates->Initialize(); Point3D newPoint; for (int index = 0; index < numberOfContourPoints; ++index) { newPoint[0] = contourPoints[ 2 * index + 0 ]; newPoint[1] = contourPoints[ 2 * index + 1 ]; newPoint[2] = 0; contourInImageIndexCoordinates->AddVertex( newPoint - mitk::Point3D::VectorType(0.5)); } free(contourPoints); Contour::Pointer contourInWorldCoordinates = FeedbackContourTool::BackProjectContourFrom2DSlice( m_ReferenceSlice->GetGeometry(), contourInImageIndexCoordinates, true ); // true: sub 0.5 for ipSegmentation correctio FeedbackContourTool::SetFeedbackContour( *contourInWorldCoordinates ); } // 5. Result HAS TO BE freed by caller, contains the binary region growing result return smoothedRegionGrowerResult; } /** Helper method for SmoothIPPicBinaryImage. Smoothes a given part of and image. \param sourceImage The original binary image. \param dest The smoothed image (will be written without bounds checking). \param contourOfs One offset of the contour. Is updated if a pixel is changed (which might change the contour). \param maskOffsets Memory offsets that describe the smoothing mask. \param maskSize Entries of the mask. \param startOffset First pixel that should be smoothed using this mask. \param endOffset Last pixel that should be smoothed using this mask. */ void mitk::RegionGrowingTool::SmoothIPPicBinaryImageHelperForRows( mitkIpPicDescriptor* sourceImage, mitkIpPicDescriptor* dest, int &contourOfs, int* maskOffsets, int maskSize, int startOffset, int endOffset ) { // work on the very first row ipMITKSegmentationTYPE* current; ipMITKSegmentationTYPE* source = ((ipMITKSegmentationTYPE*)sourceImage->data) + startOffset; // + 1! don't read at start-1 ipMITKSegmentationTYPE* end = ((ipMITKSegmentationTYPE*)dest->data) + endOffset; int ofs = startOffset; int minority = (maskSize - 1) / 2; for (current = ((ipMITKSegmentationTYPE*)dest->data) + startOffset; current minority) { *current = 1; contourOfs = ofs; } else { *current = 0; } ++source; ++ofs; } } /** Smoothes a binary ipPic image with a 5x5 mask. The image borders (some first and last rows) are treated differently. */ mitkIpPicDescriptor* mitk::RegionGrowingTool::SmoothIPPicBinaryImage( mitkIpPicDescriptor* image, int &contourOfs, mitkIpPicDescriptor* dest ) { if (!image) return NULL; // Original code from /trunk/mbi-qm/Qmitk/Qmitk2DSegTools/RegionGrowerTool.cpp (first version by T. Boettger?). Reformatted and documented and restructured. #define MSK_SIZE5x5 21 #define MSK_SIZE3x3 5 #define MSK_SIZE3x1 3 // mask is an array of coordinates that form a rastered circle like this // // OOO // OOOOO // OOOOO // OOOOO // OOO // // int mask5x5[MSK_SIZE5x5][2] = { /******/ {-1,-2}, {0,-2}, {1,-2}, /*****/ {-2,-1}, {-1,-1}, {0,-1}, {1,-1}, {2,-1}, {-2, 0}, {-1, 0}, {0, 0}, {1, 0}, {2, 0}, {-2, 1}, {-1, 1}, {0, 1}, {1, 1}, {2, 1}, /******/ {-1, 2}, {0, 2}, {1, 2} /*****/ }; int mask3x3[MSK_SIZE3x3][2] = { /******/ {0,-1}, /*****/ {-1, 0}, {0, 0}, {1, 0}, /******/ {0, 1} /*****/ }; int mask3x1[MSK_SIZE3x1][2] = { {-1, 0}, {0, 0}, {1, 0} }; // The following lines iterate over all the pixels of a (sliced) image (except the first and last three rows). // For each pixel, all the coordinates around it (according to mask) are evaluated (this means 21 pixels). // If more than 10 of the evaluated pixels are non-zero, then the central pixel is set to 1, else to 0. // This is determining a majority. If there is no clear majority, then the central pixel itself "decides". int maskOffset5x5[MSK_SIZE5x5]; int line = image->n[0]; for (int i=0; in[0]; int spareOut1Rows = 1*image->n[0]; if ( image->n[1] > 0 ) SmoothIPPicBinaryImageHelperForRows( image, dest, contourOfs, maskOffset3x1, MSK_SIZE3x1, 1, dest->n[0] ); if ( image->n[1] > 3 ) SmoothIPPicBinaryImageHelperForRows( image, dest, contourOfs, maskOffset3x3, MSK_SIZE3x3, spareOut1Rows, dest->n[0]*3 ); if ( image->n[1] > 6 ) SmoothIPPicBinaryImageHelperForRows( image, dest, contourOfs, maskOffset5x5, MSK_SIZE5x5, spareOut3Rows, dest->n[0]*dest->n[1] - spareOut3Rows ); if ( image->n[1] > 8 ) SmoothIPPicBinaryImageHelperForRows( image, dest, contourOfs, maskOffset3x3, MSK_SIZE3x3, dest->n[0]*dest->n[1] -spareOut3Rows, dest->n[0]*dest->n[1] - spareOut1Rows ); if ( image->n[1] > 10) SmoothIPPicBinaryImageHelperForRows( image, dest, contourOfs, maskOffset3x1, MSK_SIZE3x1, dest->n[0]*dest->n[1] -spareOut1Rows, dest->n[0]*dest->n[1] - 1 ); // correction for first pixel (sorry for the ugliness) if ( *((ipMITKSegmentationTYPE*)(dest->data)+1) == 1 ) { *((ipMITKSegmentationTYPE*)(dest->data)+0) = 1; } if (dest->n[0] * dest->n[1] > 2) { // correction for last pixel if ( *((ipMITKSegmentationTYPE*)(dest->data)+dest->n[0]*dest->n[1]-2) == 1 ) { *((ipMITKSegmentationTYPE*)(dest->data)+dest->n[0]*dest->n[1]-1) = 1; } } return dest; } diff --git a/Modules/Segmentation/Interactions/mitkRegionGrowingTool.h b/Modules/Segmentation/Interactions/mitkRegionGrowingTool.h index 582fb29e0f..4d6cdf85fa 100644 --- a/Modules/Segmentation/Interactions/mitkRegionGrowingTool.h +++ b/Modules/Segmentation/Interactions/mitkRegionGrowingTool.h @@ -1,119 +1,119 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkRegionGrowingTool_h_Included #define mitkRegionGrowingTool_h_Included #include "mitkFeedbackContourTool.h" #include "mitkLegacyAdaptors.h" #include "SegmentationExports.h" struct mitkIpPicDescriptor; class ModuleResource; namespace mitk { /** \brief A slice based region growing tool. \sa FeedbackContourTool \ingroup Interaction \ingroup ToolManagerEtAl When the user presses the mouse button, RegionGrowingTool will use the gray values at that position to initialize a region growing algorithm (in the affected 2D slice). By moving the mouse up and down while the button is still pressed, the user can change the parameters of the region growing algorithm (selecting more or less of an object). The current result of region growing will always be shown as a contour to the user. After releasing the button, the current result of the region growing algorithm will be written to the working image of this tool's ToolManager. If the first click is inside a segmentation that was generated by region growing (recently), the tool will try to cut off a part of the segmentation. For this reason a skeletonization of the segmentation is generated and the optimal cut point is determined. \warning Only to be instantiated by mitk::ToolManager. $Author$ */ class Segmentation_EXPORT RegionGrowingTool : public FeedbackContourTool { public: mitkClassMacro(RegionGrowingTool, FeedbackContourTool); itkNewMacro(RegionGrowingTool); virtual const char** GetXPM() const; - virtual std::string GetCursorIconPath() const; + virtual ModuleResource GetCursorIconResource() const; ModuleResource GetIconResource() const; virtual const char* GetName() const; protected: RegionGrowingTool(); // purposely hidden virtual ~RegionGrowingTool(); virtual void Activated(); virtual void Deactivated(); virtual bool OnMousePressed (Action*, const StateEvent*); virtual bool OnMousePressedInside (Action*, const StateEvent*, mitkIpPicDescriptor* workingPicSlice, int initialWorkingOffset); virtual bool OnMousePressedOutside (Action*, const StateEvent*); virtual bool OnMouseMoved (Action*, const StateEvent*); virtual bool OnMouseReleased(Action*, const StateEvent*); mitkIpPicDescriptor* PerformRegionGrowingAndUpdateContour(); Image::Pointer m_ReferenceSlice; Image::Pointer m_WorkingSlice; ScalarType m_LowerThreshold; ScalarType m_UpperThreshold; ScalarType m_InitialLowerThreshold; ScalarType m_InitialUpperThreshold; Point2I m_LastScreenPosition; int m_ScreenYDifference; private: mitkIpPicDescriptor* SmoothIPPicBinaryImage( mitkIpPicDescriptor* image, int &contourOfs, mitkIpPicDescriptor* dest = NULL ); void SmoothIPPicBinaryImageHelperForRows( mitkIpPicDescriptor* source, mitkIpPicDescriptor* dest, int &contourOfs, int* maskOffsets, int maskSize, int startOffset, int endOffset ); mitkIpPicDescriptor* m_OriginalPicSlice; int m_SeedPointMemoryOffset; ScalarType m_VisibleWindow; ScalarType m_DefaultWindow; ScalarType m_MouseDistanceScaleFactor; int m_PaintingPixelValue; int m_LastWorkingSeed; bool m_FillFeedbackContour; }; } // namespace #endif diff --git a/Modules/Segmentation/Interactions/mitkSubtractContourTool.cpp b/Modules/Segmentation/Interactions/mitkSubtractContourTool.cpp index 7436158de3..d2edfaae6a 100644 --- a/Modules/Segmentation/Interactions/mitkSubtractContourTool.cpp +++ b/Modules/Segmentation/Interactions/mitkSubtractContourTool.cpp @@ -1,61 +1,63 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkSubtractContourTool.h" #include "mitkSubtractContourTool.xpm" // us #include "mitkModule.h" #include "mitkModuleResource.h" #include namespace mitk { MITK_TOOL_MACRO(Segmentation_EXPORT, SubtractContourTool, "Subtract tool"); } mitk::SubtractContourTool::SubtractContourTool() :ContourTool(0) { FeedbackContourTool::SetFeedbackContourColor( 1.0, 0.0, 0.0 ); } mitk::SubtractContourTool::~SubtractContourTool() { } const char** mitk::SubtractContourTool::GetXPM() const { return mitkSubtractContourTool_xpm; } mitk::ModuleResource mitk::SubtractContourTool::GetIconResource() const { Module* module = GetModuleContext()->GetModule(); ModuleResource resource = module->GetResource("Subtract_48x48.png"); return resource; } -std::string mitk::SubtractContourTool::GetCursorIconPath() const +mitk::ModuleResource mitk::SubtractContourTool::GetCursorIconResource() const { - return ":/Segmentation/Subtract_Cursor_48x48.png"; + Module* module = GetModuleContext()->GetModule(); + ModuleResource resource = module->GetResource("Subtract_Cursor_48x48.png"); + return resource; } const char* mitk::SubtractContourTool::GetName() const { return "Subtract"; } diff --git a/Modules/Segmentation/Interactions/mitkSubtractContourTool.h b/Modules/Segmentation/Interactions/mitkSubtractContourTool.h index fc6c08dcd7..6dcbad9a6d 100644 --- a/Modules/Segmentation/Interactions/mitkSubtractContourTool.h +++ b/Modules/Segmentation/Interactions/mitkSubtractContourTool.h @@ -1,72 +1,72 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkSubtractContourTool_h_Included #define mitkSubtractContourTool_h_Included #include "mitkContourTool.h" #include "SegmentationExports.h" class ModuleResource; namespace mitk { /** \brief Fill the inside of a contour with 1 \sa ContourTool \ingroup Interaction \ingroup ToolManagerEtAl Fills a visible contour (from FeedbackContourTool) during mouse dragging. When the mouse button is released, SubtractContourTool tries to extract a slice from the working image and fill in the (filled) contour as a binary image. All inside pixels are set to 0. While holding the CTRL key, the contour changes color and the pixels on the inside would be filled with 1. \warning Only to be instantiated by mitk::ToolManager. $Author$ */ class Segmentation_EXPORT SubtractContourTool : public ContourTool { public: mitkClassMacro(SubtractContourTool, ContourTool); itkNewMacro(SubtractContourTool); virtual const char** GetXPM() const; - virtual std::string GetCursorIconPath() const; + virtual ModuleResource GetCursorIconResource() const; ModuleResource GetIconResource() const; virtual const char* GetName() const; protected: SubtractContourTool(); // purposely hidden virtual ~SubtractContourTool(); }; } // namespace #endif diff --git a/Modules/SegmentationUI/CMakeLists.txt b/Modules/SegmentationUI/CMakeLists.txt index 640fabfdcf..0ff775ff2e 100644 --- a/Modules/SegmentationUI/CMakeLists.txt +++ b/Modules/SegmentationUI/CMakeLists.txt @@ -1,6 +1,6 @@ MITK_CREATE_MODULE ( SegmentationUI INCLUDE_DIRS Qmitk DEPENDS Qmitk Segmentation qxt QmitkExt -PACKAGE_DEPENDS QT +PACKAGE_DEPENDS QT CTK QT_MODULE ) diff --git a/Modules/QmitkExt/QmitkOtsuToolWidgetControls.ui b/Modules/SegmentationUI/Qmitk/QmitkOtsuToolWidgetControls.ui similarity index 100% rename from Modules/QmitkExt/QmitkOtsuToolWidgetControls.ui rename to Modules/SegmentationUI/Qmitk/QmitkOtsuToolWidgetControls.ui diff --git a/Modules/SegmentationUI/files.cmake b/Modules/SegmentationUI/files.cmake index 4117de8a86..5ea26dfc12 100644 --- a/Modules/SegmentationUI/files.cmake +++ b/Modules/SegmentationUI/files.cmake @@ -1,55 +1,56 @@ set( CPP_FILES Qmitk/QmitkAdaptiveRegionGrowingToolGUI.cpp Qmitk/QmitkBinaryThresholdToolGUI.cpp Qmitk/QmitkBinaryThresholdULToolGUI.cpp Qmitk/QmitkCalculateGrayValueStatisticsToolGUI.cpp Qmitk/QmitkCopyToClipBoardDialog.cpp Qmitk/QmitkDrawPaintbrushToolGUI.cpp Qmitk/QmitkErasePaintbrushToolGUI.cpp Qmitk/QmitkFastMarchingTool3DGUI.cpp Qmitk/QmitkFastMarchingToolGUI.cpp Qmitk/QmitkLiveWireTool2DGUI.cpp Qmitk/QmitkNewSegmentationDialog.cpp Qmitk/QmitkOtsuTool3DGUI.cpp Qmitk/QmitkPaintbrushToolGUI.cpp Qmitk/QmitkPixelManipulationToolGUI.cpp Qmitk/QmitkRegionGrow3DToolGUI.cpp Qmitk/QmitkSlicesInterpolator.cpp Qmitk/QmitkToolGUI.cpp Qmitk/QmitkToolGUIArea.cpp Qmitk/QmitkToolReferenceDataSelectionBox.cpp Qmitk/QmitkToolRoiDataSelectionBox.cpp Qmitk/QmitkToolSelectionBox.cpp Qmitk/QmitkToolWorkingDataSelectionBox.cpp Qmitk/QmitkWatershedToolGUI.cpp ) set(MOC_H_FILES Qmitk/QmitkAdaptiveRegionGrowingToolGUI.h Qmitk/QmitkBinaryThresholdToolGUI.h Qmitk/QmitkBinaryThresholdULToolGUI.h Qmitk/QmitkCalculateGrayValueStatisticsToolGUI.h Qmitk/QmitkCopyToClipBoardDialog.h Qmitk/QmitkDrawPaintbrushToolGUI.h Qmitk/QmitkErasePaintbrushToolGUI.h Qmitk/QmitkFastMarchingTool3DGUI.h Qmitk/QmitkFastMarchingToolGUI.h Qmitk/QmitkLiveWireTool2DGUI.h Qmitk/QmitkNewSegmentationDialog.h Qmitk/QmitkOtsuTool3DGUI.h Qmitk/QmitkPaintbrushToolGUI.h Qmitk/QmitkPixelManipulationToolGUI.h Qmitk/QmitkRegionGrow3DToolGUI.h Qmitk/QmitkSlicesInterpolator.h Qmitk/QmitkToolGUI.h Qmitk/QmitkToolGUIArea.h Qmitk/QmitkToolReferenceDataSelectionBox.h Qmitk/QmitkToolRoiDataSelectionBox.h Qmitk/QmitkToolSelectionBox.h Qmitk/QmitkToolWorkingDataSelectionBox.h Qmitk/QmitkWatershedToolGUI.h ) set(UI_FILES Qmitk/QmitkAdaptiveRegionGrowingToolGUIControls.ui +Qmitk/QmitkOtsuToolWidgetControls.ui ) diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp index 79acc67ad1..e7ea9fd82f 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp @@ -1,1135 +1,1132 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkProperties.h" #include "mitkSegTool2D.h" #include "QmitkStdMultiWidget.h" #include "QmitkNewSegmentationDialog.h" #include #include #include "QmitkSegmentationView.h" #include "QmitkSegmentationOrganNamesHandling.cpp" #include #include "mitkVtkResliceInterpolationProperty.h" #include "mitkGetModuleContext.h" #include "mitkModule.h" #include "mitkModuleRegistry.h" +#include "mitkModuleResource.h" #include "mitkStatusBar.h" #include "mitkApplicationCursor.h" #include "mitkSegmentationObjectFactory.h" const std::string QmitkSegmentationView::VIEW_ID = "org.mitk.views.segmentation"; // public methods QmitkSegmentationView::QmitkSegmentationView() :m_Parent(NULL) ,m_Controls(NULL) ,m_MultiWidget(NULL) ,m_DataSelectionChanged(false) ,m_MouseCursorSet(false) { RegisterSegmentationObjectFactory(); mitk::NodePredicateDataType::Pointer isDwi = mitk::NodePredicateDataType::New("DiffusionImage"); mitk::NodePredicateDataType::Pointer isDti = mitk::NodePredicateDataType::New("TensorImage"); mitk::NodePredicateDataType::Pointer isQbi = mitk::NodePredicateDataType::New("QBallImage"); mitk::NodePredicateOr::Pointer isDiffusionImage = mitk::NodePredicateOr::New(isDwi, isDti); isDiffusionImage = mitk::NodePredicateOr::New(isDiffusionImage, isQbi); m_IsOfTypeImagePredicate = mitk::NodePredicateOr::New(isDiffusionImage, mitk::TNodePredicateDataType::New()); m_IsBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); m_IsNotBinaryPredicate = mitk::NodePredicateNot::New( m_IsBinaryPredicate ); m_IsNotABinaryImagePredicate = mitk::NodePredicateAnd::New( m_IsOfTypeImagePredicate, m_IsNotBinaryPredicate ); m_IsABinaryImagePredicate = mitk::NodePredicateAnd::New( m_IsOfTypeImagePredicate, m_IsBinaryPredicate); } QmitkSegmentationView::~QmitkSegmentationView() { delete m_Controls; } void QmitkSegmentationView::NewNodesGenerated() { MITK_WARN<<"Use of deprecated function: NewNodesGenerated!! This function is empty and will be removed in the next time!"; } void QmitkSegmentationView::NewNodeObjectsGenerated(mitk::ToolManager::DataVectorType* nodes) { if (!nodes) return; mitk::ToolManager* toolManager = m_Controls->m_ManualToolSelectionBox2D->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::Visible() { if (m_DataSelectionChanged) { this->OnSelectionChanged(this->GetDataManagerSelection()); } } void QmitkSegmentationView::Activated() { // should be moved to ::BecomesVisible() or similar if( m_Controls ) { m_Controls->m_ManualToolSelectionBox2D->SetAutoShowNamesWidth(250); m_Controls->m_ManualToolSelectionBox2D->setEnabled( true ); m_Controls->m_ManualToolSelectionBox3D->SetAutoShowNamesWidth(250); m_Controls->m_ManualToolSelectionBox3D->setEnabled( true ); // m_Controls->m_OrganToolSelectionBox->setEnabled( true ); // m_Controls->m_LesionToolSelectionBox->setEnabled( true ); // m_Controls->m_SlicesInterpolator->Enable3DInterpolation( m_Controls->widgetStack->currentWidget() == m_Controls->pageManual ); mitk::DataStorage::SetOfObjects::ConstPointer segmentations = this->GetDefaultDataStorage()->GetSubset( m_IsABinaryImagePredicate ); mitk::DataStorage::SetOfObjects::ConstPointer image = this->GetDefaultDataStorage()->GetSubset( m_IsNotABinaryImagePredicate ); if (!image->empty()) { OnSelectionChanged(*image->begin()); } for ( mitk::DataStorage::SetOfObjects::const_iterator iter = segmentations->begin(); iter != segmentations->end(); ++iter) { mitk::DataNode* node = *iter; itk::SimpleMemberCommand::Pointer command = itk::SimpleMemberCommand::New(); command->SetCallbackFunction(this, &QmitkSegmentationView::OnWorkingNodeVisibilityChanged); m_WorkingDataObserverTags.insert( std::pair( node, node->GetProperty("visible")->AddObserver( itk::ModifiedEvent(), command ) ) ); itk::SimpleMemberCommand::Pointer command2 = itk::SimpleMemberCommand::New(); command2->SetCallbackFunction(this, &QmitkSegmentationView::OnBinaryPropertyChanged); m_BinaryPropertyObserverTags.insert( std::pair( node, node->GetProperty("binary")->AddObserver( itk::ModifiedEvent(), command2 ) ) ); } } this->SetToolManagerSelection(m_Controls->patImageSelector->GetSelectedNode(), m_Controls->segImageSelector->GetSelectedNode()); } void QmitkSegmentationView::Deactivated() { if( m_Controls ) { m_Controls->m_ManualToolSelectionBox2D->setEnabled( false ); m_Controls->m_ManualToolSelectionBox3D->setEnabled( false ); //deactivate all tools m_Controls->m_ManualToolSelectionBox2D->GetToolManager()->ActivateTool(-1); // m_Controls->m_OrganToolSelectionBox->setEnabled( false ); // m_Controls->m_LesionToolSelectionBox->setEnabled( false ); m_Controls->m_SlicesInterpolator->EnableInterpolation( false ); //Removing all observers for ( NodeTagMapType::iterator dataIter = m_WorkingDataObserverTags.begin(); dataIter != m_WorkingDataObserverTags.end(); ++dataIter ) { (*dataIter).first->GetProperty("visible")->RemoveObserver( (*dataIter).second ); } m_WorkingDataObserverTags.clear(); for ( NodeTagMapType::iterator dataIter = m_BinaryPropertyObserverTags.begin(); dataIter != m_BinaryPropertyObserverTags.end(); ++dataIter ) { (*dataIter).first->GetProperty("binary")->RemoveObserver( (*dataIter).second ); } m_BinaryPropertyObserverTags.clear(); // gets the context of the "Mitk" (Core) module (always has id 1) // TODO Workaround until CTK plugincontext is available mitk::ModuleContext* context = mitk::ModuleRegistry::GetModule(1)->GetModuleContext(); // Workaround end mitk::ServiceReference serviceRef = context->GetServiceReference(); mitk::PlanePositionManagerService* service = dynamic_cast(context->GetService(serviceRef)); service->RemoveAllPlanePositions(); } } void QmitkSegmentationView::StdMultiWidgetAvailable( QmitkStdMultiWidget& stdMultiWidget ) { SetMultiWidget(&stdMultiWidget); } void QmitkSegmentationView::StdMultiWidgetNotAvailable() { SetMultiWidget(NULL); } void QmitkSegmentationView::StdMultiWidgetClosed( QmitkStdMultiWidget& /*stdMultiWidget*/ ) { SetMultiWidget(NULL); } void QmitkSegmentationView::SetMultiWidget(QmitkStdMultiWidget* multiWidget) { // save the current multiwidget as the working widget m_MultiWidget = multiWidget; 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_ManualToolSelectionBox2D->GetToolManager(); m_Controls->m_SlicesInterpolator->SetDataStorage( *(this->GetDefaultDataStorage())); m_Controls->m_SlicesInterpolator->Initialize( toolManager, m_MultiWidget ); } } void QmitkSegmentationView::OnPreferencesChanged(const berry::IBerryPreferences* prefs) { m_AutoSelectionEnabled = prefs->GetBool("auto selection", false); } void QmitkSegmentationView::CreateNewSegmentation() { mitk::DataNode::Pointer node = m_Controls->m_ManualToolSelectionBox2D->GetToolManager()->GetReferenceData(0); if (node.IsNotNull()) { mitk::Image::Pointer image = dynamic_cast( node->GetData() ); if (image.IsNotNull()) { if (image->GetDimension()>1) { // 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_ManualToolSelectionBox2D->GetToolManager(); mitk::Tool* firstTool = toolManager->GetToolById(0); if (firstTool) { try { std::string newNodeName = dialog->GetSegmentationName().toStdString(); if(newNodeName.empty()) newNodeName = "no_name"; mitk::DataNode::Pointer emptySegmentation = firstTool->CreateEmptySegmentationNode( image, newNodeName, 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_NEAREST) ); // 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(); if(m_Controls->m_ManualToolSelectionBox2D->GetToolManager()->GetWorkingData(0)) { m_Controls->m_ManualToolSelectionBox2D->GetToolManager()->GetWorkingData(0)->SetSelected(false); } emptySegmentation->SetSelected(true); this->GetDefaultDataStorage()->Add( emptySegmentation, node ); // add as a child, because the segmentation "derives" from the original itk::SimpleMemberCommand::Pointer command = itk::SimpleMemberCommand::New(); command->SetCallbackFunction(this, &QmitkSegmentationView::OnWorkingNodeVisibilityChanged); m_WorkingDataObserverTags.insert( std::pair( emptySegmentation, emptySegmentation->GetProperty("visible")->AddObserver( itk::ModifiedEvent(), command ) ) ); itk::SimpleMemberCommand::Pointer command2 = itk::SimpleMemberCommand::New(); command2->SetCallbackFunction(this, &QmitkSegmentationView::OnBinaryPropertyChanged); m_BinaryPropertyObserverTags.insert( std::pair( emptySegmentation, emptySegmentation->GetProperty("binary")->AddObserver( itk::ModifiedEvent(), command2 ) ) ); this->ApplyDisplayOptions( emptySegmentation ); this->FireNodeSelected( emptySegmentation ); this->OnSelectionChanged( emptySegmentation ); toolManager->SetWorkingData(emptySegmentation); // m_Controls->segImageSelector->show(); } 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::OnWorkingNodeVisibilityChanged() { m_Controls->m_ManualToolSelectionBox2D->setEnabled(false); if (!m_Controls->m_ManualToolSelectionBox2D->isEnabled()) { this->UpdateWarningLabel("The selected segmentation is currently not visible!"); } else { this->UpdateWarningLabel(""); } } void QmitkSegmentationView::OnBinaryPropertyChanged() { mitk::DataStorage::SetOfObjects::ConstPointer patImages = m_Controls->patImageSelector->GetNodes(); bool isBinary(false); for (mitk::DataStorage::SetOfObjects::ConstIterator it = patImages->Begin(); it != patImages->End(); ++it) { const mitk::DataNode* node = it->Value(); node->GetBoolProperty("binary", isBinary); if(isBinary) { m_Controls->patImageSelector->RemoveNode(node); m_Controls->segImageSelector->AddNode(node); this->SetToolManagerSelection(NULL,NULL); return; } } mitk::DataStorage::SetOfObjects::ConstPointer segImages = m_Controls->segImageSelector->GetNodes(); isBinary = true; for (mitk::DataStorage::SetOfObjects::ConstIterator it = segImages->Begin(); it != segImages->End(); ++it) { const mitk::DataNode* node = it->Value(); node->GetBoolProperty("binary", isBinary); if(!isBinary) { m_Controls->segImageSelector->RemoveNode(node); m_Controls->patImageSelector->AddNode(node); if (m_Controls->m_ManualToolSelectionBox2D->GetToolManager()->GetWorkingData(0) == node) m_Controls->m_ManualToolSelectionBox2D->GetToolManager()->SetWorkingData(NULL); return; } } } void QmitkSegmentationView::NodeAdded(const mitk::DataNode *node) { bool isBinary (false); bool isHelperObject (false); node->GetBoolProperty("binary", isBinary); node->GetBoolProperty("helper object", isHelperObject); if (m_AutoSelectionEnabled) { if (!isBinary && dynamic_cast(node->GetData())) { FireNodeSelected(const_cast(node)); } } if (isBinary && !isHelperObject) { itk::SimpleMemberCommand::Pointer command = itk::SimpleMemberCommand::New(); command->SetCallbackFunction(this, &QmitkSegmentationView::OnWorkingNodeVisibilityChanged); m_WorkingDataObserverTags.insert( std::pair( const_cast(node), node->GetProperty("visible")->AddObserver( itk::ModifiedEvent(), command ) ) ); itk::SimpleMemberCommand::Pointer command2 = itk::SimpleMemberCommand::New(); command2->SetCallbackFunction(this, &QmitkSegmentationView::OnBinaryPropertyChanged); m_BinaryPropertyObserverTags.insert( std::pair( const_cast(node), node->GetProperty("binary")->AddObserver( itk::ModifiedEvent(), command2 ) ) ); this->ApplyDisplayOptions( const_cast(node) ); } } void QmitkSegmentationView::NodeRemoved(const mitk::DataNode* node) { bool isSeg(false); bool isHelperObject(false); node->GetBoolProperty("helper object", isHelperObject); node->GetBoolProperty("binary", isSeg); mitk::Image* image = dynamic_cast(node->GetData()); if(isSeg && !isHelperObject && image) { //First of all remove all possible contour markers of the segmentation mitk::DataStorage::SetOfObjects::ConstPointer allContourMarkers = this->GetDataStorage()->GetDerivations(node, mitk::NodePredicateProperty::New("isContourMarker" , mitk::BoolProperty::New(true))); // gets the context of the "Mitk" (Core) module (always has id 1) // TODO Workaround until CTK plugincontext is available mitk::ModuleContext* context = mitk::ModuleRegistry::GetModule(1)->GetModuleContext(); // Workaround end mitk::ServiceReference serviceRef = context->GetServiceReference(); mitk::PlanePositionManagerService* service = dynamic_cast(context->GetService(serviceRef)); for (mitk::DataStorage::SetOfObjects::ConstIterator it = allContourMarkers->Begin(); it != allContourMarkers->End(); ++it) { std::string nodeName = node->GetName(); unsigned int t = nodeName.find_last_of(" "); unsigned int id = atof(nodeName.substr(t+1).c_str())-1; service->RemovePlanePosition(id); this->GetDataStorage()->Remove(it->Value()); } if ((m_Controls->m_ManualToolSelectionBox2D->GetToolManager()->GetWorkingData(0) == node) && m_Controls->patImageSelector->GetSelectedNode().IsNotNull()) { this->SetToolManagerSelection(m_Controls->m_ManualToolSelectionBox2D->GetToolManager()->GetReferenceData(0), NULL); this->UpdateWarningLabel("Select or create a segmentation!"); } mitk::SurfaceInterpolationController::GetInstance()->RemoveSegmentationFromContourList(image); } mitk::DataNode* tempNode = const_cast(node); //Since the binary property could be changed during runtime by the user if (image && !isHelperObject) { node->GetProperty("visible")->RemoveObserver( m_WorkingDataObserverTags[tempNode] ); m_WorkingDataObserverTags.erase(tempNode); node->GetProperty("binary")->RemoveObserver( m_BinaryPropertyObserverTags[tempNode] ); m_BinaryPropertyObserverTags.erase(tempNode); } if((m_Controls->m_ManualToolSelectionBox2D->GetToolManager()->GetReferenceData(0) == node)) { //as we don't know which node was actually removed e.g. our reference node, disable 'New Segmentation' button. //consider the case that there is no more image in the datastorage this->SetToolManagerSelection(NULL, NULL); } } //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_ManualToolSelectionBox2D->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::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_ManualToolSelectionBox2D->GetToolManager()->GetWorkingData(0); // if( workingData.IsNotNull() ) // { // m_Controls->segImageSelector->setCurrentIndex( m_Controls->segImageSelector->Find(workingData) ); // } // } // // 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_ManualToolSelectionBox2D->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::OnPatientComboBoxSelectionChanged( const mitk::DataNode* node ) { //mitk::DataNode* selectedNode = const_cast(node); if( node != NULL ) { this->UpdateWarningLabel(""); mitk::DataNode* segNode = m_Controls->segImageSelector->GetSelectedNode(); if (segNode) { mitk::DataStorage::SetOfObjects::ConstPointer possibleParents = this->GetDefaultDataStorage()->GetSources( segNode, m_IsNotABinaryImagePredicate ); bool isSourceNode(false); for (mitk::DataStorage::SetOfObjects::ConstIterator it = possibleParents->Begin(); it != possibleParents->End(); it++) { if (it.Value() == node) isSourceNode = true; } if ( !isSourceNode && (!this->CheckForSameGeometry(segNode, node) || possibleParents->Size() > 0 )) { this->SetToolManagerSelection(node, NULL); this->UpdateWarningLabel("The selected patient image does not\nmatch with the selected segmentation!"); } else if ((!isSourceNode && this->CheckForSameGeometry(segNode, node)) || isSourceNode ) { this->SetToolManagerSelection(node, segNode); //Doing this we can assure that the segmenation is always visible if the segmentation and the patient image are //loaded separately int layer(10); node->GetIntProperty("layer", layer); layer++; segNode->SetProperty("layer", mitk::IntProperty::New(layer)); this->UpdateWarningLabel(""); } } else { this->SetToolManagerSelection(node, NULL); this->UpdateWarningLabel("Select or create a segmentation"); } } else { this->UpdateWarningLabel("Please load an image!"); } } void QmitkSegmentationView::OnSegmentationComboBoxSelectionChanged(const mitk::DataNode *node) { if ( node == 0) return; mitk::DataNode* refNode = m_Controls->patImageSelector->GetSelectedNode(); if (m_AutoSelectionEnabled) { this->OnSelectionChanged(const_cast(node)); } else { mitk::DataStorage::SetOfObjects::ConstPointer possibleParents = this->GetDefaultDataStorage()->GetSources( node, m_IsNotABinaryImagePredicate ); if ( possibleParents->Size() == 1 ) { mitk::DataNode* parentNode = possibleParents->ElementAt(0); if (parentNode != refNode) { this->UpdateWarningLabel("The selected segmentation does not\nmatch with the selected patient image!"); this->SetToolManagerSelection(NULL, node); } else { this->UpdateWarningLabel(""); this->SetToolManagerSelection(refNode, node); } } else if (refNode && this->CheckForSameGeometry(node, refNode)) { this->UpdateWarningLabel(""); this->SetToolManagerSelection(refNode, node); } else if (!refNode || !this->CheckForSameGeometry(node, refNode)) { this->UpdateWarningLabel("Please select or load the according patient image!"); } } } void QmitkSegmentationView::OnShowMarkerNodes (bool state) { mitk::SegTool2D::Pointer manualSegmentationTool; unsigned int numberOfExistingTools = m_Controls->m_ManualToolSelectionBox2D->GetToolManager()->GetTools().size(); for(unsigned int i = 0; i < numberOfExistingTools; i++) { manualSegmentationTool = dynamic_cast(m_Controls->m_ManualToolSelectionBox2D->GetToolManager()->GetToolById(i)); if (manualSegmentationTool) { if(state == true) { manualSegmentationTool->SetShowMarkerNodes( true ); } else { manualSegmentationTool->SetShowMarkerNodes( 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->patImageSelector->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 (m_AutoSelectionEnabled && this->IsActivated()) { if (nodes.size() == 0 && m_Controls->patImageSelector->GetSelectedNode().IsNull()) { SetToolManagerSelection(NULL,NULL); } else if (nodes.size() == 1) { mitk::DataNode::Pointer selectedNode = nodes.at(0); if(selectedNode.IsNull()) { return; } std::string markerName = "Position"; unsigned int numberOfNodes = nodes.size(); std::string nodeName = nodes.at( 0 )->GetName(); if ( ( numberOfNodes == 1 ) && ( nodeName.find( markerName ) == 0) ) { this->OnContourMarkerSelected( nodes.at( 0 ) ); return; } mitk::Image::Pointer selectedImage = dynamic_cast(selectedNode->GetData()); if (selectedImage.IsNull()) { SetToolManagerSelection(NULL,NULL); return; } else { bool isASegmentation(false); selectedNode->GetBoolProperty("binary", isASegmentation); if (isASegmentation) { //If a segmentation is selected find a possible reference image: mitk::DataStorage::SetOfObjects::ConstPointer sources = this->GetDataStorage()->GetSources(selectedNode, m_IsNotABinaryImagePredicate); mitk::DataNode::Pointer refNode; if (sources->Size() != 0) { refNode = sources->ElementAt(0); refNode->SetVisibility(true); selectedNode->SetVisibility(true); SetToolManagerSelection(refNode,selectedNode); mitk::DataStorage::SetOfObjects::ConstPointer otherSegmentations = this->GetDataStorage()->GetSubset(m_IsABinaryImagePredicate); for(mitk::DataStorage::SetOfObjects::const_iterator iter = otherSegmentations->begin(); iter != otherSegmentations->end(); ++iter) { mitk::DataNode* node = *iter; if (dynamic_cast(node->GetData()) != selectedImage.GetPointer()) node->SetVisibility(false); } mitk::DataStorage::SetOfObjects::ConstPointer otherPatientImages = this->GetDataStorage()->GetSubset(m_IsNotABinaryImagePredicate); for(mitk::DataStorage::SetOfObjects::const_iterator iter = otherPatientImages->begin(); iter != otherPatientImages->end(); ++iter) { mitk::DataNode* node = *iter; if (dynamic_cast(node->GetData()) != dynamic_cast(refNode->GetData())) node->SetVisibility(false); } } else { mitk::DataStorage::SetOfObjects::ConstPointer possiblePatientImages = this->GetDataStorage()->GetSubset(m_IsNotABinaryImagePredicate); for (mitk::DataStorage::SetOfObjects::ConstIterator it = possiblePatientImages->Begin(); it != possiblePatientImages->End(); it++) { refNode = it->Value(); if (this->CheckForSameGeometry(selectedNode, it->Value())) { refNode->SetVisibility(true); selectedNode->SetVisibility(true); mitk::DataStorage::SetOfObjects::ConstPointer otherSegmentations = this->GetDataStorage()->GetSubset(m_IsABinaryImagePredicate); for(mitk::DataStorage::SetOfObjects::const_iterator iter = otherSegmentations->begin(); iter != otherSegmentations->end(); ++iter) { mitk::DataNode* node = *iter; if (dynamic_cast(node->GetData()) != selectedImage.GetPointer()) node->SetVisibility(false); } mitk::DataStorage::SetOfObjects::ConstPointer otherPatientImages = this->GetDataStorage()->GetSubset(m_IsNotABinaryImagePredicate); for(mitk::DataStorage::SetOfObjects::const_iterator iter = otherPatientImages->begin(); iter != otherPatientImages->end(); ++iter) { mitk::DataNode* node = *iter; if (dynamic_cast(node->GetData()) != dynamic_cast(refNode->GetData())) node->SetVisibility(false); } this->SetToolManagerSelection(refNode, selectedNode); //Doing this we can assure that the segmenation is always visible if the segmentation and the patient image are at the //same level in the datamanager int layer(10); refNode->GetIntProperty("layer", layer); layer++; selectedNode->SetProperty("layer", mitk::IntProperty::New(layer)); return; } } this->SetToolManagerSelection(NULL, selectedNode); } } else { if (m_Controls->m_ManualToolSelectionBox2D->GetToolManager()->GetReferenceData(0) != selectedNode) { SetToolManagerSelection(selectedNode, NULL); //May be a bug in the selection services. A node which is deselected will be passed as selected node to the OnSelectionChanged function if (!selectedNode->IsVisible(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1")))) selectedNode->SetVisibility(true); this->UpdateWarningLabel("The selected patient image does not\nmatchwith the selected segmentation!"); } } } } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkSegmentationView::OnContourMarkerSelected(const mitk::DataNode *node) { 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) { std::string nodeName = node->GetName(); unsigned int t = nodeName.find_last_of(" "); unsigned int id = atof(nodeName.substr(t+1).c_str())-1; // gets the context of the "Mitk" (Core) module (always has id 1) // TODO Workaround until CTL plugincontext is available mitk::ModuleContext* context = mitk::ModuleRegistry::GetModule(1)->GetModuleContext(); // Workaround end mitk::ServiceReference serviceRef = context->GetServiceReference(); mitk::PlanePositionManagerService* service = dynamic_cast(context->GetService(serviceRef)); selectedRenderWindow->GetSliceNavigationController()->ExecuteOperation(service->GetPlanePosition(id)); selectedRenderWindow->GetRenderer()->GetDisplayGeometry()->Fit(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkSegmentationView::OnTabWidgetChanged(int id) { //2D Tab ID = 0 //3D Tab ID = 1 if (id == 0) { //Deactivate possible active tool m_Controls->m_ManualToolSelectionBox2D->GetToolManager()->ActivateTool(-1); //TODO Remove possible visible interpolations -> Maybe changes in SlicesInterpolator } } 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_ManualToolSelectionBox2D->GetToolManager(); toolManager->SetReferenceData(const_cast(referenceData)); toolManager->SetWorkingData( const_cast(workingData)); // check original image m_Controls->btnNewSegmentation->setEnabled(referenceData != NULL); if (referenceData) { this->UpdateWarningLabel(""); disconnect( m_Controls->patImageSelector, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ), this, SLOT( OnPatientComboBoxSelectionChanged( const mitk::DataNode* ) ) ); m_Controls->patImageSelector->setCurrentIndex( m_Controls->patImageSelector->Find(referenceData) ); connect( m_Controls->patImageSelector, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ), this, SLOT( OnPatientComboBoxSelectionChanged( const mitk::DataNode* ) ) ); } // check segmentation if (referenceData) { if (workingData) { this->FireNodeSelected(const_cast(workingData)); // mitk::RenderingManager::GetInstance()->InitializeViews(workingData->GetData()->GetTimeSlicedGeometry(), // mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); // if( m_Controls->widgetStack->currentIndex() == 0 ) // { disconnect( m_Controls->segImageSelector, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ), this, SLOT( OnSegmentationComboBoxSelectionChanged( const mitk::DataNode* ) ) ); m_Controls->segImageSelector->setCurrentIndex(m_Controls->segImageSelector->Find(workingData)); connect( m_Controls->segImageSelector, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ), this, SLOT( OnSegmentationComboBoxSelectionChanged(const mitk::DataNode*)) ); // } } } } 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) ) ); } } bool QmitkSegmentationView::CheckForSameGeometry(const mitk::DataNode *node1, const mitk::DataNode *node2) const { bool isSameGeometry(true); mitk::Image* image1 = dynamic_cast(node1->GetData()); mitk::Image* image2 = dynamic_cast(node2->GetData()); if (image1 && image2) { mitk::Geometry3D* geo1 = image1->GetGeometry(); mitk::Geometry3D* geo2 = image2->GetGeometry(); isSameGeometry = isSameGeometry && mitk::Equal(geo1->GetOrigin(), geo2->GetOrigin()); isSameGeometry = isSameGeometry && mitk::Equal(geo1->GetExtent(0), geo2->GetExtent(0)); isSameGeometry = isSameGeometry && mitk::Equal(geo1->GetExtent(1), geo2->GetExtent(1)); isSameGeometry = isSameGeometry && mitk::Equal(geo1->GetExtent(2), geo2->GetExtent(2)); isSameGeometry = isSameGeometry && mitk::Equal(geo1->GetSpacing(), geo2->GetSpacing()); isSameGeometry = isSameGeometry && mitk::MatrixEqualElementWise(geo1->GetIndexToWorldTransform()->GetMatrix(), geo2->GetIndexToWorldTransform()->GetMatrix()); return isSameGeometry; } else { return false; } } void QmitkSegmentationView::UpdateWarningLabel(QString text) { if (text.size() == 0) m_Controls->lblSegmentationWarnings->hide(); else m_Controls->lblSegmentationWarnings->show(); m_Controls->lblSegmentationWarnings->setText(text); } 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->patImageSelector->SetDataStorage(this->GetDefaultDataStorage()); m_Controls->patImageSelector->SetPredicate(m_IsNotABinaryImagePredicate); this->UpdateWarningLabel("Please load an image"); if( m_Controls->patImageSelector->GetSelectedNode().IsNotNull() ) this->UpdateWarningLabel("Select or create a new segmentation"); m_Controls->segImageSelector->SetDataStorage(this->GetDefaultDataStorage()); m_Controls->segImageSelector->SetPredicate(m_IsABinaryImagePredicate); if( m_Controls->segImageSelector->GetSelectedNode().IsNotNull() ) this->UpdateWarningLabel(""); mitk::ToolManager* toolManager = m_Controls->m_ManualToolSelectionBox2D->GetToolManager(); toolManager->SetDataStorage( *(this->GetDefaultDataStorage()) ); assert ( toolManager ); //use the same ToolManager instance for our 3D Tools m_Controls->m_ManualToolSelectionBox3D->SetToolManager(*toolManager); // all part of open source MITK m_Controls->m_ManualToolSelectionBox2D->SetGenerateAccelerators(true); m_Controls->m_ManualToolSelectionBox2D->SetToolGUIArea( m_Controls->m_ManualToolGUIContainer2D ); m_Controls->m_ManualToolSelectionBox2D->SetDisplayedToolGroups("Add Subtract Correction Paint Wipe 'Region Growing' Fill Erase 'Live Wire' 'Fast Marching'"); m_Controls->m_ManualToolSelectionBox2D->SetLayoutColumns(3); m_Controls->m_ManualToolSelectionBox2D->SetEnabledMode( QmitkToolSelectionBox::EnabledWithReferenceAndWorkingDataVisible ); connect( m_Controls->m_ManualToolSelectionBox2D, SIGNAL(ToolSelected(int)), this, SLOT(OnManualTool2DSelected(int)) ); //setup 3D Tools m_Controls->m_ManualToolSelectionBox3D->SetGenerateAccelerators(true); m_Controls->m_ManualToolSelectionBox3D->SetToolGUIArea( m_Controls->m_ManualToolGUIContainer3D ); //specify tools to be added to 3D Tool area m_Controls->m_ManualToolSelectionBox3D->SetDisplayedToolGroups("Threshold 'Two Thresholds' Otsu FastMarching3D RegionGrowing Watershedding"); m_Controls->m_ManualToolSelectionBox3D->SetLayoutColumns(2); m_Controls->m_ManualToolSelectionBox3D->SetEnabledMode( QmitkToolSelectionBox::EnabledWithReferenceAndWorkingDataVisible ); // 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->patImageSelector, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ), this, SLOT( OnPatientComboBoxSelectionChanged( const mitk::DataNode* ) ) ); connect( m_Controls->segImageSelector, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ), this, SLOT( OnSegmentationComboBoxSelectionChanged( const mitk::DataNode* ) ) ); connect( m_Controls->btnNewSegmentation, SIGNAL(clicked()), this, SLOT(CreateNewSegmentation()) ); // connect( m_Controls->CreateSegmentationFromSurface, SIGNAL(clicked()), this, SLOT(CreateSegmentationFromSurface()) ); // connect( m_Controls->widgetStack, SIGNAL(currentChanged(int)), this, SLOT(ToolboxStackPageChanged(int)) ); connect( m_Controls->tabWidgetSegmentationTools, SIGNAL(currentChanged(int)), this, SLOT(OnTabWidgetChanged(int))); // connect(m_Controls->MaskSurfaces, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ), // this, SLOT( OnSurfaceSelectionChanged( ) ) ); connect(m_Controls->m_SlicesInterpolator, SIGNAL(SignalShowMarkerNodes(bool)), this, SLOT(OnShowMarkerNodes(bool))); connect(m_Controls->m_SlicesInterpolator, SIGNAL(Signal3DInterpolationEnabled(bool)), this, SLOT(On3DInterpolationEnabled(bool))); // m_Controls->MaskSurfaces->SetDataStorage(this->GetDefaultDataStorage()); // m_Controls->MaskSurfaces->SetPredicate(mitk::NodePredicateDataType::New("Surface")); } void QmitkSegmentationView::OnManualTool2DSelected(int id) { if (id >= 0) { std::string text = "Active Tool: \""; mitk::ToolManager* toolManager = m_Controls->m_ManualToolSelectionBox2D->GetToolManager(); text += toolManager->GetToolById(id)->GetName(); text += "\""; mitk::StatusBar::GetInstance()->DisplayText(text.c_str()); - std::string iconPath = toolManager->GetToolById(id)->GetCursorIconPath(); - - if (iconPath.empty()) - this->ResetMouseCursor(); - else - this->SetMouseCursor( iconPath, 0, 0 ); + mitk::ModuleResource resource = toolManager->GetToolById(id)->GetCursorIconResource(); + this->SetMouseCursor(resource, 0, 0); } else { this->ResetMouseCursor(); mitk::StatusBar::GetInstance()->DisplayText(""); } } void QmitkSegmentationView::ResetMouseCursor() { if ( m_MouseCursorSet ) { mitk::ApplicationCursor::GetInstance()->PopCursor(); m_MouseCursorSet = false; } } -void QmitkSegmentationView::SetMouseCursor( const std::string& path, int hotspotX, int hotspotY ) +void QmitkSegmentationView::SetMouseCursor( const mitk::ModuleResource resource, int hotspotX, int hotspotY ) { // Remove previously set mouse cursor if ( m_MouseCursorSet ) { mitk::ApplicationCursor::GetInstance()->PopCursor(); } - mitk::ApplicationCursor::GetInstance()->PushCursor( path, hotspotX, hotspotY ); + mitk::ApplicationCursor::GetInstance()->PushCursor( resource, hotspotX, hotspotY ); m_MouseCursorSet = true; } // ATTENTION some methods for handling the known list of (organ names, colors) are defined in QmitkSegmentationOrganNamesHandling.cpp diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.h b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.h index 669ad9c21a..16cf39a985 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.h +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.h @@ -1,184 +1,184 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkSegmentationView_h #define QmitkSegmentationView_h #include "QmitkFunctionality.h" #include #include "ui_QmitkSegmentationControls.h" class QmitkRenderWindow; /** * \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(); typedef std::map NodeTagMapType; /*! \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(); virtual void Visible(); // 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* prefs); // observer to mitk::RenderingManager's RenderingManagerViewsInitializedEvent event void RenderingManagerReinitialized(const itk::EventObject&); // observer to mitk::SliceController's SliceRotation event void SliceRotation(const itk::EventObject&); static const std::string VIEW_ID; protected slots: void OnPatientComboBoxSelectionChanged(const mitk::DataNode* node); void OnSegmentationComboBoxSelectionChanged(const mitk::DataNode* node); // reaction to the button "New segmentation" void CreateNewSegmentation(); void OnManualTool2DSelected(int id); // reaction to the button "New segmentation" // void CreateSegmentationFromSurface(); // called when one of "Manual", "Organ", "Lesion" pages of the QToolbox is selected // void ToolboxStackPageChanged(int id); // void OnSurfaceSelectionChanged(); void OnWorkingNodeVisibilityChanged(); // called if a node's binary property has changed void OnBinaryPropertyChanged(); void OnShowMarkerNodes(bool); void OnTabWidgetChanged(int); 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 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); void ResetMouseCursor( ); - void SetMouseCursor( const std::string&, int hotspotX, int hotspotY ); + void SetMouseCursor(const mitk::ModuleResource, int hotspotX, int hotspotY ); bool m_MouseCursorSet; // 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); void NodeRemoved(const mitk::DataNode* node); void NodeAdded(const mitk::DataNode *node); bool CheckForSameGeometry(const mitk::DataNode*, const mitk::DataNode*) const; void UpdateWarningLabel(QString text/*, bool overwriteExistingText = true*/); // 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; unsigned long m_VisibilityChangedObserverTag; bool m_DataSelectionChanged; NodeTagMapType m_WorkingDataObserverTags; NodeTagMapType m_BinaryPropertyObserverTags; bool m_AutoSelectionEnabled; mitk::NodePredicateOr::Pointer m_IsOfTypeImagePredicate; mitk::NodePredicateProperty::Pointer m_IsBinaryPredicate; mitk::NodePredicateNot::Pointer m_IsNotBinaryPredicate; mitk::NodePredicateAnd::Pointer m_IsNotABinaryImagePredicate; mitk::NodePredicateAnd::Pointer m_IsABinaryImagePredicate; }; #endif /*QMITKsegmentationVIEW_H_*/