diff --git a/Core/Code/Testing/mitkPointSetDataInteractorTest.cpp b/Core/Code/Testing/mitkPointSetDataInteractorTest.cpp index 712285ee04..c23f6789ab 100644 --- a/Core/Code/Testing/mitkPointSetDataInteractorTest.cpp +++ b/Core/Code/Testing/mitkPointSetDataInteractorTest.cpp @@ -1,97 +1,96 @@ /*=================================================================== 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 "mitkTestingMacros.h" #include #include #include #include #include #include class mitkPointSetDataInteractorTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkPointSetDataInteractorTestSuite); MITK_TEST(AddPointInteraction); CPPUNIT_TEST_SUITE_END(); private: mitk::DataNode::Pointer testPointSetNode; mitk::PointSetDataInteractor::Pointer dataInteractor; mitk::PointSet::Pointer testPointSet; mitk::InteractionTestHelper* interactionTestHelper; public: void setUp() { //Create DataNode as a container for our PointSet to be tested testPointSetNode = mitk::DataNode::New(); // Create PointSetData Interactor dataInteractor = mitk::PointSetDataInteractor::New(); // Load the according state machine for regular point set interaction dataInteractor->LoadStateMachine("PointSet.xml"); // Set the configuration file that defines the triggers for the transitions dataInteractor->SetEventConfig("PointSetConfig.xml"); // set the DataNode (which already is added to the DataStorage) dataInteractor->SetDataNode(testPointSetNode); //Create new PointSet which will receive the interaction input testPointSet = mitk::PointSet::New(); testPointSetNode->SetData(testPointSet); - - //Create test helper to initialize all necessary objects for interaction - interactionTestHelper = new mitk::InteractionTestHelper(); - //Add our test node to the DataStorage of our test helper - interactionTestHelper->AddNodeToStorage(testPointSetNode); } void tearDown() { testPointSetNode = NULL; testPointSet = NULL; dataInteractor = NULL; delete interactionTestHelper; } void AddPointInteraction() { //Path to the reference PointSet std::string referencePointSetPath = "/Users/schroedt/Desktop/pointsetTestRef.mps"; //Path to the interaction xml file std::string interactionXmlPath = "/Users/schroedt/Desktop/pointsetTest.xml"; - //load interaction events - interactionTestHelper->LoadInteraction(interactionXmlPath); + //Create test helper to initialize all necessary objects for interaction + interactionTestHelper = new mitk::InteractionTestHelper(interactionXmlPath); + + //Add our test node to the DataStorage of our test helper + interactionTestHelper->AddNodeToStorage(testPointSetNode); + //Start Interaction interactionTestHelper->PlaybackInteraction(); //Load the reference PointSet mitk::PointSet::Pointer referencePointSet = mitk::IOUtil::LoadPointSet(referencePointSetPath); //Compare reference with the result of the interaction MITK_ASSERT_EQUAL(testPointSet.GetPointer(), referencePointSet.GetPointer(), ""); } }; MITK_TEST_SUITE_REGISTRATION(mitkPointSetDataInteractor) diff --git a/Core/Code/TestingHelper/mitkInteractionTestHelper.cpp b/Core/Code/TestingHelper/mitkInteractionTestHelper.cpp index 5aaa9e4414..cec5607166 100644 --- a/Core/Code/TestingHelper/mitkInteractionTestHelper.cpp +++ b/Core/Code/TestingHelper/mitkInteractionTestHelper.cpp @@ -1,145 +1,157 @@ /*=================================================================== 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. ===================================================================*/ //MITK #include #include #include #include +#include //us #include +#include -mitk::InteractionTestHelper::InteractionTestHelper() + +mitk::InteractionTestHelper::InteractionTestHelper(const std::string &interactionXmlFilePath) + : m_InteractionFilePath(interactionXmlFilePath) { - this->Initialize(); + this->Initialize(interactionXmlFilePath); } -void mitk::InteractionTestHelper::Initialize() +void mitk::InteractionTestHelper::Initialize(const std::string &interactionXmlFilePath) { - // Global interaction must(!) be initialized - if(! mitk::GlobalInteraction::GetInstance()->IsInitialized()) - mitk::GlobalInteraction::GetInstance()->Initialize("global"); - - mitk::RenderingManager* rm = mitk::RenderingManager::GetInstance(); - - //########### setup axial renderwindow ################## - //create renderWindow, renderer and dispatcher - m_RenderWindowAxial = mitk::RenderWindow::New(NULL, "stdmulti.widget1", rm); //VtkRenderWindow is created within constructor if NULL - //create data storage - m_DataStorage = mitk::StandaloneDataStorage::New(); - //set storage of renderer - m_RenderWindowAxial->GetRenderer()->SetDataStorage(m_DataStorage); - - //set view direction to axial - m_RenderWindowAxial->GetSliceNavigationController()->SetDefaultViewDirection( mitk::SliceNavigationController::Axial ); - - //set renderer to render 2D - m_RenderWindowAxial->GetRenderer()->SetMapperID(mitk::BaseRenderer::Standard2D); - - //########### setup sagittal renderwindow ################## - //create renderWindow, renderer and dispatcher - m_RenderWindowSagittal = mitk::RenderWindow::New(NULL, "stdmulti.widget2", rm); //VtkRenderWindow is created within constructor if NULL - //create data storage - m_DataStorage = mitk::StandaloneDataStorage::New(); - //set storage of renderer - m_RenderWindowSagittal->GetRenderer()->SetDataStorage(m_DataStorage); - - //set view direction to axial - m_RenderWindowSagittal->GetSliceNavigationController()->SetDefaultViewDirection( mitk::SliceNavigationController::Sagittal ); - - //set renderer to render 2D - m_RenderWindowSagittal->GetRenderer()->SetMapperID(mitk::BaseRenderer::Standard2D); - - //########### setup frontal renderwindow ################## - //create renderWindow, renderer and dispatcher - m_RenderWindowFrontal = mitk::RenderWindow::New(NULL, "stdmulti.widget3", rm); //VtkRenderWindow is created within constructor if NULL - //create data storage - m_DataStorage = mitk::StandaloneDataStorage::New(); - //set storage of renderer - m_RenderWindowFrontal->GetRenderer()->SetDataStorage(m_DataStorage); - - //set view direction to axial - m_RenderWindowFrontal->GetSliceNavigationController()->SetDefaultViewDirection( mitk::SliceNavigationController::Frontal ); - - //set renderer to render 2D - m_RenderWindowFrontal->GetRenderer()->SetMapperID(mitk::BaseRenderer::Standard2D); - - //########### register display interactor to handle scroll events ################## - //use MouseModeSwitcher to ensure that the statemachine of DisplayInteractor is loaded correctly - m_MouseModeSwitcher = mitk::MouseModeSwitcher::New(); - - - //########### connect SliceNavigationControllers to timestep changed event of TimeNavigationController ############# - m_RenderWindowAxial->GetSliceNavigationController()->ConnectGeometryTimeEvent(mitk::RenderingManager::GetInstance()->GetTimeNavigationController(), false); - m_RenderWindowSagittal->GetSliceNavigationController()->ConnectGeometryTimeEvent(mitk::RenderingManager::GetInstance()->GetTimeNavigationController(), false); - m_RenderWindowFrontal->GetSliceNavigationController()->ConnectGeometryTimeEvent(mitk::RenderingManager::GetInstance()->GetTimeNavigationController(), false); + //TiXmlDocument document(interactionXmlPath.c_str()); + TiXmlDocument document(interactionXmlFilePath); + bool loadOkay = document.LoadFile(); + if (loadOkay) + { + // Global interaction must(!) be initialized + if(! mitk::GlobalInteraction::GetInstance()->IsInitialized()) + mitk::GlobalInteraction::GetInstance()->Initialize("global"); + + //get RenderingManager instance + mitk::RenderingManager* rm = mitk::RenderingManager::GetInstance(); + + //create data storage + m_DataStorage = mitk::StandaloneDataStorage::New(); + + //for each renderer found create a render window and configure + for( TiXmlElement* element = document.FirstChildElement(mitk::InteractionEventConst::xmlTagInteractions())->FirstChildElement(mitk::InteractionEventConst::xmlTagConfigRoot())->FirstChildElement(mitk::InteractionEventConst::xmlTagRenderer()); + element != NULL; + element = element->NextSiblingElement(mitk::InteractionEventConst::xmlTagRenderer()) ) + { + //get name of renderer + const char* rendererName = element->Attribute(mitk::InteractionEventConst::xmlEventPropertyRendererName().c_str()); + + //get view direction + int viewDirectionNum = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlEventPropertyViewDirection())->c_str()); + mitk::SliceNavigationController::ViewDirection viewDirection = static_cast(viewDirectionNum); + + //create renderWindow, renderer and dispatcher + mitk::RenderWindow::Pointer rw = mitk::RenderWindow::New(NULL, rendererName, rm); //VtkRenderWindow is created within constructor if NULL + + //set storage of renderer + rw->GetRenderer()->SetDataStorage(m_DataStorage); + + //set view direction to axial + rw->GetSliceNavigationController()->SetDefaultViewDirection( viewDirection ); + + //set renderer to render 2D + rw->GetRenderer()->SetMapperID(mitk::BaseRenderer::Standard2D); + + //connect SliceNavigationControllers to timestep changed event of TimeNavigationController + rw->GetSliceNavigationController()->ConnectGeometryTimeEvent(rm->GetTimeNavigationController(), false); + + //add to list of kown render windows + m_RenderWindowList.push_back(rw); + } + + //########### register display interactor to handle scroll events ################## + //use MouseModeSwitcher to ensure that the statemachine of DisplayInteractor is loaded correctly + m_MouseModeSwitcher = mitk::MouseModeSwitcher::New(); + } + else + { + mitkThrow() << "Can not load interaction xml file <" << m_InteractionFilePath << ">"; + } } mitk::InteractionTestHelper::~InteractionTestHelper() { - mitk::BaseRenderer::RemoveInstance(m_RenderWindowAxial->GetVtkRenderWindow()); - mitk::BaseRenderer::RemoveInstance(m_RenderWindowSagittal->GetVtkRenderWindow()); - mitk::BaseRenderer::RemoveInstance(m_RenderWindowFrontal->GetVtkRenderWindow()); + //unregister renderers + InteractionTestHelper::RenderWindowListType::iterator it = m_RenderWindowList.begin(); + InteractionTestHelper::RenderWindowListType::iterator end = m_RenderWindowList.end(); + + for(; it != end; it++) + { + mitk::BaseRenderer::RemoveInstance((*it)->GetVtkRenderWindow()); + } } mitk::DataStorage::Pointer mitk::InteractionTestHelper::GetDataStorage() { return m_DataStorage; } void mitk::InteractionTestHelper::AddNodeToStorage(mitk::DataNode::Pointer node) { this->m_DataStorage->Add(node); mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(m_DataStorage); } void mitk::InteractionTestHelper::PlaybackInteraction() { + //load events if not loaded yet + if(m_Events.empty()) + this->LoadInteraction(); + + //playback all events in queue for (unsigned long i=0; i < m_Events.size(); ++i) { + //let dispatcher of sending renderer process the event m_Events.at(i)->GetSender()->GetDispatcher()->ProcessEvent(m_Events.at(i)); } } -void mitk::InteractionTestHelper::LoadInteraction(std::string interactionXmlPath) +void mitk::InteractionTestHelper::LoadInteraction() { - //load interaction pattern - std::ifstream xmlStream(interactionXmlPath.c_str()); + //load interaction pattern from xml file + std::ifstream xmlStream(m_InteractionFilePath.c_str()); mitk::XML2EventParser parser(xmlStream); m_Events = parser.GetInteractions(); xmlStream.close(); } void mitk::InteractionTestHelper::SetTimeStep(int newTimeStep) { bool timeStepIsvalid = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetCreatedWorldGeometry()->IsValidTimeStep(newTimeStep); if(timeStepIsvalid) { mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetTime()->SetPos(newTimeStep); } } diff --git a/Core/Code/TestingHelper/mitkInteractionTestHelper.h b/Core/Code/TestingHelper/mitkInteractionTestHelper.h index 1d968df929..6267ed22a4 100644 --- a/Core/Code/TestingHelper/mitkInteractionTestHelper.h +++ b/Core/Code/TestingHelper/mitkInteractionTestHelper.h @@ -1,106 +1,111 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkInteractionTestHelper_h #define mitkInteractionTestHelper_h #include #include #include #include #include #include class vtkRenderWindow; class vtkRenderer; namespace mitk { /** @brief Creates everything needed to load and playback interaction events. * * The interaction is loaded from an xml file and the event are created. This file is * usually a recorded user interaction with the GUI. This can be done with InteractionEventRecorder * plugin. Also all necessary objects to handle interaction events are generated. * The user of this class is responsible to add the data object to interact with to the data storage * of InteractionTestHelper. And must also make sure that a proper data interactor is associated with the data object. * * To test PointSet interaction for instance make sure you have a PointSet node and a PointSetDataInteractor. * Then just add the node to the storage of the your InteractionTestHelper by calling InteractionTestHelper::AddNodeToStorage. * Use InteractionTestHelper::PlaybackInteraction to execute. * * \sa XML2EventParser * \sa EventFactory * \sa EventRecorder */ class MITK_TESTINGHELPER_EXPORT InteractionTestHelper { public: - InteractionTestHelper(); + InteractionTestHelper(const std::string &interactionXmlFilePath); ~InteractionTestHelper(); /** @brief Returns the datastorage, in order to modify the data inside a rendering test. **/ mitk::DataStorage::Pointer GetDataStorage(); /** * @brief AddNodeToStorage Add a node to the datastorage and perform a reinit which is necessary for rendering. * @param node The data you want to add. */ void AddNodeToStorage(mitk::DataNode::Pointer node); /** * @brief PlaybackInteraction playback loaded interaction by passing events to the dispatcher. */ void PlaybackInteraction(); - /** - * @brief LoadInteraction loads events from xml file. - * @param interactionXmlPath path to xml file with interaction events. - */ - void LoadInteraction(std::string interactionXmlPath); - /** * @brief SetTimeStep Sets timesteps of all SliceNavigationControllers to given timestep. * @param newTimeStep new timestep * * Does the same as using ImageNavigators Time slider. Use this if your data was modified in a timestep other than 0. */ void SetTimeStep(int newTimeStep); + typedef std::vector RenderWindowListType; + protected: /** * @brief Initialize Internal method to initialize the renderwindow and set the datastorage. + * @throws mitk::Exception if interaction xml file can not be loaded. */ - void Initialize(); + void Initialize(const std::string &interactionXmlFilePath); + + /** + * @brief LoadInteraction loads events from xml file. + * @param interactionXmlPath path to xml file with interaction events. + */ + void LoadInteraction(); mitk::XML2EventParser::EventContainerType m_Events; // List with loaded interaction events - mitk::VtkPropRenderer::Pointer m_Renderer; + std::string m_InteractionFilePath; + + RenderWindowListType m_RenderWindowList; mitk::RenderWindow::Pointer m_RenderWindowAxial; mitk::RenderWindow::Pointer m_RenderWindowSagittal; mitk::RenderWindow::Pointer m_RenderWindowFrontal; mitk::DataStorage::Pointer m_DataStorage; mitk::MouseModeSwitcher::Pointer m_MouseModeSwitcher; }; }//namespace mitk #endif