diff --git a/Modules/IGT/IGTFilters/mitkNavigationDataPlayer.cpp b/Modules/IGT/IGTFilters/mitkNavigationDataPlayer.cpp index b8e96572dd..4dee64981f 100644 --- a/Modules/IGT/IGTFilters/mitkNavigationDataPlayer.cpp +++ b/Modules/IGT/IGTFilters/mitkNavigationDataPlayer.cpp @@ -1,565 +1,568 @@ /*=================================================================== 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 "mitkNavigationDataPlayer.h" //for the pause #include #include #include //for exceptions #include "mitkIGTException.h" #include "mitkIGTIOException.h" // default constructor of type mitk mitk::NavigationDataPlayer::NavigationDataPlayer() : mitk::NavigationDataPlayerBase() { m_NumberOfOutputs = 0; m_Pause = false; m_Playing = false; m_Stream = NULL; m_PlayerMode = NormalFile; m_FileName = ""; m_FileVersion = 1; m_Playing = false; m_Pause = false; m_NumberOfOutputs = 0; m_StartPlayingTimeStamp = 0.0; m_PauseTimeStamp = 0.0; m_parentElement = NULL; m_currentNode = NULL; m_StreamEnd = false; m_StreamSetOutsideFromClass = false; //To get a start time mitk::TimeStamp::GetInstance()->Start(this); } mitk::NavigationDataPlayer::~NavigationDataPlayer() { StopPlaying(); delete m_parentElement; } void mitk::NavigationDataPlayer::GenerateData() { //Only produce new output if the player is started if (!m_Playing) // !m_Playing=true means player has started { //The output is not valid anymore for (unsigned int index = 0; index < m_NumberOfOutputs; index++) { mitk::NavigationData* output = this->GetOutput(index); assert(output); mitk::NavigationData::Pointer nd = mitk::NavigationData::New(); mitk::NavigationData::PositionType position; mitk::NavigationData::OrientationType orientation(0.0,0.0,0.0,0.0); position.Fill(0.0); nd->SetPosition(position); nd->SetOrientation(orientation); nd->SetDataValid(false); output->Graft(nd); } return; } //first of all get current time TimeStampType now = mitk::TimeStamp::GetInstance()->GetElapsed(); //now we make a little time arithmetic //to get the elapsed time since the start of the player TimeStampType timeSinceStart = now - m_StartPlayingTimeStamp; //init the vectors std::vector< NavigationData::Pointer > nextCandidates; std::vector< NavigationData::Pointer > lastCandidates; std::vector< NavigationData::TimeStampType > currentTimeOfData; for (unsigned int index=0; index < m_NumberOfOutputs; index++) { // m_NextToPlayNavigationData - vector nextCandidates.push_back(m_NextToPlayNavigationData.at(index)); lastCandidates.push_back(m_NextToPlayNavigationData.at(index)); currentTimeOfData.push_back(timeSinceStart + m_StartTimeOfData.at(index)); } if (m_NextToPlayNavigationData.size() != m_NumberOfOutputs) { MITK_ERROR << "Mismatch in data"; return; } // Now we try to find next NavigationData in the stream: // This means we step through the stream of NavigationDatas until we find // a NavigationData which has a current timestamp (currentTimeOfData) greater // than the current playing time. Then we store the data in // m_NextToPlayNavigationData and take the last data (lastCandidates) for the // output of this filter. // // The loop will stop when a suitable NavigationData is found or we reach EOF. // The timestamps of each recorded NavigationData should be equal // therefore we take always the time from the first. while( nextCandidates[0]->GetTimeStamp() < currentTimeOfData[0]) { for (unsigned int index=0; index < m_NumberOfOutputs; index++) { lastCandidates[index] = nextCandidates.at(index); // m_FileVersion indicates which XML encoding is used switch(m_FileVersion) { case 1: nextCandidates[index] = ReadVersion1(); break; default: //this case should not happen! therefore the return at this point return; break; } //check if the input stream delivered a correct NavigationData object //Stops playing because there is now more nextCandidate, the file ended for all outputs for (unsigned int i = 0; i < m_NumberOfOutputs; i++) { if (nextCandidates.at(index).IsNull()) { m_StreamEnd = true; StopPlaying(); return; //the case if no NavigationData is found, e.g. EOF, bad stream } } } } //Now lastCandidates stores the new output and nextCandidates is stored to the m_NextToPlay vector for (unsigned int index = 0; index < m_NumberOfOutputs; index++) { mitk::NavigationData* output = this->GetOutput(index); assert(output); //always takes the lastCandidate, because we can not go to the next Candidata at the current moment output->Graft(lastCandidates.at(index)); m_NextToPlayNavigationData[index] = nextCandidates.at(index); } } void mitk::NavigationDataPlayer::UpdateOutputInformation() { this->Modified(); // make sure that we need to be updated Superclass::UpdateOutputInformation(); } void mitk::NavigationDataPlayer::InitPlayer() { if (m_Stream == NULL){ StreamInvalid("Playing not possible. Wrong file name or path?"); return; } if (!m_Stream->good()) { StreamInvalid("Playing not possible. Stream is not good!"); return; } m_FileVersion = GetFileVersion(m_Stream); //first get the file version //check if we have a valid version //m_FileVersion has to be always be bigger than 1 for playing if (m_FileVersion < 1) { StreamInvalid("Playing not possible. Invalid file version!"); return; } //now read the number of Tracked Tools if(m_NumberOfOutputs == 0){m_NumberOfOutputs = GetNumberOfNavigationDatas(m_Stream);} //with the information about the tracked tool number we can generate the output if (m_NumberOfOutputs > 0) { //Generate the output only if there are changes to the amount of outputs //This happens when the player is stopped and start again with different file if (this->GetNumberOfOutputs() != m_NumberOfOutputs) {SetNumberOfOutputs(m_NumberOfOutputs);} //initialize the player with first data GetFirstData(); //set stream valid m_ErrorMessage = ""; m_StreamValid = true; } else { StreamInvalid("The input stream seems to have NavigationData incompatible format"); return; } } unsigned int mitk::NavigationDataPlayer::GetFileVersion(std::istream* stream) { if (stream==NULL) { MITK_ERROR << "No input stream set!"; mitkThrowException(mitk::IGTException)<<"No input stream set!"; } if (!stream->good()) { - MITK_ERROR << "Stream not good!"; - return 0; + MITK_ERROR << "Stream is not good!"; + mitkThrowException(mitk::IGTException)<<"Stream is not good!"; + return 0; //add an exception here? } int version = 1; TiXmlDeclaration* dec = new TiXmlDeclaration(); *stream >> *dec; if(strcmp(dec->Version(),"") == 0){ MITK_ERROR << "The input stream seems to have XML incompatible format"; mitkThrowException(mitk::IGTIOException) << "The input stream seems to have XML incompatible format"; } m_parentElement = new TiXmlElement(""); *stream >> *m_parentElement; //2nd line this is the file version std::string tempValue = m_parentElement->Value(); if(tempValue != "Version") { if(tempValue == "Data"){ m_parentElement->QueryIntAttribute("version",&version); } } else { m_parentElement->QueryIntAttribute("Ver",&version); } if (version > 0) return version; else return 0; } unsigned int mitk::NavigationDataPlayer::GetNumberOfNavigationDatas(std::istream* stream) { if (stream == NULL) { mitkThrowException(mitk::IGTException)<<"No input stream set!"; MITK_ERROR << "No input stream set!"; return 0; } if (!stream->good()) - { + { + mitkThrowException(mitk::IGTException)<<"Stream not good!"; MITK_ERROR << "Stream not good!"; return 0; } //If something has changed in a future version of the XML definition e.g. navigationcount or addional parameters //catch this here with a select case block (see GenerateData() method) int numberOfTools = 0; std::string tempValue = m_parentElement->Value(); if(tempValue == "Version"){ *stream >> *m_parentElement; } m_parentElement->QueryIntAttribute("ToolCount",&numberOfTools); if (numberOfTools > 0) return numberOfTools; return 0; } mitk::NavigationData::Pointer mitk::NavigationDataPlayer::ReadVersion1() { if (m_Stream == NULL) { m_Playing = false; mitkThrowException(mitk::IGTException) << "Playing not possible. Wrong file name or path? "; MITK_ERROR << "Playing not possible. Wrong file name or path? "; return NULL; } if (!m_Stream->good()) { m_Playing = false; + mitkThrowException(mitk::IGTException) << "Playing not possible. Stream is not good!"; MITK_ERROR << "Playing not possible. Stream is not good!"; return NULL; } /*TiXmlElement* elem = new TiXmlElement(""); m_currentNode = m_parentElement->IterateChildren(m_currentNode); if(m_currentNode) { elem = m_currentNode->ToElement(); }*/ TiXmlElement* elem; m_currentNode = m_parentElement->IterateChildren(m_currentNode); bool delElem; if(m_currentNode) { elem = m_currentNode->ToElement(); if(elem==NULL){mitkThrowException(mitk::IGTException) << "DamagedFileException!"; } //maybe: throw "DamagedFileException" if elem is NULL? delElem = false; } else { elem = new TiXmlElement(""); delElem = true; } mitk::NavigationData::Pointer nd = this->ReadNavigationData(elem); if(delElem) delete elem; return nd; } void mitk::NavigationDataPlayer::StartPlaying() { if (m_Stream == NULL) { m_Playing = false; //Perhaps the SetStream method was not called so we do this when a FileName is set with SetStream(PlayerMode) if (m_FileName != "") { //The PlayerMode is initialized with LastSetStream //CreateStreamFromFilename also calls InitPlayer() try { CreateStreamFromFilename(); } catch(mitk::IGTIOException e) { MITK_ERROR << "Cannot create stream from filename, please check the stream"; throw e; //todo replace by macro } catch(mitk::IGTException e2) { MITK_ERROR << "Cannot open the file, please check the file"; throw e2;//todo replace by macro } } //now check again if (m_Stream == NULL) { StopPlaying(); MITK_ERROR << "Playing not possible. Wrong file name or path?"; mitkThrowException(mitk::IGTException) << "Playing not possible. Wrong file name or path?"; } } if (!m_Playing && m_Stream->good()) { m_Playing = true; m_StartPlayingTimeStamp = mitk::TimeStamp::GetInstance()->GetElapsed(); } else { MITK_ERROR << "Player already started or stream is not good!"; StopPlaying(); } } void mitk::NavigationDataPlayer::StopPlaying() { //re init all data!! for playing again with different data //only PlayerMode and FileName are not changed m_Pause = false; m_Playing = false; if (!m_StreamSetOutsideFromClass) {delete m_Stream;} m_Stream = NULL; m_FileVersion = 1; m_Playing = false; m_Pause = false; m_StartPlayingTimeStamp = 0.0; m_PauseTimeStamp = 0.0; m_NextToPlayNavigationData.clear(); m_StartTimeOfData.clear(); } void mitk::NavigationDataPlayer::GetFirstData() { //Here we read the first lines of input (dependend on the number of inputs) for (unsigned int index=0; index < m_NumberOfOutputs; index++) { //Here we init the vector for later use m_NextToPlayNavigationData.push_back(NULL); m_StartTimeOfData.push_back(0.0); mitk::NavigationData::Pointer nd = this->GetOutput(index); switch(m_FileVersion) { case 1: m_NextToPlayNavigationData[index] = ReadVersion1(); //check if there is valid data in it if (m_NextToPlayNavigationData[index].IsNull()) { m_StreamEnd = true; StopPlaying(); //Exception is thrown mitkThrowException(mitk::IGTIOException) << "XML File is corrupt or has no NavigationData"; return; } //Have a look it the output was set already without this check the pipline will disconnect after a start/stop cycle if (nd.IsNull()) this->SetNthOutput(index, m_NextToPlayNavigationData[index]); m_StartTimeOfData[index] = m_NextToPlayNavigationData[index]->GetTimeStamp(); break; default: //this case should not happen! therefore the return at this point return; break; } } } void mitk::NavigationDataPlayer::Pause() { //player runs and pause was called -> pause the player if(m_Playing && !m_Pause) { m_Playing = false; m_Pause = true; m_PauseTimeStamp = mitk::TimeStamp::GetInstance()->GetElapsed(); } else { MITK_ERROR << "Player is either not started or already is paused" << std::endl; } } void mitk::NavigationDataPlayer::Resume() { //player is in pause mode -> play at the last position if(!m_Playing && m_Pause) { m_Playing = true; m_Pause = false; mitk::NavigationData::TimeStampType now = mitk::TimeStamp::GetInstance()->GetElapsed(); // in this case m_StartPlayingTimeStamp is set to the total elapsed time with NO playback m_StartPlayingTimeStamp = now - (m_PauseTimeStamp - m_StartPlayingTimeStamp); } else { MITK_ERROR << "Player is not paused!" << std::endl; } } void mitk::NavigationDataPlayer::CreateStreamFromFilename() { m_Stream = NULL; if (!itksys::SystemTools::FileExists(m_FileName.c_str())) { //Exception is thrown mitkThrowException(mitk::IGTIOException) << "File does not exist!"; return; } switch(m_PlayerMode) { // so we can only read normal files not zip file case NormalFile: m_Stream = new std::ifstream(m_FileName.c_str()); m_StreamSetOutsideFromClass = false; break; case ZipFile: m_Stream = NULL; MITK_ERROR << "Sorry no ZipFile support yet"; break; // Exception is thrown, if the stream is NULL default: m_Stream = NULL; mitkThrowException(mitk::IGTException)<<"The stream is NULL"; break; } this->Modified(); InitPlayer(); } void mitk::NavigationDataPlayer::SetStream( std::istream* stream ) { if ( (stream == NULL) || (!stream->good())) { // throw an exception for stream=NULL or it is not good mitkThrowException(mitk::IGTException) << "The stream is NULL or it is not good"; m_StreamEnd = true; return; } m_Stream = stream; m_StreamSetOutsideFromClass = true; this->Modified(); InitPlayer(); } bool mitk::NavigationDataPlayer::IsAtEnd() { return this->m_StreamEnd; } void mitk::NavigationDataPlayer::StreamInvalid(std::string message) { m_StreamEnd = true; StopPlaying(); m_ErrorMessage = message; m_StreamValid = false; mitkThrowException(mitk::IGTIOException) << "Invalid stream!"; return; } \ No newline at end of file diff --git a/Modules/IGT/IGTFilters/mitkNavigationDataPlayer.h b/Modules/IGT/IGTFilters/mitkNavigationDataPlayer.h index 5fb6a94786..2be6c0e6b8 100644 --- a/Modules/IGT/IGTFilters/mitkNavigationDataPlayer.h +++ b/Modules/IGT/IGTFilters/mitkNavigationDataPlayer.h @@ -1,226 +1,227 @@ /*=================================================================== 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 MITKNavigationDataPlayer_H_HEADER_INCLUDED_ #define MITKNavigationDataPlayer_H_HEADER_INCLUDED_ #include #include #include //for the Recording Mode enum #include "mitkTrackingDevice.h" #include #include "tinyxml.h" #include namespace mitk { /**Documentation * \brief This class is used to play recorded (see mitkNavigationDataRecorder class) files. * * If you want to play a file you have to set an input stream. This can be an own one (use StartPlaying(std::istream*)) * or a preset (use StartPlaying()). The presets are NormalFile and ZipFile and can be set with the method * SetPlayerMode(PlayerMode). The presets need a FileName. Therefore the FileName must be set before the preset. * For pausing the player call Pause(). A call of Resume() will continue the playing. * * * \ingroup IGT */ class MitkIGT_EXPORT NavigationDataPlayer : public NavigationDataPlayerBase { public: mitkClassMacro(NavigationDataPlayer, NavigationDataPlayerBase); itkNewMacro(Self); /** * \brief sets the file name and path for the PlayerMode NormalFile and ZipFile */ itkSetStringMacro(FileName); /** * \brief returns the file name and path for the PlayerMode NormalFile and ZipFile */ itkGetStringMacro(FileName); /** * \brief Used for pipeline update just to tell the pipeline that we always have to update */ virtual void UpdateOutputInformation(); /** * \brief This method starts the player. * * Before the stream has to be set. Either with a PlayingMode (SetStream(PlayerMode)) and FileName. Or * with an own inputstream (SetStream(istream*)). * * @throws mitk::IGTIOException Throws an exception if the file cannot be opened * @throws mitk::IGTIOException Throws an exception if there is no file choosen * @throws mitk::IGTException Throws an exception if there is no stream (i.e stream=NULL) * @throws mitk::IGTIOException Throws an exception if the file is damaged */ void StartPlaying(); /** * \brief Stops the player and closes the stream. After a call of StopPlaying() * StartPlaying() must be called to get new output data * * \warning the output is generated in this method because we know first about the number of output after * reading the first lines of the XML file. Therefore you should assign your output after the call of this method */ void StopPlaying(); /** * \brief This method pauses the player. If you want to play again call Resume() * *\warning This method is not tested yet. It is not save to use! */ void Pause(); /** * \brief This method resumes the player when it was paused. * *\warning This method is not tested yet. It is not save to use! */ void Resume(); /** * \brief This method checks if player arrived at end of file. * *\warning This method is not tested yet. It is not save to use! */ bool IsAtEnd(); /** * \brief The PlayerMode is used for generating a presetted output stream. You do not need to * set it if you want to use your own stream. * * There are: * NormalFile: ifstream * ZipFile: not implemented yet * *\warning The ZipFile Mode is not implemented yet */ enum PlayerMode { NormalFile, ZipFile }; /** * \brief sets the recording mode which causes different types of output streams * This method is overloaded with SetStream( PlayerMode ) * *@throws mitk::IGTException Throws an exception if stream is NULL or if it is not good. */ void SetStream(std::istream* stream); protected: NavigationDataPlayer(); virtual ~NavigationDataPlayer(); typedef mitk::NavigationData::TimeStampType TimeStampType; /** * \brief filter execute method */ virtual void GenerateData(); /** * \brief sets the recording mode which causes different types of output streams * This method is overloaded with SetStream( ostream* ) * * @throws mitk::IGTIOException Throws an exception if file does not exist * @throws mitk::IGTException Throws an exception if the stream is NULL */ void CreateStreamFromFilename(); /** * \brief Returns the file version out of the XML document. - * @throw Throws an exception if stream is NULL (exception havent been thrown yet)????????? + * @throws Throws an exception if stream is NULL + * @throws Throws an exception if stream in not good */ unsigned int GetFileVersion(std::istream* stream); /** * \brief Returns the number of tracked tools out of the XML document. * @throw Throws an exception if stream is NULL (exception havent been thrown yet)????????? * @throw Throws an exception if the input stream seems to have XML incompatible format */ unsigned int GetNumberOfNavigationDatas(std::istream* stream); /** * \brief Gets the first data for initializing the player */ void GetFirstData(); /** * \brief This method reads one line of the XML document and returns the data as a NavigationData object * If there is a new file version another method must be added which reads this data. * @throws mitk::IGTException Throws an exceptions if file is damaged */ mitk::NavigationData::Pointer ReadVersion1(); /** * \brief This method initializes the player with first data */ void InitPlayer(); std::istream* m_Stream; ///< stores a pointer to the input stream bool m_StreamSetOutsideFromClass; ///< stores if the stream was created in this class and must be deleted in the end PlayerMode m_PlayerMode; ///< stores the mode for the presetted PlayerMode sieh enum PlayerMode std::string m_FileName; ///< stores the filename unsigned int m_FileVersion; ///< indicates which XML encoding is used bool m_Playing; ///< indicates whether the generateoutput method generates new output or not bool m_Pause; ///< indicates if the player is paused unsigned int m_NumberOfOutputs; ///< stores the number of outputs known from the XML document TimeStampType m_StartPlayingTimeStamp; ///< the starttime of the playing set in the method StartPlaying() TimeStampType m_PauseTimeStamp; ///< stores the beginning of a pause std::vector m_NextToPlayNavigationData; ///< stores the next possible candidate for playing std::vector m_StartTimeOfData; ///< stores the start time of the different tools TiXmlElement * m_parentElement; TiXmlNode * m_currentNode; bool m_StreamEnd; ///< stores if the input stream arrived at end /** *@throws mitk::IGTIOException Throws an exception if the stream is invalid **/ void StreamInvalid(std::string message); ///< help method which sets the stream invalid and displays an error }; } // namespace mitk #endif /* MITKNavigationDataPlayer_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/Testing/mitkNavigationDataPlayerTest.cpp b/Modules/IGT/Testing/mitkNavigationDataPlayerTest.cpp index 71e4852a2e..709f6e52fb 100644 --- a/Modules/IGT/Testing/mitkNavigationDataPlayerTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationDataPlayerTest.cpp @@ -1,549 +1,550 @@ /*=================================================================== 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 "mitkNavigationDataPlayer.h" #include "mitkNavigationData.h" #include "mitkTestingMacros.h" #include "mitkStandardFileLocations.h" #include "mitkTimeStamp.h" #include #include #include #include "mitkIGTException.h" #include "mitkIGTIOException.h" #include class mitkNavigationDataPlayerTestClass { public: static void TestInstantiation() { // let's create an object of our class mitk::NavigationDataPlayer::Pointer player = mitk::NavigationDataPlayer::New(); // first test: did this work? // using MITK_TEST_CONDITION_REQUIRED makes the test stop after failure, since // it makes no sense to continue without an object. MITK_TEST_CONDITION_REQUIRED(player.IsNotNull(), "Testing instantiation"); } static void TestSimpleDataPlay() { std::string tmp = ""; // let's create an object of our class mitk::NavigationDataPlayer::Pointer player = mitk::NavigationDataPlayer::New(); std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestData.xml", "Modules/IGT/Testing/Data"); player->SetFileName( file ); MITK_TEST_CONDITION_REQUIRED( strcmp(player->GetFileName(), file.c_str()) == 0, "Testing SetFileName and GetFileName"); //exception is thrown in StartPlaying method player->StartPlaying(); player->Update(); player->StopPlaying();; mitk::NavigationData::Pointer nd = player->GetOutput(); mitk::Point3D pnt; pnt[0] = 1; pnt[1] = 0; pnt[2] = 3; MITK_TEST_CONDITION_REQUIRED( nd->GetPosition() == pnt, "Testing position of replayed NavigaionData" ); player = mitk::NavigationDataPlayer::New(); player->SetFileName( file ); std::vector times, refTimes; refTimes.resize(5); refTimes[0] = 3.9; refTimes[1] = 83.6; refTimes[2] = 174.4; refTimes[3] = 275.0; refTimes[4] = 385.39; std::vector points, refPoints; refPoints.resize(5); refPoints[0][0] = 1; refPoints[0][1] = 0; refPoints[0][2] = 3; refPoints[1][0] = 2; refPoints[1][1] = 1; refPoints[1][2] = 4; refPoints[2][0] = 3; refPoints[2][1] = 2; refPoints[2][2] = 5; refPoints[3][0] = 4; refPoints[3][1] = 3; refPoints[3][2] = 6; refPoints[4][0] = 5; refPoints[4][1] = 4; refPoints[4][2] = 7; mitk::TimeStamp::Pointer timer = mitk::TimeStamp::GetInstance(); timer->Initialize(); itk::Object::Pointer obj = itk::Object::New(); mitk::Point3D oldPos; oldPos[0] = 1; oldPos[1] = 0; oldPos[2] = 3; timer->Start( obj ); player->StartPlaying(); while( times.size()<5 ) { player->Update(); pnt = player->GetOutput()->GetPosition(); if ( pnt != oldPos ) { times.push_back( timer->GetElapsed(obj) ); points.push_back(oldPos); oldPos = pnt; } } player->StopPlaying(); // if this test fails, it may be because the dartclient runs on a virtual machine. // Under these circumstances, it may be impossible to achieve a time-accuracy of 10ms for ( int i=0;i<5;i++ ) { if ((times[i]>refTimes[i]-150 && times[i]refTimes[i]-150 && times[i]FindFile("NavigationDataTestData.xml", "Modules/IGT/Testing/Data"); player->SetFileName( file ); MITK_TEST_CONDITION_REQUIRED( strcmp(player->GetFileName(), file.c_str()) == 0, "Testing SetFileName and GetFileName"); player->StartPlaying(); player->Update(); mitk::NavigationData::Pointer nd = player->GetOutput(); mitk::Point3D pnt; pnt[0] = 1; pnt[1] = 0; pnt[2] = 3; MITK_TEST_CONDITION_REQUIRED( nd->GetPosition() == pnt, "Testing position of replayed NavigaionData" ); MITK_TEST_OUTPUT(<<"Test double call of Pause() method!"); player->Pause(); //test pause method player->Pause(); //call again to see if this causes an error MITK_TEST_OUTPUT(<<"Test double call of Resume() method!"); player->Resume(); //test resume method player->Resume(); //call again to see if this causes an error player->Update(); player->StopPlaying(); player = mitk::NavigationDataPlayer::New(); player->SetFileName( file ); std::vector times, refTimes; refTimes.resize(5); refTimes[0] = 3.9; refTimes[1] = 83.6; refTimes[2] = 174.4; refTimes[3] = 275.0; refTimes[4] = 385.39; std::vector points, refPoints; refPoints.resize(5); refPoints[0][0] = 1; refPoints[0][1] = 0; refPoints[0][2] = 3; refPoints[1][0] = 2; refPoints[1][1] = 1; refPoints[1][2] = 4; refPoints[2][0] = 3; refPoints[2][1] = 2; refPoints[2][2] = 5; refPoints[3][0] = 4; refPoints[3][1] = 3; refPoints[3][2] = 6; refPoints[4][0] = 5; refPoints[4][1] = 4; refPoints[4][2] = 7; mitk::TimeStamp::Pointer timer = mitk::TimeStamp::GetInstance(); timer->Initialize(); itk::Object::Pointer obj = itk::Object::New(); mitk::Point3D oldPos; oldPos[0] = 1; oldPos[1] = 0; oldPos[2] = 3; timer->Start( obj ); player->StartPlaying(); MITK_TEST_CONDITION_REQUIRED(!player->IsAtEnd(), "Testing method IsAtEnd() #0"); while( times.size()<3 ) { player->Update(); pnt = player->GetOutput()->GetPosition(); if ( pnt != oldPos ) { times.push_back( timer->GetElapsed(obj) ); points.push_back(oldPos); oldPos = pnt; } } MITK_TEST_OUTPUT(<<"Test pause method!"); player->Pause(); MITK_TEST_CONDITION_REQUIRED(!player->IsAtEnd(), "Testing method IsAtEnd() #1"); MITK_TEST_OUTPUT(<<"Test resume method!"); player->Resume(); while( times.size()<5 ) { player->Update(); pnt = player->GetOutput()->GetPosition(); if ( pnt != oldPos ) { times.push_back( timer->GetElapsed(obj) ); points.push_back(oldPos); oldPos = pnt; } } player->StopPlaying(); // if this test fails, it may be because the dartclient runs on a virtual machine. // Under these circumstances, it may be impossible to achieve a time-accuracy of 10ms for ( int i=0;i<5;i++ ) { if ((times[i]>refTimes[i]-150 && times[i]refTimes[i]-150 && times[i]IsAtEnd(), "Testing method IsAtEnd() #2"); } static void TestInvalidStream() { MITK_TEST_OUTPUT(<<"#### Testing invalid input data: errors are expected. ####"); //declarate test variables mitk::NavigationDataPlayer::Pointer player; std::string file; //case 0: stream not set player = mitk::NavigationDataPlayer::New(); bool InvalidStreamException0 = false; try { player->StartPlaying(); } catch(mitk::IGTException) { InvalidStreamException0=true; player->Update(); player->StopPlaying(); MITK_TEST_OUTPUT(<<"#0: Tested stream not set. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(InvalidStreamException0, "Testing Invalid Stream method if exception (stream not set) was thrown."); //case 1: non-existing file player = mitk::NavigationDataPlayer::New(); bool InvalidStreamException1 = false; player->SetFileName( "ffdsd" ); try { player->StartPlaying(); } catch(mitk::IGTException) { InvalidStreamException1=true; player->Update(); player->StopPlaying(); MITK_TEST_OUTPUT(<<"#1: Tested non-existing file. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(InvalidStreamException1, "Testing Invalid Stream method if exception (non-existing file) was thrown."); //case 2: wrong file format player = mitk::NavigationDataPlayer::New(); bool InvalidStreamException2 = false; file = mitk::StandardFileLocations::GetInstance()->FindFile("SROMFile.rom", "Modules/IGT/Testing/Data"); player->SetFileName( file ); try { player->StartPlaying(); } catch(mitk::IGTException) { InvalidStreamException2=true; player->Update(); player->StopPlaying(); MITK_TEST_OUTPUT(<<"#2: Tested wrong file format. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(InvalidStreamException2, "Testing Invalid Stream method if exception (wrong file format) was thrown."); //case 3: wrong file version player = mitk::NavigationDataPlayer::New(); file = mitk::StandardFileLocations::GetInstance()->FindFile("InvalidVersionNavigationDataTestData.xml", "Modules/IGT/Testing/Data"); player->SetFileName( file ); bool InvalidStreamException3 = false; try { player->StartPlaying(); } catch(mitk::IGTException) { InvalidStreamException3 = true; player->Update(); player->StopPlaying(); MITK_TEST_OUTPUT(<<"#3: Tested wrong file version. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(InvalidStreamException3, "Testing Invalid Stream method if exception (wrong file version) was thrown."); //case 4: wrong file player = mitk::NavigationDataPlayer::New(); player->SetFileName( "cs:\fsd/$%§²³ffdsd" ); bool InvalidStreamException4=false; try { player->StartPlaying(); } catch(mitk::IGTException) { InvalidStreamException4=true; MITK_TEST_OUTPUT(<<"#4: Tested wrong file. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(InvalidStreamException4, "Testing Invalid Stream method if exception (wrong file) was thrown."); //case 5: null stream player = mitk::NavigationDataPlayer::New(); bool InvalidStreamException5=false; try { player->StartPlaying(); } catch(mitk::IGTException) { InvalidStreamException5=true; player->Update(); player->StopPlaying(); MITK_TEST_OUTPUT(<<"#5: Tested null stream. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(InvalidStreamException5, "Testing Invalid Stream method if exception (null stream) was thrown."); //case 6: empty stream, exception is thrown in setstream player = mitk::NavigationDataPlayer::New(); bool InvalidStreamException6=false; std::ifstream* myEmptyStream; try { myEmptyStream = new std::ifstream(""); player->SetStream( myEmptyStream ); } catch(mitk::IGTException) { InvalidStreamException6=true; MITK_TEST_OUTPUT(<<"#6: Tested empty stream. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(InvalidStreamException6, "Testing Invalid Stream method if exception (empty stream) was thrown."); //case 7: wrong stream player = mitk::NavigationDataPlayer::New(); file = mitk::StandardFileLocations::GetInstance()->FindFile("SROMFile.rom", "Modules/IGT/Testing/Data"); bool InvalidStreamException7=false; std::ifstream* myWrongStream; myWrongStream = new std::ifstream(file.c_str()); try { player->SetStream( myWrongStream ); } catch(mitk::IGTIOException) { InvalidStreamException7=true; MITK_TEST_OUTPUT(<<"#7: Tested wrong stream. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(InvalidStreamException7, "Testing Invalid Stream method if exception (wrong stream) was thrown."); //case 8: invalid player = mitk::NavigationDataPlayer::New(); file = mitk::StandardFileLocations::GetInstance()->FindFile("InvalidDataNavigationDataTestData.xml", "Modules/IGT/Testing/Data"); player->SetFileName( file ); bool InvalidStreamException8=false; try { player->StartPlaying(); } catch(mitk::IGTIOException) { InvalidStreamException8=true; MITK_TEST_OUTPUT(<<"#8: Tested invalid file version. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(InvalidStreamException8, "Testing Invalid Stream method if exception (Invalid) was thrown."); //clean up delete myEmptyStream; delete myWrongStream; } static void TestSetStreamExceptions() { mitk::NavigationDataPlayer::Pointer myTestPlayer = mitk::NavigationDataPlayer::New(); std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestData.xml", "Modules/IGT/Testing/Data"); myTestPlayer->SetFileName( file ); bool exceptionThrown=false; try { std::istream* stream=NULL; myTestPlayer->SetStream(stream); } catch(mitk::IGTException) { exceptionThrown = true; MITK_TEST_OUTPUT(<<"#9: Tested exceptions in SetStream. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(exceptionThrown, "Testing SetStream method in exception was thrown."); + } static void TestStartPlayingExceptions() { MITK_INFO <<"In the following, exceptions are tested. Errors will occur and are expected."; //Case1 Testing if stream=NULL mitk::NavigationDataPlayer::Pointer myTestPlayer1 = mitk::NavigationDataPlayer::New(); bool exceptionThrown1 = false; try { myTestPlayer1->StartPlaying(); } catch(mitk::IGTException) { exceptionThrown1 = true; myTestPlayer1->StopPlaying(); MITK_TEST_OUTPUT(<<"#10: Tested exception for the case when stream=NULL in StartPlaying. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(exceptionThrown1, "Testing StartPlaying method if exception (stream=NULL) was thrown."); //Case2 Testing if file does not exist mitk::NavigationDataPlayer::Pointer myTestPlayer2 = mitk::NavigationDataPlayer::New(); myTestPlayer2->SetFileName("ffdsd"); bool exceptionThrown2 = false; try{ myTestPlayer2->StartPlaying(); } catch(mitk::IGTIOException) { exceptionThrown2 = true; myTestPlayer2->StopPlaying(); MITK_TEST_OUTPUT(<<"#11: Tested exception for the case when file does not exist in StartPlaying. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(exceptionThrown2, "Testing StartPlaying method if exception is thrown when file does not exist."); //Case3 Testing if wrong file format mitk::NavigationDataPlayer::Pointer myTestPlayer3 = mitk::NavigationDataPlayer::New(); std::string file3 = mitk::StandardFileLocations::GetInstance()->FindFile("SROMFile.rom", "Modules/IGT/Testing/Data"); myTestPlayer3->SetFileName( file3 ); bool exceptionThrown3 = false; try{ myTestPlayer3->StartPlaying(); } catch(mitk::IGTIOException) { exceptionThrown3 = true; myTestPlayer3->StopPlaying(); MITK_TEST_OUTPUT(<<"#12: Tested exception for the case when file format is wrong in StartPlaying. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(exceptionThrown3, "Testing StartPlaying method if exception (file format is wrong) was thrown."); //Case4 Testing if wrong file version mitk::NavigationDataPlayer::Pointer myTestPlayer4 = mitk::NavigationDataPlayer::New(); std::string file4 = mitk::StandardFileLocations::GetInstance()->FindFile("InvalidVersionNavigationDataTestData.xml", "Modules/IGT/Testing/Data"); myTestPlayer4->SetFileName( file3 ); bool exceptionThrown4 = false; try{ myTestPlayer4->StartPlaying(); } catch(mitk::IGTIOException) { exceptionThrown4 = true; myTestPlayer4->StopPlaying(); MITK_TEST_OUTPUT(<<"#13: Tested exception for the case when file version is wrong in StartPlaying. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(exceptionThrown4, "Testing StartPlaying method if exception (file version is wrong) was thrown."); //Case5 Testing if not existing file name mitk::NavigationDataPlayer::Pointer myTestPlayer5 = mitk::NavigationDataPlayer::New(); myTestPlayer5->SetFileName("ffdsd"); bool exceptionThrown5 = false; try{ myTestPlayer5->StartPlaying(); } catch(mitk::IGTIOException) { exceptionThrown5 = true; myTestPlayer5->StopPlaying(); MITK_TEST_OUTPUT(<<"#14: Tested exception for the case when non-existing file name in StartPlaying. Application should not crash."); } MITK_TEST_CONDITION_REQUIRED(exceptionThrown5, "Testing StartPlaying method if exception (non-existing file name) was thrown."); } }; /**Documentation * test for the class "NavigationDataPlayer". */ int mitkNavigationDataPlayerTest(int /* argc */, char* /*argv*/[]) { MITK_TEST_BEGIN("NavigationDataPlayer"); std::string tmp = ""; mitkNavigationDataPlayerTestClass::TestInstantiation(); mitkNavigationDataPlayerTestClass::TestSimpleDataPlay(); mitkNavigationDataPlayerTestClass::TestSetStreamExceptions(); mitkNavigationDataPlayerTestClass::TestStartPlayingExceptions(); mitkNavigationDataPlayerTestClass::TestPauseAndResume(); mitkNavigationDataPlayerTestClass::TestInvalidStream(); // always end with this! MITK_TEST_END(); }