Index: mitk/Applications/Tutorial/CMakeLists.txt =================================================================== --- mitk/Applications/Tutorial/CMakeLists.txt (revision 26384) +++ mitk/Applications/Tutorial/CMakeLists.txt (working copy) @@ -35,6 +35,12 @@ ENDFOREACH(stepNo) +#step 10 equals 1-8 +SET(STEP10_CPP ${STEP10_CPP} Step10.cpp QtTesting.cpp) +ADD_EXECUTABLE(Step10 ${STEP10_CPP}) +TARGET_LINK_LIBRARIES(Step10 ${ALL_LIBRARIES}) + + ADD_DEPENDENCIES(Step7 Step6) ADD_DEPENDENCIES(Step8 Step7 Step6) Index: mitk/Applications/Tutorial/Step10.cpp =================================================================== --- mitk/Applications/Tutorial/Step10.cpp (revision 0) +++ mitk/Applications/Tutorial/Step10.cpp (revision 0) @@ -0,0 +1,155 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date: 2010-04-07 16:36:18 +0200 (Mi, 07 Apr 2010) $ +Version: $Revision: 22088 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "QmitkRegisterClasses.h" +#include "QmitkRenderWindow.h" + +#include +#include +#include + +#include +#include + +//for the interaction +#include +#include "mitkGlobalInteraction.h" + +//##Documentation +//## @brief Load two or more surfaces (stl format, see e.g. Core/Code/Testing/data directory for binary.stl) and display it in a 3D view. +//## The MoveSurfaceInteractor explained in tutorial Step10.dox is used to move the surfaces in 3D by arrow keys in combination +//## with and without Shift key. Use two surfaces to see that the objects and not the camera are moving. +int main(int argc, char* argv[]) +{ + QApplication qtapplication( argc, argv ); + + if (argc < 2) + { + fprintf( stderr, "Usage: %s [filename_1] ... [filename_n] \n\n", itksys::SystemTools::GetFilenameName(argv[0]).c_str() ); + return 1; + } + + // Register Qmitk-dependent global instances + QmitkRegisterClasses(); + + //************************************************************************* + // Part I: Basic initialization + //************************************************************************* + + // Create a DataStorage + // The DataStorage manages all data objects. It is used by the + // rendering mechanism to render all data objects + // We use the standard implementation mitk::StandaloneDataStorage. + + mitk::StandaloneDataStorage::Pointer ds = mitk::StandaloneDataStorage::New(); + + + //************************************************************************* + // Part II: Create surface data by reading an stl file + //************************************************************************* + + for(int i=1; iSetFileName(filename); + reader->Update(); + } + catch(...) + { + fprintf( stderr, "Could not open file %s \n\n", filename ); + exit(2); + } + + //************************************************************************* + // Part III: Put the data into the datastorage + //************************************************************************* + + // Create a node and add the Image (which is read from the file) to it + mitk::DataNode::Pointer node = mitk::DataNode::New(); + node->SetData(reader->GetOutput()); + + // ******************************************************* + // ****************** START OF NEW PART ****************** + // ******************************************************* + + // create interactor + // use it with up, down (->z direction), left and right (x-direction) arrow keys. Also hold Shift to translate in y direction. + // see state machine pattern SelectAndMoveObjectWithArrowKeys in file StateMachine.xml for definition of interaction or use the StatemachineEditor. + mitk::MoveSurfaceInteractor::Pointer surfaceInteractor = + mitk::MoveSurfaceInteractor::New("SelectAndMoveObjectWithArrowKeys",node); + + //activate interactor at interaction controller: + mitk::GlobalInteraction::GetInstance()->AddInteractor(surfaceInteractor); + + // ******************************************************* + // ******************* END OF NEW PART ******************* + // ******************************************************* + + // Add the node to the DataStorage + ds->Add(node); + + //doesn't have to be done, but nicer! Is destroyed when leaving the sccope anyway + reader = NULL; + surfaceInteractor = NULL; + } + + //************************************************************************* + // Part IV: Create window and pass the datastorage to it + //************************************************************************* + + // Create a RenderWindow + QmitkRenderWindow renderWindow; + + // Tell the RenderWindow which (part of) the datastorage to render + renderWindow.GetRenderer()->SetDataStorage(ds); + + // Use it as a 3D view + renderWindow.GetRenderer()->SetMapperID(mitk::BaseRenderer::Standard3D); + + // Initialize the RenderWindow + mitk::TimeSlicedGeometry::Pointer geo = ds->ComputeBoundingGeometry3D(ds->GetAll()); + mitk::RenderingManager::GetInstance()->InitializeViews( geo ); + + //************************************************************************* + // Part V: Qt-specific initialization + //************************************************************************* + renderWindow.show(); + renderWindow.resize( 256, 256 ); + + MITK_INFO<<"Select an object with a mouse click. Use arrow keys (also with shift-key) to move the surface.\n"; + MITK_INFO<<"Deselecting and selecting an other surface by clicking onto it. Selected surfaces turn yellow, deselected blue.\n"; + + // for testing + #include "QtTesting.h" + if (strcmp(argv[argc-1], "-testing") != 0) + return qtapplication.exec(); + else + return QtTesting(); + + // cleanup: Remove References + ds = NULL; +} +/** +\example Step10.cpp +*/ Property changes on: mitk\Applications\Tutorial\Step10.cpp ___________________________________________________________________ Added: svn:eol-style + native Index: mitk/Core/Code/files.cmake =================================================================== --- mitk/Core/Code/files.cmake (revision 26384) +++ mitk/Core/Code/files.cmake (working copy) @@ -138,6 +138,8 @@ Interactions/mitkGlobalInteraction.cpp Interactions/mitkInteractor.cpp Interactions/mitkMouseMovePointSetInteractor.cpp + Interactions/mitkMoveSurfaceInteractor.cpp + Interactions/mitkMoveSurfaceInteractor.cpp Interactions/mitkPointSetInteractor.cpp Interactions/mitkPositionEvent.cpp Interactions/mitkPositionTracker.cpp Index: mitk/Core/Code/Interactions/mitkMoveSurfaceInteractor.cpp =================================================================== --- mitk/Core/Code/Interactions/mitkMoveSurfaceInteractor.cpp (revision 0) +++ mitk/Core/Code/Interactions/mitkMoveSurfaceInteractor.cpp (revision 0) @@ -0,0 +1,180 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date: 2010-09-14 09:48:51 +0200 (Di, 14 Sep 2010) $ +Version: $Revision: 26074 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + + +#include "mitkMoveSurfaceInteractor.h" +#include "mitkSurface.h" +#include "mitkInteractionConst.h" +#include +#include "mitkDisplayPositionEvent.h" +#include "mitkStateEvent.h" +#include "mitkProperties.h" + +//for an temporary update +#include "mitkRenderingManager.h" + +//## Default Constructor +mitk::MoveSurfaceInteractor +::MoveSurfaceInteractor(const char * type, DataNode* dataNode) +:Interactor(type, dataNode) +{ +} + +mitk::MoveSurfaceInteractor::~MoveSurfaceInteractor() +{ +} + + +bool mitk::MoveSurfaceInteractor::ExecuteAction( Action* action, mitk::StateEvent const* stateEvent ) +{ + bool ok = false; + + /*Each case must watch the type of the event!*/ + switch (action->GetActionId()) + { + case AcDONOTHING: + ok = true; + break; + case AcCHECKELEMENT: + /* + * picking: Answer the question if the given position within stateEvent is close enough to select an object + * send yes if close enough and no if not picked + */ + { + mitk::DisplayPositionEvent const *posEvent = dynamic_cast (stateEvent->GetEvent()); + if (posEvent == NULL) + { + MITK_WARN<<"Wrong usage of mitkMoveSurfaceInteractor! Aborting interaction!\n"; + return false; + } + + mitk::Point3D worldPoint = posEvent->GetWorldPosition(); + /* now we have a worldpoint. check if it is inside our object and select/deselect it accordingly */ + + mitk::StateEvent* newStateEvent = NULL; + const Geometry3D* geometry = GetData()->GetUpdatedTimeSlicedGeometry()->GetGeometry3D( m_TimeStep ); + if (geometry->IsInside(worldPoint)) + newStateEvent = new mitk::StateEvent(EIDYES, stateEvent->GetEvent()); + else + newStateEvent = new mitk::StateEvent(EIDNO, stateEvent->GetEvent()); + + /* write new state (selected/not selected) to the property */ + this->HandleEvent( newStateEvent ); + + ok = true; + break; + } + case AcSELECT: + // select the data + { + mitk::BoolProperty::Pointer selected = dynamic_cast(m_DataNode->GetProperty("selected")); + if ( selected.IsNull() ) + { + selected = mitk::BoolProperty::New(); + m_DataNode->GetPropertyList()->SetProperty("selected", selected); + } + + mitk::ColorProperty::Pointer color = dynamic_cast(m_DataNode->GetProperty("color")); + if ( color.IsNull() ) + { + color = mitk::ColorProperty::New(); + m_DataNode->GetPropertyList()->SetProperty("color", color); + } + + selected->SetValue(true); + color->SetColor(1.0, 1.0, 0.0); + + //update rendering + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + + ok = true; + break; + } + case AcDESELECT: + //deselect the data + { + mitk::BoolProperty::Pointer selected = dynamic_cast(m_DataNode->GetProperty("selected")); + if ( selected.IsNull() ) + { + selected = mitk::BoolProperty::New(); + m_DataNode->GetPropertyList()->SetProperty("selected", selected); + } + + mitk::ColorProperty::Pointer color = dynamic_cast(m_DataNode->GetProperty("color")); + if ( color.IsNull() ) + { + color = mitk::ColorProperty::New(); + m_DataNode->GetPropertyList()->SetProperty("color", color); + } + + selected = mitk::BoolProperty::New(false); + color->SetColor(0.0, 0.0, 1.0); + + //update rendering + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + + ok = true; + break; + } + case AcMOVE: + { + //modify Geometry from data as given in parameters or in event + mitk::IntProperty* xP = dynamic_cast(action->GetProperty("DIRECTION_X")); + mitk::IntProperty* yP = dynamic_cast(action->GetProperty("DIRECTION_Y")); + mitk::IntProperty* zP = dynamic_cast(action->GetProperty("DIRECTION_Z")); + if (xP == NULL || yP == NULL || zP == NULL) + { + MITK_WARN<<"No properties returned\n!"; + return false; + } + mitk::Vector3D movementVector; + movementVector.SetElement(0, (float) xP->GetValue()); + movementVector.SetElement(1, (float) yP->GetValue()); + movementVector.SetElement(2, (float) zP->GetValue()); + + //checking corresponding Data; has to be a surface or a subclass + mitk::Surface* surface = dynamic_cast(m_DataNode->GetData()); + if ( surface == NULL ) + { + MITK_WARN<<"MoveSurfaceInteractor got wrong type of data! Aborting interaction!\n"; + return false; + } + Geometry3D* geometry = surface->GetUpdatedTimeSlicedGeometry()->GetGeometry3D( m_TimeStep ); + geometry->Translate(movementVector); + + // indicate modification of data tree node + m_DataNode->Modified(); + + //update rendering + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + + ok = true; + break; + } + + default: + return Superclass::ExecuteAction( action, stateEvent ); + } + + return ok; +} + +/** \example mitkMoveSurfaceInteractor.cpp + * This is an example of how to implement a new Interactor. + * See more details about this example in tutorial Step10. + */ + Property changes on: mitk\Core\Code\Interactions\mitkMoveSurfaceInteractor.cpp ___________________________________________________________________ Added: svn:eol-style + native Index: mitk/Core/Code/Interactions/mitkMoveSurfaceInteractor.h =================================================================== --- mitk/Core/Code/Interactions/mitkMoveSurfaceInteractor.h (revision 0) +++ mitk/Core/Code/Interactions/mitkMoveSurfaceInteractor.h (revision 0) @@ -0,0 +1,76 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date: 2010-08-25 13:01:29 +0200 (Mi, 25 Aug 2010) $ +Version: $Revision: 25766 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + + +#ifndef MITKMOVESURFACEINTERACTOR_H_HEADER_INCLUDED +#define MITKMOVESURFACEINTERACTOR_H_HEADER_INCLUDED + +#include + +namespace mitk +{ + class DataNode; + + /** + * \brief Interaction to move a surface by the arrow keys. See tutorial step 10 for explanation + * + * \ingroup Interaction + */ + class MITK_CORE_EXPORT MoveSurfaceInteractor : public Interactor + { + public: + mitkClassMacro(MoveSurfaceInteractor, Interactor); + mitkNewMacro2Param(Self, const char*, DataNode*); + + /** + * \brief check how good an event can be handled + */ + //virtual float CanHandleEvent(StateEvent const* stateEvent) const; + //used from mitkInteractor + + /** + *@brief Gets called when mitk::DataNode::SetData() is called + * + * No need to use it here, because the pattern won't be complex + * and we can take care of unexpected data change + **/ + //virtual void DataChanged(){}; + + protected: + /** + * \brief Constructor + */ + MoveSurfaceInteractor(const char * type, DataNode* dataNode); + + /** + * \brief Default Destructor + **/ + virtual ~MoveSurfaceInteractor(); + + /** + * @brief Convert the given Actions to Operations and send to data and UndoController + **/ + virtual bool ExecuteAction( Action* action, mitk::StateEvent const* stateEvent ); + }; +} + +/** \example mitkMoveSurfaceInteractor.h + * This is an example of how to implement a new Interactor. + * See more details about this example in tutorial Step10. + */ + +#endif /* MITKMOVESURFACEINTERACTOR_H_HEADER_INCLUDED */ Property changes on: mitk\Core\Code\Interactions\mitkMoveSurfaceInteractor.h ___________________________________________________________________ Added: svn:eol-style + native Index: mitk/Core/Code/Interactions/StateMachine.xml =================================================================== --- mitk/Core/Code/Interactions/StateMachine.xml (revision 26384) +++ mitk/Core/Code/Interactions/StateMachine.xml (working copy) @@ -68,7 +68,19 @@ - + + + + + + + + + + + + + @@ -167,6 +179,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -214,7 +299,7 @@ - + @@ -224,7 +309,7 @@ - + @@ -234,7 +319,7 @@ - + @@ -3495,7 +3580,7 @@ - + Index: mitk/CoreUI/Bundles/org.mitk.gui.qt.common/resources/StateMachine.xml =================================================================== --- mitk/CoreUI/Bundles/org.mitk.gui.qt.common/resources/StateMachine.xml (revision 26384) +++ mitk/CoreUI/Bundles/org.mitk.gui.qt.common/resources/StateMachine.xml (working copy) @@ -68,6 +68,18 @@ + + + + + + + + + + + + @@ -167,6 +179,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -214,7 +299,7 @@ - + @@ -224,7 +309,7 @@ - + @@ -234,7 +319,7 @@ - + Index: mitk/Documentation/Doxygen/Tutorial/Step0.dox =================================================================== --- mitk/Documentation/Doxygen/Tutorial/Step0.dox (revision 26384) +++ mitk/Documentation/Doxygen/Tutorial/Step0.dox (working copy) @@ -1,15 +0,0 @@ -/** - -\page Step0Page MITK Tutorial - Step 0: Getting started - -To build the tutorials follow the \ref BuildInstructionsPage and make sure that MITK_BUILD_TUTORIAL is checked/set to ON. - -\image html configureCMake.PNG - -The tutorial source files can be found in the Applications\\Tutorial\\ subdirectory of the source tree. The tutorial executables are in the bin\\Release\\ or bin\\Debug\\ subdirectory of the binary tree after compilation. - - - -\ref Step1Page "[Next step]" \ref TutorialPage "[Main tutorial page]" - -*/ Index: mitk/Documentation/Doxygen/Tutorial/Step00.dox =================================================================== --- mitk/Documentation/Doxygen/Tutorial/Step00.dox (revision 26230) +++ mitk/Documentation/Doxygen/Tutorial/Step00.dox (working copy) @@ -1,6 +1,6 @@ /** -\page Step0Page MITK Tutorial - Step 0: Getting started +\page Step00Page MITK Tutorial - Step 0: Getting started To build the tutorials follow the \ref BuildInstructionsPage and make sure that MITK_BUILD_TUTORIAL is checked/set to ON. @@ -10,6 +10,6 @@ -\ref Step1Page "[Next step]" \ref TutorialPage "[Main tutorial page]" +\ref Step01Page "[Next step]" \ref TutorialPage "[Main tutorial page]" */ Index: mitk/Documentation/Doxygen/Tutorial/Step01.dox =================================================================== --- mitk/Documentation/Doxygen/Tutorial/Step01.dox (revision 26230) +++ mitk/Documentation/Doxygen/Tutorial/Step01.dox (working copy) @@ -1,6 +1,6 @@ /** -\page Step1Page MITK Tutorial - Step 1: Displaying an image +\page Step01Page MITK Tutorial - Step 1: Displaying an image \image html step1_result.png @@ -15,6 +15,6 @@ \include Step1.cpp -\ref Step0Page "[Previous step]" \ref Step2Page "[Next step]" \ref TutorialPage "[Main tutorial page]" +\ref Step00Page "[Previous step]" \ref Step02Page "[Next step]" \ref TutorialPage "[Main tutorial page]" */ Index: mitk/Documentation/Doxygen/Tutorial/Step02.dox =================================================================== --- mitk/Documentation/Doxygen/Tutorial/Step02.dox (revision 26230) +++ mitk/Documentation/Doxygen/Tutorial/Step02.dox (working copy) @@ -1,6 +1,6 @@ /** - \page Step2Page MITK Tutorial - Step 2: Load one or more data sets + \page Step02Page MITK Tutorial - Step 2: Load one or more data sets \image html step2_result.png @@ -25,6 +25,6 @@ - \ref Step1Page "[Previous step]" \ref Step3Page "[Next step]" \ref TutorialPage "[Main tutorial page]" + \ref Step01Page "[Previous step]" \ref Step03Page "[Next step]" \ref TutorialPage "[Main tutorial page]" */ Index: mitk/Documentation/Doxygen/Tutorial/Step03.dox =================================================================== --- mitk/Documentation/Doxygen/Tutorial/Step03.dox (revision 26230) +++ mitk/Documentation/Doxygen/Tutorial/Step03.dox (working copy) @@ -1,6 +1,6 @@ /** - \page Step3Page MITK Tutorial - Step 3: Create 3D view + \page Step03Page MITK Tutorial - Step 3: Create 3D view As in the previous step one or more data sets (many images, surface and other formats) may be loaded. The difference is that they are displayed in a 3D view. The QmitkRenderWindow is now used for displaying a 3D view, by setting the used mapper-slot to Standard3D. @@ -23,7 +23,7 @@ Tell the renderer to create a 3D view: -\skipline // use it as a 3D view! +\skipline // Use it as a 3D view! \skipline renderWindow.GetRenderer()->SetMapperID The rest of the code remains unchanged. @@ -43,6 +43,6 @@ \skipline Check \until node->SetProperty -\ref Step2Page "[Previous step]" \ref Step4Page "[Next step]" \ref TutorialPage "[Main tutorial page]" +\ref Step02Page "[Previous step]" \ref Step04Page "[Next step]" \ref TutorialPage "[Main tutorial page]" */ Index: mitk/Documentation/Doxygen/Tutorial/Step04.dox =================================================================== --- mitk/Documentation/Doxygen/Tutorial/Step04.dox (revision 26230) +++ mitk/Documentation/Doxygen/Tutorial/Step04.dox (working copy) @@ -1,6 +1,6 @@ /** -\page Step4Page MITK Tutorial - Step 4: Use several views to explore data +\page Step04Page MITK Tutorial - Step 4: Use several views to explore data As in Step 2 and Step 3 one or more data sets may be loaded. @@ -54,13 +54,13 @@ Therefore it has to be added to the tree: \dontinclude Step4.cpp -\skipline it.Add(view2.GetRenderer() -\skipline it.Add(view3.GetRenderer() +\skipline ds->Add(view2.GetRenderer() +\skipline ds->Add(view3.GetRenderer() Slice positions are now displayed as can be seen in the picture. \dontinclude Step4.cpp -\ref Step3Page "[Previous step]" \ref Step5Page "[Next step]" \ref TutorialPage "[Main tutorial page]" +\ref Step03Page "[Previous step]" \ref Step05Page "[Next step]" \ref TutorialPage "[Main tutorial page]" */ Index: mitk/Documentation/Doxygen/Tutorial/Step05.dox =================================================================== --- mitk/Documentation/Doxygen/Tutorial/Step05.dox (revision 26230) +++ mitk/Documentation/Doxygen/Tutorial/Step05.dox (working copy) @@ -1,6 +1,6 @@ /** - \page Step5Page MITK Tutorial - Step 5: Interactively add points + \page Step05Page MITK Tutorial - Step 5: Interactively add points In addition to Step 4 where 3 views on the data were created we now want to interactively add points. @@ -28,7 +28,7 @@ \skipline mitk::PointSet \until "pointsetinteractor" - \ref Step4Page "[Previous step]" \ref Step6Page "[Next step]" \ref TutorialPage "[Main tutorial page]" + \ref Step04Page "[Previous step]" \ref Step06Page "[Next step]" \ref TutorialPage "[Main tutorial page]" */ Index: mitk/Documentation/Doxygen/Tutorial/Step06.dox =================================================================== --- mitk/Documentation/Doxygen/Tutorial/Step06.dox (revision 26230) +++ mitk/Documentation/Doxygen/Tutorial/Step06.dox (working copy) @@ -1,6 +1,6 @@ /** -\page Step6Page MITK Tutorial - Step 6: Use an interactive region-grower +\page Step06Page MITK Tutorial - Step 6: Use an interactive region-grower In this step the program is enhanced by the possibility to start a region-grower at interactively added points. We will see how MITK images can be accessed as ITK images. @@ -25,15 +25,16 @@ The widgets are initialized as in the previous steps but with an additional QVBox for a button to start the segmentation: -\skipline m_TopLevelWidget = new QVBox(this); +\skipline Create controlsParent +\until hlayout->addWidget(m_LineEditThresholdMax) Then a button is created to start the segmentation and its clicked() signal is connected to the method StartRegionGrowing(): \dontinclude Step6.cpp -\skipline QPushButton -\skipline connect +\skipline QPushButton* startButton +\skipline connect(startButton \section AccessMTIKImagesAsITKImagesSection Access MITK images as ITK images @@ -106,6 +107,6 @@ \li \code mitk::Surface::SetVtkPolyData(vtkPolyData*, int time = 0) \endcode -\ref Step5Page "[Previous step]" \ref Step7Page "[Next step]" \ref TutorialPage "[Main tutorial page]" +\ref Step05Page "[Previous step]" \ref Step07Page "[Next step]" \ref TutorialPage "[Main tutorial page]" */ Index: mitk/Documentation/Doxygen/Tutorial/Step07.dox =================================================================== --- mitk/Documentation/Doxygen/Tutorial/Step07.dox (revision 26230) +++ mitk/Documentation/Doxygen/Tutorial/Step07.dox (working copy) @@ -1,6 +1,6 @@ /** - \page Step7Page MITK Tutorial - Step 7: Convert result of region growing into a surface + \page Step07Page MITK Tutorial - Step 7: Convert result of region growing into a surface In this step the result of the previous step is converted into a surface by means of a VTK filter. @@ -16,6 +16,6 @@ \skipline if(m_ResultImage \until } - \ref Step6Page "[Previous step]" \ref Step8Page "[Next step]" \ref TutorialPage "[Main tutorial page]" + \ref Step06Page "[Previous step]" \ref Step08Page "[Next step]" \ref TutorialPage "[Main tutorial page]" */ \ No newline at end of file Index: mitk/Documentation/Doxygen/Tutorial/Step08.dox =================================================================== --- mitk/Documentation/Doxygen/Tutorial/Step08.dox (revision 26230) +++ mitk/Documentation/Doxygen/Tutorial/Step08.dox (working copy) @@ -1,6 +1,6 @@ /** - \page Step8Page MITK Tutorial - Step 8: Use QmitkStdMultiWidget as widget + \page Step08Page MITK Tutorial - Step 8: Use QmitkStdMultiWidget as widget In this step a QmitkStdMultiWidget is used. It offers four views on the data. From top left to bottom the views are initialized as transversal, sagittal and coronar. The bottom right view is initialized as 3D view. @@ -15,10 +15,10 @@ Step8 inherits from Step6. The method SetupWidgets() is changed: A QmitkStdMultiWidget is used instead of one QmitkRenderWindow and two instances of QmitkSliceWidget. \dontinclude Step8.cpp - \skipline Part II - \until setCentralWidget + \skipline Part Ia + \until GetMoveAndZoomInteractor - \ref Step7Page "[Previous step]" \ref Step9Page "[Next step]" + \ref Step07Page "[Previous step]" \ref Step09Page "[Next step]" */ Index: mitk/Documentation/Doxygen/Tutorial/Step09.dox =================================================================== --- mitk/Documentation/Doxygen/Tutorial/Step09.dox (revision 26230) +++ mitk/Documentation/Doxygen/Tutorial/Step09.dox (working copy) @@ -1,6 +1,6 @@ /** -\page Step9Page MITK Tutorial - Step 9: A plug-in +\page Step09Page MITK Tutorial - Step 9: A plug-in MITK uses a very modular concept to maximize reusability and portability. You start an application (for example ExtApp, the sample application provided by MITK). An application has several bundles (or plug-ins). A bundle can be a functionality, which in turn can be a view, each of these terms specifying certain behaviour and attributes. @@ -221,6 +221,6 @@ If you meet any difficulties during your first steps, 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 Step8Page "[Previous step]" \ref TutorialPage "[Main tutorial page]" + \ref Step08Page "[Previous step]" \ref Step10Page "[Next Step]" \ref TutorialPage "[Main tutorial page]" */ Index: mitk/Documentation/Doxygen/Tutorial/Step1.dox =================================================================== --- mitk/Documentation/Doxygen/Tutorial/Step1.dox (revision 26384) +++ mitk/Documentation/Doxygen/Tutorial/Step1.dox (working copy) @@ -1,20 +0,0 @@ -/** - -\page Step1Page MITK Tutorial - Step 1: Displaying an image - -\image html step1_result.png - -The first program shows how to display an image in a 2D view. The picture above is a snapshot of the program. - -The program has to be executed using the image file mitk/Core/Code/Testing/Data/Pic3D.pic.gz. -To set the image file path in Visual Studio, right click on "Step1"-project and go to 'Properties -> Configuration Properties -> Debugging'. Now insert the image file path in the "Command Arguments" text field. Use this also in the following steps. - -\image html configureVisualStudioProperties.png - -The code is subdivided in parts I - V. First of all a DataTree has to be created. Then data has to be read from a file which afterwards has to be put into the tree. Part IV creates a window and passes the tree to it. The last part deals with some Qt-specific initialization. - -\include Step1.cpp - -\ref Step0Page "[Previous step]" \ref Step2Page "[Next step]" \ref TutorialPage "[Main tutorial page]" - -*/ Index: mitk/Documentation/Doxygen/Tutorial/Step10.dox =================================================================== --- mitk/Documentation/Doxygen/Tutorial/Step10.dox (revision 0) +++ mitk/Documentation/Doxygen/Tutorial/Step10.dox (revision 0) @@ -0,0 +1,99 @@ +/** + +\page Step10Page MITK Tutorial - Step 10: Adding new Interaction + +This tutorial step goes beyond the activation of an interactor (class/object, that modifies a data by user interaction) as shown in \ref Step05Page and shows what needs to be implemented to add a new way of interaction within your MITK application. +Please see \ref InteractionPage as an introduction to the MITK interaction mechanism. + +The beginning of a new interaction is the idea or the feature request. To lighten things up, let's say, that we want to enable the user to move a surface by using the arrow keys. So a new interactor needs to be implemented, that will be associated to a surface (data of a data node) and on an arrow event modifies the geometry of the data to move it in virtual 3D world space. + +We start with the definition of the state machine pattern to see what actions need to be implemented inside the interactor. + + \dontinclude StateMachine.xml + \skip TutorialStep10Begin + \until TutorialStep10End + +The pattern can be read like this: +\li The state machine pattern starts in state 1. It's the start state. +\li An event with the ID = 1 (left mouse button click, see corresponding definition in StateMachine.xml) leads to a state 2 and the action 30 ( \c AcCHECKELEMENT) is processed. +\li State 2 is a guard state and thus the state machine will only temporarily be in this state. \c AcCHECKELEMENT needs to check if the surface was hit by the mouse position (picking) and has to send the answer (\c EIDYES / \c EIDNO) to itself. If the answer is \c YES, then the current state will be changed to state 10 and the actions \c AcSELECT and \c AcMODE_SELECT will be processed. \c AcSELECT has to change the data to show that it is selected (e.g. change the color). \c AcMODE_SELECT causes a change in a special selection mode (for state machines) so that mitk::GlobalInteraction will favour this state machine. If the answer is \c NO, the current state will be changed to state 1 and actions \c AcDESELECT, that needs to deselect (change color) the data, and \c AcMODE_DESELECT is executed. \c AcMODE_DESELECT sets the mode of this state machine to deselected, so it will not be favoured by mitk::GlobalInteraction. +\li From state 10 a left mouse button click event will check if it still is picked by goint to state 2 and executing \c AcCHECKELEMENT. Furthermore we have several transitions, that don't leave the state 10 and wait for arrow keys (up, down, shift+up, shift+down, left, right). They all lead to action \c AcMove wich will implement the movement of the surface in 3D. Within the transitions three parameters define a movement vector that can be read within the implementation and used for the direction of movement. Several parameter types are supported. See mitkStateMachineFactory.cpp for supported types (\c BOOL_PARAMETER, \c INT_PARAMETER, \c FLOAT_PARAMETER, \c DOUBLE_PARAMETER, \c STRING_PARAMETER). + +Note, that the state id's need to be unique within the scope (state machine) but don't need to be continuous. + +Now we have a definition of states, transitions and actions, that describe the interaction of selecting a surface, highlithing the selected surface and moving the surface according to arrow keys. To later change the interaction states can be inserted that check for different conditions (e.g. if a surface may not be moved: use data node properties for as a flag). To change the keys, the \c EVENT_ID's will have to be adapted. Furthermore, the parameters can be used for a change. Because the file StateMachine.xml is loaded during runtime the interaction will change without a recompile of the application. +Note, if the application fails to read StateMachine.xml, the interaction will not be possible and a error warning will be displayed. + +So now we take a look what needs to be implemented within the new interactor: + +mitkMoveSurfaceInteractor.h + \dontinclude mitkMoveSurfaceInteractor.h + +Add includes: + \line mitkInteractor.h + + +We derive the new interactor from class Interactor and add some macros for convenience: + \skip MoveSurfaceInteractor : public + \until mitkNewMacro2Param + +The next method is called by mitk::GlobalInteraction and returns a value between 0 and 1 that represents how good a given event can be handled in the current state of the interactor. Superclass mitk::Interactor already tries to answer this question as good as possible by comparing the picked 3D world position stored within mitk::StateEvent to the center of the data bounding box, but this answer always needs to be adjusted to the corresponding data. In case of a pointset the distance to the closest point can be used to rate how good this event can be handled and in case of a mitk::Surface IsInside(...) could be used. Furthermore if the data was picked and is currently selected, a higher value can be returned. Just take care, that your interactor answers CanHandleEvent(..) right and it will get the event! But also be fair to other interactors or your interactor will get all events! +For this example we use the implementation that is given by mitk::Interactor, so we don't derive it here. + + \skip CanHandleEvent + \until used from mitkInteractor + +The following method is used for the case when someone sets a new data to the corresponding data node. Here reinitialization of this interactor can be done. Note that this method is not called if the data gets modified (points moved / added / removed). Here we don't need the method, so we neglect it. + + \line DataChanged + +Default constructor and destructor specified as protected to fullfill SmartPointer conventions. + + \skip protected + \until ~MoveSurfaceInteractor + +This is followed by one of the most important methods: + + \line ExecuteAction + +See mitkMoveSurfaceInteractor.h for whole header definition. + + \dontinclude mitkMoveSurfaceInteractor.cpp + +Now we come to the implementation within mitkMoveSurfaceInteractor.cpp and after includes we begin with constructor and destructor. Nothing special here! *boring* + + \skip Constructor + \until ~MoveSurfaceInteractor + \line { + \line } + +Remember, that events, that were sent to this interactor got handled within \c StateMachine::HandleEvent(...) according to the current state specified by the state machine pattern. If an appropriate transition is defined within the current state that waits for this event, a state change is performed. Also, all actions specified within the transition are processed by sending the action to the method ExecuteAction(Action* action, mitk::StateEvent const* stateEvent). And here we need to take care, that the actions are transformed to operations, that contain all necessary parameters so they can be sent to the data. The method \c ExecuteOperation(...) from the data object then changes the data accordingly. + + \skip ExecuteAction + \until return ok; + \line } + +Likewise to maintain readable code and to not implement too large methods, the case statements within \c ExecuteAction(...) can be devided into several methods that are connected to the method by using the \c CONNECT_ACTION macro. See doxygen documetation on \c mitk::StateMachine for an example. + +To add the newly written class to our project, we add it to the corresponding files.cmake. + +Furthermore we take care of instanciating the interactor and setting its instance to the dedicated DataNode. + +See Step10.cpp for adding the interactor to the interaction controller called mitk::GlobalInteraction and test Step10.cpp to see what the new interactor does. + + \dontinclude Step10.cpp + \skip create interactor + \until AddInteractor + +The implementation of Step10 is equal to Step1 except of loading two or more STL files, displaying the scene in 3D. +To see what mitk::MoveSurfaceInteractor does, start Step10 with the command arguments and click onto one of the displayed surfaces. It turns yellow. If it doesn't, it is probably inside another surface. Then use arrow keys (+shift key) to move the surface. Click onto the other surface to deselect the first surface and once more to select the other surface. Now use arrow keys to move the second surface. + +Have fun with creating your own interaction and please think about a contribution 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]" + +*/ Property changes on: mitk\Documentation\Doxygen\Tutorial\Step10.dox ___________________________________________________________________ Added: svn:eol-style + native Index: mitk/Documentation/Doxygen/Tutorial/Step2.dox =================================================================== --- mitk/Documentation/Doxygen/Tutorial/Step2.dox (revision 26384) +++ mitk/Documentation/Doxygen/Tutorial/Step2.dox (working copy) @@ -1,30 +0,0 @@ - /** - - \page Step2Page MITK Tutorial - Step 2: Load one or more data sets - - \image html step2_result.png - - \li \ref Step2.cpp "Step2.cpp" \n - Contains the code for this example. - - \dontinclude Step2.cpp - - This program shows how to load multiple data sets. - - A DataNodeFactory is used to produce nodes containing the data. - - The picture above shows the result of the program when reading both the image file and the surface file. - - In order to obtain the result the program has to be executed using the image file mitk/Core/Code/Testing/Data/Pic3D.pic.gz and the surface file mitk/Modules/MITKExt/Testing/Data/lungs.vtk. - - The code for this example equals the code of Step 1 except for part II and part III that are changed as follows: - \skipline Part II - \until exit(2) - \line } - \line } - - - - \ref Step1Page "[Previous step]" \ref Step3Page "[Next step]" \ref TutorialPage "[Main tutorial page]" - - */ Index: mitk/Documentation/Doxygen/Tutorial/Step3.dox =================================================================== --- mitk/Documentation/Doxygen/Tutorial/Step3.dox (revision 26384) +++ mitk/Documentation/Doxygen/Tutorial/Step3.dox (working copy) @@ -1,48 +0,0 @@ - /** - - \page Step3Page MITK Tutorial - Step 3: Create 3D view - -As in the previous step one or more data sets (many images, surface and other formats) may be loaded. The difference is that they are displayed in a 3D view. -The QmitkRenderWindow is now used for displaying a 3D view, by setting the used mapper-slot to Standard3D. -Since volume-rendering is a (rather) slow procedure, the default is that images are not displayed in the 3D view. - -In Step 3a the default is kept whereas in Step 3b volume rendering is turned on. - -As in the previous step, to obtain the results the program has to be executed using the image file mitk/Core/Code/Testing/Data/Pic3D.pic.gz and the surface file mitk/Modules/MITKExt/Testing/Data/lungs.vtk. - - -\li \ref Step3.cpp "Step3.cpp" \n -Contains the code that both creates a 3D view and turns volume rendering on. - - -\section Step3aSection Step 3a - Volume rendering turned off - -\image html step3a_result.png - -\dontinclude Step3.cpp - -Tell the renderer to create a 3D view: - -\skipline // use it as a 3D view! -\skipline renderWindow.GetRenderer()->SetMapperID - -The rest of the code remains unchanged. - -The picture above shows the result of the program when reading both the image and the surface file. -As volume rendering is off the image is not visible. - -\section Step3bSection Step 3b - Volume rendering turned on - -\image html step3b_result.png - -Volume Rendering is now turned on as shown in the picture above. - -\dontinclude Step3.cpp -The property "volumerendering" has to be turned on on the node containing the image. - -\skipline Check -\until node->SetProperty - -\ref Step2Page "[Previous step]" \ref Step4Page "[Next step]" \ref TutorialPage "[Main tutorial page]" - - */ Index: mitk/Documentation/Doxygen/Tutorial/Step4.dox =================================================================== --- mitk/Documentation/Doxygen/Tutorial/Step4.dox (revision 26384) +++ mitk/Documentation/Doxygen/Tutorial/Step4.dox (working copy) @@ -1,66 +0,0 @@ -/** - -\page Step4Page MITK Tutorial - Step 4: Use several views to explore data - -As in Step 2 and Step 3 one or more data sets may be loaded. - -Now 3 views on the data are created. -The QmitkRenderWindow is used for displaying a 3D view as in Step 3, but without volume-rendering. -Furthermore two 2D views for slicing through the data are created. -The class QmitkSliceWidget is used, which is based on the class QmitkRenderWindow, but additionally provides sliders -to slice through the data. We create two instances of -QmitkSliceWidget, one for transversal and one for sagittal slicing. Step 4b enhances the program in that the two slices are also shown at their correct position in 3D as well as intersection-line, each in the other 2D view. - -As in the previous steps, to obtain the results the program has to be executed using the image file mitk/Core/Code/Testing/Data/Pic3D.pic.gz and the surface file mitk/Modules/MITKExt/Testing/Data/lungs.vtk. - -\li \ref Step4.cpp "Step4.cpp"\n -Contains the code of step 4a + b. - -\section Step4aSection Step 4a - Create transversal and sagittal view - -\image html step4a_result.png - -\dontinclude Step4.cpp - -Create a Qt horizontal box for the layout: - -\skipline QHBox - -Then create a renderwindow: - -\skipline QmitkRenderWindow -\until SetMapperID - -Create a 2D view for slicing transversally: - -\skipline view2 -\until view2.SetData - -Then create a 2D view for slicing sagitally. - -\skipline view3 -\until view3.SetData - -The toplevelWidget is now the new main widget: - -\skipline qtapplication -\skipline toplevelWidget.show - -\section Step4bSection Step 4b - Display slice positions - -\image html step4b_result.png - -We now want to see the position of the slice in 2D and the slice itself in 3D. -Therefore it has to be added to the tree: - -\dontinclude Step4.cpp -\skipline it.Add(view2.GetRenderer() -\skipline it.Add(view3.GetRenderer() - -Slice positions are now displayed as can be seen in the picture. - -\dontinclude Step4.cpp - -\ref Step3Page "[Previous step]" \ref Step5Page "[Next step]" \ref TutorialPage "[Main tutorial page]" - -*/ Index: mitk/Documentation/Doxygen/Tutorial/Step5.dox =================================================================== --- mitk/Documentation/Doxygen/Tutorial/Step5.dox (revision 26384) +++ mitk/Documentation/Doxygen/Tutorial/Step5.dox (working copy) @@ -1,34 +0,0 @@ - /** - - \page Step5Page MITK Tutorial - Step 5: Interactively add points - - In addition to Step 4 where 3 views on the data were created we now want to interactively add points. - - A node containing a PointSet as data is added to the data tree and a PointSetInteractor is associated with the node, which handles the interaction. - The @em interaction @em pattern is defined in a state-machine, stored in an external XML file. Thus, we need to load a state-machine. - - The interaction patterns defines the @em events, on which the interactor reacts (e.g., which mouse buttons are used to set a point), the @em transition to the next state (e.g., the initial - may be "empty point set") and associated @a actions (e.g., add a point at the position where the mouse-click occured). - More information about interaction in MITK can be found \ref InteractionPage "here". - - In order to add a point the shift key has to be pressed simultaneously to marking the point with the mouse. - - \li \ref Step5.cpp "Step5.cpp"\n - Contains the code for this step. - - \image html step5_result.png - - - - \dontinclude Step5.cpp - - - A PointSet and a node for it have to be created to be able to interactively add points: - - \skipline mitk::PointSet - \until "pointsetinteractor" - - \ref Step4Page "[Previous step]" \ref Step6Page "[Next step]" \ref TutorialPage "[Main tutorial page]" - - */ - Index: mitk/Documentation/Doxygen/Tutorial/Step6.dox =================================================================== --- mitk/Documentation/Doxygen/Tutorial/Step6.dox (revision 26384) +++ mitk/Documentation/Doxygen/Tutorial/Step6.dox (working copy) @@ -1,111 +0,0 @@ -/** - -\page Step6Page MITK Tutorial - Step 6: Use an interactive region-grower - -In this step the program is enhanced by the possibility to start a region-grower at interactively added points. -We will see how MITK images can be accessed as ITK images. -We now load the image file only (mitk/Core/Code/Testing/Data/Pic3D.pic.gz) since the surface will be the result of the region-growing. - -\image html step6_result.png - -The source is now split among several files: - -\li \ref Step6.cpp "Step6.cpp" -\li \ref Step6.h "Step6.h" -\li \ref Step6RegionGrowing.txx "Step6RegionGrowing.txx" -\li \ref Step6RegionGrowing1.cpp "Step6RegionGrowing1.cpp" -\li \ref Step6RegionGrowing2.cpp "Step6RegionGrowing2.cpp" -\li \ref Step6main.cpp "Step6main.cpp" - -The class Step6 inherits from QMainWindow and provides methods for setting up the widgets. Step6RegionGrowing.cpp contains a method for performing the region-growing. Step6main.cpp contains main. -Like in ITK and VTK class member names start with m_ followed by the proper member name starting with a capital letter (e.g. m_Tree). -Function names start with capital letters. To learn more about style conventions in MITK read \ref StylesAndNotesPage "The MITK Style Guide". - -\dontinclude Step6.cpp - -The widgets are initialized as in the previous steps but with an additional QVBox for a button to start the segmentation: - -\skipline m_TopLevelWidget = new QVBox(this); - - -Then a button is created to start the segmentation and its clicked() signal is connected to the method StartRegionGrowing(): - -\dontinclude Step6.cpp - -\skipline QPushButton -\skipline connect - -\section AccessMTIKImagesAsITKImagesSection Access MITK images as ITK images - -ITK images are templated whereas mitk::Images are not. To use ITK filters with MITK images, we have to convert From MITK to ITK. To do so, first -define an access method, which is templated as an ITK image is: - -\code -template -MyAccessMethod(itk::Image* itkImage) -{ -... -} -\endcode - -If you don't understand this template syntax, you should read any C++ text book. Understanding template syntax is crucial to successfully using ITK. - -To call this templated method with an (untemplated) mitk::Image, you can use the AccessByItk macro from mitkImageAccessByItk.h. This macro checks for -the actual image type of the mitk::Image and does any neccessary conversions. Look into "Modules / Adaptor classes" for more information. - -\code -AccessByItk(mitkImage, MyAccessMethod) -\endcode - -\dontinclude Step6RegionGrowing.txx - -In this step our access method is called RegionGrowing() (defined in \ref Step6RegionGrowing.txx "Step6RegionGrowing.txx"): -\skipline template -\until } -\until } - -Additionally the access function has to be instantiated for all datatypes and two/three dimensions as some compilers have memory problems without this explicit instantiation, some even need instantiations in separate files for 2D/3D: \n -For 2D in \ref Step6RegionGrowing1.cpp "Step6RegionGrowing1.cpp" : - -\dontinclude Step6RegionGrowing1.cpp - -\skipline InstantiateAccessFunctionForFixedDimension_1 - -... and for 3D in \ref Step6RegionGrowing2.cpp "Step6RegionGrowing2.cpp": - -\dontinclude Step6RegionGrowing2.cpp - -\skipline InstantiateAccessFunctionForFixedDimension_1 - -\dontinclude Step6.cpp - -The method StartRegionGrowing() finally calls our access method RegionGrowing(): -\skipline Step6::StartRegionGrowing -\until } - -\section ConvertingITKMITKSection Converting ITK images to MITK images and vice versa - -In some cases it is useful to simply convert between ITK and MITK images. The direction ITK to MITK is easy, since mitk::Image can handle most data types. The direction MITK to ITK is more critical, since ITK images have to be instantiated with a fixed pixel type and fixed dimension at compile time. - -\li \code mitk::Image mitk::ImportItkImage(itk::Image<...>) \endcode -\li \code mitk::CastToItkImage(mitkImage, itk::Image<...>) \endcode - - -\section ConnectingMITKToVTKSection Connecting MITK images to VTK - -Images are not converted or copied: The data array is just accessed via an encapsulating VTK object. - -\li \code vtkImageData* mitk::Image::GetVtkImageData(int time = 0) \endcode - -\section SurfacesMITKToVTKSection MITK Surfaces to VTK and vice versa - -Again: not a conversion, just accessing. - -\li \code vtkPolyData* mitk::Surface::GetVtkPolyData(int time = 0) \endcode - -\li \code mitk::Surface::SetVtkPolyData(vtkPolyData*, int time = 0) \endcode - - -\ref Step5Page "[Previous step]" \ref Step7Page "[Next step]" \ref TutorialPage "[Main tutorial page]" - -*/ Index: mitk/Documentation/Doxygen/Tutorial/Step7.dox =================================================================== --- mitk/Documentation/Doxygen/Tutorial/Step7.dox (revision 26384) +++ mitk/Documentation/Doxygen/Tutorial/Step7.dox (working copy) @@ -1,21 +0,0 @@ - /** - - \page Step7Page MITK Tutorial - Step 7: Convert result of region growing into a surface - - In this step the result of the previous step is converted into a surface by means of a VTK filter. - - - \li \ref Step7.cpp "Step7.cpp"\n - \li \ref Step7.h "Step7.h"\n - \li \ref Step7main.cpp "Step7main.cpp"\n - - Step7 inherits from Step6. It enhances the method StartRegionGrowing() by processing the result image. - - - \dontinclude Step7.cpp - \skipline if(m_ResultImage - \until } - - \ref Step6Page "[Previous step]" \ref Step8Page "[Next step]" \ref TutorialPage "[Main tutorial page]" - - */ \ No newline at end of file Index: mitk/Documentation/Doxygen/Tutorial/Step8.dox =================================================================== --- mitk/Documentation/Doxygen/Tutorial/Step8.dox (revision 26384) +++ mitk/Documentation/Doxygen/Tutorial/Step8.dox (working copy) @@ -1,24 +0,0 @@ - /** - - \page Step8Page MITK Tutorial - Step 8: Use QmitkStdMultiWidget as widget - - In this step a QmitkStdMultiWidget is used. It offers four views on the data. - From top left to bottom the views are initialized as transversal, sagittal and coronar. The bottom right view is initialized as 3D view. - - \image html step8_result.png - - - \li \ref Step8.cpp "Step8.cpp"\n - \li \ref Step8.h "Step8.h"\n - \li \ref Step8main.cpp "Step8main.cpp"\n - - Step8 inherits from Step6. The method SetupWidgets() is changed: A QmitkStdMultiWidget is used instead of one QmitkRenderWindow and two instances of QmitkSliceWidget. - - \dontinclude Step8.cpp - \skipline Part II - \until setCentralWidget - - - \ref Step7Page "[Previous step]" \ref Step9Page "[Next step]" - - */ Index: mitk/Documentation/Doxygen/Tutorial/Step9.dox =================================================================== --- mitk/Documentation/Doxygen/Tutorial/Step9.dox (revision 26384) +++ mitk/Documentation/Doxygen/Tutorial/Step9.dox (working copy) @@ -1,226 +0,0 @@ -/** - -\page Step9Page MITK Tutorial - Step 9: A plug-in - -MITK uses a very modular concept to maximize reusability and portability. You start an application (for example ExtApp, the sample application provided by MITK). An application has several bundles (or plug-ins). A bundle can be a functionality, which in turn can be a view, each of these terms specifying certain behaviour and attributes. - -The creation of a MITK plug-in is considerably facilitated by using the MITK BundleGenerator as described in \ref NewPluginPage . - -The mentioned tool was used to create a plug-in QmitkRegionGrowing. -Let's first look at what files the BundleGenerator created: - -\verbatim - -documentation\doxygen\ - modules.dox............................. Doxygen file for documenting your plug-in - -META-INF\ - MANIFEST.MF............................. Information about your plug-in - -resources\ - icon.xpm................................ The icon of your plug-in. GIMP or other programs (including your text editor) - can be used to change this - QmitkMITKRegionGrowingView.qrc.......... QT file for managing resources - -src\internal\ - QmitkMITKRegionGrowingView.cpp.......... The most important file, implementing behaviour - QmitkMITKRegionGrowingView.h............ Header file of the functionality - QmitkMITKRegionGrowingViewControls.ui... XML file of the Qt Designer, describes buttons, combo boxes, etc. of your controls -src\ - RegiongrowingDll.h...................... Manages the import/export of your plug-in dll - -CMakeLists.txt \.......................... Build system related files for CMake -files.cmake / -manifest.cpp \............................ BlueBerry integration -plugin.xml / - -\endverbatim - -If you are not familiar with Qt development, please look into -this Trolltech page describing .ui files (no, forget about the please, DO it!) - -The C++ files implement a subclass of QmitkFunctionality, so they ARE functionalities. In this -special case of QmitkRegionGrowing, we added the ability to set some seed points and run a region grower. -If your are interested in the concrete changes necessary to turn a freshly generated QmitkRegionGrowing into an integrated one: - -To add a PointSet for the seed points: -QmitkRegionGrowingView.h - -Add includes: -\verbatim -#include "mitkPointSet.h" -#include -\endverbatim - -Add the point set as protected object: -\verbatim -/// \brief This is the actual seed point data object -mitk::PointSet::Pointer m_PointSet; -\endverbatim - -QmitkRegionGrowingView.cpp - -Add includes: -\verbatim -#include "QmitkPointListWidget.h" -\endverbatim - -CreateQtPartControl(): -\verbatim -// let the point set widget know about the multi widget (crosshair updates) -m_Controls->lstPoints->SetMultiWidget( m_MultiWidget ); - -// create a new DataTreeNode containing a PointSet with some interaction -m_PointSet = mitk::PointSet::New(); - -mitk::DataTreeNode::Pointer pointSetNode = mitk::DataTreeNode::New(); -pointSetNode->SetData( m_PointSet ); -pointSetNode->SetName("seed points for region growing"); -pointSetNode->SetProperty("helper object", mitk::BoolProperty::New(true) ); -pointSetNode->SetProperty("layer", mitk::IntProperty::New(1024) ); - -// add the pointset to the data tree (for rendering and access by other modules) -GetDefaultDataStorage()->Add( pointSetNode ); - -// tell the GUI widget about out point set -m_Controls->lstPoints->SetPointSetNode( pointSetNode ); -\endverbatim - -StdMultiWidgetAvailable(): -\verbatim -m_Controls->lstPoints->SetMultiWidget( m_MultiWidget ); -\endverbatim -StdMultiWidgetNotAvailable(): -\verbatim -m_Controls->lstPoints->SetMultiWidget( NULL ); -\endverbatim - -To use the ITK region grower: - -QmitkRegionGrowingView.h - -Add protected method: -\verbatim -/*! -\brief ITK image processing function - This function is templated like an ITK image. The MITK-Macro AccessByItk determines the actual pixel type and dimensionality of - a given MITK image and calls this function for further processing (in our case region growing) -*/ -template < typename TPixel, unsigned int VImageDimension > - void ItkImageProcessing( itk::Image< TPixel, VImageDimension >* itkImage, mitk::Geometry3D* imageGeometry ); -\endverbatim - -QmitkRegionGrowingView.cpp - -Add includes: -\verbatim -// MITK -#include "mitkImageAccessByItk.h" -#include "mitkITKImageImport.h" -#include "mitkProperties.h" -#include "mitkColorProperty.h" - -// ITK -#include - -\endverbatim - -DoImageProcessing(); -\verbatim -// So we have an image. Let's see if the user has set some seed points already -if ( m_PointSet->GetSize() == 0 ) -{ - // no points there. Not good for region growing - QMessageBox::information( NULL, "Region growing functionality", - "Please set some seed points inside the image first.\n" - "(hold Shift key and click left mouse button inside the image.)" - ); - return; -} - -// actually perform region growing. Here we have both an image and some seed points -AccessByItk_1( image, ItkImageProcessing, image->GetGeometry() ); // some magic to call the correctly templated function -\endverbatim - -And add the new method: -\verbatim -template < typename TPixel, unsigned int VImageDimension > -void QmitkRegionGrowingView::ItkImageProcessing( itk::Image< TPixel, VImageDimension >* itkImage, mitk::Geometry3D* imageGeometry ) -{ - typedef itk::Image< TPixel, VImageDimension > InputImageType; - typedef typename InputImageType::IndexType IndexType; - - // instantiate an ITK region growing filter, set its parameters - typedef itk::ConnectedThresholdImageFilter RegionGrowingFilterType; - typename RegionGrowingFilterType::Pointer regionGrower = RegionGrowingFilterType::New(); - regionGrower->SetInput( itkImage ); // don't forget this - - // determine a thresholding interval - IndexType seedIndex; - TPixel min( std::numeric_limits::max() ); - TPixel max( std::numeric_limits::min() ); - mitk::PointSet::PointsContainer* points = m_PointSet->GetPointSet()->GetPoints(); - for ( mitk::PointSet::PointsConstIterator pointsIterator = points->Begin(); - pointsIterator != points->End(); - ++pointsIterator ) - { - // first test if this point is inside the image at all - if ( !imageGeometry->IsInside( pointsIterator.Value()) ) - { - continue; - } - - // convert world coordinates to image indices - imageGeometry->WorldToIndex( pointsIterator.Value(), seedIndex); - - // get the pixel value at this point - TPixel currentPixelValue = itkImage->GetPixel( seedIndex ); - - // adjust minimum and maximum values - if (currentPixelValue > max) - max = currentPixelValue; - - if (currentPixelValue < min) - min = currentPixelValue; - - regionGrower->AddSeed( seedIndex ); - } - - std::cout << "Values between " << min << " and " << max << std::endl; - - min -= 30; - max += 30; - - // set thresholds and execute filter - regionGrower->SetLower( min ); - regionGrower->SetUpper( max ); - - regionGrower->Update(); - - mitk::Image::Pointer resultImage = mitk::ImportItkImage( regionGrower->GetOutput() ); - mitk::DataTreeNode::Pointer newNode = mitk::DataTreeNode::New(); - newNode->SetData( resultImage ); - - // set some properties - newNode->SetProperty("binary", mitk::BoolProperty::New(true)); - newNode->SetProperty("name", mitk::StringProperty::New("dumb segmentation")); - newNode->SetProperty("color", mitk::ColorProperty::New(1.0,0.0,0.0)); - newNode->SetProperty("volumerendering", mitk::BoolProperty::New(true)); - newNode->SetProperty("layer", mitk::IntProperty::New(1)); - newNode->SetProperty("opacity", mitk::FloatProperty::New(0.5)); - - // add result to data tree - this->GetDefaultDataStorage()->Add( newNode ); - mitk::RenderingManager::GetInstance()->RequestUpdateAll(); -} - -\endverbatim - -Have fun using MITK! - -If you meet any difficulties during your first steps, 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 Step8Page "[Previous step]" \ref TutorialPage "[Main tutorial page]" - -*/ Index: mitk/Documentation/Doxygen/Tutorial/Tutorial.dox =================================================================== --- mitk/Documentation/Doxygen/Tutorial/Tutorial.dox (revision 26384) +++ mitk/Documentation/Doxygen/Tutorial/Tutorial.dox (working copy) @@ -17,16 +17,17 @@ \section TutorialSection Tutorial chapters -\li \ref Step0Page "Step 0: Getting started" -\li \ref Step1Page "Step 1: Displaying an image" -\li \ref Step2Page "Step 2: Load one or more data sets" -\li \ref Step3Page "Step 3: Create 3D view" -\li \ref Step4Page "Step 4: Use several views to explore data" -\li \ref Step5Page "Step 5: Interactively add points" -\li \ref Step6Page "Step 6: Use an interactive region-grower" -\li \ref Step7Page "Step 7: Convert result of region growing into a surface" -\li \ref Step8Page "Step 8: Use QmitkStdMultiWidget as widget" -\li \ref Step9Page "Step 9: A functionality" +\li \ref Step00Page "Step 0: Getting started" +\li \ref Step01Page "Step 1: Displaying an image" +\li \ref Step02Page "Step 2: Load one or more data sets" +\li \ref Step03Page "Step 3: Create 3D view" +\li \ref Step04Page "Step 4: Use several views to explore data" +\li \ref Step05Page "Step 5: Interactively add points" +\li \ref Step06Page "Step 6: Use an interactive region-grower" +\li \ref Step07Page "Step 7: Convert result of region growing into a surface" +\li \ref Step08Page "Step 8: Use QmitkStdMultiWidget as widget" +\li \ref Step09Page "Step 9: A functionality" +\li \ref Step10Page "Step 10: A new Interaction" Enjoy MITK!