diff --git a/Documentation/Doxygen/2-UserManual/MITKPluginGeneralManualsList.dox b/Documentation/Doxygen/2-UserManual/MITKPluginGeneralManualsList.dox
index 1b37183912..1621c5b272 100644
--- a/Documentation/Doxygen/2-UserManual/MITKPluginGeneralManualsList.dox
+++ b/Documentation/Doxygen/2-UserManual/MITKPluginGeneralManualsList.dox
@@ -1,32 +1,32 @@
/**
\page PluginListGeneralPage List of General Purpose Plugins
\li \subpage org_mitk_views_basicimageprocessing
\li \subpage org_mitk_views_datamanager
\li \subpage org_mitk_views_properties
- \li \subpage org_mitk_gui_qt_dicom
+ \li \subpage org_mitk_editors_dicombrowser
\li \subpage org_mitk_gui_qt_dicominspector
- \li \subpage org_mitk_gui_qt_imagecropper
+ \li \subpage org_mitk_views_imagecropper
\li \subpage org_mitk_views_imagenavigator
\li \subpage org_blueberry_views_logview
\li \subpage org_mitk_gui_qt_matchpoint_algorithm_batch
\li \subpage org_mitk_gui_qt_matchpoint_algorithm_browser
\li \subpage org_mitk_gui_qt_matchpoint_algorithm_control
\li \subpage org_mitk_gui_qt_matchpoint_evaluator
\li \subpage org_mitk_gui_qt_matchpoint_framereg
\li \subpage org_mitk_gui_qt_matchpoint_manipulator
\li \subpage org_mitk_gui_qt_matchpoint_mapper
\li \subpage org_mitk_gui_qt_matchpoint_visualizer
\li \subpage org_mitk_gui_qt_measurementtoolbox
\li \subpage org_mitk_views_moviemaker
\li \subpage org_mitk_views_multilabelsegmentation
\li \subpage org_mitk_views_pointsetinteraction
\li \subpage org_mitk_gui_qt_python
\li \subpage org_mitk_gui_qt_remeshing
\li \subpage org_mitk_views_screenshotmaker
\li \subpage org_mitk_views_segmentation
\li \subpage org_mitk_gui_qt_flow_segmentation
\li \subpage org_mitk_gui_qt_viewnavigator
\li \subpage org_mitk_views_volumevisualization
*/
diff --git a/Documentation/Doxygen/2-UserManual/MITKPluginManualsList.dox b/Documentation/Doxygen/2-UserManual/MITKPluginManualsList.dox
index 89a86430bf..e191939e7c 100644
--- a/Documentation/Doxygen/2-UserManual/MITKPluginManualsList.dox
+++ b/Documentation/Doxygen/2-UserManual/MITKPluginManualsList.dox
@@ -1,84 +1,84 @@
/**
\page PluginListPage MITK Plugin Manuals
The plugins and bundles provide much of the extended functionality of MITK. Each encapsulates a solution to a problem and associated features. This way one can easily assemble the necessary capabilites for a workflow without adding a lot of bloat, by combining plugins as needed.
\subpage PluginListGeneralPage
- \ref org_mitk_views_basicimageprocessing
- \ref org_mitk_views_datamanager
- - \ref org_mitk_gui_qt_dicombrowser
+ - \ref org_mitk_editors_dicombrowser
- \ref org_mitk_gui_qt_dicominspector
- \ref org_mitk_gui_qt_flowapplication
- - \ref org_mitk_gui_qt_imagecropper
+ - \ref org_mitk_views_imagecropper
- \ref org_mitk_views_imagenavigator
- \ref org_blueberry_views_logview
- \ref org_mitk_gui_qt_matchpoint_algorithm_browser
- \ref org_mitk_gui_qt_matchpoint_algorithm_control
- \ref org_mitk_gui_qt_matchpoint_evaluator
- \ref org_mitk_gui_qt_matchpoint_framereg
- \ref org_mitk_gui_qt_matchpoint_manipulator
- \ref org_mitk_gui_qt_matchpoint_mapper
- \ref org_mitk_gui_qt_matchpoint_visualizer
- \ref org_mitk_gui_qt_measurementtoolbox
- \ref org_mitk_views_moviemaker
- \ref org_mitk_views_multilabelsegmentation
- \ref org_mitk_views_pointsetinteraction
- \ref org_mitk_gui_qt_python
- \ref org_mitk_gui_qt_remeshing
- \ref org_mitk_views_screenshotmaker
- \ref org_mitk_views_segmentation
- \ref org_mitk_gui_qt_flow_segmentation
- \ref org_mitk_gui_qt_viewnavigator
- \ref org_mitk_views_volumevisualization
\subpage PluginListSpecificPage
- \ref org_mitk_views_properties
- \ref org_mitk_gui_qt_aicpregistration
- \ref org_mitk_gui_qt_cest
- \ref org_mitk_gui_qt_classificationsegmentation
- \ref org_mitk_views_cmdlinemodules
- \ref org_mitk_gui_qt_pharmacokinetics_concentration_mri
- - \ref org_mitk_gui_qt_pharmacokinetics_mri
+ - \ref org_mitk_views_pharmacokinetics_mri
- \ref org_mitk_gui_qt_pharmacokinetics_pet
- \ref org_mitk_gui_qt_eventrecorder
- \ref org_mitk_gui_qt_examples
- \ref org_mitk_gui_qt_geometrytools
- \ref org_mitk_gui_qt_igtexample
- \ref org_mitk_gui_qt_igtlplugin
- \ref org_mitk_gui_qt_igttracking
- \ref org_mitk_gui_qt_igttrackingsemiautomaticmeasurement
- \ref org_mitk_views_imagestatistics
- \ref org_mitk_gui_qt_lasercontrol
- \ref org_mitk_gui_qt_fit_demo
- \ref org_mitk_gui_qt_fit_genericfitting
- \ref org_mitk_gui_qt_fit_inspector
- \ref org_mitkexamplesopencv
- \ref org_mitk_gui_qt_overlaymanager
- \ref org_mitk_gui_qt_mitkphenotyping
- \ref org_mitk_gui_qt_photoacoustics_pausmotioncompensation
- \ref org_mitk_example_gui_pcaexample
- \ref org_mitk_gui_qt_preprocessing_resampling
- \ref org_mitk_gui_qt_pharmacokinetics_curvedescriptor
- \ref org_mitk_gui_qt_photoacoustics_imageprocessing
- \ref org_mitk_gui_qt_pharmacokinetics_simulation
- \ref org_mitk_gui_qt_pointsetinteractionmultispectrum
- \ref org_mitk_gui_qt_renderwindowmanager
- \ref org_mitk_gui_qt_photoacoustics_spectralunmixing
- \ref org_mitk_gui_qt_spectrocamrecorder
- \ref org_surfacematerialeditor
- \ref org_toftutorial
- \ref org_blueberry_ui_qt_objectinspector
- \ref org_mitk_gui_qt_ultrasound
- \ref org_mitk_gui_qt_igt_app_echotrack
- \ref org_mitk_gui_qt_xnat
*/
diff --git a/Documentation/Doxygen/2-UserManual/MITKPluginSpecificManualsList.dox b/Documentation/Doxygen/2-UserManual/MITKPluginSpecificManualsList.dox
index 1edb2f4d54..8be8a5f620 100644
--- a/Documentation/Doxygen/2-UserManual/MITKPluginSpecificManualsList.dox
+++ b/Documentation/Doxygen/2-UserManual/MITKPluginSpecificManualsList.dox
@@ -1,45 +1,45 @@
/**
\page PluginListSpecificPage List of Application-specific Plugins
\li \subpage org_mitk_gui_qt_aicpregistration
\li \subpage org_mitk_gui_qt_cest
\li \subpage org_mitk_gui_qt_classificationsegmentation
\li \subpage org_mitk_gui_qt_flowapplication
\li \subpage org_mitk_views_cmdlinemodules
\li \subpage org_mitk_gui_qt_pharmacokinetics_concentration_mri
- \li \subpage org_mitk_gui_qt_pharmacokinetics_mri
+ \li \subpage org_mitk_views_pharmacokinetics_mri
\li \subpage org_mitk_gui_qt_pharmacokinetics_pet
\li \subpage org_mitk_gui_qt_eventrecorder
\li \subpage org_mitk_gui_qt_examples
\li \subpage org_mitk_gui_qt_geometrytools
\li \subpage org_mitk_gui_qt_igtexample
\li \subpage org_mitk_gui_qt_igtlplugin
\li \subpage org_mitk_gui_qt_igttracking
\li \subpage org_mitk_gui_qt_igttrackingsemiautomaticmeasurement
\li \subpage org_mitk_views_imagestatistics
\li \subpage org_mitk_gui_qt_lasercontrol
\li \subpage org_mitk_gui_qt_fit_demo
\li \subpage org_mitk_gui_qt_fit_genericfitting
\li \subpage org_mitk_gui_qt_fit_inspector
\li \subpage org_mitkexamplesopencv
\li \subpage org_mitk_gui_qt_overlaymanager
\li \subpage org_mitk_gui_qt_mitkphenotyping
\li \subpage org_mitk_gui_qt_photoacoustics_pausmotioncompensation
\li \subpage org_mitk_example_gui_pcaexample
\li \subpage org_mitk_gui_qt_preprocessing_resampling
\li \subpage org_mitk_gui_qt_pharmacokinetics_curvedescriptor
\li \subpage org_mitk_gui_qt_photoacoustics_imageprocessing
\li \subpage org_mitk_gui_qt_pharmacokinetics_simulation
\li \subpage org_mitk_gui_qt_pointsetinteractionmultispectrum
\li \subpage org_mitk_gui_qt_renderwindowmanager
\li \subpage org_mitk_gui_qt_photoacoustics_spectralunmixing
\li \subpage org_mitk_gui_qt_spectrocamrecorder
\li \subpage org_surfacematerialeditor
\li \subpage org_blueberry_ui_qt_objectinspector
\li \subpage org_toftutorial
\li \subpage org_mitk_gui_qt_ultrasound
\li \subpage org_mitk_gui_qt_igt_app_echotrack
\li \subpage org_mitk_gui_qt_xnat
*/
\ No newline at end of file
diff --git a/Modules/PlanarFigure/include/mitkPlanarFigureInteractor.h b/Modules/PlanarFigure/include/mitkPlanarFigureInteractor.h
index 69a7cf348b..6a22193017 100644
--- a/Modules/PlanarFigure/include/mitkPlanarFigureInteractor.h
+++ b/Modules/PlanarFigure/include/mitkPlanarFigureInteractor.h
@@ -1,201 +1,197 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
-#ifndef MITKPLANARFIGUREINTERACTOR_H_HEADER_INCLUDED
-#define MITKPLANARFIGUREINTERACTOR_H_HEADER_INCLUDED
+#ifndef MITKPLANARFIGUREINTERACTOR_H
+#define MITKPLANARFIGUREINTERACTOR_H
#include
#include "mitkCommon.h"
#include "mitkDataInteractor.h"
#include "mitkNumericTypes.h"
#pragma GCC visibility push(default)
#include
#pragma GCC visibility pop
namespace mitk
{
class DataNode;
class PlaneGeometry;
class PlanarFigure;
class PositionEvent;
class BaseRenderer;
class InteractionPositionEvent;
class StateMachineAction;
#pragma GCC visibility push(default)
// Define events for PlanarFigure interaction notifications
itkEventMacro(PlanarFigureEvent, itk::AnyEvent);
itkEventMacro(StartPlacementPlanarFigureEvent, PlanarFigureEvent);
itkEventMacro(EndPlacementPlanarFigureEvent, PlanarFigureEvent);
itkEventMacro(SelectPlanarFigureEvent, PlanarFigureEvent);
itkEventMacro(StartInteractionPlanarFigureEvent, PlanarFigureEvent);
itkEventMacro(EndInteractionPlanarFigureEvent, PlanarFigureEvent);
itkEventMacro(StartHoverPlanarFigureEvent, PlanarFigureEvent);
itkEventMacro(EndHoverPlanarFigureEvent, PlanarFigureEvent);
itkEventMacro(ContextMenuPlanarFigureEvent, PlanarFigureEvent);
#pragma GCC visibility pop
/**
* \brief Interaction with mitk::PlanarFigure objects via control-points
*
* @ingroup MitkPlanarFigureModule
*/
class MITKPLANARFIGURE_EXPORT PlanarFigureInteractor : public DataInteractor
{
public:
mitkClassMacro(PlanarFigureInteractor, DataInteractor);
itkFactorylessNewMacro(Self);
itkCloneMacro(Self);
- /** \brief Sets the amount of precision */
- void SetPrecision(ScalarType precision);
+ /** \brief Sets the amount of precision */
+ void SetPrecision(ScalarType precision);
/** \brief Sets the minimal distance between two control points. */
void SetMinimumPointDistance(ScalarType minimumDistance);
protected:
PlanarFigureInteractor();
~PlanarFigureInteractor() override;
void ConnectActionsAndFunctions() override;
//////// Conditions ////////
bool CheckFigurePlaced(const InteractionEvent *interactionEvent);
bool CheckFigureHovering(const InteractionEvent *interactionEvent);
bool CheckControlPointHovering(const InteractionEvent *interactionEvent);
bool CheckSelection(const InteractionEvent *interactionEvent);
bool CheckPointValidity(const InteractionEvent *interactionEvent);
bool CheckFigureFinished(const InteractionEvent *interactionEvent);
bool CheckResetOnPointSelect(const InteractionEvent *interactionEvent);
bool CheckFigureOnRenderingGeometry(const InteractionEvent *interactionEvent);
bool CheckMinimalFigureFinished(const InteractionEvent *interactionEvent);
bool CheckFigureIsExtendable(const InteractionEvent *interactionEvent);
bool CheckFigureIsDeletable(const InteractionEvent *interactionEvent);
bool CheckFigureIsEditable(const InteractionEvent *interactionEvent);
//////// Actions ////////
void FinalizeFigure(StateMachineAction *, InteractionEvent *interactionEvent);
void MoveCurrentPoint(StateMachineAction *, InteractionEvent *interactionEvent);
void DeselectPoint(StateMachineAction *, InteractionEvent *interactionEvent);
void AddPoint(StateMachineAction *, InteractionEvent *interactionEvent);
void AddInitialPoint(StateMachineAction *, InteractionEvent *interactionEvent);
void StartHovering(StateMachineAction *, InteractionEvent *interactionEvent);
void EndHovering(StateMachineAction *, InteractionEvent *interactionEvent);
void DeleteFigure(StateMachineAction *, InteractionEvent *interactionEvent);
void PerformPointResetOnSelect(StateMachineAction *, InteractionEvent *interactionEvent);
void SetPreviewPointPosition(StateMachineAction *, InteractionEvent *interactionEvent);
void HidePreviewPoint(StateMachineAction *, InteractionEvent *interactionEvent);
void HideControlPoints(StateMachineAction *, InteractionEvent *interactionEvent);
void RemoveSelectedPoint(StateMachineAction *, InteractionEvent *interactionEvent);
void RequestContextMenu(StateMachineAction *, InteractionEvent *interactionEvent);
void SelectFigure(StateMachineAction *, InteractionEvent *interactionEvent);
void SelectPoint(StateMachineAction *, InteractionEvent *interactionEvent);
void EndInteraction(StateMachineAction *, InteractionEvent *interactionEvent);
bool FilterEvents(InteractionEvent *interactionEvent, DataNode *) override;
/**
\brief Used when clicking to determine if a point is too close to the previous point.
*/
bool IsMousePositionAcceptableAsNewControlPoint(const mitk::InteractionPositionEvent *positionEvent,
const PlanarFigure *);
bool TransformPositionEventToPoint2D(const InteractionPositionEvent *positionEvent,
const PlaneGeometry *planarFigureGeometry,
Point2D &point2D);
bool TransformObjectToDisplay(const mitk::Point2D &point2D,
mitk::Point2D &displayPoint,
const mitk::PlaneGeometry *objectGeometry,
const mitk::PlaneGeometry *rendererGeometry,
const mitk::BaseRenderer *renderer) const;
/** \brief Returns true if the first specified point is in proximity of the line defined
* the other two point; false otherwise.
*
* Proximity is defined as the rectangle around the line with pre-defined distance
* from the line. */
bool IsPointNearLine(const mitk::Point2D &point,
const mitk::Point2D &startPoint,
const mitk::Point2D &endPoint,
mitk::Point2D &projectedPoint) const;
/** \brief Returns true if the point contained in the passed event (in display coordinates)
* is over the planar figure (with a pre-defined tolerance range); false otherwise. */
int IsPositionOverFigure(const InteractionPositionEvent *positionEvent,
PlanarFigure *planarFigure,
const PlaneGeometry *planarFigureGeometry,
const PlaneGeometry *rendererGeometry,
Point2D &pointProjectedOntoLine) const;
/** \brief Returns the index of the marker (control point) over which the point contained
* in the passed event (in display coordinates) currently is; -1 if the point is not over
* a marker. */
int IsPositionInsideMarker(const InteractionPositionEvent *positionEvent,
const PlanarFigure *planarFigure,
const PlaneGeometry *planarFigureGeometry,
const PlaneGeometry *rendererGeometry,
const BaseRenderer *renderer) const;
void LogPrintPlanarFigureQuantities(const PlanarFigure *planarFigure);
void ConfigurationChanged() override;
private:
/** \brief to store the value of precision to pick a point */
ScalarType m_Precision;
/** \brief Store the minimal distance between two control points. */
ScalarType m_MinimumPointDistance;
/** \brief True if the mouse is currently hovering over the image. */
bool m_IsHovering;
-
- bool m_LastPointWasValid;
-
- // mitk::PlanarFigure::Pointer m_PlanarFigure;
};
}
-#endif // MITKPLANARFIGUREINTERACTOR_H_HEADER_INCLUDED
+#endif // MITKPLANARFIGUREINTERACTOR_H
diff --git a/Modules/PlanarFigure/src/Interactions/mitkPlanarFigureInteractor.cpp b/Modules/PlanarFigure/src/Interactions/mitkPlanarFigureInteractor.cpp
index 82f60c6d4c..363c3ef628 100644
--- a/Modules/PlanarFigure/src/Interactions/mitkPlanarFigureInteractor.cpp
+++ b/Modules/PlanarFigure/src/Interactions/mitkPlanarFigureInteractor.cpp
@@ -1,949 +1,1113 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#define PLANARFIGUREINTERACTOR_DBG MITK_DEBUG("PlanarFigureInteractor") << __LINE__ << ": "
#include "mitkPlanarFigureInteractor.h"
#include "mitkPlanarBezierCurve.h"
#include "mitkPlanarCircle.h"
#include "mitkPlanarFigure.h"
#include "mitkPlanarPolygon.h"
#include "mitkInteractionPositionEvent.h"
#include "mitkInternalEvent.h"
#include "mitkBaseRenderer.h"
#include "mitkRenderingManager.h"
#include "mitkAbstractTransformGeometry.h"
#include "mitkPlaneGeometry.h"
mitk::PlanarFigureInteractor::PlanarFigureInteractor()
- : DataInteractor(), m_Precision(6.5), m_MinimumPointDistance(25.0), m_IsHovering(false), m_LastPointWasValid(false)
+ : DataInteractor()
+ , m_Precision(6.5)
+ , m_MinimumPointDistance(25.0)
+ , m_IsHovering(false)
{
}
mitk::PlanarFigureInteractor::~PlanarFigureInteractor()
{
}
void mitk::PlanarFigureInteractor::ConnectActionsAndFunctions()
{
CONNECT_CONDITION("figure_is_on_current_slice", CheckFigureOnRenderingGeometry);
CONNECT_CONDITION("figure_is_placed", CheckFigurePlaced);
CONNECT_CONDITION("minimal_figure_is_finished", CheckMinimalFigureFinished);
CONNECT_CONDITION("hovering_above_figure", CheckFigureHovering);
CONNECT_CONDITION("hovering_above_point", CheckControlPointHovering);
CONNECT_CONDITION("figure_is_selected", CheckSelection);
CONNECT_CONDITION("point_is_valid", CheckPointValidity);
CONNECT_CONDITION("figure_is_finished", CheckFigureFinished);
CONNECT_CONDITION("reset_on_point_select_needed", CheckResetOnPointSelect);
CONNECT_CONDITION("points_can_be_added_or_removed", CheckFigureIsExtendable);
CONNECT_CONDITION("figure_can_be_deleted", CheckFigureIsDeletable);
CONNECT_CONDITION("figure_is_editable", CheckFigureIsEditable);
CONNECT_FUNCTION("finalize_figure", FinalizeFigure);
CONNECT_FUNCTION("hide_preview_point", HidePreviewPoint)
CONNECT_FUNCTION("hide_control_points", HideControlPoints)
CONNECT_FUNCTION("set_preview_point_position", SetPreviewPointPosition)
CONNECT_FUNCTION("move_current_point", MoveCurrentPoint);
CONNECT_FUNCTION("deselect_point", DeselectPoint);
CONNECT_FUNCTION("add_new_point", AddPoint);
CONNECT_FUNCTION("add_initial_point", AddInitialPoint);
CONNECT_FUNCTION("remove_selected_point", RemoveSelectedPoint);
CONNECT_FUNCTION("request_context_menu", RequestContextMenu);
CONNECT_FUNCTION("select_figure", SelectFigure);
CONNECT_FUNCTION("select_point", SelectPoint);
CONNECT_FUNCTION("end_interaction", EndInteraction);
CONNECT_FUNCTION("start_hovering", StartHovering)
CONNECT_FUNCTION("end_hovering", EndHovering);
CONNECT_FUNCTION("delete_figure", DeleteFigure);
CONNECT_FUNCTION("reset_on_point_select", PerformPointResetOnSelect);
}
bool mitk::PlanarFigureInteractor::CheckFigurePlaced(const InteractionEvent * /*interactionEvent*/)
{
- const mitk::PlanarFigure *planarFigure = dynamic_cast(GetDataNode()->GetData());
+ auto planarFigure = dynamic_cast(GetDataNode()->GetData());
+ if (nullptr == planarFigure)
+ {
+ return false;
+ }
bool isFigureFinished = false;
planarFigure->GetPropertyList()->GetBoolProperty("initiallyplaced", isFigureFinished);
return planarFigure->IsPlaced() && isFigureFinished;
}
void mitk::PlanarFigureInteractor::MoveCurrentPoint(StateMachineAction *, InteractionEvent *interactionEvent)
{
- auto *positionEvent = dynamic_cast(interactionEvent);
- if (positionEvent == nullptr)
+ auto positionEvent = dynamic_cast(interactionEvent);
+ if (nullptr == positionEvent)
+ {
return;
+ }
bool isEditable = true;
GetDataNode()->GetBoolProperty("planarfigure.iseditable", isEditable);
- auto *planarFigure = dynamic_cast(GetDataNode()->GetData());
+ auto planarFigure = dynamic_cast(GetDataNode()->GetData());
+ if (nullptr == planarFigure)
+ {
+ return;
+ }
- const mitk::PlaneGeometry *planarFigureGeometry = planarFigure->GetPlaneGeometry();
- const mitk::AbstractTransformGeometry *abstractTransformGeometry =
- dynamic_cast(planarFigure->GetGeometry(0));
+ auto planarFigureGeometry = planarFigure->GetPlaneGeometry();
+ if (nullptr == planarFigureGeometry)
+ {
+ return;
+ }
- if (abstractTransformGeometry != nullptr)
+ auto abstractTransformGeometry = dynamic_cast(planarFigure->GetGeometry(0));
+ if (nullptr != abstractTransformGeometry)
+ {
return;
+ }
- // Extract point in 2D world coordinates (relative to PlaneGeometry of
- // PlanarFigure)
+ // Extract point in 2D world coordinates (relative to PlaneGeometry of PlanarFigure)
Point2D point2D;
if (!this->TransformPositionEventToPoint2D(positionEvent, planarFigureGeometry, point2D) || !isEditable)
{
return;
}
planarFigure->InvokeEvent(StartInteractionPlanarFigureEvent());
// check if the control points shall be hidden during interaction
bool hidecontrolpointsduringinteraction = false;
GetDataNode()->GetBoolProperty("planarfigure.hidecontrolpointsduringinteraction", hidecontrolpointsduringinteraction);
// hide the control points if necessary
// interactionEvent->GetSender()->GetDataStorage()->BlockNodeModifiedEvents( true );
GetDataNode()->SetBoolProperty("planarfigure.drawcontrolpoints", !hidecontrolpointsduringinteraction);
// interactionEvent->GetSender()->GetDataStorage()->BlockNodeModifiedEvents( false );
// Move current control point to this point
planarFigure->SetCurrentControlPoint(point2D);
// Re-evaluate features
planarFigure->EvaluateFeatures();
// Update rendered scene
RenderingManager::GetInstance()->RequestUpdateAll();
}
void mitk::PlanarFigureInteractor::FinalizeFigure(StateMachineAction *, InteractionEvent *)
{
- auto *planarFigure = dynamic_cast(GetDataNode()->GetData());
+ auto planarFigure = dynamic_cast(GetDataNode()->GetData());
+ if (nullptr == planarFigure)
+ {
+ return;
+ }
planarFigure->Modified();
planarFigure->DeselectControlPoint();
planarFigure->RemoveLastControlPoint();
planarFigure->SetProperty("initiallyplaced", mitk::BoolProperty::New(true));
GetDataNode()->SetBoolProperty("planarfigure.drawcontrolpoints", true);
GetDataNode()->Modified();
planarFigure->InvokeEvent(EndPlacementPlanarFigureEvent());
planarFigure->InvokeEvent(EndInteractionPlanarFigureEvent());
// Shape might change when figure is finalized, e.g., smoothing of subdivision polygon
planarFigure->EvaluateFeatures();
RenderingManager::GetInstance()->RequestUpdateAll();
}
void mitk::PlanarFigureInteractor::EndInteraction(StateMachineAction *, InteractionEvent *)
{
- auto *planarFigure = dynamic_cast(GetDataNode()->GetData());
+ auto planarFigure = dynamic_cast(GetDataNode()->GetData());
+ if (nullptr == planarFigure)
+ {
+ return;
+ }
+
GetDataNode()->SetBoolProperty("planarfigure.drawcontrolpoints", true);
planarFigure->Modified();
planarFigure->InvokeEvent(EndInteractionPlanarFigureEvent());
RenderingManager::GetInstance()->RequestUpdateAll();
}
bool mitk::PlanarFigureInteractor::FilterEvents(InteractionEvent *interactionEvent, mitk::DataNode * /*dataNode*/)
{
if (interactionEvent->GetSender() == nullptr)
return false;
if (interactionEvent->GetSender()->GetMapperID() == BaseRenderer::Standard3D)
return false;
return true;
}
void mitk::PlanarFigureInteractor::EndHovering(StateMachineAction *, InteractionEvent *)
{
- auto *planarFigure = dynamic_cast(GetDataNode()->GetData());
+ auto planarFigure = dynamic_cast(GetDataNode()->GetData());
+ if (nullptr == planarFigure)
+ {
+ return;
+ }
+
planarFigure->ResetPreviewContolPoint();
// Invoke end-hover event once the mouse is exiting the figure area
m_IsHovering = false;
planarFigure->InvokeEvent(EndHoverPlanarFigureEvent());
// Set bool property to indicate that planar figure is no longer in "hovering" mode
GetDataNode()->SetBoolProperty("planarfigure.ishovering", false);
RenderingManager::GetInstance()->RequestUpdateAll();
}
void mitk::PlanarFigureInteractor::DeleteFigure(StateMachineAction *, InteractionEvent *interactionEvent)
{
- auto *planarFigure = dynamic_cast(GetDataNode()->GetData());
+ auto planarFigure = dynamic_cast(GetDataNode()->GetData());
+ if (nullptr == planarFigure)
+ {
+ return;
+ }
+
planarFigure->RemoveAllObservers();
GetDataNode()->RemoveAllObservers();
interactionEvent->GetSender()->GetDataStorage()->Remove(GetDataNode());
RenderingManager::GetInstance()->RequestUpdateAll();
}
void mitk::PlanarFigureInteractor::PerformPointResetOnSelect(StateMachineAction *, InteractionEvent *)
{
- auto *planarFigure = dynamic_cast(GetDataNode()->GetData());
+ auto planarFigure = dynamic_cast(GetDataNode()->GetData());
+ if (nullptr == planarFigure)
+ {
+ return;
+ }
+
planarFigure->ResetOnPointSelect();
}
bool mitk::PlanarFigureInteractor::CheckMinimalFigureFinished(const InteractionEvent * /*interactionEvent*/)
{
- const mitk::PlanarFigure *planarFigure = dynamic_cast(GetDataNode()->GetData());
- return (planarFigure->GetNumberOfControlPoints() >= planarFigure->GetMinimumNumberOfControlPoints());
+ auto planarFigure = dynamic_cast(GetDataNode()->GetData());
+ if (nullptr == planarFigure)
+ {
+ return false;
+ }
+
+ return planarFigure->GetNumberOfControlPoints() >= planarFigure->GetMinimumNumberOfControlPoints();
}
bool mitk::PlanarFigureInteractor::CheckFigureFinished(const InteractionEvent * /*interactionEvent*/)
{
- const mitk::PlanarFigure *planarFigure = dynamic_cast(GetDataNode()->GetData());
- return (planarFigure->GetNumberOfControlPoints() >= planarFigure->GetMaximumNumberOfControlPoints());
+ auto planarFigure = dynamic_cast(GetDataNode()->GetData());
+ if (nullptr == planarFigure)
+ {
+ return false;
+ }
+
+ return planarFigure->GetNumberOfControlPoints() >= planarFigure->GetMaximumNumberOfControlPoints();
}
bool mitk::PlanarFigureInteractor::CheckFigureIsExtendable(const InteractionEvent * /*interactionEvent*/)
{
bool isExtendable(false);
GetDataNode()->GetBoolProperty("planarfigure.isextendable", isExtendable);
return isExtendable;
}
bool mitk::PlanarFigureInteractor::CheckFigureIsDeletable(const InteractionEvent * /*interactionEvent*/)
{
bool isDeletable(true);
GetDataNode()->GetBoolProperty("planarfigure.isdeletable", isDeletable);
return isDeletable;
}
bool mitk::PlanarFigureInteractor::CheckFigureIsEditable(const InteractionEvent * /*interactionEvent*/)
{
bool isEditable(true);
GetDataNode()->GetBoolProperty("planarfigure.iseditable", isEditable);
return isEditable;
}
void mitk::PlanarFigureInteractor::DeselectPoint(StateMachineAction *, InteractionEvent * /*interactionEvent*/)
{
- auto *planarFigure = dynamic_cast(GetDataNode()->GetData());
+ auto planarFigure = dynamic_cast(GetDataNode()->GetData());
+ if (nullptr == planarFigure)
+ {
+ return;
+ }
const bool wasSelected = planarFigure->DeselectControlPoint();
if (wasSelected)
{
// Issue event so that listeners may update themselves
planarFigure->Modified();
planarFigure->InvokeEvent(EndInteractionPlanarFigureEvent());
GetDataNode()->SetBoolProperty("planarfigure.drawcontrolpoints", true);
- // GetDataNode()->SetBoolProperty( "planarfigure.ishovering", false );
GetDataNode()->Modified();
}
}
void mitk::PlanarFigureInteractor::AddPoint(StateMachineAction *, InteractionEvent *interactionEvent)
{
- const mitk::InteractionPositionEvent *positionEvent =
- dynamic_cast(interactionEvent);
- if (positionEvent == nullptr)
+ auto positionEvent = dynamic_cast(interactionEvent);
+ if (nullptr == positionEvent)
+ {
return;
-
- const DataNode::Pointer node = this->GetDataNode();
- const BaseData::Pointer data = node->GetData();
+ }
/*
* Added check for "initiallyplaced" due to bug 13097:
*
* There are two possible cases in which a point can be inserted into a PlanarPolygon:
*
* 1. The figure is currently drawn -> the point will be appended at the end of the figure
* 2. A point is inserted at a userdefined position after the initial placement of the figure is finished
*
* In the second case we need to determine the proper insertion index. In the first case the index always has
* to be -1 so that the point is appended to the end.
*
* These changes are necessary because of a macOS specific issue: If a users draws a PlanarPolygon then the
* next point to be added moves according to the mouse position. If then the user left clicks in order to add
* a point one would assume the last move position is identical to the left click position. This is actually the
* case for windows and linux but somehow NOT for mac. Because of the insertion logic of a new point in the
* PlanarFigure then for mac the wrong current selected point is determined.
*
* With this check here this problem can be avoided. However a redesign of the insertion logic should be considered
*/
+ const DataNode::Pointer node = this->GetDataNode();
+ const BaseData::Pointer data = node->GetData();
+
bool isFigureFinished = false;
data->GetPropertyList()->GetBoolProperty("initiallyplaced", isFigureFinished);
bool selected = false;
bool isEditable = true;
node->GetBoolProperty("selected", selected);
node->GetBoolProperty("planarfigure.iseditable", isEditable);
if (!selected || !isEditable)
{
return;
}
- auto *planarFigure = dynamic_cast(data.GetPointer());
+ auto planarFigure = dynamic_cast(data.GetPointer());
+ if (nullptr == planarFigure)
+ {
+ return;
+ }
// We can't derive a new control point from a polyline of a Bezier curve
// as all control points contribute to each polyline point.
if (dynamic_cast(planarFigure) != nullptr && isFigureFinished)
return;
- const mitk::PlaneGeometry *planarFigureGeometry = planarFigure->GetPlaneGeometry();
- const mitk::AbstractTransformGeometry *abstractTransformGeometry =
- dynamic_cast(planarFigure->GetGeometry(0));
+ auto planarFigureGeometry = planarFigure->GetPlaneGeometry();
+ if (nullptr == planarFigureGeometry)
+ {
+ return;
+ }
- if (abstractTransformGeometry != nullptr)
+ auto abstractTransformGeometry = dynamic_cast(planarFigure->GetGeometry(0));
+ if (nullptr != abstractTransformGeometry)
+ {
return;
+ }
// If the planarFigure already has reached the maximum number
if (planarFigure->GetNumberOfControlPoints() >= planarFigure->GetMaximumNumberOfControlPoints())
{
return;
}
// Extract point in 2D world coordinates (relative to PlaneGeometry of
// PlanarFigure)
Point2D point2D, projectedPoint;
if (!this->TransformPositionEventToPoint2D(positionEvent, planarFigureGeometry, point2D))
{
return;
}
// TODO: check segment of polyline we clicked in
int nextIndex = -1;
// We only need to check which position to insert the control point
// when interacting with a PlanarPolygon. For all other types
// new control points will always be appended
const mitk::BaseRenderer *renderer = interactionEvent->GetSender();
const PlaneGeometry *projectionPlane = renderer->GetCurrentWorldPlaneGeometry();
if (dynamic_cast(planarFigure) && isFigureFinished)
{
nextIndex =
this->IsPositionOverFigure(positionEvent, planarFigure, planarFigureGeometry, projectionPlane, projectedPoint);
}
// Add point as new control point
if (planarFigure->IsPreviewControlPointVisible())
{
point2D = planarFigure->GetPreviewControlPoint();
}
planarFigure->AddControlPoint(point2D, planarFigure->GetControlPointForPolylinePoint(nextIndex, 0));
if (planarFigure->IsPreviewControlPointVisible())
{
planarFigure->SelectControlPoint(nextIndex);
planarFigure->ResetPreviewContolPoint();
}
// Re-evaluate features
planarFigure->EvaluateFeatures();
// this->LogPrintPlanarFigureQuantities( planarFigure );
// Update rendered scene
RenderingManager::GetInstance()->RequestUpdateAll();
}
void mitk::PlanarFigureInteractor::AddInitialPoint(StateMachineAction *, InteractionEvent *interactionEvent)
{
- const mitk::InteractionPositionEvent *positionEvent =
- dynamic_cast(interactionEvent);
- if (positionEvent == nullptr)
+ auto positionEvent = dynamic_cast(interactionEvent);
+ if (nullptr == positionEvent)
+ {
return;
+ }
+
+ auto planarFigure = dynamic_cast(GetDataNode()->GetData());
+ if (nullptr == planarFigure)
+ {
+ return;
+ }
- auto *planarFigure = dynamic_cast(GetDataNode()->GetData());
mitk::BaseRenderer *renderer = interactionEvent->GetSender();
- auto *planarFigureGeometry = dynamic_cast(planarFigure->GetGeometry(0));
- const mitk::AbstractTransformGeometry *abstractTransformGeometry =
- dynamic_cast(planarFigure->GetGeometry(0));
+ auto abstractTransformGeometry = dynamic_cast(planarFigure->GetGeometry(0));
// Invoke event to notify listeners that placement of this PF starts now
planarFigure->InvokeEvent(StartPlacementPlanarFigureEvent());
// Use PlaneGeometry of the renderer clicked on for this PlanarFigure
auto *planeGeometry = const_cast(
dynamic_cast(renderer->GetSliceNavigationController()->GetCurrentPlaneGeometry()));
if (planeGeometry != nullptr && abstractTransformGeometry == nullptr)
{
- planarFigureGeometry = planeGeometry;
planarFigure->SetPlaneGeometry(planeGeometry);
}
else
{
return;
}
// Extract point in 2D world coordinates (relative to PlaneGeometry of
// PlanarFigure)
Point2D point2D;
- if (!this->TransformPositionEventToPoint2D(positionEvent, planarFigureGeometry, point2D))
+ if (!this->TransformPositionEventToPoint2D(positionEvent, planeGeometry, point2D))
{
return;
}
// Place PlanarFigure at this point
planarFigure->PlaceFigure(point2D);
// Re-evaluate features
planarFigure->EvaluateFeatures();
// this->LogPrintPlanarFigureQuantities( planarFigure );
// Set a bool property indicating that the figure has been placed in
// the current RenderWindow. This is required so that the same render
// window can be re-aligned to the PlaneGeometry of the PlanarFigure later
// on in an application.
GetDataNode()->SetBoolProperty("PlanarFigureInitializedWindow", true, renderer);
// Update rendered scene
RenderingManager::GetInstance()->RequestUpdateAll();
}
void mitk::PlanarFigureInteractor::StartHovering(StateMachineAction *, InteractionEvent *interactionEvent)
{
- const mitk::InteractionPositionEvent *positionEvent =
- dynamic_cast(interactionEvent);
- if (positionEvent == nullptr)
+ auto positionEvent = dynamic_cast(interactionEvent);
+ if (nullptr == positionEvent)
+ {
return;
+ }
- auto *planarFigure = dynamic_cast(GetDataNode()->GetData());
+ auto planarFigure = dynamic_cast(GetDataNode()->GetData());
+ if (nullptr == planarFigure)
+ {
+ return;
+ }
if (!m_IsHovering)
{
// Invoke hover event once when the mouse is entering the figure area
m_IsHovering = true;
planarFigure->InvokeEvent(StartHoverPlanarFigureEvent());
// Set bool property to indicate that planar figure is currently in "hovering" mode
GetDataNode()->SetBoolProperty("planarfigure.ishovering", true);
RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void mitk::PlanarFigureInteractor::SetPreviewPointPosition(StateMachineAction *, InteractionEvent *interactionEvent)
{
- const mitk::InteractionPositionEvent *positionEvent =
- dynamic_cast(interactionEvent);
- if (positionEvent == nullptr)
+ auto positionEvent = dynamic_cast(interactionEvent);
+ if (nullptr == positionEvent)
+ {
+ return;
+ }
+
+ auto planarFigure = dynamic_cast(GetDataNode()->GetData());
+ if (nullptr == planarFigure)
+ {
return;
+ }
- auto *planarFigure = dynamic_cast(GetDataNode()->GetData());
const mitk::BaseRenderer *renderer = interactionEvent->GetSender();
planarFigure->DeselectControlPoint();
mitk::Point2D pointProjectedOntoLine = positionEvent->GetPointerPositionOnScreen();
bool selected(false);
bool isExtendable(false);
bool isEditable(true);
GetDataNode()->GetBoolProperty("selected", selected);
GetDataNode()->GetBoolProperty("planarfigure.isextendable", isExtendable);
GetDataNode()->GetBoolProperty("planarfigure.iseditable", isEditable);
if (selected && isExtendable && isEditable)
{
renderer->DisplayToPlane(pointProjectedOntoLine, pointProjectedOntoLine);
planarFigure->SetPreviewControlPoint(pointProjectedOntoLine);
}
RenderingManager::GetInstance()->RequestUpdateAll();
}
void mitk::PlanarFigureInteractor::HideControlPoints(StateMachineAction *, InteractionEvent * /*interactionEvent*/)
{
GetDataNode()->SetBoolProperty("planarfigure.drawcontrolpoints", false);
}
void mitk::PlanarFigureInteractor::HidePreviewPoint(StateMachineAction *, InteractionEvent *)
{
- auto *planarFigure = dynamic_cast(GetDataNode()->GetData());
+ auto planarFigure = dynamic_cast(GetDataNode()->GetData());
+ if (nullptr == planarFigure)
+ {
+ return;
+ }
+
planarFigure->ResetPreviewContolPoint();
RenderingManager::GetInstance()->RequestUpdateAll();
}
bool mitk::PlanarFigureInteractor::CheckFigureHovering(const InteractionEvent *interactionEvent)
{
- const auto *positionEvent =
- dynamic_cast(interactionEvent);
- if (positionEvent == nullptr)
+ auto positionEvent = dynamic_cast(interactionEvent);
+ if (nullptr == positionEvent)
+ {
return false;
+ }
- auto *planarFigure = dynamic_cast(GetDataNode()->GetData());
- const mitk::BaseRenderer *renderer = interactionEvent->GetSender();
- const mitk::PlaneGeometry *planarFigureGeometry = planarFigure->GetPlaneGeometry();
- auto *abstractTransformGeometry =
- dynamic_cast(planarFigure->GetGeometry(0));
- const PlaneGeometry *projectionPlane = renderer->GetCurrentWorldPlaneGeometry();
+ auto planarFigure = dynamic_cast(GetDataNode()->GetData());
+ if (nullptr == planarFigure)
+ {
+ return false;
+ }
+
+ auto planarFigureGeometry = planarFigure->GetPlaneGeometry();
+ if (nullptr == planarFigureGeometry)
+ {
+ return false;
+ }
- if (abstractTransformGeometry != nullptr)
+ auto abstractTransformGeometry = dynamic_cast(planarFigure->GetGeometry(0));
+ if (nullptr != abstractTransformGeometry)
+ {
return false;
+ }
+
+ const mitk::BaseRenderer *renderer = interactionEvent->GetSender();
+ const PlaneGeometry *projectionPlane = renderer->GetCurrentWorldPlaneGeometry();
mitk::Point2D pointProjectedOntoLine;
int previousControlPoint = this->IsPositionOverFigure(
positionEvent, planarFigure, planarFigureGeometry, projectionPlane, pointProjectedOntoLine);
bool isHovering = (previousControlPoint != -1);
+ return isHovering;
+}
- if (isHovering)
+bool mitk::PlanarFigureInteractor::CheckControlPointHovering(const InteractionEvent *interactionEvent)
+{
+ auto positionEvent = dynamic_cast(interactionEvent);
+ if (nullptr == positionEvent)
{
- return true;
+ return false;
}
- else
+
+ auto planarFigure = dynamic_cast(GetDataNode()->GetData());
+ if (nullptr == planarFigure)
{
return false;
}
- return false;
-}
+ auto planarFigureGeometry = planarFigure->GetPlaneGeometry();
+ if (nullptr == planarFigureGeometry)
+ {
+ return false;
+ }
-bool mitk::PlanarFigureInteractor::CheckControlPointHovering(const InteractionEvent *interactionEvent)
-{
- const auto *positionEvent =
- dynamic_cast(interactionEvent);
- if (positionEvent == nullptr)
+ auto abstractTransformGeometry = dynamic_cast(planarFigure->GetGeometry(0));
+ if (nullptr != abstractTransformGeometry)
+ {
return false;
+ }
- const mitk::PlanarFigure *planarFigure = dynamic_cast(GetDataNode()->GetData());
const mitk::BaseRenderer *renderer = interactionEvent->GetSender();
- const mitk::PlaneGeometry *planarFigureGeometry = dynamic_cast(planarFigure->GetGeometry(0));
- const mitk::AbstractTransformGeometry *abstractTransformGeometry =
- dynamic_cast(planarFigure->GetGeometry(0));
const PlaneGeometry *projectionPlane = renderer->GetCurrentWorldPlaneGeometry();
- if (abstractTransformGeometry != nullptr)
- return false;
-
int pointIndex = -1;
pointIndex = mitk::PlanarFigureInteractor::IsPositionInsideMarker(
positionEvent, planarFigure, planarFigureGeometry, projectionPlane, renderer);
- if (pointIndex >= 0)
- {
- return true;
- }
- else
- {
- return false;
- }
+ return pointIndex >= 0;
}
bool mitk::PlanarFigureInteractor::CheckSelection(const InteractionEvent * /*interactionEvent*/)
{
bool selected = false;
GetDataNode()->GetBoolProperty("selected", selected);
return selected;
}
void mitk::PlanarFigureInteractor::SelectFigure(StateMachineAction *, InteractionEvent * /*interactionEvent*/)
{
- auto *planarFigure = dynamic_cast(GetDataNode()->GetData());
+ auto planarFigure = dynamic_cast(GetDataNode()->GetData());
+ if (nullptr == planarFigure)
+ {
+ return;
+ }
+
planarFigure->InvokeEvent(SelectPlanarFigureEvent());
}
void mitk::PlanarFigureInteractor::SelectPoint(StateMachineAction *, InteractionEvent *interactionEvent)
{
- const mitk::InteractionPositionEvent *positionEvent =
- dynamic_cast(interactionEvent);
- if (positionEvent == nullptr)
+ auto positionEvent = dynamic_cast(interactionEvent);
+ if (nullptr == positionEvent)
+ {
return;
+ }
- auto *planarFigure = dynamic_cast(GetDataNode()->GetData());
- const mitk::BaseRenderer *renderer = interactionEvent->GetSender();
- const mitk::PlaneGeometry *planarFigureGeometry = dynamic_cast(planarFigure->GetGeometry(0));
- const mitk::AbstractTransformGeometry *abstractTransformGeometry =
- dynamic_cast(planarFigure->GetGeometry(0));
- const PlaneGeometry *projectionPlane = renderer->GetCurrentWorldPlaneGeometry();
+ auto planarFigure = dynamic_cast(GetDataNode()->GetData());
+ if (nullptr == planarFigure)
+ {
+ return;
+ }
- if (abstractTransformGeometry != nullptr)
+ auto planarFigureGeometry = planarFigure->GetPlaneGeometry();
+ if (nullptr == planarFigureGeometry)
+ {
return;
+ }
+
+ auto abstractTransformGeometry = dynamic_cast(planarFigure->GetGeometry(0));
+ if (nullptr != abstractTransformGeometry)
+ {
+ return;
+ }
+
+ const mitk::BaseRenderer *renderer = interactionEvent->GetSender();
+ const PlaneGeometry *projectionPlane = renderer->GetCurrentWorldPlaneGeometry();
const int pointIndex = mitk::PlanarFigureInteractor::IsPositionInsideMarker(
positionEvent, planarFigure, planarFigureGeometry, projectionPlane, renderer);
if (pointIndex >= 0)
{
// If mouse is above control point, mark it as selected
planarFigure->SelectControlPoint(pointIndex);
}
else
{
planarFigure->DeselectControlPoint();
}
}
bool mitk::PlanarFigureInteractor::CheckPointValidity(const InteractionEvent *interactionEvent)
{
// Check if the distance of the current point to the previously set point in display coordinates
// is sufficient (if a previous point exists)
- // Extract display position
- const auto *positionEvent =
- dynamic_cast(interactionEvent);
- if (positionEvent == nullptr)
+ auto positionEvent = dynamic_cast(interactionEvent);
+ if (nullptr == positionEvent)
+ {
return false;
+ }
- const mitk::PlanarFigure *planarFigure = dynamic_cast(GetDataNode()->GetData());
+ auto planarFigure = dynamic_cast(GetDataNode()->GetData());
+ if (nullptr == planarFigure)
+ {
+ return false;
+ }
- m_LastPointWasValid = IsMousePositionAcceptableAsNewControlPoint(positionEvent, planarFigure);
- return m_LastPointWasValid;
+ return IsMousePositionAcceptableAsNewControlPoint(positionEvent, planarFigure);
}
void mitk::PlanarFigureInteractor::RemoveSelectedPoint(StateMachineAction *, InteractionEvent *interactionEvent)
{
- auto *planarFigure = dynamic_cast(GetDataNode()->GetData());
- mitk::BaseRenderer *renderer = interactionEvent->GetSender();
+ auto planarFigure = dynamic_cast(GetDataNode()->GetData());
+ if (nullptr == planarFigure)
+ {
+ return;
+ }
const int selectedControlPoint = planarFigure->GetSelectedControlPoint();
planarFigure->RemoveControlPoint(selectedControlPoint);
// Re-evaluate features
planarFigure->EvaluateFeatures();
planarFigure->Modified();
GetDataNode()->SetBoolProperty("planarfigure.drawcontrolpoints", true);
planarFigure->InvokeEvent(EndInteractionPlanarFigureEvent());
RenderingManager::GetInstance()->RequestUpdateAll();
+ mitk::BaseRenderer *renderer = interactionEvent->GetSender();
HandleEvent(mitk::InternalEvent::New(renderer, this, "Dummy-Event"), GetDataNode());
}
void mitk::PlanarFigureInteractor::RequestContextMenu(StateMachineAction *, InteractionEvent * /*interactionEvent*/)
{
- auto *planarFigure = dynamic_cast(GetDataNode()->GetData());
+ auto planarFigure = dynamic_cast(GetDataNode()->GetData());
+ if (nullptr == planarFigure)
+ {
+ return;
+ }
bool selected = false;
GetDataNode()->GetBoolProperty("selected", selected);
// no need to invoke this if the figure is already selected
if (!selected)
{
planarFigure->InvokeEvent(SelectPlanarFigureEvent());
}
planarFigure->InvokeEvent(ContextMenuPlanarFigureEvent());
}
bool mitk::PlanarFigureInteractor::CheckResetOnPointSelect(const InteractionEvent * /*interactionEvent*/)
{
- auto *planarFigure = dynamic_cast(GetDataNode()->GetData());
+ auto planarFigure = dynamic_cast(GetDataNode()->GetData());
+ if (nullptr == planarFigure)
+ {
+ return false;
+ }
bool isEditable = true;
GetDataNode()->GetBoolProperty("planarfigure.iseditable", isEditable);
// Reset the PlanarFigure if required
return isEditable && planarFigure->ResetOnPointSelectNeeded();
}
bool mitk::PlanarFigureInteractor::CheckFigureOnRenderingGeometry(const InteractionEvent *interactionEvent)
{
- const auto *posEvent =
- dynamic_cast(interactionEvent);
-
- if (posEvent == nullptr)
+ auto positionEvent = dynamic_cast(interactionEvent);
+ if (nullptr == positionEvent)
+ {
return false;
+ }
- const mitk::Point3D worldPoint3D = posEvent->GetPositionInWorld();
- const mitk::PlanarFigure *planarFigure = dynamic_cast(GetDataNode()->GetData());
-
- const mitk::PlaneGeometry *planarFigurePlaneGeometry = dynamic_cast(planarFigure->GetGeometry(0));
- const mitk::AbstractTransformGeometry *abstractTransformGeometry =
- dynamic_cast(planarFigure->GetGeometry(0));
+ const mitk::Point3D worldPoint3D = positionEvent->GetPositionInWorld();
+ auto planarFigure = dynamic_cast(GetDataNode()->GetData());
+ if (nullptr == planarFigure)
+ {
+ return false;
+ }
- if (abstractTransformGeometry != nullptr)
+ auto planarFigureGeometry = planarFigure->GetPlaneGeometry();
+ if (nullptr == planarFigureGeometry)
+ {
return false;
+ }
- const double planeThickness = planarFigurePlaneGeometry->GetExtentInMM(2);
- if (planarFigurePlaneGeometry->Distance(worldPoint3D) > planeThickness)
+ auto abstractTransformGeometry = dynamic_cast(planarFigure->GetGeometry(0));
+ if (nullptr != abstractTransformGeometry)
{
- // don't react, when interaction is too far away
return false;
}
- return true;
+
+ const double planeThickness = planarFigureGeometry->GetExtentInMM(2);
+ return planarFigureGeometry->Distance(worldPoint3D) <= planeThickness;
}
void mitk::PlanarFigureInteractor::SetPrecision(mitk::ScalarType precision)
{
m_Precision = precision;
}
void mitk::PlanarFigureInteractor::SetMinimumPointDistance(ScalarType minimumDistance)
{
m_MinimumPointDistance = minimumDistance;
}
bool mitk::PlanarFigureInteractor::TransformPositionEventToPoint2D(const InteractionPositionEvent *positionEvent,
const PlaneGeometry *planarFigureGeometry,
Point2D &point2D)
{
+ if (nullptr == positionEvent || nullptr == planarFigureGeometry)
+ {
+ return false;
+ }
+
const mitk::Point3D worldPoint3D = positionEvent->GetPositionInWorld();
// TODO: proper handling of distance tolerance
if (planarFigureGeometry->Distance(worldPoint3D) > 0.1)
{
return false;
}
// Project point onto plane of this PlanarFigure
planarFigureGeometry->Map(worldPoint3D, point2D);
return true;
}
bool mitk::PlanarFigureInteractor::TransformObjectToDisplay(const mitk::Point2D &point2D,
mitk::Point2D &displayPoint,
const mitk::PlaneGeometry *objectGeometry,
const mitk::PlaneGeometry *rendererGeometry,
const mitk::BaseRenderer *renderer) const
{
+ if (nullptr == objectGeometry || nullptr == rendererGeometry || nullptr == renderer)
+ {
+ return false;
+ }
+
mitk::Point3D point3D;
// Map circle point from local 2D geometry into 3D world space
objectGeometry->Map(point2D, point3D);
const double planeThickness = objectGeometry->GetExtentInMM(2);
// TODO: proper handling of distance tolerance
if (rendererGeometry->Distance(point3D) < planeThickness / 3.0)
{
// Project 3D world point onto display geometry
renderer->WorldToDisplay(point3D, displayPoint);
return true;
}
return false;
}
bool mitk::PlanarFigureInteractor::IsPointNearLine(const mitk::Point2D &point,
const mitk::Point2D &startPoint,
const mitk::Point2D &endPoint,
mitk::Point2D &projectedPoint) const
{
mitk::Vector2D n1 = endPoint - startPoint;
n1.Normalize();
// Determine dot products between line vector and startpoint-point / endpoint-point vectors
const double l1 = n1 * (point - startPoint);
const double l2 = -n1 * (point - endPoint);
// Determine projection of specified point onto line defined by start / end point
const mitk::Point2D crossPoint = startPoint + n1 * l1;
projectedPoint = crossPoint;
const float dist1 = crossPoint.SquaredEuclideanDistanceTo(point);
const float dist2 = endPoint.SquaredEuclideanDistanceTo(point);
const float dist3 = startPoint.SquaredEuclideanDistanceTo(point);
// Point is inside encompassing rectangle IF
// - its distance to its projected point is small enough
// - it is not further outside of the line than the defined tolerance
if (((dist1 < 20.0) && (l1 > 0.0) && (l2 > 0.0)) || dist2 < 20.0 || dist3 < 20.0)
{
return true;
}
return false;
}
int mitk::PlanarFigureInteractor::IsPositionOverFigure(const InteractionPositionEvent *positionEvent,
PlanarFigure *planarFigure,
const PlaneGeometry *planarFigureGeometry,
const PlaneGeometry *rendererGeometry,
Point2D &pointProjectedOntoLine) const
{
+ if (nullptr == positionEvent || nullptr == planarFigure || nullptr == planarFigureGeometry
+ || nullptr == rendererGeometry)
+ {
+ return -1;
+ }
+
mitk::Point2D displayPosition = positionEvent->GetPointerPositionOnScreen();
// Iterate over all polylines of planar figure, and check if
// any one is close to the current display position
typedef mitk::PlanarFigure::PolyLineType VertexContainerType;
Point2D polyLinePoint;
Point2D firstPolyLinePoint;
Point2D previousPolyLinePoint;
for (unsigned short loop = 0; loop < planarFigure->GetPolyLinesSize(); ++loop)
{
const VertexContainerType polyLine = planarFigure->GetPolyLine(loop);
bool firstPoint(true);
for (auto it = polyLine.begin(); it != polyLine.end(); ++it)
{
// Get plane coordinates of this point of polyline (if possible)
if (!this->TransformObjectToDisplay(
*it, polyLinePoint, planarFigureGeometry, rendererGeometry, positionEvent->GetSender()))
{
break; // Poly line invalid (not on current 2D plane) --> skip it
}
if (firstPoint)
{
firstPolyLinePoint = polyLinePoint;
firstPoint = false;
}
else if (this->IsPointNearLine(displayPosition, previousPolyLinePoint, polyLinePoint, pointProjectedOntoLine))
{
// Point is close enough to line segment --> Return index of the segment
return std::distance(polyLine.begin(), it);
}
previousPolyLinePoint = polyLinePoint;
}
// For closed figures, also check last line segment
if (planarFigure->IsClosed() &&
this->IsPointNearLine(displayPosition, polyLinePoint, firstPolyLinePoint, pointProjectedOntoLine))
{
return 0; // Return index of first control point
}
}
return -1;
}
int mitk::PlanarFigureInteractor::IsPositionInsideMarker(const InteractionPositionEvent *positionEvent,
const PlanarFigure *planarFigure,
const PlaneGeometry *planarFigureGeometry,
const PlaneGeometry *rendererGeometry,
const BaseRenderer *renderer) const
{
+ if (nullptr == positionEvent || nullptr == planarFigure || nullptr == planarFigureGeometry
+ || nullptr == rendererGeometry || nullptr == renderer)
+ {
+ return -1;
+ }
+
const mitk::Point2D displayPosition = positionEvent->GetPointerPositionOnScreen();
// Iterate over all control points of planar figure, and check if
// any one is close to the current display position
mitk::Point2D displayControlPoint;
const int numberOfControlPoints = planarFigure->GetNumberOfControlPoints();
for (int i = 0; i < numberOfControlPoints; i++)
{
if (this->TransformObjectToDisplay(
planarFigure->GetControlPoint(i), displayControlPoint, planarFigureGeometry, rendererGeometry, renderer))
{
// TODO: variable size of markers
if (displayPosition.SquaredEuclideanDistanceTo(displayControlPoint) < 20.0)
{
return i;
}
}
}
return -1;
}
void mitk::PlanarFigureInteractor::LogPrintPlanarFigureQuantities(const PlanarFigure *planarFigure)
{
+ if (nullptr == planarFigure)
+ {
+ MITK_INFO << "PlanarFigure invalid.";
+ }
+
MITK_INFO << "PlanarFigure: " << planarFigure->GetNameOfClass();
for (unsigned int i = 0; i < planarFigure->GetNumberOfFeatures(); ++i)
{
MITK_INFO << "* " << planarFigure->GetFeatureName(i) << ": " << planarFigure->GetQuantity(i) << " "
<< planarFigure->GetFeatureUnit(i);
}
}
bool mitk::PlanarFigureInteractor::IsMousePositionAcceptableAsNewControlPoint(
const mitk::InteractionPositionEvent *positionEvent, const PlanarFigure *planarFigure)
{
- assert(positionEvent && planarFigure);
+ if (nullptr == positionEvent || nullptr == planarFigure)
+ {
+ return false;
+
+ }
const BaseRenderer *renderer = positionEvent->GetSender();
- assert(renderer);
+ if (nullptr == renderer)
+ {
+ return false;
+ }
// Get the timestep to support 3D+t
const int timeStep(renderer->GetTimeStep(planarFigure));
bool tooClose(false);
- const mitk::PlaneGeometry *planarFigureGeometry =
- dynamic_cast(planarFigure->GetGeometry(timeStep));
- const mitk::AbstractTransformGeometry *abstractTransformGeometry =
- dynamic_cast(planarFigure->GetGeometry(timeStep));
+ auto planarFigureGeometry = dynamic_cast(planarFigure->GetGeometry(timeStep));
+ if (nullptr == planarFigureGeometry)
+ {
+ return false;
+ }
- if (abstractTransformGeometry != nullptr)
+ auto abstractTransformGeometry = dynamic_cast(planarFigure->GetGeometry(timeStep));
+ if (nullptr != abstractTransformGeometry)
+ {
return false;
+ }
Point2D point2D;
// Get the point2D from the positionEvent
if (!this->TransformPositionEventToPoint2D(positionEvent, planarFigureGeometry, point2D))
{
return false;
}
// apply the controlPoint constraints of the planarFigure to get the
// coordinates that would actually be used.
const Point2D correctedPoint = const_cast(planarFigure)->ApplyControlPointConstraints(0, point2D);
// map the 2D coordinates of the new point to world-coordinates
// and transform those to display-coordinates
mitk::Point3D newPoint3D;
planarFigureGeometry->Map(correctedPoint, newPoint3D);
mitk::Point2D newDisplayPosition;
renderer->WorldToDisplay(newPoint3D, newDisplayPosition);
const int selectedControlPoint = planarFigure->GetSelectedControlPoint();
for (int i = 0; i < (int)planarFigure->GetNumberOfControlPoints(); ++i)
{
if (i != selectedControlPoint)
{
// Try to convert previous point to current display coordinates
mitk::Point3D previousPoint3D;
// map the 2D coordinates of the control-point to world-coordinates
planarFigureGeometry->Map(planarFigure->GetControlPoint(i), previousPoint3D);
if (renderer->GetCurrentWorldPlaneGeometry()->Distance(previousPoint3D) < 0.1) // ugly, but assert makes this work
{
mitk::Point2D previousDisplayPosition;
// transform the world-coordinates into display-coordinates
renderer->WorldToDisplay(previousPoint3D, previousDisplayPosition);
// Calculate the distance. We use display-coordinates here to make
// the check independent of the zoom-level of the rendering scene.
const double a = newDisplayPosition[0] - previousDisplayPosition[0];
const double b = newDisplayPosition[1] - previousDisplayPosition[1];
// If point is to close, do not set a new point
tooClose = (a * a + b * b < m_MinimumPointDistance);
}
if (tooClose)
return false; // abort loop early
}
}
return !tooClose; // default
}
void mitk::PlanarFigureInteractor::ConfigurationChanged()
{
const mitk::PropertyList::Pointer properties = GetAttributes();
std::string precision = "";
if (properties->GetStringProperty("precision", precision))
{
m_Precision = atof(precision.c_str());
}
else
{
m_Precision = (ScalarType)6.5;
}
std::string minPointDistance = "";
if (properties->GetStringProperty("minPointDistance", minPointDistance))
{
m_MinimumPointDistance = atof(minPointDistance.c_str());
}
else
{
m_MinimumPointDistance = (ScalarType)25.0;
}
}
diff --git a/Modules/Segmentation/Controllers/mitkToolManager.cpp b/Modules/Segmentation/Controllers/mitkToolManager.cpp
index 6e2fbd852c..4a71cac9a9 100644
--- a/Modules/Segmentation/Controllers/mitkToolManager.cpp
+++ b/Modules/Segmentation/Controllers/mitkToolManager.cpp
@@ -1,589 +1,603 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#include "mitkToolManager.h"
#include "mitkToolManagerProvider.h"
#include "mitkCoreObjectFactory.h"
#include
#include
#include
#include "mitkInteractionEventObserver.h"
#include "mitkSegTool2D.h"
#include "mitkRenderingManager.h"
#include "mitkSliceNavigationController.h"
#include "usGetModuleContext.h"
#include "usModuleContext.h"
mitk::ToolManager::ToolManager(DataStorage *storage)
: m_ActiveTool(nullptr), m_ActiveToolID(-1), m_RegisteredClients(0), m_DataStorage(storage)
{
CoreObjectFactory::GetInstance(); // to make sure a CoreObjectFactory was instantiated (and in turn, possible tools
// are registered) - bug 1029
this->InitializeTools();
}
void mitk::ToolManager::EnsureTimeObservation()
{
if (nullptr != mitk::RenderingManager::GetInstance() && nullptr != mitk::RenderingManager::GetInstance()->GetTimeNavigationController())
{
auto timeController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
m_LastTimePoint = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint();
auto currentTimeController = m_CurrentTimeNavigationController.Lock();
if (timeController != currentTimeController)
{
if (currentTimeController.IsNotNull())
{
currentTimeController->RemoveObserver(m_TimePointObserverTag);
}
itk::MemberCommand::Pointer command = itk::MemberCommand::New();
command->SetCallbackFunction(this, &ToolManager::OnTimeChanged);
command->SetCallbackFunction(this, &ToolManager::OnTimeChangedConst);
m_CurrentTimeNavigationController = timeController;
m_TimePointObserverTag = timeController->AddObserver(SliceNavigationController::GeometryTimeEvent(nullptr,0), command);
}
}
}
void mitk::ToolManager::StopTimeObservation()
{
auto currentTimeController = m_CurrentTimeNavigationController.Lock();
if (currentTimeController.IsNotNull())
{
currentTimeController->RemoveObserver(m_TimePointObserverTag);
m_CurrentTimeNavigationController = nullptr;
m_TimePointObserverTag = 0;
}
}
mitk::ToolManager::~ToolManager()
{
for (auto dataIter = m_WorkingData.begin(); dataIter != m_WorkingData.end(); ++dataIter)
(*dataIter)->RemoveObserver(m_WorkingDataObserverTags[(*dataIter)]);
if (this->GetDataStorage() != nullptr)
this->GetDataStorage()->RemoveNodeEvent.RemoveListener(
mitk::MessageDelegate1(this, &ToolManager::OnNodeRemoved));
if (m_ActiveTool)
{
m_ActiveTool->Deactivated();
m_ActiveToolRegistration.Unregister();
m_ActiveTool = nullptr;
m_ActiveToolID = -1; // no tool active
ActiveToolChanged.Send();
}
for (auto observerTagMapIter = m_ReferenceDataObserverTags.begin();
observerTagMapIter != m_ReferenceDataObserverTags.end();
++observerTagMapIter)
{
observerTagMapIter->first->RemoveObserver(observerTagMapIter->second);
}
this->StopTimeObservation();
}
void mitk::ToolManager::InitializeTools()
{
// clear all previous tool pointers (tools may be still activated from another recently used plugin)
if (m_ActiveTool)
{
m_ActiveTool->Deactivated();
m_ActiveToolRegistration.Unregister();
m_ActiveTool = nullptr;
m_ActiveToolID = -1; // no tool active
ActiveToolChanged.Send();
}
m_Tools.clear();
// get a list of all known mitk::Tools
std::list thingsThatClaimToBeATool = itk::ObjectFactoryBase::CreateAllInstance("mitkTool");
// remember these tools
for (auto iter = thingsThatClaimToBeATool.begin();
iter != thingsThatClaimToBeATool.end();
++iter)
{
if (auto *tool = dynamic_cast(iter->GetPointer()))
{
tool->InitializeStateMachine();
tool->SetToolManager(this); // important to call right after instantiation
tool->ErrorMessage += MessageDelegate1(this, &ToolManager::OnToolErrorMessage);
tool->GeneralMessage +=
MessageDelegate1(this, &ToolManager::OnGeneralToolMessage);
m_Tools.push_back(tool);
}
}
}
void mitk::ToolManager::OnToolErrorMessage(std::string s)
{
this->ToolErrorMessage(s);
}
void mitk::ToolManager::OnGeneralToolMessage(std::string s)
{
this->GeneralToolMessage(s);
}
const mitk::ToolManager::ToolVectorTypeConst mitk::ToolManager::GetTools()
{
ToolVectorTypeConst resultList;
for (auto iter = m_Tools.begin(); iter != m_Tools.end(); ++iter)
{
resultList.push_back(iter->GetPointer());
}
return resultList;
}
mitk::Tool *mitk::ToolManager::GetToolById(int id)
{
try
{
return m_Tools.at(id);
}
catch (const std::exception &)
{
return nullptr;
}
}
bool mitk::ToolManager::ActivateTool(int id)
{
- if (id != -1 && !this->GetToolById(id)->CanHandle(this->GetReferenceData(0)->GetData()))
+ const auto workingDataNode = this->GetWorkingData(0);
+ const mitk::BaseData* workingData = nullptr;
+ if (nullptr != workingDataNode)
+ {
+ workingData = workingDataNode->GetData();
+ }
+
+ const auto referenceDataNode = this->GetReferenceData(0);
+ const mitk::BaseData* referenceData = nullptr;
+ if (nullptr != referenceDataNode)
+ {
+ referenceData = referenceDataNode->GetData();
+ }
+
+ if (id != -1 && !this->GetToolById(id)->CanHandle(referenceData, workingData))
return false;
if (this->GetDataStorage())
{
this->GetDataStorage()->RemoveNodeEvent.AddListener(
mitk::MessageDelegate1(this, &ToolManager::OnNodeRemoved));
}
if (GetToolById(id) == m_ActiveTool)
return true; // no change needed
static int nextTool = -1;
nextTool = id;
static bool inActivateTool = false;
if (inActivateTool)
{
return true;
}
inActivateTool = true;
while (nextTool != m_ActiveToolID)
{
// Deactivate all other active tools to ensure a globally single active tool
for (const auto& toolManager : ToolManagerProvider::GetInstance()->GetToolManagers())
{
if (nullptr != toolManager.second->m_ActiveTool)
{
toolManager.second->m_ActiveTool->Deactivated();
toolManager.second->m_ActiveToolRegistration.Unregister();
// The active tool of *this* ToolManager is handled below this loop
if (this != toolManager.second)
{
toolManager.second->m_ActiveTool = nullptr;
toolManager.second->m_ActiveToolID = -1;
toolManager.second->ActiveToolChanged.Send();
}
}
}
m_ActiveTool = GetToolById(nextTool);
m_ActiveToolID = m_ActiveTool ? nextTool : -1; // current ID if tool is valid, otherwise -1
ActiveToolChanged.Send();
if (m_ActiveTool)
{
this->EnsureTimeObservation();
if (m_RegisteredClients > 0)
{
m_ActiveTool->Activated();
m_ActiveToolRegistration =
us::GetModuleContext()->RegisterService(m_ActiveTool, us::ServiceProperties());
}
}
}
inActivateTool = false;
return (m_ActiveTool != nullptr);
}
void mitk::ToolManager::SetReferenceData(DataVectorType data)
{
if (data != m_ReferenceData)
{
// remove observers from old nodes
for (auto dataIter = m_ReferenceData.begin(); dataIter != m_ReferenceData.end(); ++dataIter)
{
auto searchIter = m_ReferenceDataObserverTags.find(*dataIter);
if (searchIter != m_ReferenceDataObserverTags.end())
{
(*dataIter)->RemoveObserver(searchIter->second);
}
}
m_ReferenceData = data;
// TODO tell active tool?
// attach new observers
m_ReferenceDataObserverTags.clear();
for (auto dataIter = m_ReferenceData.begin(); dataIter != m_ReferenceData.end(); ++dataIter)
{
itk::MemberCommand::Pointer command = itk::MemberCommand::New();
command->SetCallbackFunction(this, &ToolManager::OnOneOfTheReferenceDataDeleted);
command->SetCallbackFunction(this, &ToolManager::OnOneOfTheReferenceDataDeletedConst);
m_ReferenceDataObserverTags.insert(
std::pair((*dataIter), (*dataIter)->AddObserver(itk::DeleteEvent(), command)));
}
ReferenceDataChanged.Send();
}
}
void mitk::ToolManager::OnOneOfTheReferenceDataDeletedConst(const itk::Object *caller, const itk::EventObject &e)
{
OnOneOfTheReferenceDataDeleted(const_cast(caller), e);
}
void mitk::ToolManager::OnOneOfTheReferenceDataDeleted(itk::Object *caller, const itk::EventObject &itkNotUsed(e))
{
DataVectorType v;
for (auto dataIter = m_ReferenceData.begin(); dataIter != m_ReferenceData.end(); ++dataIter)
{
if ((void *)(*dataIter) != (void *)caller)
{
v.push_back(*dataIter);
}
else
{
m_ReferenceDataObserverTags.erase(*dataIter); // no tag to remove anymore
}
}
this->SetReferenceData(v);
}
void mitk::ToolManager::SetReferenceData(DataNode *data)
{
DataVectorType v;
if (data)
{
v.push_back(data);
}
SetReferenceData(v);
}
void mitk::ToolManager::SetWorkingData(DataVectorType data)
{
if (data != m_WorkingData)
{
// remove observers from old nodes
for (auto dataIter = m_WorkingData.begin(); dataIter != m_WorkingData.end(); ++dataIter)
{
auto searchIter = m_WorkingDataObserverTags.find(*dataIter);
if (searchIter != m_WorkingDataObserverTags.end())
{
(*dataIter)->RemoveObserver(searchIter->second);
}
}
m_WorkingData = data;
// TODO tell active tool?
// Quick workaround for bug #16598
if (m_WorkingData.empty())
this->ActivateTool(-1);
// workaround end
// attach new observers
m_WorkingDataObserverTags.clear();
for (auto dataIter = m_WorkingData.begin(); dataIter != m_WorkingData.end(); ++dataIter)
{
itk::MemberCommand::Pointer command = itk::MemberCommand::New();
command->SetCallbackFunction(this, &ToolManager::OnOneOfTheWorkingDataDeleted);
command->SetCallbackFunction(this, &ToolManager::OnOneOfTheWorkingDataDeletedConst);
m_WorkingDataObserverTags.insert(
std::pair((*dataIter), (*dataIter)->AddObserver(itk::DeleteEvent(), command)));
}
WorkingDataChanged.Send();
}
}
void mitk::ToolManager::OnOneOfTheWorkingDataDeletedConst(const itk::Object *caller, const itk::EventObject &e)
{
OnOneOfTheWorkingDataDeleted(const_cast(caller), e);
}
void mitk::ToolManager::OnOneOfTheWorkingDataDeleted(itk::Object *caller, const itk::EventObject &itkNotUsed(e))
{
DataVectorType v;
for (auto dataIter = m_WorkingData.begin(); dataIter != m_WorkingData.end(); ++dataIter)
{
if ((void *)(*dataIter) != (void *)caller)
{
v.push_back(*dataIter);
}
else
{
m_WorkingDataObserverTags.erase(*dataIter); // no tag to remove anymore
}
}
this->SetWorkingData(v);
}
void mitk::ToolManager::SetWorkingData(DataNode *data)
{
DataVectorType v;
if (data) // don't allow for nullptr nodes
{
v.push_back(data);
}
SetWorkingData(v);
}
void mitk::ToolManager::SetRoiData(DataVectorType data)
{
if (data != m_RoiData)
{
// remove observers from old nodes
for (auto dataIter = m_RoiData.begin(); dataIter != m_RoiData.end(); ++dataIter)
{
auto searchIter = m_RoiDataObserverTags.find(*dataIter);
if (searchIter != m_RoiDataObserverTags.end())
{
(*dataIter)->RemoveObserver(searchIter->second);
}
}
m_RoiData = data;
// TODO tell active tool?
// attach new observers
m_RoiDataObserverTags.clear();
for (auto dataIter = m_RoiData.begin(); dataIter != m_RoiData.end(); ++dataIter)
{
itk::MemberCommand::Pointer command = itk::MemberCommand::New();
command->SetCallbackFunction(this, &ToolManager::OnOneOfTheRoiDataDeleted);
command->SetCallbackFunction(this, &ToolManager::OnOneOfTheRoiDataDeletedConst);
m_RoiDataObserverTags.insert(
std::pair((*dataIter), (*dataIter)->AddObserver(itk::DeleteEvent(), command)));
}
RoiDataChanged.Send();
}
}
void mitk::ToolManager::SetRoiData(DataNode *data)
{
DataVectorType v;
if (data)
{
v.push_back(data);
}
this->SetRoiData(v);
}
void mitk::ToolManager::OnOneOfTheRoiDataDeletedConst(const itk::Object *caller, const itk::EventObject &e)
{
OnOneOfTheRoiDataDeleted(const_cast(caller), e);
}
void mitk::ToolManager::OnOneOfTheRoiDataDeleted(itk::Object *caller, const itk::EventObject &itkNotUsed(e))
{
DataVectorType v;
for (auto dataIter = m_RoiData.begin(); dataIter != m_RoiData.end(); ++dataIter)
{
if ((void *)(*dataIter) != (void *)caller)
{
v.push_back(*dataIter);
}
else
{
m_RoiDataObserverTags.erase(*dataIter); // no tag to remove anymore
}
}
this->SetRoiData(v);
}
mitk::ToolManager::DataVectorType mitk::ToolManager::GetReferenceData()
{
return m_ReferenceData;
}
mitk::DataNode *mitk::ToolManager::GetReferenceData(int idx)
{
try
{
return m_ReferenceData.at(idx);
}
catch (const std::exception &)
{
return nullptr;
}
}
mitk::ToolManager::DataVectorType mitk::ToolManager::GetWorkingData()
{
return m_WorkingData;
}
mitk::ToolManager::DataVectorType mitk::ToolManager::GetRoiData()
{
return m_RoiData;
}
mitk::DataNode *mitk::ToolManager::GetRoiData(int idx)
{
try
{
return m_RoiData.at(idx);
}
catch (const std::exception &)
{
return nullptr;
}
}
mitk::DataStorage *mitk::ToolManager::GetDataStorage()
{
if (!m_DataStorage.IsExpired())
{
return m_DataStorage.Lock();
}
else
{
return nullptr;
}
}
void mitk::ToolManager::SetDataStorage(DataStorage &storage)
{
m_DataStorage = &storage;
}
mitk::DataNode *mitk::ToolManager::GetWorkingData(unsigned int idx)
{
if (m_WorkingData.empty())
return nullptr;
if (m_WorkingData.size() > idx)
return m_WorkingData[idx];
return nullptr;
}
int mitk::ToolManager::GetActiveToolID()
{
return m_ActiveToolID;
}
mitk::Tool *mitk::ToolManager::GetActiveTool()
{
return m_ActiveTool;
}
void mitk::ToolManager::RegisterClient()
{
if (m_RegisteredClients < 1)
{
if (m_ActiveTool)
{
m_ActiveTool->Activated();
m_ActiveToolRegistration =
us::GetModuleContext()->RegisterService(m_ActiveTool, us::ServiceProperties());
}
}
++m_RegisteredClients;
}
void mitk::ToolManager::UnregisterClient()
{
if (m_RegisteredClients < 1)
return;
--m_RegisteredClients;
if (m_RegisteredClients < 1)
{
if (m_ActiveTool)
{
m_ActiveTool->Deactivated();
m_ActiveToolRegistration.Unregister();
}
}
}
int mitk::ToolManager::GetToolID(const Tool *tool)
{
int id(0);
for (auto iter = m_Tools.begin(); iter != m_Tools.end(); ++iter, ++id)
{
if (tool == iter->GetPointer())
{
return id;
}
}
return -1;
}
void mitk::ToolManager::OnNodeRemoved(const mitk::DataNode *node)
{
// check all storage vectors
OnOneOfTheReferenceDataDeleted(const_cast(node), itk::DeleteEvent());
OnOneOfTheRoiDataDeleted(const_cast(node), itk::DeleteEvent());
OnOneOfTheWorkingDataDeleted(const_cast(node), itk::DeleteEvent());
}
void mitk::ToolManager::OnTimeChanged(itk::Object* caller, const itk::EventObject& e)
{
this->OnTimeChangedConst(caller, e);
}
void mitk::ToolManager::OnTimeChangedConst(const itk::Object* caller, const itk::EventObject& /*e*/)
{
auto currentController = m_CurrentTimeNavigationController.Lock();
if (caller == currentController)
{
const auto currentTimePoint = currentController->GetSelectedTimePoint();
if (currentTimePoint != m_LastTimePoint)
{
m_LastTimePoint = currentTimePoint;
SelectedTimePointChanged.Send();
}
}
}
mitk::TimePointType mitk::ToolManager::GetCurrentTimePoint() const
{
return m_LastTimePoint;
}
diff --git a/Modules/Segmentation/Interactions/mitkAdaptiveRegionGrowingTool.cpp b/Modules/Segmentation/Interactions/mitkAdaptiveRegionGrowingTool.cpp
index 306d0fcac8..64de93da55 100644
--- a/Modules/Segmentation/Interactions/mitkAdaptiveRegionGrowingTool.cpp
+++ b/Modules/Segmentation/Interactions/mitkAdaptiveRegionGrowingTool.cpp
@@ -1,117 +1,117 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#include "mitkAdaptiveRegionGrowingTool.h"
#include "mitkImage.h"
#include "mitkProperties.h"
#include "mitkToolManager.h"
// us
#include
#include
#include
#include
namespace mitk
{
MITK_TOOL_MACRO(MITKSEGMENTATION_EXPORT, AdaptiveRegionGrowingTool, "AdaptiveRegionGrowingTool");
}
mitk::AdaptiveRegionGrowingTool::AdaptiveRegionGrowingTool()
{
m_PointSetNode = mitk::DataNode::New();
m_PointSetNode->GetPropertyList()->SetProperty("name", mitk::StringProperty::New("3D_Regiongrowing_Seedpoint"));
m_PointSetNode->GetPropertyList()->SetProperty("helper object", mitk::BoolProperty::New(true));
m_PointSet = mitk::PointSet::New();
m_PointSetNode->SetData(m_PointSet);
}
mitk::AdaptiveRegionGrowingTool::~AdaptiveRegionGrowingTool()
{
}
-bool mitk::AdaptiveRegionGrowingTool::CanHandle(BaseData *referenceData) const
+bool mitk::AdaptiveRegionGrowingTool::CanHandle(const BaseData* referenceData, const BaseData* /*workingData*/) const
{
if (referenceData == nullptr)
return false;
- auto *image = dynamic_cast(referenceData);
+ auto *image = dynamic_cast(referenceData);
if (image == nullptr)
return false;
if (image->GetDimension() < 3)
return false;
return true;
}
const char **mitk::AdaptiveRegionGrowingTool::GetXPM() const
{
return nullptr;
}
const char *mitk::AdaptiveRegionGrowingTool::GetName() const
{
return "Region Growing 3D";
}
us::ModuleResource mitk::AdaptiveRegionGrowingTool::GetIconResource() const
{
us::Module *module = us::GetModuleContext()->GetModule();
us::ModuleResource resource = module->GetResource("RegionGrowing_48x48.png");
return resource;
}
void mitk::AdaptiveRegionGrowingTool::Activated()
{
Superclass::Activated();
if (!GetDataStorage()->Exists(m_PointSetNode))
GetDataStorage()->Add(m_PointSetNode, GetWorkingData());
m_SeedPointInteractor = mitk::SinglePointDataInteractor::New();
m_SeedPointInteractor->LoadStateMachine("PointSet.xml");
m_SeedPointInteractor->SetEventConfig("PointSetConfig.xml");
m_SeedPointInteractor->SetDataNode(m_PointSetNode);
}
void mitk::AdaptiveRegionGrowingTool::Deactivated()
{
m_PointSet->Clear();
GetDataStorage()->Remove(m_PointSetNode);
Superclass::Deactivated();
}
void mitk::AdaptiveRegionGrowingTool::ConfirmSegmentation()
{
m_ToolManager->ActivateTool(-1);
}
mitk::DataNode *mitk::AdaptiveRegionGrowingTool::GetReferenceData()
{
return this->m_ToolManager->GetReferenceData(0);
}
mitk::DataStorage *mitk::AdaptiveRegionGrowingTool::GetDataStorage()
{
return this->m_ToolManager->GetDataStorage();
}
mitk::DataNode *mitk::AdaptiveRegionGrowingTool::GetWorkingData()
{
return this->m_ToolManager->GetWorkingData(0);
}
mitk::DataNode::Pointer mitk::AdaptiveRegionGrowingTool::GetPointSetNode()
{
return m_PointSetNode;
}
diff --git a/Modules/Segmentation/Interactions/mitkAdaptiveRegionGrowingTool.h b/Modules/Segmentation/Interactions/mitkAdaptiveRegionGrowingTool.h
index 31797bffbc..7924978442 100644
--- a/Modules/Segmentation/Interactions/mitkAdaptiveRegionGrowingTool.h
+++ b/Modules/Segmentation/Interactions/mitkAdaptiveRegionGrowingTool.h
@@ -1,128 +1,128 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#ifndef mitkAdaptiveRegionGrowingTool_h_Included
#define mitkAdaptiveRegionGrowingTool_h_Included
#include "mitkAutoSegmentationTool.h"
#include "mitkCommon.h"
#include "mitkDataStorage.h"
#include "mitkPointSet.h"
#include "mitkSinglePointDataInteractor.h"
#include
namespace us
{
class ModuleResource;
}
namespace mitk
{
/**
\brief Dummy Tool for AdaptiveRegionGrowingToolGUI to get Tool functionality for AdaptiveRegionGrowing.
The actual logic is implemented in QmitkAdaptiveRegionGrowingToolGUI.
\ingroup ToolManagerEtAl
\sa mitk::Tool
\sa QmitkInteractiveSegmentation
*/
class MITKSEGMENTATION_EXPORT AdaptiveRegionGrowingTool : public AutoSegmentationTool
{
public:
/**
* @brief mitkClassMacro
*/
mitkClassMacro(AdaptiveRegionGrowingTool, AutoSegmentationTool);
itkFactorylessNewMacro(Self);
itkCloneMacro(Self);
- bool CanHandle(BaseData *referenceData) const override;
+ bool CanHandle(const BaseData* referenceData, const BaseData* workingData) const override;
/**
* @brief Get XPM
* @return nullptr
*/
const char **GetXPM() const override;
/**
* @brief Get name
* @return name of the Tool
*/
const char *GetName() const override;
/**
* @brief Get icon resource
* @return the resource Object of the Icon
*/
us::ModuleResource GetIconResource() const override;
/**
* @brief Adds interactor for the seedpoint and creates a seedpoint if neccessary.
*
*
*/
void Activated() override;
/**
* @brief Removes all set points and interactors.
*
*
*/
void Deactivated() override;
/**
* @brief get pointset node
* @return the point set node
*/
virtual DataNode::Pointer GetPointSetNode();
/**
* @brief get reference data
* @return the current reference data.
*/
mitk::DataNode *GetReferenceData();
/**
* @brief Get working data
* @return a list of all working data.
*/
mitk::DataNode *GetWorkingData();
/**
* @brief Get datastorage
* @return the current data storage.
*/
mitk::DataStorage *GetDataStorage();
void ConfirmSegmentation();
protected:
/**
* @brief constructor
*/
AdaptiveRegionGrowingTool(); // purposely hidden
/**
* @brief destructor
*/
~AdaptiveRegionGrowingTool() override;
private:
PointSet::Pointer m_PointSet;
SinglePointDataInteractor::Pointer m_SeedPointInteractor;
DataNode::Pointer m_PointSetNode;
};
} // namespace
#endif
diff --git a/Modules/Segmentation/Interactions/mitkAutoSegmentationTool.cpp b/Modules/Segmentation/Interactions/mitkAutoSegmentationTool.cpp
index 0539cb7df1..96ba360d0f 100644
--- a/Modules/Segmentation/Interactions/mitkAutoSegmentationTool.cpp
+++ b/Modules/Segmentation/Interactions/mitkAutoSegmentationTool.cpp
@@ -1,97 +1,97 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#include "mitkAutoSegmentationTool.h"
#include "mitkImage.h"
#include "mitkToolManager.h"
#include
mitk::AutoSegmentationTool::AutoSegmentationTool() : Tool("dummy"), m_OverwriteExistingSegmentation(false)
{
}
mitk::AutoSegmentationTool::~AutoSegmentationTool()
{
}
const char *mitk::AutoSegmentationTool::GetGroup() const
{
return "autoSegmentation";
}
-mitk::Image::ConstPointer mitk::AutoSegmentationTool::Get3DImage(const mitk::Image* image, unsigned int timestep) const
+mitk::Image::ConstPointer mitk::AutoSegmentationTool::GetImageByTimeStep(const mitk::Image* image, unsigned int timestep)
{
if (nullptr == image)
return image;
if (image->GetDimension() != 4)
return image;
mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New();
imageTimeSelector->SetInput(image);
imageTimeSelector->SetTimeNr(static_cast(timestep));
imageTimeSelector->UpdateLargestPossibleRegion();
return imageTimeSelector->GetOutput();
}
-mitk::Image::ConstPointer mitk::AutoSegmentationTool::Get3DImageByTimePoint(const mitk::Image* image, TimePointType timePoint) const
+mitk::Image::ConstPointer mitk::AutoSegmentationTool::GetImageByTimePoint(const mitk::Image* image, TimePointType timePoint)
{
if (nullptr == image)
return image;
if (!image->GetTimeGeometry()->IsValidTimePoint(timePoint))
return nullptr;
- return this->Get3DImage(image, image->GetTimeGeometry()->TimePointToTimeStep(timePoint));
+ return AutoSegmentationTool::GetImageByTimeStep(image, image->GetTimeGeometry()->TimePointToTimeStep(timePoint));
}
void mitk::AutoSegmentationTool::SetOverwriteExistingSegmentation(bool overwrite)
{
m_OverwriteExistingSegmentation = overwrite;
}
std::string mitk::AutoSegmentationTool::GetCurrentSegmentationName()
{
if (m_ToolManager->GetWorkingData(0))
return m_ToolManager->GetWorkingData(0)->GetName();
else
return "";
}
mitk::DataNode *mitk::AutoSegmentationTool::GetTargetSegmentationNode()
{
mitk::DataNode::Pointer segmentationNode = m_ToolManager->GetWorkingData(0);
if (!m_OverwriteExistingSegmentation)
{
mitk::DataNode::Pointer refNode = m_ToolManager->GetReferenceData(0);
if (refNode.IsNull())
{
// TODO create and use segmentation exceptions instead!!
MITK_ERROR << "No valid reference data!";
return nullptr;
}
std::string nodename = refNode->GetName() + "_" + this->GetName();
mitk::Color color;
color.SetRed(1);
color.SetBlue(0);
color.SetGreen(0);
//create a new segmentation node based on the current segmentation as template
segmentationNode = CreateEmptySegmentationNode(dynamic_cast(segmentationNode->GetData()), nodename, color);
m_ToolManager->GetDataStorage()->Add(segmentationNode, refNode);
}
return segmentationNode;
}
diff --git a/Modules/Segmentation/Interactions/mitkAutoSegmentationTool.h b/Modules/Segmentation/Interactions/mitkAutoSegmentationTool.h
index 1a2d458950..dfb36b908c 100644
--- a/Modules/Segmentation/Interactions/mitkAutoSegmentationTool.h
+++ b/Modules/Segmentation/Interactions/mitkAutoSegmentationTool.h
@@ -1,65 +1,71 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#ifndef mitkAutoSegmentationTool_h_Included
#define mitkAutoSegmentationTool_h_Included
#include "mitkCommon.h"
#include "mitkTool.h"
#include
namespace mitk
{
class Image;
/**
\brief Superclass for tool that create a new segmentation without user interaction in render windows
This class is undocumented. Ask the creator ($Author$) to supply useful comments.
*/
class MITKSEGMENTATION_EXPORT AutoSegmentationTool : public Tool
{
public:
mitkClassMacro(AutoSegmentationTool, Tool);
+ /** This function controls wether a confirmed segmentation should replace the old
+ * segmentation/working node (true) or if it should be stored as new and additional
+ * node (false).
+ */
void SetOverwriteExistingSegmentation(bool overwrite);
/**
* @brief Gets the name of the currently selected segmentation node
* @return the name of the segmentation node or an empty string if
* none is selected
*/
std::string GetCurrentSegmentationName();
/**
* @brief Depending on the selected mode either returns the currently selected segmentation
* or creates a new one from the selected reference data and adds the new segmentation
* to the datastorage
* @return a mitk::DataNode which contains a segmentation image
*/
virtual mitk::DataNode *GetTargetSegmentationNode();
protected:
AutoSegmentationTool(); // purposely hidden
~AutoSegmentationTool() override;
const char *GetGroup() const override;
- virtual Image::ConstPointer Get3DImage(const Image* image, unsigned int timestep) const;
- virtual Image::ConstPointer Get3DImageByTimePoint(const Image* image, TimePointType timePoint) const;
+ /** Helper that extracts the image for the passed timestep, if the image has multiple time steps.*/
+ static Image::ConstPointer GetImageByTimeStep(const Image* image, unsigned int timestep);
+ /** Helper that extracts the image for the passed time point, if the image has multiple time steps.*/
+ static Image::ConstPointer GetImageByTimePoint(const Image* image, TimePointType timePoint);
bool m_OverwriteExistingSegmentation;
};
} // namespace
#endif
diff --git a/Modules/Segmentation/Interactions/mitkAutoSegmentationWithPreviewTool.cpp b/Modules/Segmentation/Interactions/mitkAutoSegmentationWithPreviewTool.cpp
new file mode 100644
index 0000000000..8e9b4291f7
--- /dev/null
+++ b/Modules/Segmentation/Interactions/mitkAutoSegmentationWithPreviewTool.cpp
@@ -0,0 +1,474 @@
+/*============================================================================
+
+The Medical Imaging Interaction Toolkit (MITK)
+
+Copyright (c) German Cancer Research Center (DKFZ)
+All rights reserved.
+
+Use of this source code is governed by a 3-clause BSD license that can be
+found in the LICENSE file.
+
+============================================================================*/
+
+#include "mitkAutoSegmentationWithPreviewTool.h"
+
+#include "mitkToolManager.h"
+
+#include "mitkColorProperty.h"
+#include "mitkLevelWindowProperty.h"
+#include "mitkProperties.h"
+
+#include "mitkDataStorage.h"
+#include "mitkRenderingManager.h"
+#include
+
+#include "mitkImageAccessByItk.h"
+#include "mitkImageCast.h"
+#include "mitkImageStatisticsHolder.h"
+#include "mitkImageTimeSelector.h"
+#include "mitkLabelSetImage.h"
+#include "mitkMaskAndCutRoiImageFilter.h"
+#include "mitkPadImageFilter.h"
+#include "mitkNodePredicateGeometry.h"
+
+mitk::AutoSegmentationWithPreviewTool::AutoSegmentationWithPreviewTool(bool lazyDynamicPreviews): m_LazyDynamicPreviews(lazyDynamicPreviews)
+{
+ m_ProgressCommand = mitk::ToolCommand::New();
+}
+
+mitk::AutoSegmentationWithPreviewTool::~AutoSegmentationWithPreviewTool()
+{
+}
+
+bool mitk::AutoSegmentationWithPreviewTool::CanHandle(const BaseData* referenceData, const BaseData* workingData) const
+{
+ if (!Superclass::CanHandle(referenceData, workingData))
+ return false;
+
+ if (workingData == nullptr)
+ return true;
+
+ auto* labelSet = dynamic_cast(workingData);
+
+ if (labelSet != nullptr)
+ return true;
+
+ auto* image = dynamic_cast(workingData);
+
+ if (image == nullptr)
+ return false;
+
+ //if it is a normal image and not a label set image is used as working data
+ //it must have the same pixel type as a label set.
+ return MakeScalarPixelType< DefaultSegmentationDataType >() == image->GetPixelType();
+}
+
+void mitk::AutoSegmentationWithPreviewTool::Activated()
+{
+ Superclass::Activated();
+
+ m_ToolManager->RoiDataChanged +=
+ mitk::MessageDelegate(this, &mitk::AutoSegmentationWithPreviewTool::OnRoiDataChanged);
+
+ m_ToolManager->SelectedTimePointChanged +=
+ mitk::MessageDelegate(this, &mitk::AutoSegmentationWithPreviewTool::OnTimePointChanged);
+
+ m_ReferenceDataNode = m_ToolManager->GetReferenceData(0);
+ m_SegmentationInputNode = m_ReferenceDataNode;
+
+ m_LastTimePointOfUpdate = 0;
+
+ if (m_PreviewSegmentationNode.IsNull())
+ {
+ m_PreviewSegmentationNode = DataNode::New();
+ m_PreviewSegmentationNode->SetProperty("color", ColorProperty::New(0.0, 1.0, 0.0));
+ m_PreviewSegmentationNode->SetProperty("name", StringProperty::New(std::string(this->GetName())+" preview"));
+ m_PreviewSegmentationNode->SetProperty("opacity", FloatProperty::New(0.3));
+ m_PreviewSegmentationNode->SetProperty("binary", BoolProperty::New(true));
+ m_PreviewSegmentationNode->SetProperty("helper object", BoolProperty::New(true));
+ }
+
+ if (m_SegmentationInputNode.IsNotNull())
+ {
+ this->ResetPreviewNode();
+ this->InitiateToolByInput();
+ }
+ else
+ {
+ m_ToolManager->ActivateTool(-1);
+ }
+}
+
+void mitk::AutoSegmentationWithPreviewTool::Deactivated()
+{
+ m_ToolManager->RoiDataChanged -=
+ mitk::MessageDelegate(this, &mitk::AutoSegmentationWithPreviewTool::OnRoiDataChanged);
+
+ m_ToolManager->SelectedTimePointChanged -=
+ mitk::MessageDelegate(this, &mitk::AutoSegmentationWithPreviewTool::OnTimePointChanged);
+
+ m_SegmentationInputNode = nullptr;
+ m_ReferenceDataNode = nullptr;
+
+ try
+ {
+ if (DataStorage *storage = m_ToolManager->GetDataStorage())
+ {
+ storage->Remove(m_PreviewSegmentationNode);
+ RenderingManager::GetInstance()->RequestUpdateAll();
+ }
+ }
+ catch (...)
+ {
+ // don't care
+ }
+
+ m_PreviewSegmentationNode->SetData(nullptr);
+
+ Superclass::Deactivated();
+}
+
+void mitk::AutoSegmentationWithPreviewTool::ConfirmSegmentation()
+{
+ if (m_LazyDynamicPreviews && m_CreateAllTimeSteps)
+ { // The tool should create all time steps but is currently in lazy mode,
+ // thus ensure that a preview for all time steps is available.
+ this->UpdatePreview(true);
+ }
+
+ CreateResultSegmentationFromPreview();
+
+ RenderingManager::GetInstance()->RequestUpdateAll();
+
+ if (!m_KeepActiveAfterAccept)
+ {
+ m_ToolManager->ActivateTool(-1);
+ }
+}
+
+void mitk::AutoSegmentationWithPreviewTool::InitiateToolByInput()
+{
+ //default implementation does nothing.
+ //implement in derived classes to change behavior
+}
+
+mitk::Image* mitk::AutoSegmentationWithPreviewTool::GetPreviewSegmentation()
+{
+ if (m_PreviewSegmentationNode.IsNull())
+ {
+ return nullptr;
+ }
+
+ return dynamic_cast(m_PreviewSegmentationNode->GetData());
+}
+
+mitk::DataNode* mitk::AutoSegmentationWithPreviewTool::GetPreviewSegmentationNode()
+{
+ return m_PreviewSegmentationNode;
+}
+
+const mitk::Image* mitk::AutoSegmentationWithPreviewTool::GetSegmentationInput() const
+{
+ if (m_SegmentationInputNode.IsNull())
+ {
+ return nullptr;
+ }
+
+ return dynamic_cast(m_SegmentationInputNode->GetData());
+}
+
+const mitk::Image* mitk::AutoSegmentationWithPreviewTool::GetReferenceData() const
+{
+ if (m_ReferenceDataNode.IsNull())
+ {
+ return nullptr;
+ }
+
+ return dynamic_cast(m_ReferenceDataNode->GetData());
+}
+
+void mitk::AutoSegmentationWithPreviewTool::ResetPreviewNode()
+{
+ itk::RGBPixel previewColor;
+ previewColor[0] = 0.0f;
+ previewColor[1] = 1.0f;
+ previewColor[2] = 0.0f;
+
+ const auto image = this->GetSegmentationInput();
+ if (nullptr != image)
+ {
+ mitk::LabelSetImage::ConstPointer workingImage =
+ dynamic_cast(m_ToolManager->GetWorkingData(0)->GetData());
+
+ if (workingImage.IsNotNull())
+ {
+ auto newPreviewImage = workingImage->Clone();
+ if (newPreviewImage.IsNull())
+ {
+ MITK_ERROR << "Cannot create preview helper objects. Unable to clone working image";
+ return;
+ }
+
+ m_PreviewSegmentationNode->SetData(newPreviewImage);
+
+ // Let's paint the feedback node green...
+ newPreviewImage->GetActiveLabel()->SetColor(previewColor);
+ newPreviewImage->GetActiveLabelSet()->UpdateLookupTable(newPreviewImage->GetActiveLabel()->GetValue());
+ }
+ else
+ {
+ mitk::Image::ConstPointer workingImageBin = dynamic_cast(m_ToolManager->GetWorkingData(0)->GetData());
+ if (workingImageBin.IsNotNull())
+ {
+ auto newPreviewImage = workingImageBin->Clone();
+ if (newPreviewImage.IsNull())
+ {
+ MITK_ERROR << "Cannot create preview helper objects. Unable to clone working image";
+ return;
+ }
+
+ m_PreviewSegmentationNode->SetData(newPreviewImage->Clone());
+ }
+ else
+ {
+ mitkThrow() << "Tool is an invalid state. Cannot setup preview node. Working data is an unsupported class and should have not been accepted by CanHandle().";
+ }
+ }
+
+ m_PreviewSegmentationNode->SetColor(previewColor);
+ m_PreviewSegmentationNode->SetOpacity(0.5);
+
+ int layer(50);
+ m_ReferenceDataNode->GetIntProperty("layer", layer);
+ m_PreviewSegmentationNode->SetIntProperty("layer", layer + 1);
+
+ if (DataStorage *ds = m_ToolManager->GetDataStorage())
+ {
+ if (!ds->Exists(m_PreviewSegmentationNode))
+ ds->Add(m_PreviewSegmentationNode, m_ReferenceDataNode);
+ }
+ }
+}
+
+template
+static void ITKSetVolume(const itk::Image *originalImage,
+ mitk::Image *segmentation,
+ unsigned int timeStep)
+{
+ auto constPixelContainer = originalImage->GetPixelContainer();
+ //have to make a const cast because itk::PixelContainer does not provide a const correct access :(
+ auto pixelContainer = const_cast::PixelContainer*>(constPixelContainer);
+
+ segmentation->SetVolume((void *)pixelContainer->GetBufferPointer(), timeStep);
+}
+
+void mitk::AutoSegmentationWithPreviewTool::TransferImageAtTimeStep(const Image* sourceImage, Image* destinationImage, const TimeStepType timeStep)
+{
+ try
+ {
+ Image::ConstPointer image3D = this->GetImageByTimeStep(sourceImage, timeStep);
+
+ if (image3D->GetPixelType() != destinationImage->GetPixelType())
+ {
+ mitkThrow() << "Cannot transfer images. Tool is in an invalid state, source image and destination image do not have the same pixel type. "
+ << "Source pixel type: " << sourceImage->GetPixelType().GetTypeAsString()
+ << "; destination pixel type: " << destinationImage->GetPixelType().GetTypeAsString();
+ }
+
+ if (!Equal(*(sourceImage->GetGeometry(timeStep)), *(destinationImage->GetGeometry(timeStep)), NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_PRECISION, false))
+ {
+ mitkThrow() << "Cannot transfer images. Tool is in an invalid state, source image and destination image do not have the same geometry.";
+ }
+
+ if (image3D->GetDimension() == 2)
+ {
+ AccessFixedDimensionByItk_2(
+ image3D, ITKSetVolume, 2, destinationImage, timeStep);
+ }
+ else
+ {
+ AccessFixedDimensionByItk_2(
+ image3D, ITKSetVolume, 3, destinationImage, timeStep);
+ }
+ }
+ catch (...)
+ {
+ Tool::ErrorMessage("Error accessing single time steps of the original image. Cannot create segmentation.");
+ throw;
+ }
+}
+
+void mitk::AutoSegmentationWithPreviewTool::CreateResultSegmentationFromPreview()
+{
+ const auto segInput = this->GetSegmentationInput();
+ auto previewImage = this->GetPreviewSegmentation();
+ if (nullptr != segInput && nullptr != previewImage)
+ {
+ DataNode::Pointer resultSegmentationNode = GetTargetSegmentationNode();
+
+ if (resultSegmentationNode.IsNotNull())
+ {
+ const auto timePoint = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint();
+ auto resultSegmentation = dynamic_cast(resultSegmentationNode->GetData());
+
+ // REMARK: the following code in this scope assumes that previewImage and resultSegmentation
+ // are clones of the working image (segmentation provided to the tool). Therefore they have
+ // the same time geometry.
+ if (previewImage->GetTimeSteps() != resultSegmentation->GetTimeSteps())
+ {
+ mitkThrow() << "Cannot perform threshold. Internal tool state is invalid."
+ << " Preview segmentation and segmentation result image have different time geometries.";
+ }
+
+ if (m_CreateAllTimeSteps)
+ {
+ for (unsigned int timeStep = 0; timeStep < previewImage->GetTimeSteps(); ++timeStep)
+ {
+ TransferImageAtTimeStep(previewImage, resultSegmentation, timeStep);
+ }
+ }
+ else
+ {
+ const auto timeStep = resultSegmentation->GetTimeGeometry()->TimePointToTimeStep(timePoint);
+ TransferImageAtTimeStep(previewImage, resultSegmentation, timeStep);
+ }
+
+ // since we are maybe working on a smaller image, pad it to the size of the original image
+ if (m_ReferenceDataNode.GetPointer() != m_SegmentationInputNode.GetPointer())
+ {
+ mitk::PadImageFilter::Pointer padFilter = mitk::PadImageFilter::New();
+
+ padFilter->SetInput(0, resultSegmentation);
+ padFilter->SetInput(1, dynamic_cast(m_ReferenceDataNode->GetData()));
+ padFilter->SetBinaryFilter(true);
+ padFilter->SetUpperThreshold(1);
+ padFilter->SetLowerThreshold(1);
+ padFilter->Update();
+
+ resultSegmentationNode->SetData(padFilter->GetOutput());
+ }
+
+ m_ToolManager->SetWorkingData(resultSegmentationNode);
+ m_ToolManager->GetWorkingData(0)->Modified();
+ }
+ }
+}
+
+void mitk::AutoSegmentationWithPreviewTool::OnRoiDataChanged()
+{
+ mitk::DataNode::ConstPointer node = m_ToolManager->GetRoiData(0);
+
+ if (node.IsNotNull())
+ {
+ mitk::MaskAndCutRoiImageFilter::Pointer roiFilter = mitk::MaskAndCutRoiImageFilter::New();
+ mitk::Image::Pointer image = dynamic_cast(m_SegmentationInputNode->GetData());
+
+ if (image.IsNull())
+ return;
+
+ roiFilter->SetInput(image);
+ roiFilter->SetRegionOfInterest(node->GetData());
+ roiFilter->Update();
+
+ mitk::DataNode::Pointer tmpNode = mitk::DataNode::New();
+ tmpNode->SetData(roiFilter->GetOutput());
+
+ m_SegmentationInputNode = tmpNode;
+ }
+ else
+ m_SegmentationInputNode = m_ReferenceDataNode;
+
+ this->ResetPreviewNode();
+ this->InitiateToolByInput();
+ this->UpdatePreview();
+}
+
+void mitk::AutoSegmentationWithPreviewTool::OnTimePointChanged()
+{
+ if (m_IsTimePointChangeAware && m_PreviewSegmentationNode.IsNotNull() && m_SegmentationInputNode.IsNotNull())
+ {
+ const auto timePoint = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint();
+
+ const bool isStaticSegOnDynamicImage = m_PreviewSegmentationNode->GetData()->GetTimeSteps() == 1 && m_SegmentationInputNode->GetData()->GetTimeSteps() > 1;
+ if (timePoint!=m_LastTimePointOfUpdate && (isStaticSegOnDynamicImage || m_LazyDynamicPreviews))
+ { //we only need to update either because we are lazzy
+ //or because we have a static segmentation with a dynamic image
+ this->UpdatePreview();
+ }
+ }
+}
+
+void mitk::AutoSegmentationWithPreviewTool::UpdatePreview(bool ignoreLazyPreviewSetting)
+{
+ const auto inputImage = this->GetSegmentationInput();
+ auto previewImage = this->GetPreviewSegmentation();
+ int progress_steps = 200;
+
+ this->UpdatePrepare();
+
+ const auto timePoint = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint();
+
+ try
+ {
+ this->CurrentlyBusy.Send(true);
+ if (nullptr != inputImage && nullptr != previewImage)
+ {
+ m_ProgressCommand->AddStepsToDo(progress_steps);
+
+ if (previewImage->GetTimeSteps() > 1 && (ignoreLazyPreviewSetting || !m_LazyDynamicPreviews))
+ {
+ for (unsigned int timeStep = 0; timeStep < inputImage->GetTimeSteps(); ++timeStep)
+ {
+ auto feedBackImage3D = this->GetImageByTimeStep(inputImage, timeStep);
+
+ this->DoUpdatePreview(feedBackImage3D, previewImage, timeStep);
+ }
+ }
+ else
+ {
+ auto feedBackImage3D = this->GetImageByTimePoint(inputImage, timePoint);
+ auto timeStep = previewImage->GetTimeGeometry()->TimePointToTimeStep(timePoint);
+
+ this->DoUpdatePreview(feedBackImage3D, previewImage, timeStep);
+ }
+ RenderingManager::GetInstance()->RequestUpdateAll();
+ }
+ }
+ catch (itk::ExceptionObject & excep)
+ {
+ MITK_ERROR << "Exception caught: " << excep.GetDescription();
+
+ m_ProgressCommand->SetProgress(progress_steps);
+
+ std::string msg = excep.GetDescription();
+ ErrorMessage.Send(msg);
+ }
+ catch (...)
+ {
+ m_ProgressCommand->SetProgress(progress_steps);
+ CurrentlyBusy.Send(false);
+ throw;
+ }
+
+ this->UpdateCleanUp();
+ m_LastTimePointOfUpdate = timePoint;
+ m_ProgressCommand->SetProgress(progress_steps);
+ CurrentlyBusy.Send(false);
+}
+
+void mitk::AutoSegmentationWithPreviewTool::UpdatePrepare()
+{
+ // default implementation does nothing
+ //reimplement in derived classes for special behavior
+}
+
+void mitk::AutoSegmentationWithPreviewTool::UpdateCleanUp()
+{
+ // default implementation does nothing
+ //reimplement in derived classes for special behavior
+}
+
+mitk::TimePointType mitk::AutoSegmentationWithPreviewTool::GetLastTimePointOfUpdate() const
+{
+ return m_LastTimePointOfUpdate;
+}
diff --git a/Modules/Segmentation/Interactions/mitkAutoSegmentationWithPreviewTool.h b/Modules/Segmentation/Interactions/mitkAutoSegmentationWithPreviewTool.h
new file mode 100644
index 0000000000..848ff0c005
--- /dev/null
+++ b/Modules/Segmentation/Interactions/mitkAutoSegmentationWithPreviewTool.h
@@ -0,0 +1,152 @@
+/*============================================================================
+
+The Medical Imaging Interaction Toolkit (MITK)
+
+Copyright (c) German Cancer Research Center (DKFZ)
+All rights reserved.
+
+Use of this source code is governed by a 3-clause BSD license that can be
+found in the LICENSE file.
+
+============================================================================*/
+
+#ifndef mitkAutoSegmentationWithPreviewTool_h_Included
+#define mitkAutoSegmentationWithPreviewTool_h_Included
+
+#include "mitkAutoSegmentationTool.h"
+#include "mitkCommon.h"
+#include "mitkDataNode.h"
+#include "mitkToolCommand.h"
+#include
+
+namespace mitk
+{
+ /**
+ \brief Base class for any auto segmentation tool that provides a preview of the new segmentation.
+
+ This tool class implements a lot basic logic to handle auto segmentation tools with preview,
+ Time point and ROI support. Derived classes will ask to update the segmentation preview if needed
+ (e.g. because the ROI or the current time point has changed) or because derived tools
+ indicated the need to update themselves.
+ This class also takes care to properly transfer a confirmed preview into the segementation
+ result.
+
+ \ingroup ToolManagerEtAl
+ \sa mitk::Tool
+ \sa QmitkInteractiveSegmentation
+ */
+ class MITKSEGMENTATION_EXPORT AutoSegmentationWithPreviewTool : public AutoSegmentationTool
+ {
+ public:
+
+ mitkClassMacro(AutoSegmentationWithPreviewTool, AutoSegmentationTool);
+
+ void Activated() override;
+ void Deactivated() override;
+
+ void ConfirmSegmentation();
+
+ itkSetMacro(CreateAllTimeSteps, bool);
+ itkGetMacro(CreateAllTimeSteps, bool);
+ itkBooleanMacro(CreateAllTimeSteps);
+
+ itkSetMacro(KeepActiveAfterAccept, bool);
+ itkGetMacro(KeepActiveAfterAccept, bool);
+ itkBooleanMacro(KeepActiveAfterAccept);
+
+ itkSetMacro(IsTimePointChangeAware, bool);
+ itkGetMacro(IsTimePointChangeAware, bool);
+ itkBooleanMacro(IsTimePointChangeAware);
+
+ bool CanHandle(const BaseData* referenceData, const BaseData* workingData) const override;
+
+ /** Triggers the actualization of the preview
+ * @param ignoreLazyPreviewSetting If set true UpdatePreview will always
+ * generate the preview for all time steps. If set to false, UpdatePreview
+ * will regard the setting specified by the constructor.
+ * To define the update generation for time steps implement DoUpdatePreview.
+ * To alter what should be done directly before or after the update of the preview,
+ * reimplement UpdatePrepare() or UpdateCleanUp().*/
+ void UpdatePreview(bool ignoreLazyPreviewSetting = false);
+
+ protected:
+ mitk::ToolCommand::Pointer m_ProgressCommand;
+
+ /** Member is always called if GetSegmentationInput() has changed
+ * (e.g. because a new ROI was defined, or on activation) to give derived
+ * classes the posibility to initiate their state accordingly.
+ * Reimplement this function to implement special behavior.
+ */
+ virtual void InitiateToolByInput();
+
+ virtual void UpdatePrepare();
+ virtual void UpdateCleanUp();
+
+ /** This function does the real work. Here the preview for a given
+ * input image should be computed and stored in the also passed
+ * preview image at the passed time step.
+ */
+ virtual void DoUpdatePreview(const Image* inputAtTimeStep, Image* previewImage, TimeStepType timeStep) = 0;
+
+ AutoSegmentationWithPreviewTool(bool lazyDynamicPreviews = false);
+ ~AutoSegmentationWithPreviewTool() override;
+
+ /** Returns the image that contains the preview of the current segmentation.
+ * Returns null if the node is not set or does not contain an image.*/
+ Image* GetPreviewSegmentation();
+ DataNode* GetPreviewSegmentationNode();
+
+ /** Returns the input that should be used for any segmentation/preview or tool update.
+ * It is either the data of ReferenceDataNode itself or a part of it defined by a ROI mask
+ * provided by the tool manager. Derived classes should regard this as the relevant
+ * input data for any processing.
+ * Returns null if the node is not set or does not contain an image.*/
+ const Image* GetSegmentationInput() const;
+
+ /** Returns the image that is provided by the ReferenceDataNode.
+ * Returns null if the node is not set or does not contain an image.*/
+ const Image* GetReferenceData() const;
+
+ /** Resets the preview node so it is empty and ready to be filled by the tool*/
+ void ResetPreviewNode();
+
+ TimePointType GetLastTimePointOfUpdate() const;
+
+ private:
+ void TransferImageAtTimeStep(const Image* sourceImage, Image* destinationImage, const TimeStepType timeStep);
+
+ void CreateResultSegmentationFromPreview();
+
+ void OnRoiDataChanged();
+ void OnTimePointChanged();
+
+ /** Node that containes the preview data generated and managed by this class or derived ones.*/
+ DataNode::Pointer m_PreviewSegmentationNode;
+ /** The reference data recieved from ToolManager::GetReferenceData when tool was activated.*/
+ DataNode::Pointer m_ReferenceDataNode;
+ /** Node that containes the data that should be used as input for any auto segmentation. It might
+ * be the same like m_ReferenceDataNode (if no ROI is set) or a sub region (if ROI is set).*/
+ DataNode::Pointer m_SegmentationInputNode;
+
+ /** Indicates if Accepting the threshold should transfer/create the segmentations
+ of all time steps (true) or only of the currently selected timepoint (false).*/
+ bool m_CreateAllTimeSteps = false;
+
+ /** Indicates if the tool should kept active after accepting the segmentation or not.*/
+ bool m_KeepActiveAfterAccept = false;
+
+ /** Relevant if the working data / preview image has multiple time steps (dynamic segmentations).
+ * This flag has to be set by derived classes accordingly to there way to generate dynamic previews.
+ * If LazyDynamicPreview is true, the tool generates only the preview for the current time step.
+ * Therefore it always has to update the preview if current time point has changed and it has to (re)compute
+ * all timeframes if ConfirmSegmentation() is called.*/
+ bool m_LazyDynamicPreviews = false;
+
+ bool m_IsTimePointChangeAware = true;
+
+ TimePointType m_LastTimePointOfUpdate = 0.;
+ };
+
+} // namespace
+
+#endif
diff --git a/Modules/Segmentation/Interactions/mitkBinaryThresholdBaseTool.cpp b/Modules/Segmentation/Interactions/mitkBinaryThresholdBaseTool.cpp
index f48232e055..a8ee655db0 100644
--- a/Modules/Segmentation/Interactions/mitkBinaryThresholdBaseTool.cpp
+++ b/Modules/Segmentation/Interactions/mitkBinaryThresholdBaseTool.cpp
@@ -1,466 +1,126 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#include "mitkBinaryThresholdBaseTool.h"
-#include "mitkToolManager.h"
-
-#include "mitkColorProperty.h"
-#include "mitkLevelWindowProperty.h"
-#include "mitkProperties.h"
-
-#include "mitkDataStorage.h"
-#include "mitkRenderingManager.h"
-#include
-
#include "mitkImageAccessByItk.h"
#include "mitkImageCast.h"
#include "mitkImageStatisticsHolder.h"
-#include "mitkImageTimeSelector.h"
#include "mitkLabelSetImage.h"
-#include "mitkMaskAndCutRoiImageFilter.h"
-#include "mitkPadImageFilter.h"
#include
#include
mitk::BinaryThresholdBaseTool::BinaryThresholdBaseTool()
: m_SensibleMinimumThresholdValue(-100),
m_SensibleMaximumThresholdValue(+100),
m_CurrentLowerThresholdValue(1),
m_CurrentUpperThresholdValue(1)
{
- m_ThresholdFeedbackNode = DataNode::New();
- m_ThresholdFeedbackNode->SetProperty("color", ColorProperty::New(0.0, 1.0, 0.0));
- m_ThresholdFeedbackNode->SetProperty("name", StringProperty::New("Thresholding feedback"));
- m_ThresholdFeedbackNode->SetProperty("opacity", FloatProperty::New(0.3));
- m_ThresholdFeedbackNode->SetProperty("binary", BoolProperty::New(true));
- m_ThresholdFeedbackNode->SetProperty("helper object", BoolProperty::New(true));
}
mitk::BinaryThresholdBaseTool::~BinaryThresholdBaseTool()
{
}
-void mitk::BinaryThresholdBaseTool::Activated()
-{
- Superclass::Activated();
-
- m_ToolManager->RoiDataChanged +=
- mitk::MessageDelegate(this, &mitk::BinaryThresholdBaseTool::OnRoiDataChanged);
-
- m_ToolManager->SelectedTimePointChanged +=
- mitk::MessageDelegate(this, &mitk::BinaryThresholdBaseTool::OnTimePointChanged);
-
- m_OriginalImageNode = m_ToolManager->GetReferenceData(0);
- m_NodeForThresholding = m_OriginalImageNode;
-
- if (m_NodeForThresholding.IsNotNull())
- {
- SetupPreviewNode();
- }
- else
- {
- m_ToolManager->ActivateTool(-1);
- }
-}
-
-void mitk::BinaryThresholdBaseTool::Deactivated()
-{
- m_ToolManager->RoiDataChanged -=
- mitk::MessageDelegate(this, &mitk::BinaryThresholdBaseTool::OnRoiDataChanged);
-
- m_ToolManager->SelectedTimePointChanged -=
- mitk::MessageDelegate(this, &mitk::BinaryThresholdBaseTool::OnTimePointChanged);
-
- m_NodeForThresholding = nullptr;
- m_OriginalImageNode = nullptr;
- try
- {
- if (DataStorage *storage = m_ToolManager->GetDataStorage())
- {
- storage->Remove(m_ThresholdFeedbackNode);
- RenderingManager::GetInstance()->RequestUpdateAll();
- }
- }
- catch (...)
- {
- // don't care
- }
- m_ThresholdFeedbackNode->SetData(nullptr);
-
- Superclass::Deactivated();
-}
-
void mitk::BinaryThresholdBaseTool::SetThresholdValues(double lower, double upper)
{
/* If value is not in the min/max range, do nothing. In that case, this
method will be called again with a proper value right after. The only
known case where this happens is with an [0.0, 1.0[ image, where value
could be an epsilon greater than the max. */
if (lower < m_SensibleMinimumThresholdValue
|| lower > m_SensibleMaximumThresholdValue
|| upper < m_SensibleMinimumThresholdValue
|| upper > m_SensibleMaximumThresholdValue)
{
return;
}
m_CurrentLowerThresholdValue = lower;
m_CurrentUpperThresholdValue = upper;
- if (m_ThresholdFeedbackNode.IsNotNull())
+ if (nullptr != this->GetPreviewSegmentation())
{
-
UpdatePreview();
}
}
-void mitk::BinaryThresholdBaseTool::AcceptCurrentThresholdValue()
-{
- CreateNewSegmentationFromThreshold();
-
- RenderingManager::GetInstance()->RequestUpdateAll();
- m_ToolManager->ActivateTool(-1);
-}
-
-void mitk::BinaryThresholdBaseTool::CancelThresholding()
+void mitk::BinaryThresholdBaseTool::InitiateToolByInput()
{
- m_ToolManager->ActivateTool(-1);
-}
-
-void mitk::BinaryThresholdBaseTool::SetupPreviewNode()
-{
- itk::RGBPixel pixel;
- pixel[0] = 0.0f;
- pixel[1] = 1.0f;
- pixel[2] = 0.0f;
-
- if (m_NodeForThresholding.IsNotNull())
+ const auto referenceImage = this->GetReferenceData();
+ if (nullptr != referenceImage)
{
- Image::Pointer image = dynamic_cast(m_NodeForThresholding->GetData());
- Image::Pointer originalImage = dynamic_cast(m_OriginalImageNode->GetData());
-
- if (image.IsNotNull())
+ m_SensibleMinimumThresholdValue = std::numeric_limits::max();
+ m_SensibleMaximumThresholdValue = std::numeric_limits::lowest();
+ Image::StatisticsHolderPointer statistics = referenceImage->GetStatistics();
+ for (unsigned int ts = 0; ts < referenceImage->GetTimeSteps(); ++ts)
{
- mitk::LabelSetImage::Pointer workingImage =
- dynamic_cast(m_ToolManager->GetWorkingData(0)->GetData());
-
- if (workingImage.IsNotNull())
- {
- m_ThresholdFeedbackNode->SetData(workingImage->Clone());
- m_IsOldBinary = false;
-
- // Let's paint the feedback node green...
- mitk::LabelSetImage::Pointer previewImage =
- dynamic_cast(m_ThresholdFeedbackNode->GetData());
-
- if (previewImage.IsNull())
- {
- MITK_ERROR << "Cannot create helper objects.";
- return;
- }
-
- previewImage->GetActiveLabel()->SetColor(pixel);
- previewImage->GetActiveLabelSet()->UpdateLookupTable(previewImage->GetActiveLabel()->GetValue());
- }
- else
- {
- mitk::Image::Pointer workingImageBin = dynamic_cast(m_ToolManager->GetWorkingData(0)->GetData());
- if (workingImageBin)
- {
- m_ThresholdFeedbackNode->SetData(workingImageBin->Clone());
- m_IsOldBinary = true;
- }
- else
- m_ThresholdFeedbackNode->SetData(mitk::Image::New());
- }
-
- m_ThresholdFeedbackNode->SetColor(pixel);
- m_ThresholdFeedbackNode->SetOpacity(0.5);
-
- int layer(50);
- m_NodeForThresholding->GetIntProperty("layer", layer);
- m_ThresholdFeedbackNode->SetIntProperty("layer", layer + 1);
-
- if (DataStorage *ds = m_ToolManager->GetDataStorage())
- {
- if (!ds->Exists(m_ThresholdFeedbackNode))
- ds->Add(m_ThresholdFeedbackNode, m_OriginalImageNode);
- }
-
- if (image.GetPointer() == originalImage.GetPointer())
- {
- m_SensibleMinimumThresholdValue = std::numeric_limits::max();
- m_SensibleMaximumThresholdValue = std::numeric_limits::lowest();
- Image::StatisticsHolderPointer statistics = originalImage->GetStatistics();
- for (unsigned int ts = 0; ts < originalImage->GetTimeSteps(); ++ts)
- {
- m_SensibleMinimumThresholdValue = std::min(m_SensibleMinimumThresholdValue, static_cast(statistics->GetScalarValueMin()));
- m_SensibleMaximumThresholdValue = std::max(m_SensibleMaximumThresholdValue, static_cast(statistics->GetScalarValueMax()));
- }
- }
-
- if (m_LockedUpperThreshold)
- {
- m_CurrentLowerThresholdValue = (m_SensibleMaximumThresholdValue + m_SensibleMinimumThresholdValue) / 2.0;
- m_CurrentUpperThresholdValue = m_SensibleMaximumThresholdValue;
- }
- else
- {
- double range = m_SensibleMaximumThresholdValue - m_SensibleMinimumThresholdValue;
- m_CurrentLowerThresholdValue = m_SensibleMinimumThresholdValue + range / 3.0;
- m_CurrentUpperThresholdValue = m_SensibleMinimumThresholdValue + 2 * range / 3.0;
- }
-
- bool isFloatImage = false;
- if ((originalImage->GetPixelType().GetPixelType() == itk::ImageIOBase::SCALAR) &&
- (originalImage->GetPixelType().GetComponentType() == itk::ImageIOBase::FLOAT ||
- originalImage->GetPixelType().GetComponentType() == itk::ImageIOBase::DOUBLE))
- {
- isFloatImage = true;
- }
-
- IntervalBordersChanged.Send(m_SensibleMinimumThresholdValue, m_SensibleMaximumThresholdValue, isFloatImage);
- ThresholdingValuesChanged.Send(m_CurrentLowerThresholdValue, m_CurrentUpperThresholdValue);
+ m_SensibleMinimumThresholdValue = std::min(m_SensibleMinimumThresholdValue, static_cast(statistics->GetScalarValueMin()));
+ m_SensibleMaximumThresholdValue = std::max(m_SensibleMaximumThresholdValue, static_cast(statistics->GetScalarValueMax()));
}
- }
-}
-template
-static void ITKSetVolume(const itk::Image *originalImage,
- mitk::Image *segmentation,
- unsigned int timeStep)
-{
- auto constPixelContainer = originalImage->GetPixelContainer();
- //have to make a const cast because itk::PixelContainer does not provide a const correct access :(
- auto pixelContainer = const_cast::PixelContainer*>(constPixelContainer);
-
- segmentation->SetVolume((void *)pixelContainer->GetBufferPointer(), timeStep);
-}
-
-void mitk::BinaryThresholdBaseTool::TransferImageAtTimeStep(const Image* sourceImage, Image* destinationImage, const TimeStepType timeStep)
-{
- try
- {
- Image::ConstPointer image3D = this->Get3DImage(sourceImage, timeStep);
-
- if (image3D->GetDimension() == 2)
+ if (m_LockedUpperThreshold)
{
- AccessFixedDimensionByItk_2(
- image3D, ITKSetVolume, 2, destinationImage, timeStep);
+ m_CurrentLowerThresholdValue = (m_SensibleMaximumThresholdValue + m_SensibleMinimumThresholdValue) / 2.0;
+ m_CurrentUpperThresholdValue = m_SensibleMaximumThresholdValue;
}
else
{
- AccessFixedDimensionByItk_2(
- image3D, ITKSetVolume, 3, destinationImage, timeStep);
+ double range = m_SensibleMaximumThresholdValue - m_SensibleMinimumThresholdValue;
+ m_CurrentLowerThresholdValue = m_SensibleMinimumThresholdValue + range / 3.0;
+ m_CurrentUpperThresholdValue = m_SensibleMinimumThresholdValue + 2 * range / 3.0;
}
- }
- catch (...)
- {
- Tool::ErrorMessage("Error accessing single time steps of the original image. Cannot create segmentation.");
- }
-}
-void mitk::BinaryThresholdBaseTool::CreateNewSegmentationFromThreshold()
-{
- if (m_NodeForThresholding.IsNotNull() && m_ThresholdFeedbackNode.IsNotNull())
- {
- Image::Pointer feedBackImage = dynamic_cast(m_ThresholdFeedbackNode->GetData());
- if (feedBackImage.IsNotNull())
+ bool isFloatImage = false;
+ if ((referenceImage->GetPixelType().GetPixelType() == itk::ImageIOBase::SCALAR) &&
+ (referenceImage->GetPixelType().GetComponentType() == itk::ImageIOBase::FLOAT ||
+ referenceImage->GetPixelType().GetComponentType() == itk::ImageIOBase::DOUBLE))
{
- // create a new image of the same dimensions and smallest possible pixel type
- DataNode::Pointer emptySegmentationNode = GetTargetSegmentationNode();
-
- if (emptySegmentationNode)
- {
- const auto timePoint = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint();
- auto emptySegmentation = dynamic_cast(emptySegmentationNode->GetData());
-
- // actually perform a thresholding
- // REMARK: the following code in this scope assumes that feedBackImage and emptySegmentationImage
- // are clones of the working image (segmentation provided to the tool). Therefor the have the same
- // time geometry.
- if (feedBackImage->GetTimeSteps() != emptySegmentation->GetTimeSteps())
- {
- mitkThrow() << "Cannot performe threshold. Internal tool state is invalid."
- << " Preview segmentation and segmentation result image have different time geometries.";
- }
-
- if (m_CreateAllTimeSteps)
- {
- for (unsigned int timeStep = 0; timeStep < feedBackImage->GetTimeSteps(); ++timeStep)
- {
- TransferImageAtTimeStep(feedBackImage, emptySegmentation, timeStep);
- }
- }
- else
- {
- const auto timeStep = emptySegmentation->GetTimeGeometry()->TimePointToTimeStep(timePoint);
- TransferImageAtTimeStep(feedBackImage, emptySegmentation, timeStep);
- }
-
- // since we are maybe working on a smaller image, pad it to the size of the original image
- if (m_OriginalImageNode.GetPointer() != m_NodeForThresholding.GetPointer())
- {
- mitk::PadImageFilter::Pointer padFilter = mitk::PadImageFilter::New();
-
- padFilter->SetInput(0, emptySegmentation);
- padFilter->SetInput(1, dynamic_cast(m_OriginalImageNode->GetData()));
- padFilter->SetBinaryFilter(true);
- padFilter->SetUpperThreshold(1);
- padFilter->SetLowerThreshold(1);
- padFilter->Update();
-
- emptySegmentationNode->SetData(padFilter->GetOutput());
- }
-
- m_ToolManager->SetWorkingData(emptySegmentationNode);
- m_ToolManager->GetWorkingData(0)->Modified();
- }
+ isFloatImage = true;
}
- }
-}
-
-void mitk::BinaryThresholdBaseTool::OnRoiDataChanged()
-{
- mitk::DataNode::Pointer node = m_ToolManager->GetRoiData(0);
-
- if (node.IsNotNull())
- {
- mitk::MaskAndCutRoiImageFilter::Pointer roiFilter = mitk::MaskAndCutRoiImageFilter::New();
- mitk::Image::Pointer image = dynamic_cast(m_NodeForThresholding->GetData());
-
- if (image.IsNull())
- return;
- roiFilter->SetInput(image);
- roiFilter->SetRegionOfInterest(node->GetData());
- roiFilter->Update();
-
- mitk::DataNode::Pointer tmpNode = mitk::DataNode::New();
- tmpNode->SetData(roiFilter->GetOutput());
-
- m_SensibleMinimumThresholdValue = static_cast(roiFilter->GetMinValue());
- m_SensibleMaximumThresholdValue = static_cast(roiFilter->GetMaxValue());
-
- m_NodeForThresholding = tmpNode;
- }
- else
- m_NodeForThresholding = m_OriginalImageNode;
-
- this->SetupPreviewNode();
- this->UpdatePreview();
-}
-
-void mitk::BinaryThresholdBaseTool::OnTimePointChanged()
-{
- if (m_ThresholdFeedbackNode.IsNotNull() && m_NodeForThresholding.IsNotNull())
- {
- if (m_ThresholdFeedbackNode->GetData()->GetTimeSteps() == 1)
- {
- this->UpdatePreview();
- }
+ IntervalBordersChanged.Send(m_SensibleMinimumThresholdValue, m_SensibleMaximumThresholdValue, isFloatImage);
+ ThresholdingValuesChanged.Send(m_CurrentLowerThresholdValue, m_CurrentUpperThresholdValue);
}
}
template
static void ITKThresholding(const itk::Image *originalImage,
mitk::Image *segmentation,
double lower,
double upper,
unsigned int timeStep)
{
typedef itk::Image ImageType;
typedef itk::Image SegmentationType;
typedef itk::BinaryThresholdImageFilter ThresholdFilterType;
typename ThresholdFilterType::Pointer filter = ThresholdFilterType::New();
filter->SetInput(originalImage);
filter->SetLowerThreshold(lower);
filter->SetUpperThreshold(upper);
filter->SetInsideValue(1);
filter->SetOutsideValue(0);
filter->Update();
segmentation->SetVolume((void *)(filter->GetOutput()->GetPixelContainer()->GetBufferPointer()), timeStep);
}
-template
-static void ITKThresholdingOldBinary(const itk::Image *originalImage,
- mitk::Image *segmentation,
- double lower,
- double upper,
- unsigned int timeStep)
+void mitk::BinaryThresholdBaseTool::DoUpdatePreview(const Image* inputAtTimeStep, Image* previewImage, TimeStepType timeStep)
{
- typedef itk::Image ImageType;
- typedef itk::Image SegmentationType;
- typedef itk::BinaryThresholdImageFilter ThresholdFilterType;
-
- typename ThresholdFilterType::Pointer filter = ThresholdFilterType::New();
- filter->SetInput(originalImage);
- filter->SetLowerThreshold(lower);
- filter->SetUpperThreshold(upper);
- filter->SetInsideValue(1);
- filter->SetOutsideValue(0);
- filter->Update();
-
- segmentation->SetVolume((void *)(filter->GetOutput()->GetPixelContainer()->GetBufferPointer()), timeStep);
-}
-
-void mitk::BinaryThresholdBaseTool::UpdatePreview()
-{
- mitk::Image::Pointer thresholdImage = dynamic_cast(m_NodeForThresholding->GetData());
- mitk::Image::Pointer previewImage = dynamic_cast(m_ThresholdFeedbackNode->GetData());
- if (thresholdImage && previewImage)
+ if (nullptr != inputAtTimeStep && nullptr != previewImage)
{
- if (previewImage->GetTimeSteps() > 1)
- {
- for (unsigned int timeStep = 0; timeStep < thresholdImage->GetTimeSteps(); ++timeStep)
- {
- auto feedBackImage3D = this->Get3DImage(thresholdImage, timeStep);
-
- if (m_IsOldBinary)
- {
- AccessByItk_n(feedBackImage3D,
- ITKThresholdingOldBinary,
- (previewImage, m_CurrentLowerThresholdValue, m_CurrentUpperThresholdValue, timeStep));
- }
- else
- {
- AccessByItk_n(feedBackImage3D,
- ITKThresholding,
- (previewImage, m_CurrentLowerThresholdValue, m_CurrentUpperThresholdValue, timeStep));
- }
- }
- }
- else
- {
- const auto timePoint = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint();
- auto feedBackImage3D = this->Get3DImageByTimePoint(thresholdImage, timePoint);
- auto timeStep = previewImage->GetTimeGeometry()->TimePointToTimeStep(timePoint);
-
- if (m_IsOldBinary)
- {
- AccessByItk_n(feedBackImage3D,
- ITKThresholdingOldBinary,
- (previewImage, m_CurrentLowerThresholdValue, m_CurrentUpperThresholdValue, timeStep));
- }
- else
- {
- AccessByItk_n(feedBackImage3D,
- ITKThresholding,
- (previewImage, m_CurrentLowerThresholdValue, m_CurrentUpperThresholdValue, timeStep));
- }
- }
- RenderingManager::GetInstance()->RequestUpdateAll();
+ AccessByItk_n(inputAtTimeStep,
+ ITKThresholding,
+ (previewImage, m_CurrentLowerThresholdValue, m_CurrentUpperThresholdValue, timeStep));
}
}
diff --git a/Modules/Segmentation/Interactions/mitkBinaryThresholdBaseTool.h b/Modules/Segmentation/Interactions/mitkBinaryThresholdBaseTool.h
index dece9ae498..cdc15f18be 100644
--- a/Modules/Segmentation/Interactions/mitkBinaryThresholdBaseTool.h
+++ b/Modules/Segmentation/Interactions/mitkBinaryThresholdBaseTool.h
@@ -1,98 +1,70 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#ifndef mitkBinaryThresholdBaseTool_h_Included
#define mitkBinaryThresholdBaseTool_h_Included
-#include "mitkAutoSegmentationTool.h"
+#include "mitkAutoSegmentationWithPreviewTool.h"
#include "mitkCommon.h"
#include "mitkDataNode.h"
#include
#include
#include
namespace mitk
{
/**
\brief Base class for binary threshold tools.
\ingroup ToolManagerEtAl
\sa mitk::Tool
\sa QmitkInteractiveSegmentation
*/
- class MITKSEGMENTATION_EXPORT BinaryThresholdBaseTool : public AutoSegmentationTool
+ class MITKSEGMENTATION_EXPORT BinaryThresholdBaseTool : public AutoSegmentationWithPreviewTool
{
public:
Message3 IntervalBordersChanged;
Message2 ThresholdingValuesChanged;
- mitkClassMacro(BinaryThresholdBaseTool, AutoSegmentationTool);
-
- void Activated() override;
- void Deactivated() override;
+ mitkClassMacro(BinaryThresholdBaseTool, AutoSegmentationWithPreviewTool);
virtual void SetThresholdValues(double lower, double upper);
- virtual void AcceptCurrentThresholdValue();
- virtual void CancelThresholding();
-
- itkSetMacro(CreateAllTimeSteps, bool);
- itkGetMacro(CreateAllTimeSteps, bool);
- itkBooleanMacro(CreateAllTimeSteps);
-
protected:
BinaryThresholdBaseTool(); // purposely hidden
~BinaryThresholdBaseTool() override;
itkSetMacro(LockedUpperThreshold, bool);
itkGetMacro(LockedUpperThreshold, bool);
itkBooleanMacro(LockedUpperThreshold);
itkGetMacro(SensibleMinimumThresholdValue, ScalarType);
itkGetMacro(SensibleMaximumThresholdValue, ScalarType);
- private:
- void SetupPreviewNode();
-
- void TransferImageAtTimeStep(const Image* sourceImage, Image* destinationImage, const TimeStepType timeStep);
-
- void CreateNewSegmentationFromThreshold();
-
- void OnRoiDataChanged();
- void OnTimePointChanged();
-
- void UpdatePreview();
-
- DataNode::Pointer m_ThresholdFeedbackNode;
- DataNode::Pointer m_OriginalImageNode;
- DataNode::Pointer m_NodeForThresholding;
+ void InitiateToolByInput() override;
+ void DoUpdatePreview(const Image* inputAtTimeStep, Image* previewImage, TimeStepType timeStep) override;
+ private:
ScalarType m_SensibleMinimumThresholdValue;
ScalarType m_SensibleMaximumThresholdValue;
ScalarType m_CurrentLowerThresholdValue;
ScalarType m_CurrentUpperThresholdValue;
- bool m_IsOldBinary = false;
-
- /** Indicates if Accepting the threshold should transfer/create the segmentations
- of all time steps (true) or only of the currently selected timepoint (false).*/
- bool m_CreateAllTimeSteps = false;
-
/** Indicates if the tool should behave like a single threshold tool (true)
or like a upper/lower threshold tool (false)*/
bool m_LockedUpperThreshold = false;
};
} // namespace
#endif
diff --git a/Modules/Segmentation/Interactions/mitkFastMarchingTool3D.cpp b/Modules/Segmentation/Interactions/mitkFastMarchingTool3D.cpp
index 4e5191b32f..48a1301bf6 100644
--- a/Modules/Segmentation/Interactions/mitkFastMarchingTool3D.cpp
+++ b/Modules/Segmentation/Interactions/mitkFastMarchingTool3D.cpp
@@ -1,460 +1,334 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#include "mitkFastMarchingTool3D.h"
#include "mitkToolManager.h"
#include "mitkBaseRenderer.h"
#include "mitkInteractionConst.h"
#include "mitkRenderingManager.h"
-#include "itkOrImageFilter.h"
-#include "mitkImageCast.h"
-#include "mitkImageTimeSelector.h"
+#include "mitkImageAccessByItk.h"
+
+// itk filter
+#include "itkBinaryThresholdImageFilter.h"
+#include "itkCurvatureAnisotropicDiffusionImageFilter.h"
+#include "itkGradientMagnitudeRecursiveGaussianImageFilter.h"
+#include "itkSigmoidImageFilter.h"
// us
#include
#include
#include
#include
namespace mitk
{
MITK_TOOL_MACRO(MITKSEGMENTATION_EXPORT, FastMarchingTool3D, "FastMarching3D tool");
}
mitk::FastMarchingTool3D::FastMarchingTool3D()
- : /*FeedbackContourTool*/ AutoSegmentationTool(),
- m_NeedUpdate(true),
- m_CurrentTimeStep(0),
+ : AutoSegmentationWithPreviewTool(),
m_LowerThreshold(0),
m_UpperThreshold(200),
m_StoppingValue(100),
m_Sigma(1.0),
m_Alpha(-0.5),
m_Beta(3.0),
m_PointSetAddObserverTag(0),
m_PointSetRemoveObserverTag(0)
{
}
mitk::FastMarchingTool3D::~FastMarchingTool3D()
{
}
-bool mitk::FastMarchingTool3D::CanHandle(BaseData *referenceData) const
+bool mitk::FastMarchingTool3D::CanHandle(const BaseData* referenceData, const BaseData* workingData) const
{
+ if(!Superclass::CanHandle(referenceData, workingData))
+ return false;
+
if (referenceData == nullptr)
return false;
- auto *image = dynamic_cast(referenceData);
+ auto *image = dynamic_cast(referenceData);
if (image == nullptr)
return false;
if (image->GetDimension() < 3)
return false;
return true;
}
const char **mitk::FastMarchingTool3D::GetXPM() const
{
return nullptr; // mitkFastMarchingTool3D_xpm;
}
us::ModuleResource mitk::FastMarchingTool3D::GetIconResource() const
{
us::Module *module = us::GetModuleContext()->GetModule();
us::ModuleResource resource = module->GetResource("FastMarching_48x48.png");
return resource;
}
const char *mitk::FastMarchingTool3D::GetName() const
{
return "Fast Marching 3D";
}
void mitk::FastMarchingTool3D::SetUpperThreshold(double value)
{
m_UpperThreshold = value / 10.0;
- m_ThresholdFilter->SetUpperThreshold(m_UpperThreshold);
- m_NeedUpdate = true;
}
void mitk::FastMarchingTool3D::SetLowerThreshold(double value)
{
m_LowerThreshold = value / 10.0;
- m_ThresholdFilter->SetLowerThreshold(m_LowerThreshold);
- m_NeedUpdate = true;
}
void mitk::FastMarchingTool3D::SetBeta(double value)
{
if (m_Beta != value)
{
m_Beta = value;
- m_SigmoidFilter->SetBeta(m_Beta);
- m_NeedUpdate = true;
}
}
void mitk::FastMarchingTool3D::SetSigma(double value)
{
if (m_Sigma != value)
{
if (value > 0.0)
{
m_Sigma = value;
- m_GradientMagnitudeFilter->SetSigma(m_Sigma);
- m_NeedUpdate = true;
}
}
}
void mitk::FastMarchingTool3D::SetAlpha(double value)
{
if (m_Alpha != value)
{
m_Alpha = value;
- m_SigmoidFilter->SetAlpha(m_Alpha);
- m_NeedUpdate = true;
}
}
void mitk::FastMarchingTool3D::SetStoppingValue(double value)
{
if (m_StoppingValue != value)
{
m_StoppingValue = value;
- m_FastMarchingFilter->SetStoppingValue(m_StoppingValue);
- m_NeedUpdate = true;
}
}
void mitk::FastMarchingTool3D::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_ToolManager->GetReferenceData(0));
-
m_SeedsAsPointSet = mitk::PointSet::New();
m_SeedsAsPointSetNode = mitk::DataNode::New();
m_SeedsAsPointSetNode->SetData(m_SeedsAsPointSet);
m_SeedsAsPointSetNode->SetName("3D_FastMarching_PointSet");
m_SeedsAsPointSetNode->SetBoolProperty("helper object", true);
m_SeedsAsPointSetNode->SetColor(0.0, 1.0, 0.0);
m_SeedsAsPointSetNode->SetVisibility(true);
// Create PointSetData Interactor
m_SeedPointInteractor = mitk::PointSetDataInteractor::New();
// Load the according state machine for regular point set interaction
m_SeedPointInteractor->LoadStateMachine("PointSet.xml");
// Set the configuration file that defines the triggers for the transitions
m_SeedPointInteractor->SetEventConfig("PointSetConfig.xml");
// set the DataNode (which already is added to the DataStorage
m_SeedPointInteractor->SetDataNode(m_SeedsAsPointSetNode);
- m_ReferenceImageAsITK = InternalImageType::New();
-
- m_ProgressCommand = mitk::ToolCommand::New();
-
- m_ThresholdFilter = ThresholdingFilterType::New();
- m_ThresholdFilter->SetLowerThreshold(m_LowerThreshold);
- m_ThresholdFilter->SetUpperThreshold(m_UpperThreshold);
- m_ThresholdFilter->SetOutsideValue(0);
- m_ThresholdFilter->SetInsideValue(1.0);
-
- m_SmoothFilter = SmoothingFilterType::New();
- m_SmoothFilter->AddObserver(itk::ProgressEvent(), m_ProgressCommand);
- m_SmoothFilter->SetTimeStep(0.05);
- m_SmoothFilter->SetNumberOfIterations(2);
- m_SmoothFilter->SetConductanceParameter(9.0);
-
- m_GradientMagnitudeFilter = GradientFilterType::New();
- m_GradientMagnitudeFilter->AddObserver(itk::ProgressEvent(), m_ProgressCommand);
- m_GradientMagnitudeFilter->SetSigma(m_Sigma);
-
- m_SigmoidFilter = SigmoidFilterType::New();
- m_SigmoidFilter->AddObserver(itk::ProgressEvent(), m_ProgressCommand);
- m_SigmoidFilter->SetAlpha(m_Alpha);
- m_SigmoidFilter->SetBeta(m_Beta);
- m_SigmoidFilter->SetOutputMinimum(0.0);
- m_SigmoidFilter->SetOutputMaximum(1.0);
-
- m_FastMarchingFilter = FastMarchingFilterType::New();
- m_FastMarchingFilter->AddObserver(itk::ProgressEvent(), m_ProgressCommand);
- m_FastMarchingFilter->SetStoppingValue(m_StoppingValue);
+ m_ToolManager->GetDataStorage()->Add(m_SeedsAsPointSetNode, m_ToolManager->GetWorkingData(0));
m_SeedContainer = NodeContainer::New();
m_SeedContainer->Initialize();
- m_FastMarchingFilter->SetTrialPoints(m_SeedContainer);
-
- // set up pipeline
- m_SmoothFilter->SetInput(m_ReferenceImageAsITK);
- m_GradientMagnitudeFilter->SetInput(m_SmoothFilter->GetOutput());
- m_SigmoidFilter->SetInput(m_GradientMagnitudeFilter->GetOutput());
- m_FastMarchingFilter->SetInput(m_SigmoidFilter->GetOutput());
- m_ThresholdFilter->SetInput(m_FastMarchingFilter->GetOutput());
-
- m_ToolManager->GetDataStorage()->Add(m_SeedsAsPointSetNode, m_ToolManager->GetWorkingData(0));
itk::SimpleMemberCommand::Pointer pointAddedCommand =
itk::SimpleMemberCommand::New();
pointAddedCommand->SetCallbackFunction(this, &mitk::FastMarchingTool3D::OnAddPoint);
m_PointSetAddObserverTag = m_SeedsAsPointSet->AddObserver(mitk::PointSetAddEvent(), pointAddedCommand);
itk::SimpleMemberCommand::Pointer pointRemovedCommand =
itk::SimpleMemberCommand::New();
pointRemovedCommand->SetCallbackFunction(this, &mitk::FastMarchingTool3D::OnDelete);
m_PointSetRemoveObserverTag = m_SeedsAsPointSet->AddObserver(mitk::PointSetRemoveEvent(), pointRemovedCommand);
-
- this->Initialize();
}
void mitk::FastMarchingTool3D::Deactivated()
{
- m_ToolManager->GetDataStorage()->Remove(this->m_ResultImageNode);
- m_ToolManager->GetDataStorage()->Remove(this->m_SeedsAsPointSetNode);
this->ClearSeeds();
- this->m_SmoothFilter->RemoveAllObservers();
- this->m_SigmoidFilter->RemoveAllObservers();
- this->m_GradientMagnitudeFilter->RemoveAllObservers();
- this->m_FastMarchingFilter->RemoveAllObservers();
- m_ResultImageNode = nullptr;
- mitk::RenderingManager::GetInstance()->RequestUpdateAll();
- unsigned int numberOfPoints = m_SeedsAsPointSet->GetSize();
- for (unsigned int i = 0; i < numberOfPoints; ++i)
- {
- mitk::Point3D point = m_SeedsAsPointSet->GetPoint(i);
- auto *doOp = new mitk::PointOperation(mitk::OpREMOVE, point, 0);
- m_SeedsAsPointSet->ExecuteOperation(doOp);
- }
// Deactivate Interaction
m_SeedPointInteractor->SetDataNode(nullptr);
m_ToolManager->GetDataStorage()->Remove(m_SeedsAsPointSetNode);
m_SeedsAsPointSetNode = nullptr;
m_SeedsAsPointSet->RemoveObserver(m_PointSetAddObserverTag);
m_SeedsAsPointSet->RemoveObserver(m_PointSetRemoveObserverTag);
+ m_SeedsAsPointSet = nullptr;
Superclass::Deactivated();
}
-void mitk::FastMarchingTool3D::Initialize()
-{
- m_ReferenceImage = dynamic_cast(m_ToolManager->GetReferenceData(0)->GetData());
- if (m_ReferenceImage->GetTimeGeometry()->CountTimeSteps() > 1)
- {
- mitk::ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New();
- timeSelector->SetInput(m_ReferenceImage);
- timeSelector->SetTimeNr(m_CurrentTimeStep);
- timeSelector->UpdateLargestPossibleRegion();
- m_ReferenceImage = timeSelector->GetOutput();
- }
- CastToItkImage(m_ReferenceImage, m_ReferenceImageAsITK);
- m_SmoothFilter->SetInput(m_ReferenceImageAsITK);
- m_NeedUpdate = true;
-}
-
-void mitk::FastMarchingTool3D::ConfirmSegmentation()
-{
- // combine preview image with current working segmentation
- if (dynamic_cast(m_ResultImageNode->GetData()))
- {
- // logical or combination of preview and segmentation slice
- OutputImageType::Pointer segmentationImageInITK = OutputImageType::New();
-
- mitk::Image::Pointer workingImage = dynamic_cast(GetTargetSegmentationNode()->GetData());
- if (workingImage->GetTimeGeometry()->CountTimeSteps() > 1)
- {
- mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New();
- timeSelector->SetInput(workingImage);
- timeSelector->SetTimeNr(m_CurrentTimeStep);
- timeSelector->UpdateLargestPossibleRegion();
- CastToItkImage(timeSelector->GetOutput(), segmentationImageInITK);
- }
- else
- {
- CastToItkImage(workingImage, segmentationImageInITK);
- }
-
- typedef itk::OrImageFilter OrImageFilterType;
- OrImageFilterType::Pointer orFilter = OrImageFilterType::New();
-
- orFilter->SetInput(0, m_ThresholdFilter->GetOutput());
- orFilter->SetInput(1, segmentationImageInITK);
- orFilter->Update();
-
- // set image volume in current time step from itk image
- workingImage->SetVolume((void *)(m_ThresholdFilter->GetOutput()->GetPixelContainer()->GetBufferPointer()),
- m_CurrentTimeStep);
- this->m_ResultImageNode->SetVisibility(false);
- this->ClearSeeds();
- workingImage->Modified();
- }
-
- mitk::RenderingManager::GetInstance()->RequestUpdateAll();
- m_ToolManager->ActivateTool(-1);
-}
-
void mitk::FastMarchingTool3D::OnAddPoint()
{
// Add a new seed point for FastMarching algorithm
mitk::Point3D clickInIndex;
- m_ReferenceImage->GetGeometry()->WorldToIndex(m_SeedsAsPointSet->GetPoint(m_SeedsAsPointSet->GetSize() - 1),
+ this->GetReferenceData()->GetGeometry()->WorldToIndex(m_SeedsAsPointSet->GetPoint(m_SeedsAsPointSet->GetSize() - 1),
clickInIndex);
itk::Index<3> seedPosition;
seedPosition[0] = clickInIndex[0];
seedPosition[1] = clickInIndex[1];
seedPosition[2] = clickInIndex[2];
NodeType node;
const double seedValue = 0.0;
node.SetValue(seedValue);
node.SetIndex(seedPosition);
this->m_SeedContainer->InsertElement(this->m_SeedContainer->Size(), node);
- m_FastMarchingFilter->Modified();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
- m_NeedUpdate = true;
-
- this->Update();
-
- m_ReadyMessage.Send();
+ this->UpdatePreview();
}
void mitk::FastMarchingTool3D::OnDelete()
{
// delete last seed point
if (!(this->m_SeedContainer->empty()))
{
// delete last element of seeds container
this->m_SeedContainer->pop_back();
- m_FastMarchingFilter->Modified();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
- m_NeedUpdate = true;
-
- this->Update();
- }
-}
-
-void mitk::FastMarchingTool3D::Update()
-{
- const unsigned int progress_steps = 200;
-
- if (m_NeedUpdate)
- {
- m_ProgressCommand->AddStepsToDo(progress_steps);
-
- // remove interaction with poinset while updating
- m_SeedPointInteractor->SetDataNode(nullptr);
- CurrentlyBusy.Send(true);
- try
- {
- m_ThresholdFilter->Update();
- }
- catch (itk::ExceptionObject &excep)
- {
- MITK_ERROR << "Exception caught: " << excep.GetDescription();
-
- m_ProgressCommand->SetProgress(progress_steps);
- CurrentlyBusy.Send(false);
-
- std::string msg = excep.GetDescription();
- ErrorMessage.Send(msg);
-
- return;
- }
- m_ProgressCommand->SetProgress(progress_steps);
- CurrentlyBusy.Send(false);
-
- // make output visible
- mitk::Image::Pointer result = mitk::Image::New();
- CastToMitkImage(m_ThresholdFilter->GetOutput(), result);
- result->GetGeometry()->SetOrigin(m_ReferenceImage->GetGeometry()->GetOrigin());
- result->GetGeometry()->SetIndexToWorldTransform(m_ReferenceImage->GetGeometry()->GetIndexToWorldTransform());
- m_ResultImageNode->SetData(result);
- m_ResultImageNode->SetVisibility(true);
- mitk::RenderingManager::GetInstance()->RequestUpdateAll();
-
- // add interaction with poinset again
- m_SeedPointInteractor->SetDataNode(m_SeedsAsPointSetNode);
+ this->UpdatePreview();
}
}
void mitk::FastMarchingTool3D::ClearSeeds()
{
// clear seeds for FastMarching as well as the PointSet for visualization
if (this->m_SeedContainer.IsNotNull())
this->m_SeedContainer->Initialize();
if (this->m_SeedsAsPointSet.IsNotNull())
{
// remove observers from current pointset
m_SeedsAsPointSet->RemoveObserver(m_PointSetAddObserverTag);
m_SeedsAsPointSet->RemoveObserver(m_PointSetRemoveObserverTag);
// renew pointset
this->m_SeedsAsPointSet = mitk::PointSet::New();
this->m_SeedsAsPointSetNode->SetData(this->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);
// add callback function for adding and removing points
itk::SimpleMemberCommand::Pointer pointAddedCommand =
itk::SimpleMemberCommand::New();
pointAddedCommand->SetCallbackFunction(this, &mitk::FastMarchingTool3D::OnAddPoint);
m_PointSetAddObserverTag = m_SeedsAsPointSet->AddObserver(mitk::PointSetAddEvent(), pointAddedCommand);
itk::SimpleMemberCommand::Pointer pointRemovedCommand =
itk::SimpleMemberCommand::New();
pointRemovedCommand->SetCallbackFunction(this, &mitk::FastMarchingTool3D::OnDelete);
m_PointSetRemoveObserverTag = m_SeedsAsPointSet->AddObserver(mitk::PointSetRemoveEvent(), pointRemovedCommand);
}
+}
- if (this->m_FastMarchingFilter.IsNotNull())
- m_FastMarchingFilter->Modified();
+template
+void mitk::FastMarchingTool3D::DoITKFastMarching(const itk::Image* inputImage,
+ mitk::Image* segmentation, unsigned int timeStep)
+{
+ typedef itk::Image InputImageType;
+
+ /* typedefs for itk pipeline */
+
+ typedef mitk::Tool::DefaultSegmentationDataType OutputPixelType;
+ typedef itk::Image OutputImageType;
+
+ typedef itk::CurvatureAnisotropicDiffusionImageFilter SmoothingFilterType;
+ typedef itk::GradientMagnitudeRecursiveGaussianImageFilter GradientFilterType;
+ typedef itk::SigmoidImageFilter SigmoidFilterType;
+ typedef itk::BinaryThresholdImageFilter ThresholdingFilterType;
+
+ auto smoothFilter = SmoothingFilterType::New();
+ smoothFilter->AddObserver(itk::ProgressEvent(), m_ProgressCommand);
+ smoothFilter->SetTimeStep(0.05);
+ smoothFilter->SetNumberOfIterations(2);
+ smoothFilter->SetConductanceParameter(9.0);
+
+ auto gradientMagnitudeFilter = GradientFilterType::New();
+ gradientMagnitudeFilter->AddObserver(itk::ProgressEvent(), m_ProgressCommand);
+ gradientMagnitudeFilter->SetSigma(m_Sigma);
+
+ auto sigmoidFilter = SigmoidFilterType::New();
+ sigmoidFilter->AddObserver(itk::ProgressEvent(), m_ProgressCommand);
+ sigmoidFilter->SetAlpha(m_Alpha);
+ sigmoidFilter->SetBeta(m_Beta);
+ sigmoidFilter->SetOutputMinimum(0.0);
+ sigmoidFilter->SetOutputMaximum(1.0);
+
+ auto fastMarchingFilter = FastMarchingFilterType::New();
+ fastMarchingFilter->AddObserver(itk::ProgressEvent(), m_ProgressCommand);
+ fastMarchingFilter->SetStoppingValue(m_StoppingValue);
+ fastMarchingFilter->SetTrialPoints(m_SeedContainer);
+
+ auto thresholdFilter = ThresholdingFilterType::New();
+ thresholdFilter->SetLowerThreshold(m_LowerThreshold);
+ thresholdFilter->SetUpperThreshold(m_UpperThreshold);
+ thresholdFilter->SetOutsideValue(0);
+ thresholdFilter->SetInsideValue(1.0);
- this->m_NeedUpdate = true;
+ // set up pipeline
+ smoothFilter->SetInput(inputImage);
+ gradientMagnitudeFilter->SetInput(smoothFilter->GetOutput());
+ sigmoidFilter->SetInput(gradientMagnitudeFilter->GetOutput());
+ fastMarchingFilter->SetInput(sigmoidFilter->GetOutput());
+ thresholdFilter->SetInput(fastMarchingFilter->GetOutput());
+ thresholdFilter->Update();
+
+ segmentation->SetVolume((void*)(thresholdFilter->GetOutput()->GetPixelContainer()->GetBufferPointer()), timeStep);
}
-void mitk::FastMarchingTool3D::Reset()
+void mitk::FastMarchingTool3D::UpdatePrepare()
{
- // clear all seeds and preview empty result
- this->ClearSeeds();
-
- m_ResultImageNode->SetVisibility(false);
+ // remove interaction with poinset while updating
+ if (m_SeedPointInteractor.IsNotNull())
+ m_SeedPointInteractor->SetDataNode(nullptr);
+}
- mitk::RenderingManager::GetInstance()->RequestUpdateAll();
+void mitk::FastMarchingTool3D::UpdateCleanUp()
+{
+ // add interaction with poinset again
+ if (m_SeedPointInteractor.IsNotNull())
+ m_SeedPointInteractor->SetDataNode(m_SeedsAsPointSetNode);
}
-void mitk::FastMarchingTool3D::SetCurrentTimeStep(int t)
+void mitk::FastMarchingTool3D::DoUpdatePreview(const Image* inputAtTimeStep, Image* previewImage, TimeStepType timeStep)
{
- if (m_CurrentTimeStep != t)
+ if (nullptr != inputAtTimeStep && nullptr != previewImage && m_SeedContainer.IsNotNull() && !m_SeedContainer->empty())
{
- m_CurrentTimeStep = t;
-
- this->Initialize();
+ AccessFixedDimensionByItk_n(inputAtTimeStep, DoITKFastMarching, 3, (previewImage, timeStep));
}
}
diff --git a/Modules/Segmentation/Interactions/mitkFastMarchingTool3D.h b/Modules/Segmentation/Interactions/mitkFastMarchingTool3D.h
index eeefc20b4f..652e0d550b 100644
--- a/Modules/Segmentation/Interactions/mitkFastMarchingTool3D.h
+++ b/Modules/Segmentation/Interactions/mitkFastMarchingTool3D.h
@@ -1,164 +1,124 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#ifndef mitkFastMarchingTool3D_h_Included
#define mitkFastMarchingTool3D_h_Included
-#include "mitkAutoSegmentationTool.h"
+#include "mitkAutoSegmentationWithPreviewTool.h"
#include "mitkDataNode.h"
#include "mitkPointSet.h"
#include "mitkPointSetDataInteractor.h"
#include "mitkToolCommand.h"
-#include
-
-#include "mitkMessage.h"
#include "itkImage.h"
-
-// itk filter
-#include "itkBinaryThresholdImageFilter.h"
-#include "itkCurvatureAnisotropicDiffusionImageFilter.h"
#include "itkFastMarchingImageFilter.h"
-#include "itkGradientMagnitudeRecursiveGaussianImageFilter.h"
-#include "itkSigmoidImageFilter.h"
+
+#include
namespace us
{
class ModuleResource;
}
namespace mitk
{
/**
\brief FastMarching semgentation tool.
The segmentation is done by setting one or more seed points on the image
and adapting the time range and 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 MITKSEGMENTATION_EXPORT FastMarchingTool3D : public AutoSegmentationTool
+ class MITKSEGMENTATION_EXPORT FastMarchingTool3D : public AutoSegmentationWithPreviewTool
{
- mitkNewMessageMacro(Ready);
-
public:
- mitkClassMacro(FastMarchingTool3D, AutoSegmentationTool);
+ mitkClassMacro(FastMarchingTool3D, AutoSegmentationWithPreviewTool);
itkFactorylessNewMacro(Self);
itkCloneMacro(Self);
- /* typedefs for itk pipeline */
- typedef float InternalPixelType;
- typedef itk::Image InternalImageType;
- typedef mitk::Tool::DefaultSegmentationDataType OutputPixelType;
- typedef itk::Image OutputImageType;
-
- typedef itk::BinaryThresholdImageFilter ThresholdingFilterType;
- typedef itk::CurvatureAnisotropicDiffusionImageFilter SmoothingFilterType;
- typedef itk::GradientMagnitudeRecursiveGaussianImageFilter GradientFilterType;
- typedef itk::SigmoidImageFilter SigmoidFilterType;
- typedef itk::FastMarchingImageFilter FastMarchingFilterType;
- typedef FastMarchingFilterType::NodeContainer NodeContainer;
- typedef FastMarchingFilterType::NodeType NodeType;
-
- bool CanHandle(BaseData *referenceData) const override;
+ bool CanHandle(const BaseData* referenceData, const BaseData* workingData) const override;
/* icon stuff */
const char **GetXPM() const override;
const char *GetName() const override;
us::ModuleResource GetIconResource() const override;
+ void Activated() override;
+ void Deactivated() override;
+
/// \brief Set parameter used in Threshold filter.
void SetUpperThreshold(double);
/// \brief Set parameter used in Threshold filter.
void SetLowerThreshold(double);
/// \brief Set parameter used in Fast Marching filter.
void SetStoppingValue(double);
/// \brief Set parameter used in Gradient Magnitude filter.
void SetSigma(double);
/// \brief Set parameter used in Fast Marching filter.
void SetAlpha(double);
/// \brief Set parameter used in Fast Marching filter.
void SetBeta(double);
- /// \brief Adds the feedback image to the current working image.
- virtual void ConfirmSegmentation();
-
- /// \brief Set the working time step.
- virtual void SetCurrentTimeStep(int t);
-
/// \brief Clear all seed points.
void ClearSeeds();
- /// \brief Updates the itk pipeline and shows the result of FastMarching.
- void Update();
-
protected:
FastMarchingTool3D();
~FastMarchingTool3D() override;
- void Activated() override;
- void Deactivated() override;
- virtual void Initialize();
-
/// \brief Add point action of StateMachine pattern
virtual void OnAddPoint();
/// \brief Delete action of StateMachine pattern
virtual void OnDelete();
- /// \brief Reset all relevant inputs of the itk pipeline.
- void Reset();
-
- mitk::ToolCommand::Pointer m_ProgressCommand;
-
- Image::Pointer m_ReferenceImage;
-
- bool m_NeedUpdate;
+ void UpdatePrepare() override;
+ void UpdateCleanUp() override;
+ void DoUpdatePreview(const Image* inputAtTimeStep, Image* previewImage, TimeStepType timeStep) override;
- int m_CurrentTimeStep;
+ template
+ void DoITKFastMarching(const itk::Image* inputImage,
+ mitk::Image* segmentation, unsigned int timeStep);
float m_LowerThreshold; // used in Threshold filter
float m_UpperThreshold; // used in Threshold filter
float m_StoppingValue; // used in Fast Marching filter
float m_Sigma; // used in GradientMagnitude filter
float m_Alpha; // used in Sigmoid filter
float m_Beta; // used in Sigmoid filter
- NodeContainer::Pointer m_SeedContainer; // seed points for FastMarching
-
- InternalImageType::Pointer m_ReferenceImageAsITK; // the reference image as itk::Image
+ typedef float InternalPixelType;
+ typedef itk::Image InternalImageType;
+ typedef itk::FastMarchingImageFilter FastMarchingFilterType;
+ typedef FastMarchingFilterType::NodeContainer NodeContainer;
+ typedef FastMarchingFilterType::NodeType NodeType;
- mitk::DataNode::Pointer m_ResultImageNode; // holds the result as a preview image
+ NodeContainer::Pointer m_SeedContainer; // seed points for FastMarching
mitk::DataNode::Pointer m_SeedsAsPointSetNode; // used to visualize the seed points
mitk::PointSet::Pointer m_SeedsAsPointSet;
mitk::PointSetDataInteractor::Pointer m_SeedPointInteractor;
unsigned int m_PointSetAddObserverTag;
unsigned int m_PointSetRemoveObserverTag;
-
- ThresholdingFilterType::Pointer m_ThresholdFilter;
- SmoothingFilterType::Pointer m_SmoothFilter;
- GradientFilterType::Pointer m_GradientMagnitudeFilter;
- SigmoidFilterType::Pointer m_SigmoidFilter;
- FastMarchingFilterType::Pointer m_FastMarchingFilter;
};
} // namespace
#endif
diff --git a/Modules/Segmentation/Interactions/mitkOtsuTool3D.cpp b/Modules/Segmentation/Interactions/mitkOtsuTool3D.cpp
index 917451a48c..9a5f4cc388 100644
--- a/Modules/Segmentation/Interactions/mitkOtsuTool3D.cpp
+++ b/Modules/Segmentation/Interactions/mitkOtsuTool3D.cpp
@@ -1,277 +1,253 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
// MITK
#include "mitkOtsuTool3D.h"
#include "mitkImageAccessByItk.h"
#include "mitkLabelSetImage.h"
#include "mitkOtsuSegmentationFilter.h"
#include "mitkRenderingManager.h"
#include "mitkToolManager.h"
#include
#include
#include
#include
#include
#include
// ITK
#include
#include
#include
// us
#include
#include
#include