diff --git a/Modules/IGT/IO/mitkNavigationDataSequentialPlayer.cpp b/Modules/IGT/IO/mitkNavigationDataSequentialPlayer.cpp index 918a3b5a46..ab6acbc5ea 100644 --- a/Modules/IGT/IO/mitkNavigationDataSequentialPlayer.cpp +++ b/Modules/IGT/IO/mitkNavigationDataSequentialPlayer.cpp @@ -1,84 +1,92 @@ /*=================================================================== 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 "mitkNavigationDataSequentialPlayer.h" #include //for the pause #include #include //Exceptions #include "mitkIGTException.h" #include "mitkIGTIOException.h" mitk::NavigationDataSequentialPlayer::NavigationDataSequentialPlayer() : m_Repeat(false) { } mitk::NavigationDataSequentialPlayer::~NavigationDataSequentialPlayer() { } void mitk::NavigationDataSequentialPlayer::GoToSnapshot(unsigned int i) { if( !m_Repeat && (this->GetNumberOfSnapshots() <= i) ) { MITK_ERROR << "Snaphot " << i << " does not exist and repat is off: can't go to that snapshot!"; mitkThrowException(mitk::IGTException) << "Snapshot " << i << " does not exist and repat is off: can't go to that snapshot!"; } // set iterator to given position (modulo for allowing repeat) m_NavigationDataSetIterator = m_NavigationDataSet->Begin() + ( i % this->GetNumberOfSnapshots() ); // set outputs to selected snapshot - this->Update(); + this->GoToNextSnapshot(); } -void mitk::NavigationDataSequentialPlayer::GenerateData() +bool mitk::NavigationDataSequentialPlayer::GoToNextSnapshot() { if ( m_NavigationDataSetIterator == m_NavigationDataSet->End() ) { if ( m_Repeat ) { // set data back to start if repeat is enabled m_NavigationDataSetIterator = m_NavigationDataSet->Begin(); } else { // no more data available this->GraftEmptyOutput(); - return; + return false; } } for (unsigned int index = 0; index < m_NumberOfOutputs; index++) { mitk::NavigationData* output = this->GetOutput(index); if( !output ) { mitkThrowException(mitk::IGTException) << "Output of index "<Graft(m_NavigationDataSetIterator->at(index)); } ++m_NavigationDataSetIterator; + + return true; +} + +void mitk::NavigationDataSequentialPlayer::GenerateData() +{ + // nothing done here, as GoToNextSnapshot() should be called to update the + // output data } void mitk::NavigationDataSequentialPlayer::UpdateOutputInformation() { this->Modified(); // make sure that we need to be updated Superclass::UpdateOutputInformation(); } diff --git a/Modules/IGT/IO/mitkNavigationDataSequentialPlayer.h b/Modules/IGT/IO/mitkNavigationDataSequentialPlayer.h index 0da4eef70e..bbabaf757d 100644 --- a/Modules/IGT/IO/mitkNavigationDataSequentialPlayer.h +++ b/Modules/IGT/IO/mitkNavigationDataSequentialPlayer.h @@ -1,85 +1,95 @@ /*=================================================================== 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 MITKNavigationDataSequentialPlayer_H_HEADER_INCLUDED_ #define MITKNavigationDataSequentialPlayer_H_HEADER_INCLUDED_ #include namespace mitk { /**Documentation * \brief This class is a slightly changed reimplementation of the * NavigationDataPlayer which does not care about timestamps and just * outputs the navigationdatas in their sequential order * * \ingroup IGT */ class MitkIGT_EXPORT NavigationDataSequentialPlayer : public NavigationDataPlayerBase { public: mitkClassMacro(NavigationDataSequentialPlayer, NavigationDataPlayerBase); itkNewMacro(Self); /** * \brief Set to true if the data player should repeat the outputs. */ itkSetMacro(Repeat, bool); /** * \return Returns if the data player should repeat the outputs. */ itkGetMacro(Repeat, bool); /** * \brief Advance the output to the i-th snapshot of mitk::NavigationData. * E.g. if you want to have the NavData of snapshot * 18 then you can call GoToSnapshot(17). Index begins at 0. * You can only go back if m_Repeat is set true. * * Filter output is updated inside the function. * * @throw mitk::IGTException Throws an exception if cannot go back to particular snapshot. */ void GoToSnapshot(unsigned int i); + /** + * \brief Advance the output to the next snapshot of mitk::NavigationData. + * Filter output is updated inside the function. + * + * \return false if no next snapshot is available (happens only if m_Repeat is set to false). + * @throw mitk::IGTException Throws an exception if an output is null. + */ + bool GoToNextSnapshot(); + /** * \brief Used for pipeline update just to tell the pipeline * that we always have to update */ virtual void UpdateOutputInformation(); protected: NavigationDataSequentialPlayer(); virtual ~NavigationDataSequentialPlayer(); /** - * - * @throw mitk::IGTException Throws an exception if an output is null. + * \brief Does nothing. + * mitk::NavigationDataSequentialPlayer::GoToNextSnapshot() should be called + * for generating next data. */ virtual void GenerateData(); /** * \brief If the player should repeat outputs. Default is false. */ bool m_Repeat; }; } // namespace mitk #endif /* MITKNavigationDataSequentialPlayer_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp b/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp index 956a754196..25f33a9abe 100644 --- a/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp @@ -1,242 +1,266 @@ /*=================================================================== 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 #include #include "mitkTestingMacros.h" #include "mitkNavigationDataReaderXML.h" #include #include //foe exceptions #include "mitkIGTException.h" #include "mitkIGTIOException.h" vnl_vector tTool0Snapshot1(3); vnl_vector tTool1Snapshot2(3); mitk::Quaternion qTool0Snapshot0; mitk::Quaternion qTool1Snapshot1; mitk::NavigationDataSequentialPlayer::Pointer player( mitk::NavigationDataSequentialPlayer::New()); bool runLoop() { bool success = true; mitk::NavigationData::Pointer nd0; mitk::NavigationData::Pointer nd1; for(unsigned int i=0; iGetNumberOfSnapshots();++i) { + player->GoToNextSnapshot(); player->Update(); nd0 = player->GetOutput(); nd1 = player->GetOutput(1); // test some values if(nd0.IsNull() || nd1.IsNull()) return false; if(i==0) { if (!(qTool0Snapshot0.as_vector() == nd0->GetOrientation().as_vector())) {success = false;} } else if(i==1) { if (!(tTool0Snapshot1 == nd0->GetPosition().GetVnlVector())) {success = false;} else if (!(qTool1Snapshot1.as_vector() == nd1->GetOrientation().as_vector())) {success = false;} } else if(i==2) // should be repeated { if (!(tTool1Snapshot2 == nd1->GetPosition().GetVnlVector())) {success = false;} } } return success; } void TestStandardWorkflow() { // create test values valid for the xml data above tTool0Snapshot1[0] = -336.65; tTool0Snapshot1[1] = 138.5; tTool0Snapshot1[2]= -2061.07; tTool1Snapshot2[0] = -56.93; tTool1Snapshot2[1] = 233.79; tTool1Snapshot2[2]= -2042.6; vnl_vector_fixed qVec; qVec[0] = 0.0085; qVec[1] = -0.0576; qVec[2]= -0.0022; qVec[3]= 0.9982; qTool0Snapshot0 = mitk::Quaternion(qVec); qVec[0] = 0.4683; qVec[1] = 0.0188; qVec[2]= -0.8805; qVec[3]= 0.0696; qTool1Snapshot1 = mitk::Quaternion(qVec); //test SetXMLString() std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestData_2ToolsDouble.xml", "Modules/IGT/Testing/Data"); mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); player->SetNavigationDataSet(reader->Read(file)); - MITK_TEST_CONDITION_REQUIRED(player->GetNumberOfSnapshots() == 3,"Testing method SetXMLString with 3 navigation datas."); - MITK_TEST_CONDITION_REQUIRED(player->GetNumberOfIndexedOutputs() == 2,"Testing number of outputs"); + MITK_TEST_CONDITION(player->GetNumberOfSnapshots() == 3,"Testing method SetXMLString with 3 navigation datas."); + MITK_TEST_CONDITION(player->GetNumberOfIndexedOutputs() == 2,"Testing number of outputs"); //rest repeat player->SetRepeat(true); - MITK_TEST_CONDITION_REQUIRED(runLoop(),"Testing first run."); - MITK_TEST_CONDITION_REQUIRED(runLoop(),"Testing second run."); //repeat is on should work a second time + MITK_TEST_CONDITION(runLoop(),"Testing first run."); + MITK_TEST_CONDITION(runLoop(),"Testing second run."); //repeat is on should work a second time // now test the go to snapshot function player->GoToSnapshot(2); mitk::NavigationData::Pointer nd1 = player->GetOutput(1); MITK_TEST_CONDITION(tTool1Snapshot2 == nd1->GetPosition().GetVnlVector(), "Testing GoToSnapshot() [1]"); MITK_TEST_OUTPUT( << tTool1Snapshot2 << "\t" << nd1->GetPosition().GetVnlVector()); player->GoToSnapshot(0); mitk::NavigationData::Pointer nd0 = player->GetOutput(); MITK_TEST_CONDITION(qTool0Snapshot0.as_vector() == nd0->GetOrientation().as_vector(), "Testing GoToSnapshot() [2]"); MITK_TEST_OUTPUT( << qTool0Snapshot0.as_vector() << "\t" <GetOrientation().as_vector() ); player->GoToSnapshot(2); // and a third time - MITK_TEST_CONDITION_REQUIRED(runLoop(),"Tested if repeat works again."); + MITK_TEST_CONDITION(runLoop(),"Tested if repeat works again."); } void TestRestartWithNewNavigationDataSet() { mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); mitk::NavigationDataSequentialPlayer::Pointer player(mitk::NavigationDataSequentialPlayer::New()); std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestData_2ToolsDouble.xml", "Modules/IGT/Testing/Data"); player->SetNavigationDataSet(reader->Read(file)); mitk::NavigationData::Pointer nd1 = player->GetOutput(0); player->SetNavigationDataSet(reader->Read(file)); player->Update(); mitk::NavigationData::Pointer nd2 = player->GetOutput(0); MITK_TEST_CONDITION(nd1->GetPosition() == nd2->GetPosition(), "First output must be the same after setting same navigation data again."); // setting new NavigationDataSet with different tool count should result in an exception file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestData.xml", "Modules/IGT/Testing/Data"); MITK_TEST_FOR_EXCEPTION(mitk::IGTException, player->SetNavigationDataSet(reader->Read(file))); } void TestSetFileNameException() { //testing exception if file name hasnt been set mitk::NavigationDataSequentialPlayer::Pointer myTestPlayer = mitk::NavigationDataSequentialPlayer::New(); bool exceptionThrown=false; try { mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); myTestPlayer->SetNavigationDataSet(reader->Read("")); } catch(mitk::IGTIOException) { exceptionThrown=true; MITK_TEST_OUTPUT(<<"Tested exception for the case when file version is wrong in SetFileName. Application should not crash."); } - MITK_TEST_CONDITION_REQUIRED(exceptionThrown, "Testing SetFileName method if exception (if file name hasnt been set) was thrown."); + MITK_TEST_CONDITION(exceptionThrown, "Testing SetFileName method if exception (if file name hasnt been set) was thrown."); //testing ReInItXML method if data element is not found mitk::NavigationDataSequentialPlayer::Pointer myTestPlayer1 = mitk::NavigationDataSequentialPlayer::New(); std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestDataInvalidTags.xml", "Modules/IGT/Testing/Data"); bool exceptionThrown1=false; try { mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); myTestPlayer1->SetNavigationDataSet(reader->Read(file)); } catch(mitk::IGTException) { exceptionThrown1=true; } - MITK_TEST_CONDITION_REQUIRED(exceptionThrown1, "Testing SetFileName method if exception (if data element not found) was thrown."); + MITK_TEST_CONDITION(exceptionThrown1, "Testing SetFileName method if exception (if data element not found) was thrown."); } void TestGoToSnapshotException() { //testing GoToSnapShot for exception mitk::NavigationDataSequentialPlayer::Pointer myTestPlayer2 = mitk::NavigationDataSequentialPlayer::New(); std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestData_2Tools.xml", "Modules/IGT/Testing/Data"); mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); myTestPlayer2->SetNavigationDataSet(reader->Read(file)); bool exceptionThrown2=false; try { myTestPlayer2->GoToSnapshot(1000); } catch(mitk::IGTException) { exceptionThrown2=true; } - MITK_TEST_CONDITION_REQUIRED(exceptionThrown2, "Testing if exception is thrown when GoToSnapShot method is called with an index that doesn't exist."); + MITK_TEST_CONDITION(exceptionThrown2, "Testing if exception is thrown when GoToSnapShot method is called with an index that doesn't exist."); } void TestSetXMLStringException() { mitk::NavigationDataSequentialPlayer::Pointer myTestPlayer3 = mitk::NavigationDataSequentialPlayer::New(); bool exceptionThrown3=false; //The string above XML_INVALID_TESTSTRING is a wrong string, some element were deleted in above try { std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("InvalidVersionNavigationDataTestData.xml", "Modules/IGT/Testing/Data"); mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); myTestPlayer3->SetNavigationDataSet(reader->Read(file)); } catch(mitk::IGTIOException) { exceptionThrown3=true; } - MITK_TEST_CONDITION_REQUIRED(exceptionThrown3, "Testing SetXMLString method with an invalid XML string."); + MITK_TEST_CONDITION(exceptionThrown3, "Testing SetXMLString method with an invalid XML string."); +} + +void TestDoubleUpdate() +{ + std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestData_2Tools.xml", "Modules/IGT/Testing/Data"); + + mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); + player->SetNavigationDataSet(reader->Read(file)); + + player->Update(); + mitk::Quaternion nd1Orientation = player->GetOutput()->GetOrientation(); + + player->Update(); + mitk::Quaternion nd2Orientation = player->GetOutput()->GetOrientation(); + + MITK_TEST_CONDITION(nd1Orientation.as_vector() == nd2Orientation.as_vector(), "Output must be the same no matter if Update() was called between."); + + MITK_TEST_CONDITION(player->GoToNextSnapshot(), "There must be a next snapshot available."); + player->Update(); + mitk::Quaternion nd3Orientation = player->GetOutput()->GetOrientation(); + + MITK_TEST_CONDITION(nd1Orientation.as_vector() != nd3Orientation.as_vector(), "Output must be different if GoToNextSnapshot() was called between."); } /**Documentation * test for the class "NavigationDataRecorder". */ int mitkNavigationDataSequentialPlayerTest(int /* argc */, char* /*argv*/[]) { MITK_TEST_BEGIN("NavigationDataSequentialPlayer"); TestStandardWorkflow(); TestRestartWithNewNavigationDataSet(); - //TestSetFileNameException(); + TestSetFileNameException(); TestSetXMLStringException(); TestGoToSnapshotException(); + TestDoubleUpdate(); MITK_TEST_END(); }