diff --git a/Core/Documentation/Doxygen/Concepts/DataInteraction.dox b/Core/Documentation/Doxygen/Concepts/DataInteraction.dox index 8c2a60803e..27fe6f6ec3 100644 --- a/Core/Documentation/Doxygen/Concepts/DataInteraction.dox +++ b/Core/Documentation/Doxygen/Concepts/DataInteraction.dox @@ -1,224 +1,226 @@ /** \page DataInteractionPage Interaction Concepts \tableofcontents \section DataInteractionPage_Introduction Introduction to Interaction in MITK Interaction is a very important task in medical image processing software. Therefore MITK provides a special interaction concept that provides the developer with an easy way to develop and maintain user interaction separately from the algorithms processing the input. This allows e.g. for common interaction schemes to be re-used in different contexts. The core of the interaction concept is based on entities called \b DataInteractors that listen for certain pre-defined events and execute actions when such an event is triggered.\n In the following the different components of the interaction concept are explained. First a a high-level overview about how the different components interact is given, then some parts are explained in more detail. \subsection FurtherReadingInteraction Topics related to interaction - further information: See the \ref DataInteractionTechnicalPage page for a more technical explanation. \n Consult \ref HowToUseDataInteractor for usage information.\n See \ref SectionImplementationDataInteractor for an example on how to implement a new mitk::DataInteractor \n for information about how to create new events refer to ImplementNewEventsPage.\n The documentation of the depricated former concept can be found at \ref InteractionPage. \n For a list of changes with respect to the previous interaction concept please refer to the \ref InteractionMigration \section DataInteractionPage_HandlingSection Event Handling & GUI Toolkit Abstraction The following sequence diagram gives an exemplary overview of the process from creating an event until executing an action in the mitk::DataInteractor. This diagram assumes the usage of the Qt framework, but also shows that the interaction concept itself is implemented independent of any specific graphical user interface toolkit. \imageMacro{event_handling.png,"",16}
  1. a user event is triggered and send to MITK
  2. this layer serves as an adapter from the GUI toolkit (here Qt) events to MITK internal events (later referred to as \link mitk::InteractionEvent InteractionEvents\endlink).
  3. once the event is adapted it is send to a mitk::Dispatcher, which is linked to a render window, to be handled.
  4. on the mitk::Dispatcher level all objects are known that can react to incoming events (mitk::DataInteractor and mitk::InteractionEventObserver instances)
  5. a mitk::DataInteractor is offered an event and checks its mitk::EventConfig object, which returns if a variant of this event has been defined for this DataInteractor.
  6. if the DataInteractor has a variant for the event, it consults its state machine to check if the input can be handled in the current state
  7. the actions associated with a state change (transition) are executed and the event is successfully handled.
\section DataInteractionPage_EventPage Events Events can describe any sort of user input, such as key strokes, mouse clicks or touch gestures. These events are mapped from an UI framework like Qt to an MITK internal representation and send to the mitk::Dispatcher which in turn deals with further processing of the event. These events are not limited to classical input devices but can be extended at will, by introducing new classes which e.g. describe events from tracking devices, etc. Refer to \subpage ImplementNewEventsPage to see how new events and thereby input devices can be integrated. For an overview of available Events see mitk::InteractionEvent, for on overview of parameters see the \subpage DataInteractionTechnicalPage. \section DataInteractionPage_InteractionEventHandlerSection InteractionEventHandler Is the term describing objects in general that can handle events. These objects can be divided into two groups, namely \link mitk::DataInteractor DataInteractors\endlink and mitk::InteractionEventObserver. Their difference is that mitk::DataInteractor instances are linked with a mitk::DataNode which they manipulate, whereas mitk::InteractionEventObserver instances do not have a mitk::DataNode and therefore are not supposed to manipulate any data. \dot digraph linker_deps { node [shape=record, fontname=Helvetica, fontsize=10]; a [ label="InteractionEventHandler" ]; d [ label="{EventStateMachine|HandleEvent()}" ]; b [ label="{DataInteractor|PerformAction()}" ]; a -> d; d -> b; } \enddot \subsection DataInteractionPage_DataInteractorsSection DataInteractors DataInteractors are specialized mitk::InteractionEventHandler which handle events for one spefific DataNode. They are implemented following a concept called state machines (see e.g. Wikipedia ). \subsubsection DataInteractionPage_StateMachinesSection StateMachines A specific events action is usually desired to depend on the content of the data object and the state of the interaction. For example when adding a line by clicking with the mouse, the first two clicks are supposed to add a point. But the second click should additionally finish the interaction and a subsequent third click should be ignored. State machines provide a great way to model such interaction in which the same user interaction can trigger different actions depending on the current state. Therefore DataInteractors work with so called state machine patterns. The basic idea here is that each interaction can be described by states and transitions which in turn trigger actions. These patterns define a workflow and different patterns can be applied to the same mitk::DataInteractor and cause this mitk::DataInteractor to perform different user interactions. This principle is best described by an example. Imagine a mitk::DataInteractor with the functionality (1) to add Points at a given mouse position and connect them by a line and (2) check if two points are on the same position. Using this mitk::DataInteractor, different mitk::StateMachine patterns/descriptions can be given which each cause the mitk::DataInteractor to perform different interaction schemes. State machine pattern 1: We want the user to draw a line. A simple state machine could express this by three states like this: \dot digraph linker_deps { node [shape=circle, fontname=Helvetica, fontsize=10]; a [ label="NoPoints" ]; b [ label="OnePoint" ]; c [ label="TwoPoints" ]; a -> b [label="MousePress/AddPoint",fontname=Helvetica, fontsize=10]; b -> c [label="MousePress/AddPoint",fontname=Helvetica, fontsize=10]; { rank=same; a b c } } \enddot With each MousePress event the AddPoint function is called and adds a point at the mouse position, unless two points already exist. State machine pattern 2: The same mitk::DataInteractor can also operate after the following state machine, which models the interaction to input a closed contour. The mitk::DataInteractor can detect an AddPoint event on an already existing point and will trigger a PointsMatch event. \dot digraph { node [shape=circle, fontname=Helvetica, fontsize=10]; a [ label="StartState" ]; b [ label="ClosedContour"]; a -> a [label="MousePress/AddPoint",fontname=Helvetica, fontsize=10]; a -> b [label="PointsMatch/AddPoint",fontname=Helvetica, fontsize=10]; } \enddot In this way state machines provide both, a nice and structured way to represent interaction tasks and description of the interaction which is separated from the code. One DataInteractor can be re-used for different tasks by simply exchanging the state machine pattern. These patterns are described in XML files. \subsubsection DataInteractionPage_DefinitionStateMachine Definition of a State Machine -The definition is made up out of three components. +The definition is made up out of four components. Each state machine needs exactly one designated start state into which the state machine is set in the beginning. An example of a state machine describing the interaction of example 2 looks like this: \code + \endcode Example 1: State machine pattern, that describes adding points to a contour until the PointsMatch event is triggered. For a more detailed description of state machine patterns see here. \subsection DataInteractionPage_InteractionEventObserverSection InteractionEventObserver mitk::InteractionEventObserver instances are objects which will receive all user input and are intended for observation only, they should never modify any DataNodes. For mitk::InteractionEventObserver it is optional to use the state machine functionality, the default is without. How to use the state machine functionality is described in the documentation of mitk::InteractionEventObserver::Notify. \dot digraph event_observer { node [shape=record, fontname=Helvetica, fontsize=10]; c [ label="{InteractionEventObserver|Notify()}" ]; a [ label="InteractionEventHandler" ]; b [ label="{EventStateMachine|HandleEvent()}" ]; d [ label="{MyCustomObserver|PerformAction()}" ]; c -> d; a -> b; b -> d [style="dashed",label="optional"]; } \enddot \subsection DataInteractionPage_ConfigurationSection Configuration In a lot of cases it is preferable to implement interactions independent of a specific event (e.g. left click with mouse), such that it is possible to easily change this. This is achieved through configuration of \link mitk::InteractioinEventHandler InteractionEventHandlers\endlink. This allows to change the behavior at runtime. The mitk::InteractionEventHandler class provides an interface to easily modify the user input that triggers an action by loading a different configuration. This allows to implement user-specific behavior of the software on an abstract level and to switch it at runtime. This is achieved through XML files describing a configuration. These files can be loaded by the mitk::InteractionEventHandler and will lead to an internal mapping from specific user input to an abstract description of the event given in the config file. In order to do this we distinguish between a specific event and an event variant. A specific event is described by its event class, which determines the category of an event, e.g. the class mitk::MousePressEvent, and its parameter which make this event unique, e.g. LeftMouseButton pressed and no modifier keys pressed. The event variant is a name that is assigned to a specific event, and to which an mitk::InteractionEventHandler listens. To illustrate this, an example is given here for two different configuration files. We assume that a mitk::InteractionEventHandler listens to the event variant 'AddPoint', two possible config files could then look like this: \code \endcode Example 2: Event description of a left click with the mouse and \code \endcode Example 3: Event description of a left click with the mouse while pressing the shift-key If the mitk::InteractionEventHandler is loaded with the first configuration the event variant 'MousePress' is triggered when the user performs a mouse click, while when the second configuration is loaded 'MousePress' is triggered when the user performs a right click while pressing the shift button. In this way all objects derived from mitk::InteractionEventHandler can be configured. For a detailed description about how to create the XML file see the \ref DataInteractionTechnicalPage page. \section DataInteractionPage_DispatcherSection Dispatcher Instances of mitk::Dispatcher receive all events and distribute them to their related mitk::DataInteractor instances. This is done by ordering the DataInteractors according to the layer of their mitk::DataNode in descending order. Then the event is offered to the first mitk::DataInteractor, which in turn checks if it can handle the event. This is done for each mitk::DataInteractor until the first processes the event, after this the other DataInteractors are skipped and all InteractionEventObservers are notified. */ diff --git a/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step10.dox b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step10.dox index 7e2c77ce9e..6c32c2b6f4 100644 --- a/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step10.dox +++ b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step10.dox @@ -1,475 +1,494 @@ /** \page Step10Page MITK Tutorial - Step 10: Adding new Interaction \tableofcontents \section HowToUseDataInteractor Step 01 - How to use an existing DataInteractor in your Module/Plugin/... MITK provides finished DataInteractors for a variety of tasks, they can be found in Code/Core/Interactors. They can be used with state machine patterns and config files located under Resources/Interactions. A mitk::DataInteractor consists of four parts. The class describing the functionality and two XML files; one describes the state machine pattern, that is the workflow of an interaction and the second describes the user events which trigger an action. Lastly every mitk::DataInteractor works on a mitk::DataNode in which it stores and manipulates data. To use a mitk::DataInteractor these parts have to be brought together. ** TODO add code of mitk::PointSetDataInteractor Plugin .. This code demonstrates the use of an existing mitk::DataInteractor exemplary for the mitk::PointSetDataInteractor: First we need a mitk::DataNode in which the PointSets is stored. It has to be added to the mitk::DataStorage. \code mitk::DataNode::Pointer dataNode = mitk::DataNode::New(); GetDataStorage()->Add(dataNode.GetPointer()); \endcode Then we create an instance of a mitk::PointSetDataInteractor and load a predefined statemachine pattern as well as a configuration for it: \code m_CurrentInteractor = mitk::PointSetDataInteractor::New(); m_CurrentInteractor->LoadStateMachine("PointSet.xml"); m_CurrentInteractor->SetEventConfig("PointSetConfig.xml"); \endcode Lastly the mitk::DataNode is added to the mitk::DataInteractor \code m_CurrentInteractor->SetDataNode(dataNode); \endcode now the mitk::DataInteractor is ready for usage. \section HowToModifyInteraction Step 02 - How to modify the behaviour of a DataInteractor The behavior of a mitk::DataInteractor is determined by two aspects. One, the state machine pattern which describes the flow/order of actions that are performed. Secondly the configuration which determines which user interaction triggers the actions. \subsection ModifyDisplayInteractorBehavior How to modify the display interactor behavior Sometimes it may be desirable to change the behaviour of the mitk::DisplayInteractor which controls zooming, panning and scrolling, e.g. when a Tool is activated that reacts to the same events. Changing the behavior of the DisplayInteractor (or possibly any other EventHandler) can be achieved from anywhere in the code by requesting the InteractionEventObserver and assigning an alternative configuration to it, as demonstrated in this example: \code std::ifstream* configStream = new std::ifstream( #path to alternative configuration file# ); mitk::EventConfig newConfig(configStream); // Requesting all registered EventObservers std::list listEventObserver = GetModuleContext()->GetServiceReferences(); for (std::list::iterator it = listEventObserver.begin(); it != listEventObserver.end(); ++it) { DisplayInteractor* displayInteractor = dynamic_cast(GetModuleContext()->GetService(*it)); // filtering: only adjust the DisplayInteractor if (displayInteractor != NULL) { displayInteractor->SetEventConfig(newConfig); } } \endcode \section SectionImplementationDataInteractor How to implement a new DataInteractor This second part of the tutorial step goes beyond the activation of an interactor, that modifies data by user interaction) as shown above. It shows what needs to be implemented to add a new way of interaction within your MITK application. Please see \ref DataInteractionPage as an introduction to the MITK interaction mechanism, you may also want to read \ref DataInteractionTechnicalPage. This tutorial is structured as follows: The first section deals with config files, describing all the parameters of events and how to use them in a configuration file. In the second section the basics are described that are needed to write a state machine pattern. The last section deals with brining configuration, state machine pattern and code together and gives an exemplary implementation of a mitk::DataInteractor. \section ConfigFileDescriptionSection How to create a Config-File \subsection EventDescriptionSection Event Description Events are described by their parameters. Each event type has its own set of parameters that can be set in the configuration file. If a parameter is omitted it is set to its default value. All possible parameters are listed and described below. Event parameters are also described in the documentation of the event class itself. Mandatory for each event description is the event class and the event variant. The parameters of an event are set by attribute tags. \note Refer to \ref EventClassSection for the meaning of event class. \b Mouse \b Buttons \n mitk::InteractionEvent::MouseButtons represent the buttons. They can be used for two attributes. First the EventButton attribute which describes the button that triggered the event, this always is a single button. Secondly the ButtonState attribute that describes which buttons were pressed at the moment the event has been generated. For example assume the right mouse button and the middle mouse button are already pressed, now the left mouse button is pressed too and generates a second event, this would be described as follows: \code \endcode Note: Technically the LeftMouseButton is also pressed and should be listed in the ButtonState, but this is taken care of by the mitk::EventFactory . Key Events \n mitk::InteractionKeyEvent represents a pressed key, which key is pressed is provided with the Key attribute like this \code \endcode or \code \endcode \note Key Events do not require an explicit configuration, for all key events there exists a predefined event variant with the name 'Std' + value, that is key a is named 'StdA'. The names for special keys are listed here: \dontinclude mitkInteractionEvent.h \skipline // Special Keys \until // End special keys Modifier Keys \n mitk::InteractionEvent::ModifierKeys represent the combination of pressed modifier keys, several modifier keys pressed at the same time are denoted by listing them all separated by commas. \code \endcode \b ScrollDirection \n This attribute is unique to the mitk::MouseWheelEvent and describes the direction in which the mouse wheel is rotated. In the event description actual only the direction is provided, but the event is generated with the actual value, and this value can be retrieved from the object. \code \endcode \subsection ExamplesSection Examples Examples for key events: \code \endcode Examples for MousePress events: \code \endcode There exists a standard configuration file for the most common events called GlobalConfig.xml that can be used to as a default and can be extended by a specific definition. \subsection ParameterDescriptionSection Parameter Description It is also possible to store parameters in the config file. Those are stored using the param-tag, like this: \code \endcode Within the application these properties can then be access via a mitk::PropertyList like this: \code // sm - state machine loaded with config file example2 mitk::PropertyList::Pointer properties = GetAttributes(); std::string prop1; properties->GetStringProperty("property1",prop1); \endcode \section HowToStateMachine HowTo Write a State Machine A state machine pattern is described in a XML file. \subsection StateSection States States are described using the state-tag. Each state has to have a name. Exactly one state has to be a start state in each state machine to indicate the state in which the state machine is set when it is constructed. So a valid, but rather useless state machine would like like this: \code \endcode Optionally a state can be assigned a special mode that influences the event distribution. These modes are GRAB_INPUT , PREFER_INPUT and REGULAR (where REGULAR is default and does not need to be indicated). See \ref DataInteractionTechnicalPage_DispatcherEventDistSection for a description of these modes. Use the special modes only when necessary as they prevent other DataInteractors to receive events. \code \endcode \subsection TransitionSection Transitions Transitions are part of a state and describe all possible state switches, and are therefore important for modeling an interaction scheme. Transitions consist a part that describes the event which triggers the transition (event class and event variant) and a target which is state to which the state machine switches after executing a transition. An event class describes the event type (see mitk::InteractionEvent for the different classes) and the event variant is a specification thereof and the exact description is taken from a config file. Together they determine which event can trigger this transition. For example this state machine will switch from state A to state B when the StdMousePressPrimaryButton event (left mouse button is pressed) occurs. \subsubsection EventClassSection Event Class The event class description supports the polymorphism of the event classes. Therefore state machine patters should be written in the most general ways possible. So for a given class hierarchy like this: \dot digraph { node [shape=record, fontname=Helvetica, fontsize=10]; a [ label="{InteractionPositionEvent}"]; b [ label="{MousePressEvent}" ]; c [ label="MouseReleaseEvent" ]; d [ label="TouchEvent", style=dotted ]; a -> b; a -> c; a -> d; } \enddot in the state machine pattern the mitk::InteractionPositionEvent can be declared as event class to restrict to the events which hold a position information. The actual implementation is then given in the configuration file. In this case it allows to define events of the classes mitk::InteractionPositionEvent itself, or mitk::MousePressEvent, mitk::MouseReleaseEvent, mitk::TouchEvent. This has the advantage that the patterns remain the same no matter what input devices are used, and the state machine patterns can be configured for newly added event classes as long as they match the class hierarchy (this ensures they hold the necessary properties). \code \endcode \subsection ActionSection Actions Actions can be added to transitions and represent functions in the mitk::DataInteractor that are executed on taking a transition. The following simple state machine will listen for left mouse clicks and execute two actions (and actually never stop). \code \endcode In order to tell the mitk::DataInteractor which function to execute these actions are made known to the mitk::DataInteractor using the CONNECT_FUNCTION macro. This example assumes that there exists an ExampleInteractor which inherits from mitkDataInteractor. This class implements the functions AddPoint and CountClicks. The actions are introduced by implementing the virtual method ConnectActionsAndFunctions(): \code void mitk::ExampleInteractor::ConnectActionsAndFunctions() { CONNECT_FUNCTION("addPoint", AddPoint); CONNECT_FUNCTION("countClicks", CountClicks); } \endcode +\subsection ConditionSection Conditions +Conditions can be added to transitions and represent functions in the mitk::DataInteractor that are executed on taking a transition. +A condition is used to determine if a following action should be executed or not. +\code + + + + + + + + + +\endcode + +In order to tell the mitk::DataInteractor which function to execute these conditions are made known to the mitk::DataInteractor using +the CONNECT_CONDITION macro. The ConnectActionsAndFunctions() method has to be augmented accordingly: + +\code +void mitk::ExampleInteractor::ConnectActionsAndFunctions() +{ + CONNECT_CONDITION("checkPoint", CheckPoint); + CONNECT_FUNCTION("addPoint", AddPoint); + CONNECT_FUNCTION("countClicks", CountClicks); +} +\endcode + \section ReferenceToIncludeFiles Integration of the pattern and configuration files See \ref IncludeFiles for a description. \section HowToDataInteractor Implementation of a new mitk::DataInteractor DataInteractors are to inherit from mitk::DataInteractor. Their functionality is implemented in functions that follow this interface: +For Actions: \code bool SomeFunctionality(StateMachineAction* , InteractionEvent*); \endcode -Your functions are connected with actions by implementing the function ConnectActionsAndFunctions(), e.g. +For Conditions: +\code +bool SomeFunctionality(const InteractionEvent*); +\endcode + +Your functions are connected with actions and conditions by implementing the function ConnectActionsAndFunctions(), e.g. \code void mitk::ExampleInteractor::ConnectActionsAndFunctions() { + CONNECT_CONDITION("checkPoint", CheckPoint); CONNECT_FUNCTION("addPoint", AddPoint); CONNECT_FUNCTION("enoughPoints", EnoughPoints); } \endcode Now all that is left is to write a state machine pattern and a config file as is described in the tutorials. -\subsection ExampleInternalEvent PointSetDataInteractor To provide a useful example the mitk::PointSetDataInteractor is annotated with comments that describe the important parts for an implementation of a mitk::DataInteractor. This step assumes knowledge of the Interaction concept described in \ref DataInteractionPage and some background of the implementation which is described in \ref DataInteractionPageTechnical. Please refer to these pages before proceeding. - - - -DataInteractor are to inherit from mitk::DataInteractor. Their functionality is implemented in functions that follow this interface: -\code -bool SomeFunctionality(StateMachineAction* , InteractionEvent*); -\endcode - -Your functions are connected with actions by implementing the function ConnectActionsAndFunctions(), e.g. - -\code -void mitk::ExampleInteractor::ConnectActionsAndFunctions() -{ - CONNECT_FUNCTION("addPoint", AddPoint); - CONNECT_FUNCTION("enoughPoints", EnoughPoints); -} -\endcode - Now all that is left it to write a state machine pattern and a config file as is described in the tutorials. \subsection ExampleInternalEvent Example Interactor using InternalEvent A useful tool in creating DataInteractors is mitk::InternalEvent which allows the mitk::DataInteractor to send signals on its own. The following will describe how to build a mitk::DataInteractor that allows to add points until a certain number of points is reached. The number of accepted points is provided in the config file as a parameter. So we start by writing a state machine pattern that add points until it receives an mitk::InternalEvent telling it, that enough points have been added. \code + <--! dead state, nothing happens any more, once we reached this --> \endcode In our config file we set the number of maximal points to 10, and define AddPointClick as a right mouse click with the ctrl button pressed. \code \endcode The implementation is described in the following. \see Step10.h \see Step10.cpp \dontinclude Step10.h Implementation of protected functions: \skipline protected: \until virtual void ConfigurationChanged(); ConnectActionsAndFunctions - Is inherited from mitk::InteractionStateMachine, here action strings from the xml are connected with functions in the mitk::DataInteractor (as seen above). In our example this looks like this: \dontinclude Step10.cpp \skipline void mitk::ExampleInteractor::ConnectActionsAndFunctions() \until } ConfigurationChanged - Is called whenever a new configuration file is loaded (by the mitk::InteractionEventHandler super class), this function allows to implement initialization code that depends on configuration values. In our example we want to set the limit of allowed points: \dontinclude Step10.cpp \skipline void mitk::ExampleInteractor::ConfigurationChang \until } -Next the actual functionality of the DataInteractor is implemented, by providing one function per action, following this prototype: - -\code -bool FUNCTION_NAME (StateMachineAction* , InteractionEvent*); -\endcode +Next the actual functionality of the DataInteractor is implemented, by providing one function per action, following this prototype described before. \dontinclude Step10.h \skipline private: -\until bool EnoughPoints(StateMac +\until bool CheckPoint(cons Each function has to return a boolean value. True if the action has been executed, and false if the action has not been executed. \dontinclude Step10.cpp \skipline bool mitk::ExampleInteractor::AddPoint(StateM \until //- +If the conditions returns false the following actions in the same transition will not be executed. + +\dontinclude Step10.cpp + +\skipline bool mitk::ExampleInteractor::CheckPoint( +\until // end CheckPoint + Here we see an internal event used to signal that the point set reached the maximal number of allowed points. The event is created and added to the Dispatchers event queue. \dontinclude Step10.cpp \skipline // create internal \until positionEvent->GetSender( \note Internal events do not need any mapping to event variants. Their signal name is equivalent with the event variant. There are also two documented classes implementing a mitk::DataInteractor and a mitk::InteractionEventObserver which can be looked at for further understanding: \see mitk::PointSetDataInteractor \see mitk::DisplayInteractor Have fun with creating your own interaction and please think about contributing it to MITK! If you meet any difficulties during this step, don't hesitate to ask on the MITK mailing list mitk-users@lists.sourceforge.net! People there are kind and will try to help you. \ref Step09Page "[Previous step]" \ref TutorialPage "[Main tutorial page]" */ diff --git a/Examples/Tutorial/Step10/Step10.cpp b/Examples/Tutorial/Step10/Step10.cpp index a2777b5a4c..86853d7dbd 100644 --- a/Examples/Tutorial/Step10/Step10.cpp +++ b/Examples/Tutorial/Step10/Step10.cpp @@ -1,92 +1,110 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "Step10.h" #include "mitkMouseMoveEvent.h" #include #include "mitkRenderingManager.h" #include "mitkInternalEvent.h" // #include "mitkDispatcher.h" #include "mitkBaseRenderer.h" #include void mitk::ExampleInteractor::ConnectActionsAndFunctions() { - // connect the action names of the state machine pattern with function within + // connect the action and condition names of the state machine pattern with function within // this DataInteractor + CONNECT_CONDITION("checkPoint", CheckPoint); CONNECT_FUNCTION("addPoint", AddPoint); CONNECT_FUNCTION("enoughPoints", EnoughPoints); } +bool mitk::MitralModelInteractor::CheckPoint(const InteractionEvent *interactionEvent) +{ + // check if a point close to the clicked position already exists + float epsilon = 0.3; // do not accept new points within 3mm range of existing points + InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent); + if (positionEvent != NULL) + { + // query the position of the mouse in the world geometry + mitk::Point3D point = positionEvent->GetPositionInWorld(); + int retVal = m_PointSet->SearchPoint(point, epsilon); + if ( retVal == -1 ) // SearchPoint returns -1 if no point was found within given range + return true; + } + return false; // if the positionEvent is NULL or a point was found return false. AddPoint will not be executed + // end CheckPoint +} + bool mitk::ExampleInteractor::AddPoint(StateMachineAction*, InteractionEvent* interactionEvent) { // cast InteractionEvent to a position event in order to read out the mouse position // we stay here as general as possible so that a different state machine pattern // can reuse this code with MouseRelease or MouseMoveEvents. InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent); if (positionEvent != NULL) { // query the position of the mouse in the world geometry mitk::Point3D point = positionEvent->GetPositionInWorld(); m_PointSet->InsertPoint(m_NumberOfPoints, point, 0); m_NumberOfPoints++; GetDataNode()->SetData(m_PointSet); GetDataNode()->Modified(); if (m_NumberOfPoints != 0 && m_NumberOfPoints >= m_MaximalNumberOfPoints) { // create internal event that signal that the maximal number of points is reached InternalEvent::Pointer event = InternalEvent::New(NULL,this, "enoughPointsAdded"); // add the internal event to the event queue of the Dispatcher positionEvent->GetSender()->GetDispatcher()->QueueEvent(event.GetPointer()); } // update the RenderWindow to show new points mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return true; } else { return false; } } bool mitk::ExampleInteractor::EnoughPoints(StateMachineAction*, InteractionEvent*) { GetDataNode()->SetProperty("contourcolor", ColorProperty::New(1.0, 1.0, 0.0)); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return true; } //- mitk::ExampleInteractor::ExampleInteractor() { m_NumberOfPoints = 0; m_MaximalNumberOfPoints = 0; m_PointSet = PointSet::New(); // create PointSet to store our point in } mitk::ExampleInteractor::~ExampleInteractor() { } void mitk::ExampleInteractor::ConfigurationChanged() { // read how many points we accept from the config properties mitk::PropertyList::Pointer properties = GetPropertyList(); std::string maxNumber; properties->GetStringProperty("NumberOfPoints",maxNumber); m_MaximalNumberOfPoints = atoi(maxNumber.c_str()); } diff --git a/Examples/Tutorial/Step10/Step10.h b/Examples/Tutorial/Step10/Step10.h index 7574c459d6..51248899e3 100644 --- a/Examples/Tutorial/Step10/Step10.h +++ b/Examples/Tutorial/Step10/Step10.h @@ -1,55 +1,56 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "itkObject.h" #include "itkSmartPointer.h" #include "itkObjectFactory.h" #include "mitkCommon.h" #include #include "mitkDataInteractor.h" #include namespace mitk { class MITK_CORE_EXPORT ExampleInteractor: public DataInteractor { public: mitkClassMacro(ExampleInteractor, DataInteractor); itkFactorylessNewMacro(Self) itkCloneMacro(Self) protected: ExampleInteractor(); virtual ~ExampleInteractor(); virtual void ConnectActionsAndFunctions(); /** * Derived function. * Is executed when config object is set / changed. * Here it is used to read out the parameters set in the configuration file, * and set the member variables accordingly. */ virtual void ConfigurationChanged(); private: bool AddPoint(StateMachineAction* , InteractionEvent*); // function to add new points bool EnoughPoints(StateMachineAction* , InteractionEvent*); // function changes color of pointset to indicate, it is full + bool CheckPoint(const InteractionEvent* interactionEvent); // function checks if the clicked point is valid PointSet::Pointer m_PointSet; int m_NumberOfPoints; int m_MaximalNumberOfPoints; }; }