diff --git a/Modules/IGT/DataManagement/mitkNavigationDataSet.cpp b/Modules/IGT/DataManagement/mitkNavigationDataSet.cpp new file mode 100644 index 0000000000..f0b1269770 --- /dev/null +++ b/Modules/IGT/DataManagement/mitkNavigationDataSet.cpp @@ -0,0 +1,161 @@ +/*=================================================================== + +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 "mitkNavigationDataSet.h" + +mitk::NavigationDataSet::NavigationDataSet( unsigned int numberOfTools ) + : m_NavigationDataVectors(std::vector >()), m_NumberOfTools(numberOfTools) +{ +} + +mitk::NavigationDataSet::~NavigationDataSet( ) +{ +} + +bool mitk::NavigationDataSet::AddNavigationDatas( std::vector navigationDatas ) +{ + // test if tool with given index exist + if ( navigationDatas.size() != m_NumberOfTools ) + { + MITK_WARN("NavigationDataSet") << "Tried to add to many or too few navigation Datas to NavigationDataSet. " << m_NavigationDataVectors.size() << " required, tried to add " << navigationDatas.size() << "."; + return false; + } + + // test for consistent timestamp + if ( m_NavigationDataVectors.size() > 0) + { + for (int i = 0; i < navigationDatas.size(); i++) + if (navigationDatas[i]->GetIGTTimeStamp() <= m_NavigationDataVectors.back()[i]->GetIGTTimeStamp()) + { + MITK_WARN("NavigationDataSet") << "IGTTimeStamp of new NavigationData should be newer than timestamp of last NavigationData."; + return false; + } + } + + m_NavigationDataVectors.push_back(navigationDatas); + return true; +} + +mitk::NavigationData::Pointer mitk::NavigationDataSet::GetNavigationDataForIndex( unsigned int index, unsigned int toolIndex ) const +{ + if ( index >= m_NavigationDataVectors.size() ) + { + MITK_WARN("NavigationDataSet") << "There is no NavigationData available at index " << index << "."; + return NULL; + } + + if ( toolIndex >= m_NavigationDataVectors.at(index).size() ) + { + MITK_WARN("NavigationDataSet") << "There is NavigatitionData available at index " << index << " for tool " << toolIndex << "."; + return NULL; + } + + return m_NavigationDataVectors.at(toolIndex).at(index); +} + +// Method not yet supported, code below compiles but delivers wrong results +//mitk::NavigationData::Pointer mitk::NavigationDataSet::GetNavigationDataBeforeTimestamp( +// mitk::NavigationData::TimeStampType timestamp, unsigned int toolIndex) const +//{ +// if ( toolIndex >= m_NavigationDataVectors.size() ) +// { +// MITK_WARN("NavigationDataSet") << "There is no tool with index " << toolIndex << "."; +// return NULL; +// } +// +// std::vector::const_iterator it; +// +// // iterate through all NavigationData objects of the given tool index +// // till the timestamp of the NavigationData is greater then the given timestamp +// for (it = m_NavigationDataVectors.at(toolIndex).begin(); +// it != m_NavigationDataVectors.at(toolIndex).end(); ++it) +// { +// if ( (*it)->GetIGTTimeStamp() > timestamp) { break; } +// } +// +// // first element was greater than timestamp -> return null +// if ( it == m_NavigationDataVectors.at(toolIndex).begin() ) +// { +// MITK_WARN("NavigationDataSet") << "No NavigationData was recorded before given timestamp."; +// return NULL; +// } +// +// // return last element smaller than the given timestamp +// return *(it-1); +//} + +std::vector< mitk::NavigationData::Pointer > mitk::NavigationDataSet::GetDataStreamForTool(unsigned int toolIndex) +{ + if (toolIndex >= m_NumberOfTools ) + { + MITK_WARN("NavigationDataSet") << "Invalid toolIndex: " << m_NumberOfTools << " Tools known, requested index " << toolIndex << ""; + return std::vector(); + } + + std::vector< mitk::NavigationData::Pointer > result; + + for(int i = 0; i < m_NavigationDataVectors.size(); i++) + result.push_back(m_NavigationDataVectors[i][toolIndex]); + + return result; +} + +std::vector< mitk::NavigationData::Pointer > mitk::NavigationDataSet::GetTimeStep(unsigned int index) +{ + return m_NavigationDataVectors[index]; +} + +unsigned int mitk::NavigationDataSet::GetNumberOfTools() +{ + return m_NumberOfTools; +} + +unsigned int mitk::NavigationDataSet::Size() +{ + return m_NavigationDataVectors.size(); +} + +// ---> methods necessary for BaseData +void mitk::NavigationDataSet::SetRequestedRegionToLargestPossibleRegion() +{ +} + +bool mitk::NavigationDataSet::RequestedRegionIsOutsideOfTheBufferedRegion() +{ + return false; +} + +bool mitk::NavigationDataSet::VerifyRequestedRegion() +{ + return true; +} + +void mitk::NavigationDataSet::SetRequestedRegion(const DataObject * ) +{ +} +// <--- methods necessary for BaseData + +// ---> methods for Iterators + +mitk::NavigationDataSet::NavigationDataSetIterator mitk::NavigationDataSet::Begin() +{ + return m_NavigationDataVectors.begin(); +} + +mitk::NavigationDataSet::NavigationDataSetIterator mitk::NavigationDataSet::End() +{ + return m_NavigationDataVectors.end(); +} \ No newline at end of file diff --git a/Modules/IGT/DataManagement/mitkNavigationDataSet.h b/Modules/IGT/DataManagement/mitkNavigationDataSet.h new file mode 100644 index 0000000000..2c3675a127 --- /dev/null +++ b/Modules/IGT/DataManagement/mitkNavigationDataSet.h @@ -0,0 +1,158 @@ +/*=================================================================== + +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 MITKNAVIGATIONDATASET_H_HEADER_INCLUDED_ +#define MITKNAVIGATIONDATASET_H_HEADER_INCLUDED_ + +#include +#include "mitkBaseData.h" +#include "mitkNavigationData.h" + +namespace mitk { + /** + * \brief Data structure which stores streams of mitk::NavigationData for + * multiple tools. + * + * Use mitk::NavigationDataRecorder to create these sets easily from pipelines. + * Use mitk::NavigationDataPlayer to stream from these sets easily. + * + */ + class MitkIGT_EXPORT NavigationDataSet : public BaseData + { + public: + + /** + * \brief This iterator iterates over the distinct time steps in this set. + * + * It returns an array of the length equal to GetNumberOfTools(), containing a + * mitk::NavigationData for each tool.. + */ + typedef std::vector< std::vector >::iterator NavigationDataSetIterator; + + mitkClassMacro(NavigationDataSet, BaseData); + + mitkNewMacro1Param(Self, unsigned int); + + /** + * \brief Add mitk::NavigationData of the given tool to the Set. + * + * @param navigationDatas vector of mitk::NavigationData objects to be added. Make sure that the size of the + * vector equals the number of tools given in the constructor + * @return true if object was be added to the set successfully, false otherwise + */ + bool AddNavigationDatas( std::vector navigationDatas ); + + /** + * \brief Get mitk::NavigationData from the given tool at given index. + * + * @param toolIndex Index of the tool from which mitk::NavigationData should be returned. + * @param index Index of the mitk::NavigationData object that should be returned. + * @return mitk::NavigationData at the specified indices, 0 if there is no object at the indices. + */ + NavigationData::Pointer GetNavigationDataForIndex( unsigned int index, unsigned int toolIndex ) const; + + ///** + //* \brief Get last mitk::Navigation object for given tool whose timestamp is less than the given timestamp. + //* @param toolIndex Index of the tool from which mitk::NavigationData should be returned. + //* @param timestamp Timestamp for selecting last object before. + //* @return Last mitk::NavigationData with timestamp less than given timestamp, 0 if there is no adequate object. + //*/ + // Method not yet supported! + //NavigationData::Pointer GetNavigationDataBeforeTimestamp( mitk::NavigationData::TimeStampType timestamp , unsigned int toolIndex ) const; + + /** + * \brief Returns a vector that contains all tracking data for a given tool. + * + * This is a relatively expensive operation, as it requires the construction of a new vector. + * + * @param toolIndex Index of the tool for which the stream should be returned. + * @return Returns a vector that contains all tracking data for a given tool. + */ + virtual std::vector< mitk::NavigationData::Pointer > GetDataStreamForTool(unsigned int toolIndex); + + /** + * \brief Returns a vector that contains NavigationDatas for each tool for a given timestep. + * + * If GetNumberOFTools() equals four, then 4 NavigationDatas will be returned. + * + * @param index Index of the timeStep for which the datas should be returned. cannot be larger than mitk::NavigationDataSet::Size() + * @return Returns a vector that contains all tracking data for a given tool. + */ + virtual std::vector< mitk::NavigationData::Pointer > GetTimeStep(unsigned int index); + + /** + * \brief Returns the number of tools for which NavigationDatas are stored in this set. + * + * This is always equal to the number given in the constructor of this class. + * + * @return the number of tools for which NavigationDatas are stored in this set. + */ + unsigned int GetNumberOfTools(); + + /** + * \brief Returns the number of time steps stored in this NavigationDataSet. + * + * This is not the total number of Navigation Datas stored in this set, but the number stored for each tool. + * i.e. the total number of NavigationDatas equals Size() * GetNumberOfTools(); + * + * @return Returns the number of time steps stored in this NavigationDataSet. + */ + unsigned int Size(); + + /** + * \brief Returns an iterator pointing to the first TimeStep. + * + * @return Returns an iterator pointing to the first TimeStep. + */ + virtual NavigationDataSetIterator Begin(); + + /** + * \brief Returns an iterator pointing behind to the last TimeStep. + * + * @return Returns an iterator pointing behind to the last TimeStep. + */ + virtual NavigationDataSetIterator End(); + + // virtual methods, that need to be implemented, but aren't reasonable for NavigationData + virtual void SetRequestedRegionToLargestPossibleRegion( ); + virtual bool RequestedRegionIsOutsideOfTheBufferedRegion( ); + virtual bool VerifyRequestedRegion( ); + virtual void SetRequestedRegion( const itk::DataObject *data ); + + protected: + /** + * \brief Constructs set with fixed number of tools. + * @param numTools How many tools are used with this mitk::NavigationDataSet. + */ + NavigationDataSet( unsigned int numTools ); + virtual ~NavigationDataSet( ); + + /** + * \brief Holds all the mitk::NavigationData objects managed by this class. + * + * The first dimension is the index of the navigation data, the second is the + * tool to which this data belongs. i.e. the first dimension is usually the longer one. + */ + std::vector > m_NavigationDataVectors; + + /** + * \brief The Number of Tools that this class is going to support. + */ + int m_NumberOfTools; + }; +} + +#endif // MITKNAVIGATIONDATASET_H_HEADER_INCLUDED_ diff --git a/Modules/IGT/IO/mitkNavigationDataPlayer.cpp b/Modules/IGT/IO/mitkNavigationDataPlayer.cpp index 04a7c3a564..9a06ad2dfb 100644 --- a/Modules/IGT/IO/mitkNavigationDataPlayer.cpp +++ b/Modules/IGT/IO/mitkNavigationDataPlayer.cpp @@ -1,549 +1,161 @@ /*=================================================================== 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 #include #include +#include "mitkNavigationDataReaderXML.h" -//includes for exceptions #include "mitkIGTException.h" -#include "mitkIGTIOException.h" -mitk::NavigationDataPlayer::NavigationDataPlayer() : mitk::NavigationDataPlayerBase() +mitk::NavigationDataPlayer::NavigationDataPlayer() + : m_CurPlayerState(PlayerStopped), + m_StartPlayingTimeStamp(0.0), m_PauseTimeStamp(0.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 + // to get a start time mitk::IGTTimeStamp::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 + if (m_CurPlayerState != PlayerRunning) { //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); - } + this->GraftEmptyOutput(); return; } - //first of all get current time - TimeStampType now = mitk::IGTTimeStamp::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++) - { - nextCandidates.push_back(m_NextToPlayNavigationData.at(index)); - lastCandidates.push_back(m_NextToPlayNavigationData.at(index)); + // get elapsed time since start of playing + m_TimeStampSinceStart = mitk::IGTTimeStamp::GetInstance()->GetElapsed() - m_StartPlayingTimeStamp; - currentTimeOfData.push_back(timeSinceStart + m_StartTimeOfData.at(index)); - } - if (m_NextToPlayNavigationData.size() != m_NumberOfOutputs) + // iterate through all NavigationData objects of the given tool index + // till the timestamp of the NavigationData is greater then the given timestamp + for (; m_NavigationDataSetIterator != m_NavigationDataSet->End(); ++m_NavigationDataSetIterator) { - 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]->GetIGTTimeStamp() < currentTimeOfData[0]) - { - for (unsigned int index=0; index < m_NumberOfOutputs; index++) + if ( m_NavigationDataSetIterator->at(0)->GetIGTTimeStamp() > m_TimeStampSinceStart) { - lastCandidates[index] = nextCandidates.at(index); - switch(m_FileVersion) // m_FileVersion indicates which XML encoding is used - { - case 1: - nextCandidates[index] = ReadVersion1(); - break; - default: //this case should not happen! therefore return at this point - MITK_ERROR << "File encoding format was not stored, aborting!"; - return; - break; - } - - //check if the input stream delivered a correct NavigationData object - for (unsigned int i = 0; i < m_NumberOfOutputs; i++) - { - if (nextCandidates.at(index).IsNull()) - //Stops playing because there is now more nextCandidate, the file ended for all outputs - { - m_StreamEnd = true; - StopPlaying(); - return; //the case if no NavigationData is found, e.g. EOF, bad stream - } - } + break; } - - } - - //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); - 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; } - //first get the file version - m_FileVersion = GetFileVersion(m_Stream); - - //check if we have a valid version: m_FileVersion has to be always bigger than 1 for playing - if (m_FileVersion < 1) + // first element was greater than timestamp -> return null + if ( m_NavigationDataSetIterator == m_NavigationDataSet->Begin() ) { - StreamInvalid("Playing not possible. Invalid file version!"); - return; - } + MITK_WARN("NavigationDataSet") << "No NavigationData was recorded before given timestamp."; - 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) {SetNumberOfIndexedOutputs(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"); + //The output is not at this time + this->GraftEmptyOutput(); 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 is not good!"; - mitkThrowException(mitk::IGTException)<<"Stream is not good!"; - } - int version = 1; - - TiXmlDeclaration* dec = new TiXmlDeclaration(); - *stream >> *dec; - if(strcmp(dec->Version(),"") == 0) + for (unsigned int index = 0; index < m_NumberOfOutputs; index++) { - 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 + mitk::NavigationData* output = this->GetOutput(index); + if( !output ) { mitkThrowException(mitk::IGTException) << "Output of index "<Value(); - if(tempValue != "Version") - { - if(tempValue == "Data"){ - m_parentElement->QueryIntAttribute("version",&version); - } - } - else - { - m_parentElement->QueryIntAttribute("Ver",&version); + mitk::NavigationDataSet::NavigationDataSetIterator curIterator = m_NavigationDataSetIterator-1; + output->Graft(curIterator->at(index)); } - if (version > 0) - return version; - else - return 0; - -} - - -unsigned int mitk::NavigationDataPlayer::GetNumberOfNavigationDatas(std::istream* stream) -{ - if (stream == NULL) + // stop playing if the last NavigationData objects were grafted + if (m_NavigationDataSetIterator == m_NavigationDataSet->End()) { - MITK_ERROR << "No input stream set!"; - mitkThrowException(mitk::IGTException)<<"No input stream set!"; + this->StopPlaying(); } - if (!stream->good()) - { - MITK_ERROR << "Stream not good!"; - mitkThrowException(mitk::IGTException)<<"Stream not good!"; - } - - //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() +void mitk::NavigationDataPlayer::UpdateOutputInformation() { - if (m_Stream == NULL) - { - m_Playing = false; - MITK_ERROR << "Playing not possible. Wrong file name or path? "; - mitkThrowException(mitk::IGTException) << "Playing not possible. Wrong file name or path? "; - } - if (!m_Stream->good()) - { - m_Playing = false; - MITK_ERROR << "Playing not possible. Stream is not good!"; - mitkThrowException(mitk::IGTException) << "Playing not possible. Stream is not good!"; - } - - /*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) << "Cannot find element: Is this file damaged?"; - } - delElem = false; - } - - else - { - elem = new TiXmlElement(""); - delElem = true; - } - - - mitk::NavigationData::Pointer nd = this->ReadNavigationData(elem); - - if(delElem) - delete elem; - - return nd; + this->Modified(); // make sure that we need to be updated + Superclass::UpdateOutputInformation(); } 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?"; - } - } + // make sure that player is initialized before playing starts + this->InitPlayer(); - if (!m_Playing && m_Stream->good()) - { - m_Playing = true; - m_StartPlayingTimeStamp = mitk::IGTTimeStamp::GetInstance()->GetElapsed(); - } - else - { - MITK_ERROR << "Player already started or stream is not good!"; - StopPlaying(); - } + // set state and iterator for playing from start + m_CurPlayerState = PlayerRunning; + m_NavigationDataSetIterator = m_NavigationDataSet->Begin(); + // timestamp for indicating playing start is set to the past + // so that the first navigation data object will be shown NOW + m_StartPlayingTimeStamp = mitk::IGTTimeStamp::GetInstance()->GetElapsed() + - m_NavigationDataSet->Begin()->at(0)->GetIGTTimeStamp(); } - - - 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); + m_CurPlayerState = PlayerStopped; - 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(); - mitkThrowException(mitk::IGTIOException) << "XML File is corrupt or has no NavigationData."; - } - - //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]->GetIGTTimeStamp(); - break; - - default: //this case should not happen! therefore the return at this point - return; - break; - } - } + // reset playing timestamps + m_StartPlayingTimeStamp = 0; + m_PauseTimeStamp = 0; } - void mitk::NavigationDataPlayer::Pause() { //player runs and pause was called -> pause the player - if(m_Playing && !m_Pause) + if(m_CurPlayerState == PlayerRunning) { - m_Playing = false; - m_Pause = true; + m_CurPlayerState = PlayerPaused; m_PauseTimeStamp = mitk::IGTTimeStamp::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) + // player is in pause mode -> play at the last position + if(m_CurPlayerState == PlayerPaused) { - m_Playing = true; - m_Pause = false; - mitk::NavigationData::TimeStampType now = mitk::IGTTimeStamp::GetInstance()->GetElapsed(); + m_CurPlayerState = PlayerRunning; // in this case m_StartPlayingTimeStamp is set to the total elapsed time with NO playback - m_StartPlayingTimeStamp = now - (m_PauseTimeStamp - m_StartPlayingTimeStamp); + m_StartPlayingTimeStamp = mitk::IGTTimeStamp::GetInstance()->GetElapsed() + - (m_PauseTimeStamp - m_StartPlayingTimeStamp); } else { MITK_ERROR << "Player is not paused!" << std::endl; } } - -void mitk::NavigationDataPlayer::CreateStreamFromFilename() +mitk::NavigationDataPlayer::PlayerState mitk::NavigationDataPlayer::GetCurrentPlayerState() { - m_Stream = NULL; - - if (!itksys::SystemTools::FileExists(m_FileName.c_str())) - { - mitkThrowException(mitk::IGTIOException) << "File does not exist!"; - } - - switch(m_PlayerMode) - { - 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; - - 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(); + return m_CurPlayerState; } -bool mitk::NavigationDataPlayer::IsAtEnd() +mitk::NavigationDataPlayer::TimeStampType mitk::NavigationDataPlayer::GetTimeStampSinceStart() { - 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 m_TimeStampSinceStart; } diff --git a/Modules/IGT/IO/mitkNavigationDataPlayer.h b/Modules/IGT/IO/mitkNavigationDataPlayer.h index 0d2e7e1b56..3b95e9409f 100644 --- a/Modules/IGT/IO/mitkNavigationDataPlayer.h +++ b/Modules/IGT/IO/mitkNavigationDataPlayer.h @@ -1,226 +1,110 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #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); itkFactorylessNewMacro(Self) itkCloneMacro(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); - + enum PlayerState { PlayerStopped, PlayerRunning, PlayerPaused }; + typedef mitk::NavigationData::TimeStampType TimeStampType; /** * \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*)). + * The method mitk::NavigationDataPlayer::SetNavigationDataSet() has to be called before. * - * @throw mitk::IGTIOException Throws an exception if the file cannot be opened. - * @throw mitk::IGTIOException Throws an exception if there is no valid filename. - * @throw mitk::IGTIOException Throws an exception if the file is damaged. - * @throw mitk::IGTException Throws an exception if there is no stream (i.e stream=NULL). + * @throw mitk::IGTException If m_NavigationDataSet is null. */ 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() */ void Pause(); /** * \brief This method resumes the player when it was paused. */ void Resume(); + PlayerState GetCurrentPlayerState(); - /** - * \brief This method checks if player arrived at end of file. - * - */ - 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 - }; - - /** @return Returns the current playing mode of the player. */ - itkGetMacro(PlayerMode,PlayerMode); - - /** @brief Sets the playing mode of the player. */ - itkSetMacro(PlayerMode,PlayerMode); - - /** - * \brief Sets the stream of this player. - * @throw mitk::IGTException Throws an exception if stream is NULL or if it is not good. - */ - void SetStream(std::istream* stream); + TimeStampType GetTimeStampSinceStart(); protected: NavigationDataPlayer(); virtual ~NavigationDataPlayer(); - typedef mitk::NavigationData::TimeStampType TimeStampType; - /** - * \brief filter execute method + * \brief Set outputs to the navigation data object corresponding to current time. */ virtual void GenerateData(); - /** - * \brief Creates a stream out of the filename given by the variable m_FileName. - * The stream is then set to m_Stream. - * - * @throw mitk::IGTIOException Throws an exception if file does not exist - * @throw mitk::IGTException Throws an exception if the stream is NULL - */ - void CreateStreamFromFilename(); - - /** - * \brief Returns the file version out of the XML document. - * @throw mitk::IGTException Throws an mitk::IGTException an exception if stream is NULL or not good. - * @throw mitk::IGTIOException Throws an mitk::IGTIOException if the stream has an incompatible XML format. - */ - 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. - * @throw Throws an exception if the input stream has an 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. - * @throw mitk::IGTException Throws an exceptions if file is damaged. - */ - mitk::NavigationData::Pointer ReadVersion1(); + PlayerState m_CurPlayerState; /** - * \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 + * \brief The start time of the playing. Set in the method mitk::NavigationDataPlayer::StartPlaying(). + */ + TimeStampType m_StartPlayingTimeStamp; /** - * @brief This is a helping method which gives an error message and throws an exception with the given message. - * It can be used if a stream is found to be invalid. - * - * @throw mitk::IGTIOException Always throws an exception. - */ - void StreamInvalid(std::string message); ///< help method which sets the stream invalid and displays an error + * \brief Stores the time when a pause began. + */ + TimeStampType m_PauseTimeStamp; + TimeStampType m_TimeStampSinceStart; }; } // namespace mitk #endif /* MITKNavigationDataPlayer_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/IO/mitkNavigationDataPlayerBase.cpp b/Modules/IGT/IO/mitkNavigationDataPlayerBase.cpp index 8edca1fb68..8a364da16e 100644 --- a/Modules/IGT/IO/mitkNavigationDataPlayerBase.cpp +++ b/Modules/IGT/IO/mitkNavigationDataPlayerBase.cpp @@ -1,118 +1,115 @@ /*=================================================================== 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 "mitkNavigationDataPlayerBase.h" +// include for exceptions +#include "mitkIGTException.h" -mitk::NavigationDataPlayerBase::NavigationDataPlayerBase() : m_StreamValid(true), m_ErrorMessage("") +mitk::NavigationDataPlayerBase::NavigationDataPlayerBase() + : m_NumberOfOutputs(0) { m_Name ="Navigation Data Player Source"; } mitk::NavigationDataPlayerBase::~NavigationDataPlayerBase() { } - - - - void mitk::NavigationDataPlayerBase::UpdateOutputInformation() { this->Modified(); // make sure that we need to be updated Superclass::UpdateOutputInformation(); } +bool mitk::NavigationDataPlayerBase::IsAtEnd() +{ + return m_NavigationDataSetIterator == m_NavigationDataSet->End(); +} -mitk::NavigationData::Pointer mitk::NavigationDataPlayerBase::ReadNavigationData(TiXmlElement* elem) +void mitk::NavigationDataPlayerBase::SetNavigationDataSet(NavigationDataSet::Pointer navigationDataSet) { - if (elem == NULL) {mitkThrow() << "Error: Element is NULL!";} + m_NavigationDataSet = navigationDataSet; + m_NavigationDataSetIterator = navigationDataSet->Begin(); - mitk::NavigationData::Pointer nd = mitk::NavigationData::New(); + this->InitPlayer(); +} - mitk::NavigationData::PositionType position; - mitk::NavigationData::OrientationType orientation(0.0,0.0,0.0,0.0); - mitk::NavigationData::TimeStampType timestamp = -1; - mitk::NavigationData::CovarianceMatrixType matrix; +unsigned int mitk::NavigationDataPlayerBase::GetNumberOfSnapshots() +{ + return m_NavigationDataSet.IsNull() ? 0 : m_NavigationDataSet->Size(); +} - bool hasPosition = true; - bool hasOrientation = true; - bool dataValid = false; +unsigned int mitk::NavigationDataPlayerBase::GetCurrentSnapshotNumber() +{ + return m_NavigationDataSet.IsNull() ? 0 : m_NavigationDataSetIterator - m_NavigationDataSet->Begin(); +} + +void mitk::NavigationDataPlayerBase::InitPlayer() +{ + if ( m_NavigationDataSet.IsNull() ) + { + mitkThrowException(mitk::IGTException) + << "NavigationDataSet has to be set before initializing player."; + } - position.Fill(0.0); - matrix.SetIdentity(); - elem->QueryDoubleAttribute("Time",×tamp); - if (timestamp == -1) + if (m_NumberOfOutputs == 0) + { + m_NumberOfOutputs = m_NavigationDataSet->GetNumberOfTools(); + this->SetNumberOfRequiredOutputs(m_NumberOfOutputs); + + for (unsigned int n = 0; n < m_NumberOfOutputs; ++n) + { + mitk::NavigationData* output = this->GetOutput(n); + if (!output) + { + DataObjectPointer newOutput = this->MakeOutput(n); + this->SetNthOutput(n, newOutput); + this->Modified(); + } + } + } + else if (m_NumberOfOutputs != m_NavigationDataSet->GetNumberOfTools()) { - return NULL; //the calling method should check the return value if it is valid/not NULL + mitkThrowException(mitk::IGTException) + << "Number of tools cannot be changed in existing player. Please create " + << "a new player, if the NavigationDataSet has another number of tools now."; } - elem->QueryDoubleAttribute("X", &position[0]); - elem->QueryDoubleAttribute("Y", &position[1]); - elem->QueryDoubleAttribute("Z", &position[2]); - - elem->QueryDoubleAttribute("QX", &orientation[0]); - elem->QueryDoubleAttribute("QY", &orientation[1]); - elem->QueryDoubleAttribute("QZ", &orientation[2]); - elem->QueryDoubleAttribute("QR", &orientation[3]); - - elem->QueryDoubleAttribute("C00", &matrix[0][0]); - elem->QueryDoubleAttribute("C01", &matrix[0][1]); - elem->QueryDoubleAttribute("C02", &matrix[0][2]); - elem->QueryDoubleAttribute("C03", &matrix[0][3]); - elem->QueryDoubleAttribute("C04", &matrix[0][4]); - elem->QueryDoubleAttribute("C05", &matrix[0][5]); - elem->QueryDoubleAttribute("C10", &matrix[1][0]); - elem->QueryDoubleAttribute("C11", &matrix[1][1]); - elem->QueryDoubleAttribute("C12", &matrix[1][2]); - elem->QueryDoubleAttribute("C13", &matrix[1][3]); - elem->QueryDoubleAttribute("C14", &matrix[1][4]); - elem->QueryDoubleAttribute("C15", &matrix[1][5]); - - int tmpval = 0; - elem->QueryIntAttribute("Valid", &tmpval); - if (tmpval == 0) - dataValid = false; - else - dataValid = true; - - tmpval = 0; - elem->QueryIntAttribute("hO", &tmpval); - if (tmpval == 0) - hasOrientation = false; - else - hasOrientation = true; - - tmpval = 0; - elem->QueryIntAttribute("hP", &tmpval); - if (tmpval == 0) - hasPosition = false; - else - hasPosition = true; - - nd->SetIGTTimeStamp(timestamp); - nd->SetPosition(position); - nd->SetOrientation(orientation); - nd->SetCovErrorMatrix(matrix); - nd->SetDataValid(dataValid); - nd->SetHasOrientation(hasOrientation); - nd->SetHasPosition(hasPosition); - - - return nd; + this->Modified(); +} + +void mitk::NavigationDataPlayerBase::GraftEmptyOutput() +{ + for (unsigned int index = 0; index < m_NavigationDataSet->GetNumberOfTools(); 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); + } } diff --git a/Modules/IGT/IO/mitkNavigationDataPlayerBase.h b/Modules/IGT/IO/mitkNavigationDataPlayerBase.h index ab86df8d2d..82b38abef6 100644 --- a/Modules/IGT/IO/mitkNavigationDataPlayerBase.h +++ b/Modules/IGT/IO/mitkNavigationDataPlayerBase.h @@ -1,78 +1,106 @@ /*=================================================================== 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 MITKNavigationDataPlayerBase_H_HEADER_INCLUDED_ #define MITKNavigationDataPlayerBase_H_HEADER_INCLUDED_ -#include -#include "tinyxml.h" - +#include "mitkNavigationDataSource.h" +#include "mitkNavigationDataSet.h" 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 - */ + * \brief Base class for using mitk::NavigationData as a filter source. + * Subclasses can play objects of mitk::NavigationDataSet. + * + * \ingroup IGT + */ class MitkIGT_EXPORT NavigationDataPlayerBase : public NavigationDataSource { public: mitkClassMacro(NavigationDataPlayerBase, NavigationDataSource); /** - * \brief Used for pipeline update just to tell the pipeline that we always have to update - */ + * \brief Used for pipeline update just to tell the pipeline that we always have to update. + */ virtual void UpdateOutputInformation(); - /** @return Returns an error message if there was one (e.g. if the stream is invalid). - * Returns an empty string if there was no error in the current stream. + itkGetMacro(NavigationDataSet, NavigationDataSet::Pointer); + + /** + * \brief Set mitk::NavigationDataSet for playing. + * Player is initialized by call to mitk::NavigationDataPlayerBase::InitPlayer() + * inside this method. Method must be called before this object can be used as + * a filter source. + * + * @param navigationDataSet mitk::NavigationDataSet which will be played by this player. + */ + void SetNavigationDataSet(NavigationDataSet::Pointer navigationDataSet); + + /** + * \brief Getter for the size of the mitk::NavigationDataSet used in this object. + * + * @return Returns the number of navigation data snapshots available in the player. */ - itkGetStringMacro(ErrorMessage); + unsigned int GetNumberOfSnapshots(); - /** @return Retruns if the current stream is valid or not. */ - itkGetMacro(StreamValid,bool); + unsigned int GetCurrentSnapshotNumber(); - /** - * \brief This method checks if player arrived at end of file. - * - *\warning This method is not tested yet. It is not save to use! - */ + /** + * \brief This method checks if player arrived at end of file. + * + * @return true if last mitk::NavigationData object is in the outputs, false otherwise + */ bool IsAtEnd(); protected: NavigationDataPlayerBase(); virtual ~NavigationDataPlayerBase(); + + /** + * \brief Every subclass hast to implement this method. See ITK filter documentation for details. + */ virtual void GenerateData() = 0; + /** + * \brief Initializes the outputs of this NavigationDataSource. + */ + void InitPlayer(); /** - * \brief Creates NavigationData from XML element and returns it - * @throw mitk::Exception Throws an exception if elem is NULL. - */ - mitk::NavigationData::Pointer ReadNavigationData(TiXmlElement* elem); + * \brief Convenience method for subclasses. + * When there are no further mitk::NavigationData objects available, this + * method can be called in the implementation of mitk::NavigationDataPlayerBase::GenerateData(). + */ + void GraftEmptyOutput(); - bool m_StreamValid; ///< stores if the input stream is valid or not - std::string m_ErrorMessage; ///< stores the error message if the stream is invalid + NavigationDataSet::Pointer m_NavigationDataSet; + /** + * \brief Iterator always points to the NavigationData object which is in the outputs at the moment. + */ + mitk::NavigationDataSet::NavigationDataSetIterator m_NavigationDataSetIterator; + + /** + * \brief Stores the number of outputs known from NavigationDataSet. + */ + unsigned int m_NumberOfOutputs; }; } // namespace mitk #endif /* MITKNavigationDataSequentialPlayer_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/IO/mitkNavigationDataReaderCSV.cpp b/Modules/IGT/IO/mitkNavigationDataReaderCSV.cpp new file mode 100644 index 0000000000..610bd67bab --- /dev/null +++ b/Modules/IGT/IO/mitkNavigationDataReaderCSV.cpp @@ -0,0 +1,17 @@ +/*=================================================================== + +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 "mitkNavigationDataReaderCSV.h" \ No newline at end of file diff --git a/Modules/IGT/IO/mitkNavigationDataReaderCSV.h b/Modules/IGT/IO/mitkNavigationDataReaderCSV.h new file mode 100644 index 0000000000..36133667a0 --- /dev/null +++ b/Modules/IGT/IO/mitkNavigationDataReaderCSV.h @@ -0,0 +1,30 @@ +/*=================================================================== + +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 MITKNavigationDataReaderCSV_H_HEADER_INCLUDED_ +#define MITKNavigationDataReaderCSV_H_HEADER_INCLUDED_ + +#include "mitkNavigationDataReaderInterface.h" + +namespace mitk { + class MitkIGT_EXPORT NavigationDataReaderCSV : public NavigationDataReaderInterface + { + + }; +} + +#endif // MITKNavigationDataReaderCSV_H_HEADER_INCLUDED_ diff --git a/Modules/IGT/IO/mitkNavigationDataReaderInterface.cpp b/Modules/IGT/IO/mitkNavigationDataReaderInterface.cpp new file mode 100644 index 0000000000..1e89800b77 --- /dev/null +++ b/Modules/IGT/IO/mitkNavigationDataReaderInterface.cpp @@ -0,0 +1,25 @@ +/*=================================================================== + +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 "mitkNavigationDataReaderInterface.h" + +mitk::NavigationDataReaderInterface::NavigationDataReaderInterface() +{ +} + +mitk::NavigationDataReaderInterface::~NavigationDataReaderInterface() +{ +} diff --git a/Modules/IGT/IO/mitkNavigationDataReaderInterface.h b/Modules/IGT/IO/mitkNavigationDataReaderInterface.h new file mode 100644 index 0000000000..09d7e6b183 --- /dev/null +++ b/Modules/IGT/IO/mitkNavigationDataReaderInterface.h @@ -0,0 +1,39 @@ +/*=================================================================== + +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 MITKNavigationDataReaderInterface_H_HEADER_INCLUDED_ +#define MITKNavigationDataReaderInterface_H_HEADER_INCLUDED_ + +#include "itkObject.h" +#include "mitkCommon.h" +#include "mitkNavigationDataSet.h" + +namespace mitk { + class MitkIGT_EXPORT NavigationDataReaderInterface : public itk::Object + { + public: + mitkClassMacro(NavigationDataReaderInterface, itk::Object); + + virtual mitk::NavigationDataSet::Pointer Read(std::string filename) = 0; + + protected: + NavigationDataReaderInterface(); + virtual ~NavigationDataReaderInterface(); + }; +} + +#endif // MITKNavigationDataReaderInterface_H_HEADER_INCLUDED_ diff --git a/Modules/IGT/IO/mitkNavigationDataReaderXML.cpp b/Modules/IGT/IO/mitkNavigationDataReaderXML.cpp new file mode 100644 index 0000000000..5d2f8186fc --- /dev/null +++ b/Modules/IGT/IO/mitkNavigationDataReaderXML.cpp @@ -0,0 +1,331 @@ +/*=================================================================== + +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 "mitkNavigationDataReaderXML.h" +#include +#include +#include "tinyxml.h" + +//includes for exceptions +#include "mitkIGTException.h" +#include "mitkIGTIOException.h" + +mitk::NavigationDataReaderXML::NavigationDataReaderXML() + : m_parentElement(0), m_currentNode(0) +{ +} + +mitk::NavigationDataReaderXML::~NavigationDataReaderXML() +{ + +} + +mitk::NavigationDataSet::Pointer mitk::NavigationDataReaderXML::Read(std::string fileName) +{ + m_FileName = fileName; + + TiXmlDocument document; + if ( !document.LoadFile(fileName)) + { + mitkThrowException(mitk::IGTIOException) << "File '"<QueryIntAttribute("Ver", &m_FileVersion) != TIXML_SUCCESS) + { + if (m_DataElem->QueryIntAttribute("version", &m_FileVersion) != TIXML_SUCCESS) + { + mitkThrowException(mitk::IGTIOException) << "Version not specified in XML file."; + } + } + + if (m_FileVersion != 1) + { + mitkThrowException(mitk::IGTIOException) << "File format version "<QueryIntAttribute("ToolCount", &m_NumberOfOutputs); + + mitk::NavigationDataSet::Pointer navigationDataSet = this->ReadNavigationDataSet(); + + return navigationDataSet; +} + +mitk::NavigationDataSet::Pointer mitk::NavigationDataReaderXML::Read(std::istream* stream) +{ + // first get the file version + m_FileVersion = this->GetFileVersion(stream); + + // check if we have a valid version: m_FileVersion has to be always bigger than 1 for playing + if (m_FileVersion < 1) + { + StreamInvalid("Playing not possible. Invalid file version!"); + return 0; + } + + m_NumberOfOutputs = this->GetNumberOfNavigationDatas(stream); + if (m_NumberOfOutputs == 0) { return 0; } + + return this->ReadNavigationDataSet(); +} + +mitk::NavigationDataSet::Pointer mitk::NavigationDataReaderXML::ReadNavigationDataSet() +{ + mitk::NavigationDataSet::Pointer navigationDataSet = mitk::NavigationDataSet::New(m_NumberOfOutputs); + mitk::NavigationData::Pointer curNavigationData; + + do + { + std::vector navDatas(m_NumberOfOutputs, NULL); + for (unsigned int n = 0; n < m_NumberOfOutputs; ++n) + { + curNavigationData = this->ReadVersion1(); + + if (curNavigationData.IsNull()) + { + if (n != 0) + { + MITK_WARN("mitkNavigationDataReaderXML") + << "Different number of NavigationData objects for different tools. Ignoring last ones."; + } + break; + } + navDatas.at(n) = curNavigationData; + } + + if (curNavigationData.IsNotNull()) + { + navigationDataSet->AddNavigationDatas(navDatas); + } + } + while (curNavigationData.IsNotNull()); + + return navigationDataSet; +} + +mitk::NavigationData::Pointer mitk::NavigationDataReaderXML::ReadVersion1() +{ + if ( !m_parentElement ) + { + mitkThrowException(mitk::IGTIOException) + << "Reading XML is not possible. Parent element is not set."; + } + + TiXmlElement* elem; + m_currentNode = m_parentElement->IterateChildren(m_currentNode); + + bool delElem; + + if(m_currentNode) + { + elem = m_currentNode->ToElement(); + if(elem==NULL) + { + mitkThrowException(mitk::IGTException) << "Cannot find element: Is this file damaged?"; + } + delElem = false; + } + + else + { + elem = new TiXmlElement(""); + delElem = true; + } + + + mitk::NavigationData::Pointer nd = this->ReadNavigationData(elem); + + if(delElem) { delete elem; } + + return nd; +} + +mitk::NavigationData::Pointer mitk::NavigationDataReaderXML::ReadNavigationData(TiXmlElement* elem) +{ + if (elem == NULL) {mitkThrow() << "Error: Element is NULL!";} + + mitk::NavigationData::Pointer nd = mitk::NavigationData::New(); + + mitk::NavigationData::PositionType position; + mitk::NavigationData::OrientationType orientation(0.0,0.0,0.0,0.0); + mitk::NavigationData::TimeStampType timestamp = -1; + mitk::NavigationData::CovarianceMatrixType matrix; + + bool hasPosition = true; + bool hasOrientation = true; + bool dataValid = false; + + position.Fill(0.0); + matrix.SetIdentity(); + + elem->QueryDoubleAttribute("Time",×tamp); + if (timestamp == -1) + { + return NULL; //the calling method should check the return value if it is valid/not NULL + } + + elem->QueryDoubleAttribute("X", &position[0]); + elem->QueryDoubleAttribute("Y", &position[1]); + elem->QueryDoubleAttribute("Z", &position[2]); + + elem->QueryDoubleAttribute("QX", &orientation[0]); + elem->QueryDoubleAttribute("QY", &orientation[1]); + elem->QueryDoubleAttribute("QZ", &orientation[2]); + elem->QueryDoubleAttribute("QR", &orientation[3]); + + elem->QueryDoubleAttribute("C00", &matrix[0][0]); + elem->QueryDoubleAttribute("C01", &matrix[0][1]); + elem->QueryDoubleAttribute("C02", &matrix[0][2]); + elem->QueryDoubleAttribute("C03", &matrix[0][3]); + elem->QueryDoubleAttribute("C04", &matrix[0][4]); + elem->QueryDoubleAttribute("C05", &matrix[0][5]); + elem->QueryDoubleAttribute("C10", &matrix[1][0]); + elem->QueryDoubleAttribute("C11", &matrix[1][1]); + elem->QueryDoubleAttribute("C12", &matrix[1][2]); + elem->QueryDoubleAttribute("C13", &matrix[1][3]); + elem->QueryDoubleAttribute("C14", &matrix[1][4]); + elem->QueryDoubleAttribute("C15", &matrix[1][5]); + + int tmpval = 0; + elem->QueryIntAttribute("Valid", &tmpval); + if (tmpval == 0) + dataValid = false; + else + dataValid = true; + + tmpval = 0; + elem->QueryIntAttribute("hO", &tmpval); + if (tmpval == 0) + hasOrientation = false; + else + hasOrientation = true; + + tmpval = 0; + elem->QueryIntAttribute("hP", &tmpval); + if (tmpval == 0) + hasPosition = false; + else + hasPosition = true; + + nd->SetIGTTimeStamp(timestamp); + nd->SetPosition(position); + nd->SetOrientation(orientation); + nd->SetCovErrorMatrix(matrix); + nd->SetDataValid(dataValid); + nd->SetHasOrientation(hasOrientation); + nd->SetHasPosition(hasPosition); + + + return nd; +} + +// -- deprecated | begin +unsigned int mitk::NavigationDataReaderXML::GetFileVersion(std::istream* stream) +{ + if (stream==NULL) + { + MITK_ERROR << "No input stream set!"; + mitkThrowException(mitk::IGTIOException)<<"No input stream set!"; + } + if (!stream->good()) + { + MITK_ERROR << "Stream is not good!"; + mitkThrowException(mitk::IGTIOException)<<"Stream is not good!"; + } + 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::NavigationDataReaderXML::GetNumberOfNavigationDatas(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!"; + mitkThrowException(mitk::IGTException)<<"Stream not good!"; + } + + //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; +} + +void mitk::NavigationDataReaderXML::StreamInvalid(std::string message) +{ + m_StreamEnd = true; + m_ErrorMessage = message; + m_StreamValid = false; + mitkThrowException(mitk::IGTIOException) << "Invalid stream!"; +} +// -- deprecated | end + diff --git a/Modules/IGT/IO/mitkNavigationDataReaderXML.h b/Modules/IGT/IO/mitkNavigationDataReaderXML.h new file mode 100644 index 0000000000..3cdf561fe3 --- /dev/null +++ b/Modules/IGT/IO/mitkNavigationDataReaderXML.h @@ -0,0 +1,109 @@ +/*=================================================================== + +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 MITKNavigationDataReaderXML_H_HEADER_INCLUDED_ +#define MITKNavigationDataReaderXML_H_HEADER_INCLUDED_ + +#include "mitkNavigationDataReaderInterface.h" + +class TiXmlElement; +class TiXmlNode; + +namespace mitk { + + class MitkIGT_EXPORT NavigationDataReaderXML : public NavigationDataReaderInterface + { + public: + mitkClassMacro(NavigationDataReaderXML, NavigationDataReaderInterface); + itkNewMacro(Self); + + virtual mitk::NavigationDataSet::Pointer Read(std::string fileName); + virtual mitk::NavigationDataSet::Pointer Read(std::istream* stream); + + // -- deprecated | begin + /** + * \brief Sets the stream of this player. + * @throw mitk::IGTException Throws an exception if stream is NULL or if it is not good. + * \deprecated Will be removed in one of the next releases. Use SetFileName() instead. + */ + //void SetStream(std::istream* stream); + // -- deprecated | end + + protected: + NavigationDataReaderXML(); + virtual ~NavigationDataReaderXML(); + + NavigationDataSet::Pointer ReadNavigationDataSet(); + + /** + * \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. + * @throw mitk::IGTException Throws an exceptions if file is damaged. + */ + mitk::NavigationData::Pointer ReadVersion1(); + mitk::NavigationData::Pointer ReadNavigationData(TiXmlElement* elem); + + std::string m_FileName; + + TiXmlElement* m_parentElement; + TiXmlNode* m_currentNode; + + int m_FileVersion; ///< indicates which XML encoding is used + int m_NumberOfOutputs; ///< stores the number of outputs known from the XML document + + // -- deprecated | begin + //std::istream* m_Stream; ///< stores a pointer to the input stream + bool m_StreamEnd; ///< stores if the input stream arrived at end + bool m_StreamValid; ///< stores if the input stream is valid or not + std::string m_ErrorMessage; ///< stores the error message if the stream is invalid + + /** + * \brief Creates a stream out of the filename given by the variable m_FileName. + * The stream is then set to m_Stream. + * + * @throw mitk::IGTIOException Throws an exception if file does not exist + * @throw mitk::IGTException Throws an exception if the stream is NULL + */ + //void CreateStreamFromFilename(); + + /** + * \brief Returns the file version out of the XML document. + * @throw mitk::IGTException Throws an mitk::IGTException an exception if stream is NULL or not good. + * @throw mitk::IGTIOException Throws an mitk::IGTIOException if the stream has an incompatible XML format. + */ + 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. + * @throw Throws an exception if the input stream has an XML incompatible format. + */ + unsigned int GetNumberOfNavigationDatas(std::istream* stream); + + /** + * @brief This is a helping method which gives an error message and throws an exception with the given message. + * It can be used if a stream is found to be invalid. + * + * @throw mitk::IGTIOException Always throws an exception. + */ + void StreamInvalid(std::string message); ///< help method which sets the stream invalid and displays an error + // -- deprecated | end + }; + +} // namespace mitk + +#endif // MITKNavigationDataReaderXML_H_HEADER_INCLUDED_ diff --git a/Modules/IGT/IO/mitkNavigationDataRecorder.cpp b/Modules/IGT/IO/mitkNavigationDataRecorder.cpp index fb5fe23f1f..019546d60d 100644 --- a/Modules/IGT/IO/mitkNavigationDataRecorder.cpp +++ b/Modules/IGT/IO/mitkNavigationDataRecorder.cpp @@ -1,366 +1,115 @@ /*=================================================================== 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 "mitkNavigationDataRecorder.h" -#include #include -#include -#include - -//headers for exceptions -#include "mitkIGTException.h" -#include "mitkIGTIOException.h" mitk::NavigationDataRecorder::NavigationDataRecorder() { //set default values m_NumberOfInputs = 0; - m_RecordingMode = NormalFile; m_Recording = false; - m_NumberOfRecordedFiles = 0; - m_Stream = NULL; - m_FileName = ""; - m_SystemTimeClock = RealTimeClock::New(); - m_OutputFormat = mitk::NavigationDataRecorder::xml; - m_RecordCounter = 0; + m_StandardizedTimeInitialized = false; m_RecordCountLimit = -1; - m_DoNotOverwriteFiles = false; - m_StreamMustBeDeleted = false; - - //To get a start time - mitk::IGTTimeStamp::GetInstance()->Start(this); } mitk::NavigationDataRecorder::~NavigationDataRecorder() { + mitk::IGTTimeStamp::GetInstance()->Stop(this); } - void mitk::NavigationDataRecorder::GenerateData() { + // get each input, lookup the associated BaseData and transfer the data + DataObjectPointerArray inputs = this->GetIndexedInputs(); //get all inputs -} - -void mitk::NavigationDataRecorder::AddNavigationData( const NavigationData* nd ) -{ - // Process object is not const-correct so the const_cast is required here - this->SetNthInput(m_NumberOfInputs, - const_cast< mitk::NavigationData * >( nd ) ); - - m_NumberOfInputs++; + //This vector will hold the NavigationDatas that are copied from the inputs + std::vector< mitk::NavigationData::Pointer > clonedDatas; - this->Modified(); -} - -void mitk::NavigationDataRecorder::SetRecordingMode( RecordingMode mode ) -{ - m_RecordingMode = mode; - this->Modified(); -} - -void mitk::NavigationDataRecorder::Update() -{ - if (m_Recording) + // For each input + for (unsigned int index=0; index < inputs.size(); index++) { - DataObjectPointerArray inputs = this->GetInputs(); //get all inputs - mitk::NavigationData::TimeStampType timestamp=0.0; // timestamp for mitk time - timestamp = mitk::IGTTimeStamp::GetInstance()->GetElapsed(); - + // First copy input to output + this->GetOutput(index)->Graft(this->GetInput(index)); - mitk::NavigationData::TimeStampType sysTimestamp = 0.0; // timestamp for system time - sysTimestamp = m_SystemTimeClock->GetCurrentStamp(); + // if we are not recording, that's all there is to do + if (! m_Recording) continue; - // cast system time double value to stringstream to avoid low precision rounding - std::ostringstream strs; - strs.precision(15); // rounding precision for system time double value - strs << sysTimestamp; - std::string sysTimeStr = strs.str(); + // Clone a Navigation Data + mitk::NavigationData::Pointer clone = mitk::NavigationData::New(); + clone->Graft(this->GetInput(index)); + clonedDatas.push_back(clone); - //if csv-mode: write csv header and timestamp at beginning - if (m_OutputFormat == mitk::NavigationDataRecorder::csv) - { - //write header only when it's the first line - if (m_firstLine) - { - m_firstLine = false; - *m_Stream << "TimeStamp"; - for (unsigned int index = 0; index < inputs.size(); index++){ *m_Stream << ";Valid_Tool" << index << - ";X_Tool" << index << - ";Y_Tool" << index << - ";Z_Tool" << index << - ";QX_Tool" << index << - ";QY_Tool" << index << - ";QZ_Tool" << index << - ";QR_Tool" << index;} - *m_Stream << "\n"; - } - //write timestamp (always) - *m_Stream << timestamp; - } - - //write tool data for every tool - for (unsigned int index = 0; index < inputs.size(); index++) + if (m_StandardizeTime) { - mitk::NavigationData* nd = dynamic_cast(inputs[index].GetPointer()); - nd->Update(); // call update to propagate update to previous filters - - mitk::NavigationData::PositionType position; - mitk::NavigationData::OrientationType orientation(0.0, 0.0, 0.0, 0.0); - mitk::NavigationData::CovarianceMatrixType matrix; - - bool hasPosition = true; - bool hasOrientation = true; - bool dataValid = false; - - position.Fill(0.0); - matrix.SetIdentity(); - - position = nd->GetPosition(); - orientation = nd->GetOrientation(); - matrix = nd->GetCovErrorMatrix(); - - hasPosition = nd->GetHasPosition(); - hasOrientation = nd->GetHasOrientation(); - dataValid = nd->IsDataValid(); - - //use this one if you want the timestamps of the source - //timestamp = nd->GetIGTTimeStamp(); - - //a timestamp is never < 0! this case happens only if you are using the timestamp of the nd object instead of getting a new one - if (timestamp >= 0) - { - if (this->m_OutputFormat == mitk::NavigationDataRecorder::xml) - { - TiXmlElement* elem = new TiXmlElement("NavigationData"); - - elem->SetDoubleAttribute("Time", timestamp); - elem->SetAttribute("SystemTime", sysTimeStr); // tag for system time - elem->SetDoubleAttribute("Tool", index); - elem->SetDoubleAttribute("X", position[0]); - elem->SetDoubleAttribute("Y", position[1]); - elem->SetDoubleAttribute("Z", position[2]); - - elem->SetDoubleAttribute("QX", orientation[0]); - elem->SetDoubleAttribute("QY", orientation[1]); - elem->SetDoubleAttribute("QZ", orientation[2]); - elem->SetDoubleAttribute("QR", orientation[3]); - - elem->SetDoubleAttribute("C00", matrix[0][0]); - elem->SetDoubleAttribute("C01", matrix[0][1]); - elem->SetDoubleAttribute("C02", matrix[0][2]); - elem->SetDoubleAttribute("C03", matrix[0][3]); - elem->SetDoubleAttribute("C04", matrix[0][4]); - elem->SetDoubleAttribute("C05", matrix[0][5]); - elem->SetDoubleAttribute("C10", matrix[1][0]); - elem->SetDoubleAttribute("C11", matrix[1][1]); - elem->SetDoubleAttribute("C12", matrix[1][2]); - elem->SetDoubleAttribute("C13", matrix[1][3]); - elem->SetDoubleAttribute("C14", matrix[1][4]); - elem->SetDoubleAttribute("C15", matrix[1][5]); - - if (dataValid) - elem->SetAttribute("Valid",1); - else - elem->SetAttribute("Valid",0); - - if (hasOrientation) - elem->SetAttribute("hO",1); - else - elem->SetAttribute("hO",0); - - if (hasPosition) - elem->SetAttribute("hP",1); - else - elem->SetAttribute("hP",0); - - // set additional attribute? - std::map >::iterator - it = m_AdditionalAttributes.find( nd ); - if( it != m_AdditionalAttributes.end() ) - { - elem->SetAttribute(it->second.first, it->second.second); - } - - *m_Stream << " " << *elem << std::endl; - - delete elem; - } - else if (this->m_OutputFormat == mitk::NavigationDataRecorder::csv) - { - *m_Stream << ";" << dataValid << ";" << position[0] << ";" << position[1] << ";" << position[2] << ";" << orientation[0] << ";" << orientation[1] << ";" << orientation[2] << ";" << orientation[3]; - } - } - } - if (this->m_OutputFormat == mitk::NavigationDataRecorder::csv) - { - *m_Stream << "\n"; + mitk::NavigationData::TimeStampType igtTimestamp = mitk::IGTTimeStamp::GetInstance()->GetElapsed(this); + clonedDatas[index]->SetIGTTimeStamp(igtTimestamp); } } - m_RecordCounter++; - if ((m_RecordCountLimit<=m_RecordCounter)&&(m_RecordCountLimit != -1)) {StopRecording();} -} -void mitk::NavigationDataRecorder::SetAdditionalAttribute(const NavigationData* nd, - const std::string& attributeName - , const std::string& attributeValue ) -{ - std::map >::iterator - it = m_AdditionalAttributes.find( nd ); - if( it == m_AdditionalAttributes.end() ) - m_AdditionalAttributes[nd] = std::pair(attributeName, attributeValue); - else - { - it->second.first = attributeName; - it->second.second = attributeValue; - } + // if limitation is set and has been reached, stop recording + if ((m_RecordCountLimit > 0) && (m_NavigationDataSet->Size() >= m_RecordCountLimit)) m_Recording = false; + // We can skip the rest of the method, if recording is deactivated + if (!m_Recording) return; -} -void mitk::NavigationDataRecorder::RemoveAdditionalAttribute( const NavigationData* nd ) -{ - std::map >::iterator - it = m_AdditionalAttributes.find( nd ); - if( it != m_AdditionalAttributes.end() ) - m_AdditionalAttributes.erase(it); + // Add data to set + m_NavigationDataSet->AddNavigationDatas(clonedDatas); } void mitk::NavigationDataRecorder::StartRecording() -{ - - if(!m_Recording) - { - if (m_Stream == NULL) - { - std::stringstream ss; - std::ostream* stream; - - //An existing extension will be cut and replaced with .xml - std::string tmpPath = itksys::SystemTools::GetFilenamePath(m_FileName); - m_FileName = itksys::SystemTools::GetFilenameWithoutExtension(m_FileName); - std::string extension = ".xml"; - if (m_OutputFormat == mitk::NavigationDataRecorder::csv) - extension = ".csv"; - - ss << tmpPath << "/" << m_FileName << "-" << m_NumberOfRecordedFiles << extension; - - if( m_DoNotOverwriteFiles ) - { - unsigned int index = m_NumberOfRecordedFiles+1; - while( itksys::SystemTools::FileExists( ss.str().c_str() ) ) - { - ss.str(""); - ss << tmpPath << "/" << m_FileName << "-" << index << extension; - index++; - } - } - - switch(m_RecordingMode) - { - case Console: - stream = &std::cout; - break; - - case NormalFile: - if (m_FileName == "") //Check if there is a file name and path - { - std::string message = "No file name or file path set."; - MITK_ERROR << message; - mitkThrowException(mitk::IGTException) << message; - } - else - { - stream = new std::ofstream(ss.str().c_str()); - } - break; - - case ZipFile: - stream = &std::cout; - MITK_WARN << "Sorry no ZipFile support yet"; - break; - - default: - stream = &std::cout; - break; - } - m_Stream = stream; - m_StreamMustBeDeleted = true; - m_firstLine = true; - m_RecordCounter = 0; - StartRecording(stream); - } - } -else if (m_Recording) - { - MITK_WARN << "Already recording please stop before start new recording session"; - return; - } -} - -void mitk::NavigationDataRecorder::StartRecording(std::ostream* stream) { if (m_Recording) { MITK_WARN << "Already recording please stop before start new recording session"; return; } + m_Recording = true; - m_Stream = stream; - m_Stream->precision(10); + // The first time this StartRecording is called, we initialize the standardized time. + // Afterwards, it can be reset via ResetNavigationDataSet(); + if (! m_StandardizedTimeInitialized) + mitk::IGTTimeStamp::GetInstance()->Start(this); - //TODO store date and GMT time - //cheking if the stream is good - if (m_Stream->good()) - { - if (m_OutputFormat == mitk::NavigationDataRecorder::xml) - { - *m_Stream << "" << std::endl; - /**m_Stream << "" << std::endl;*/ - // should be a generic version, meaning a member variable, which has the actual version - *m_Stream << " " << "" << std::endl; - } - m_Recording = true; - } - else - { - m_Recording = false; - mitkThrowException(mitk::IGTException)<<"The stream is not good"; - } + if (m_NavigationDataSet.IsNull()) + m_NavigationDataSet = mitk::NavigationDataSet::New(GetNumberOfIndexedInputs()); } - void mitk::NavigationDataRecorder::StopRecording() { if (!m_Recording) { std::cout << "You have to start a recording first" << std::endl; return; } + m_Recording = false; +} - if ((m_Stream) && (m_OutputFormat == mitk::NavigationDataRecorder::xml)) +void mitk::NavigationDataRecorder::ResetRecording() +{ + m_NavigationDataSet = mitk::NavigationDataSet::New(GetNumberOfIndexedInputs()); + + if (m_Recording) { - *m_Stream << "" << std::endl; + mitk::IGTTimeStamp::GetInstance()->Stop(this); + mitk::IGTTimeStamp::GetInstance()->Start(this); } - - m_NumberOfRecordedFiles++; - m_Recording = false; - m_Stream->flush(); - if (m_StreamMustBeDeleted) //stream must only be deleted if it was created inside this class - { - m_StreamMustBeDeleted = false; - delete m_Stream; - } - m_Stream = NULL; } + +int mitk::NavigationDataRecorder::GetNumberOfRecordedSteps() +{ + return m_NavigationDataSet->Size(); +} \ No newline at end of file diff --git a/Modules/IGT/IO/mitkNavigationDataRecorder.h b/Modules/IGT/IO/mitkNavigationDataRecorder.h index 167ac15bb3..edccd2fe95 100644 --- a/Modules/IGT/IO/mitkNavigationDataRecorder.h +++ b/Modules/IGT/IO/mitkNavigationDataRecorder.h @@ -1,220 +1,120 @@ /*=================================================================== 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 _MITK_NavigationDataRecorder_H #define _MITK_NavigationDataRecorder_H -#include +#include "mitkNavigationDataToNavigationDataFilter.h" #include "mitkNavigationData.h" - -#include - -#include +#include "mitkNavigationDataSet.h" namespace mitk { - - /**Documentation - * \brief This class records NavigationData objects. - * - * The output of this class is formated as a XML document. - * - * Internal this class uses streams for recording NavigationData objects. Therefore different types of output are possible - * and can be set with the SetOutputMode() method. The default output is directed to the console. If you want to save into a - * file you have to set a file name and the path. The recording is started with the call of the method StartRecording(). Now - * every Update() stores the current state of the added NavigationDatas. With StopRecording() the stream is stopped. With - * another call of StartRecording() the output is written to a new file with incremented filename counter. - * - * \warning At the moment there is no check if the file is already existing and this class will override existing files. - * \ingroup IGT - */ - -class MitkIGT_EXPORT NavigationDataRecorder : public itk::ProcessObject -{ -public: - mitkClassMacro( NavigationDataRecorder, itk::ProcessObject ); + /**Documentation + * \brief This class records NavigationData objects into NavigationDataSets. + * + * The recording is started with the call of the method StartRecording(). Now + * every Update() stores the current state of the added NavigationDatas into the NavigationDataSet. + * With StopRecording() the stream is stopped, but can be resumed anytime. + * To start recording to a new NavigationDataSet, call ResetRecording(); + * + * \warning Do not add inputs while the recorder ist recording. The recorder can't handle that and will cause a nullpointer exception. + * \ingroup IGT + */ + + class MitkIGT_EXPORT NavigationDataRecorder : public NavigationDataToNavigationDataFilter + { + public: + + mitkClassMacro( NavigationDataRecorder, NavigationDataToNavigationDataFilter ); itkFactorylessNewMacro(Self) itkCloneMacro(Self) - /**Documentation - * \brief Determines where the output is directed to - * - * Console: std::cout - * NormalFile: std::ofstream - * ZipFile: Not supported yet -> std::cout - */ - enum RecordingMode - { - Console, - NormalFile, - ZipFile - }; - - /**Documentation - * \brief Determines the output format - * - * xml: XML format, also default, can be read by NavigationDataPlayer - * csv: use to export in excel, matlab, etc. - */ - enum OutputFormatEnum - { - xml, - csv - }; - /** - * \brief sets the file name for the OutputMode NormalFile and ZipFile - * - * Any extensions will be cut - * \warning existing files will be overridden - * \warning do not use "." in file names at the end + * \brief Returns whether the NavigationDataRecorder is currently recording or not */ - itkSetStringMacro(FileName); + itkGetMacro(Recording, bool); /** - * \brief Returns the file name of the recording file (in OutputMode NormalFile and ZipFile) + * \brief Returns the set that contains all of the recorded data. */ - itkGetStringMacro(FileName); - + itkGetMacro(NavigationDataSet, mitk::NavigationDataSet::Pointer); /** - * \brief If true the recorder will never overwrite a file + * \brief Sets a limit of recorded data sets / frames. Recording will be stopped if the number is reached. values < 1 disable this behaviour. Default is -1. */ - itkSetMacro(DoNotOverwriteFiles,bool); + itkSetMacro(RecordCountLimit, int); /** - * \brief Returns whether the NavigationDataRecorder is recording or not + * \brief Returns whether to use the navigationdata's time stamp or to create a new one upon recording. */ - itkGetMacro(Recording,bool); + itkGetMacro(StandardizeTime, bool); /** - * \brief Returns the recording mode + * \brief If set to false, the navigationDatas Timestamp will be used. If set to false, the recorder + * will generate a timestamp when it copies the data to the navigationdataset. */ - itkGetMacro(RecordingMode,RecordingMode); + itkSetMacro(StandardizeTime, bool); /** - * \brief Returns the number of data sets / frames which were recorded by the NavigationDataRecorder since start + * \brief Starts recording NavigationData into the NAvigationDataSet */ - itkGetMacro(RecordCounter,int); + virtual void StartRecording(); /** - * \brief Sets a limit of recorded data sets / frames. Recording will be stopped if the number is reached. -1 disables the limit, -1 is default value as well. + * \brief Stops StopsRecording to the NavigationDataSet. + * + * Recording can be resumed to the same Dataset by just calling StartRecording() again. + * Call ResetRecording() to start recording to a new Dataset; */ - itkSetMacro(RecordCountLimit,int); + virtual void StopRecording(); /** - * \brief Adds the input NavigationDatas + * \brief Resets the Datasets and the timestamp, so a new recording can happen. + * + * Do not forget to save the old Dataset, it will be lost after calling this function. */ - virtual void AddNavigationData(const NavigationData* nd); - - /// - /// set an additional attribute for a specified navigation data - /// this will be written for each navigation data and may be - /// updated before calling Update() - /// - void SetAdditionalAttribute( const NavigationData* nd, const std::string& attributeName - , const std::string& attributeValue ); - void RemoveAdditionalAttribute( const NavigationData* nd ); + virtual void ResetRecording(); /** - * Documentation - * \brief Starts the recording with the presetted OutputMode. - * This method calls StartRecording(std::ostream*). - * Does nothing if the recorder is already recording and - * the method StartRecording is called again. - * @throw mitk::IGTException Throws an exception if no file name or file path is set. - */ - void StartRecording(); - - /** - * Documentation - * \brief Starts the recording with an own preinitialized stream - * Does nothing if it is already recording and method StartRecorded is called - * @throw mitk::IGTException Throws an exception if the stream is not good. - */ - void StartRecording(std::ostream* stream); - - /**Documentation - * \brief Stops the recording and closes the stream - */ - void StopRecording(); - - /**Documentation - * \brief Every call of update causes one line for each added NavigationData in the output if the recording was started - */ - - virtual void Update(); - - - /**Documentation - * \brief Sets the recording mode which causes different types of output streams - * see enum RecordingMode - */ - void SetRecordingMode(RecordingMode mode); - - /**Documentation - * \brief Sets the output format which causes different formats of output streams. The XML format is default. - * Also see enum OutputFormat for more information. + * \brief Returns the number of time steps that were recorded in the current set. + * Warning: This Method does NOT Stop Recording! */ - itkSetMacro(OutputFormat,mitk::NavigationDataRecorder::OutputFormatEnum); + virtual int GetNumberOfRecordedSteps(); -protected: + protected: - /**Documentation - * \brief filter execute method here it is not used - * - */ virtual void GenerateData(); NavigationDataRecorder(); virtual ~NavigationDataRecorder(); - std::string m_FileName; ///< stores the file name and path - unsigned int m_NumberOfInputs; ///< counts the numbers of added input NavigationDatas - std::ostream* m_Stream; ///< the output stream - - bool m_StreamMustBeDeleted; - - RecordingMode m_RecordingMode; ///< stores the mode see enum RecordingMode - - OutputFormatEnum m_OutputFormat; ///< stores the output format; see enum OutputFormat + mitk::NavigationDataSet::Pointer m_NavigationDataSet; bool m_Recording; ///< indicates whether the recording is started or not - int m_RecordCounter; ///< counts the number of frames which are recorded since StartRecording - - int m_RecordCountLimit; ///< limits the number of frames, recording will be stopped if the limit is reached. -1 disables the limit - - bool m_firstLine; //for the csv writer to detect wether the header must be written - - unsigned int m_NumberOfRecordedFiles; ///< necessary for the naming of the file if there is more than one start-stop cycle + bool m_StandardizeTime; //< indicates whether one should use the timestamps in NavigationData or create new timestamps upon recording - mitk::RealTimeClock::Pointer m_SystemTimeClock; ///< system time clock for system time tag in output xml file - - bool m_DoNotOverwriteFiles; ///< do not overwrite any files if true - - std::map > m_AdditionalAttributes; - -}; + bool m_StandardizedTimeInitialized; //< set to true the first time start recording is called. + int m_RecordCountLimit; ///< limits the number of frames, recording will be stopped if the limit is reached. -1 disables the limit + }; } #endif // #define _MITK_POINT_SET_SOURCE_H - diff --git a/Modules/IGT/IO/mitkNavigationDataSequentialPlayer.cpp b/Modules/IGT/IO/mitkNavigationDataSequentialPlayer.cpp index 82557229d8..9a43dffa84 100644 --- a/Modules/IGT/IO/mitkNavigationDataSequentialPlayer.cpp +++ b/Modules/IGT/IO/mitkNavigationDataSequentialPlayer.cpp @@ -1,226 +1,94 @@ /*=================================================================== 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() - : mitk::NavigationDataPlayerBase() - , m_Doc(new TiXmlDocument) - , m_DataElem(0) - , m_CurrentElem(0) - , m_Repeat(false) - , m_NumberOfSnapshots(0) - , m_LastGoTo(0) + : m_Repeat(false) { } - mitk::NavigationDataSequentialPlayer::~NavigationDataSequentialPlayer() { - delete m_Doc; } -void mitk::NavigationDataSequentialPlayer::ReinitXML() +void mitk::NavigationDataSequentialPlayer::GoToSnapshot(unsigned int i) { - m_DataElem = m_Doc->FirstChildElement("Data"); - int toolcount; - if(!m_DataElem) + if( !m_Repeat && (this->GetNumberOfSnapshots() <= i) ) { - MITK_WARN << "Data element not found"; - mitkThrowException(mitk::IGTException) << "Data element not found"; + 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!"; } - else - { - m_DataElem->QueryIntAttribute("ToolCount", &toolcount); - this->SetNumberOfRequiredOutputs(toolcount); - mitk::NavigationData::Pointer emptyNd = mitk::NavigationData::New(); - mitk::NavigationData::PositionType position; - mitk::NavigationData::OrientationType orientation(0.0,0.0,0.0,0.0); - position.Fill(0.0); + // set iterator to given position (modulo for allowing repeat) + m_NavigationDataSetIterator = m_NavigationDataSet->Begin() + ( i % this->GetNumberOfSnapshots() ); - emptyNd->SetPosition(position); - emptyNd->SetOrientation(orientation); - emptyNd->SetDataValid(false); - - mitk::NavigationData::Pointer tmp; - - for (unsigned int index = 0; index < this->GetNumberOfRequiredOutputs(); index++) - { - tmp = mitk::NavigationData::New(); - tmp->Graft(emptyNd); - this->SetNthOutput(index, tmp.GetPointer()); - } - - // find out _NumberOfSnapshots - m_NumberOfSnapshots = 0; - TiXmlElement* nextND = m_DataElem->FirstChildElement("NavigationData"); - while(nextND) - { - ++m_NumberOfSnapshots; - nextND = nextND->NextSiblingElement("NavigationData"); - } - // e.g. 12 nd found and 2 tools used => number of snapshots is 12:2=6 - m_NumberOfSnapshots = m_NumberOfSnapshots/toolcount; - - } + // set outputs to selected snapshot + this->GoToNextSnapshot(); } -void mitk::NavigationDataSequentialPlayer::GoToSnapshot(unsigned int i) +bool mitk::NavigationDataSequentialPlayer::GoToNextSnapshot() { - if(!m_Repeat && (this->GetNumberOfSnapshots() numOfUpdateCalls = 4 - if(m_LastGoTo <= i) - numOfUpdateCalls = i - m_LastGoTo; - // goto(4), m_LastGoTo=7 => numOfUpdateCalls = 7 - else + if ( m_NavigationDataSetIterator == m_NavigationDataSet->End() ) { - if(!m_Repeat) + if ( m_Repeat ) { - std::stringstream message; - message <<"Cannot go back to snapshot " << i << " because the " - << this->GetNameOfClass() << " is configured to not repeat the" - << " navigation data."; - MITK_WARN << message.str(); - mitkThrowException(mitk::IGTException) << message.str(); + // set data back to start if repeat is enabled + m_NavigationDataSetIterator = m_NavigationDataSet->Begin(); } else { - numOfUpdateCalls = (m_NumberOfSnapshots - m_LastGoTo) + i; + return false; } } - for(int j=0; jUpdate(); - - m_LastGoTo = i; -} - -void mitk::NavigationDataSequentialPlayer:: - SetFileName(const std::string& _FileName) -{ - m_FileName = _FileName; - - if(!m_Doc->LoadFile(m_FileName)) - { - this->SetNumberOfIndexedOutputs(0); - std::ostringstream s; - s << "File " << _FileName << " could not be loaded"; - mitkThrowException(mitk::IGTIOException)<ReinitXML(); - } + ++m_NavigationDataSetIterator; - this->Modified(); + return true; } -void mitk::NavigationDataSequentialPlayer:: - SetXMLString(const std::string& _XMLString) +void mitk::NavigationDataSequentialPlayer::GenerateData() { - m_XMLString = _XMLString; - if((m_Doc->Parse( m_XMLString.c_str()))== NULL) + if ( m_NavigationDataSetIterator == m_NavigationDataSet->End() ) { - this->ReinitXML(); + // no more data available + this->GraftEmptyOutput(); } else { - //if the string is not an XML string - std::ostringstream s; - s << "String" << _XMLString << " is not an XML string"; - mitkThrowException(mitk::IGTIOException)<Modified(); -} - -void mitk::NavigationDataSequentialPlayer::GenerateData() -{ - assert(m_DataElem); - // very important: go through the tools (there could be more than one) - mitk::NavigationData::Pointer tmp; + for (unsigned int index = 0; index < m_NumberOfOutputs; index++) + { + mitk::NavigationData* output = this->GetOutput(index); + if( !output ) { mitkThrowException(mitk::IGTException) << "Output of index "<GetNumberOfIndexedOutputs(); index++) - { - // go to the first element - if(!m_CurrentElem) - m_CurrentElem = m_DataElem->FirstChildElement("NavigationData"); - // go to the next element - else - { - m_CurrentElem = m_CurrentElem->NextSiblingElement(); - } - - // if repeat is on: go back to the first element (prior calls delivered NULL - // elem) - if(!m_CurrentElem && m_Repeat) - m_CurrentElem = m_DataElem->FirstChildElement("NavigationData"); - - mitk::NavigationData* output = this->GetOutput(index); - tmp = this->ReadVersion1(); - if(tmp.IsNotNull()) - { - output->Graft(tmp); - m_StreamValid = true; - } - else // no valid output - { - output->SetDataValid(false); - m_StreamValid = false; - - m_ErrorMessage = "Error: Cannot parse input file."; - mitkThrowException(mitk::IGTException)<Graft(m_NavigationDataSetIterator->at(index)); + } } } -mitk::NavigationData::Pointer mitk::NavigationDataSequentialPlayer::ReadVersion1() -{ - - TiXmlElement* elem = m_CurrentElem; - - if(!elem) - return NULL; - - return this->ReadNavigationData(elem); -} - void mitk::NavigationDataSequentialPlayer::UpdateOutputInformation() { this->Modified(); // make sure that we need to be updated Superclass::UpdateOutputInformation(); -} - - - +} \ No newline at end of file diff --git a/Modules/IGT/IO/mitkNavigationDataSequentialPlayer.h b/Modules/IGT/IO/mitkNavigationDataSequentialPlayer.h index 53bd3260f7..bbabaf757d 100644 --- a/Modules/IGT/IO/mitkNavigationDataSequentialPlayer.h +++ b/Modules/IGT/IO/mitkNavigationDataSequentialPlayer.h @@ -1,123 +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 -#include "tinyxml.h" - 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); - itkFactorylessNewMacro(Self) - itkCloneMacro(Self) - - /** - * \brief sets the file name and path (if XMLString is set, this is neglected) - * @throw mitk::IGTIOException Throws an exception if the given file cannot be loaded. - */ - void SetFileName(const std::string& _FileName); - - /** - * \brief returns the file name and path - */ - itkGetStringMacro(FileName); - - /** - * \brief sets a xml string (by this, the xml string is not read from file) - * @throw mitk::IGTExcepton Throws an mitk::IGTExcepton if the string to set is not an XMLString - */ - void SetXMLString(const std::string& _XMLString); - - /** - * \brief returns the current xml string - */ - itkGetStringMacro(XMLString); + itkNewMacro(Self); /** - * @brief Set to true if the data player should repeat the outputs. + * \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. + * \return Returns if the data player should repeat the outputs. */ itkGetMacro(Repeat, bool); /** - * @return Returns the number of navigation data snapshots available in the file - */ - itkGetMacro(NumberOfSnapshots, unsigned int); - - /** - * advance the output to the i-th snapshot - * e.g. if you want to have the NavData of snapshot - * 17 then you can call GoToSnapshot(17). index begins at 1! - * you can then also go back to snapshot 1 with GoToSnapshot(1) + * \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 data element is not found. - */ - void ReinitXML(); - - mitk::NavigationData::Pointer ReadVersion1(); - - /** - * @throw mitk::IGTException Throws an exception if cannot parse input file + * \brief Does nothing. + * mitk::NavigationDataSequentialPlayer::GoToNextSnapshot() should be called + * for generating next data. */ virtual void GenerateData(); - std::string m_FileName; - std::string m_XMLString; - TiXmlDocument* m_Doc; - TiXmlElement* m_DataElem; - TiXmlElement* m_CurrentElem; + /** + * \brief If the player should repeat outputs. Default is false. + */ bool m_Repeat; - unsigned int m_NumberOfSnapshots; - unsigned int m_LastGoTo; }; } // namespace mitk #endif /* MITKNavigationDataSequentialPlayer_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/IO/mitkNavigationDataSetWriterCSV.cpp b/Modules/IGT/IO/mitkNavigationDataSetWriterCSV.cpp new file mode 100644 index 0000000000..136f9b4f9d --- /dev/null +++ b/Modules/IGT/IO/mitkNavigationDataSetWriterCSV.cpp @@ -0,0 +1,17 @@ +/*=================================================================== + +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 "mitkNavigationDataSetWriterCSV.h" \ No newline at end of file diff --git a/Modules/IGT/IO/mitkNavigationDataSetWriterCSV.h b/Modules/IGT/IO/mitkNavigationDataSetWriterCSV.h new file mode 100644 index 0000000000..8836083c41 --- /dev/null +++ b/Modules/IGT/IO/mitkNavigationDataSetWriterCSV.h @@ -0,0 +1,28 @@ +/*=================================================================== + +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 MITKNavigationDataSetWriterCSV_H_HEADER_INCLUDED_ +#define MITKNavigationDataSetWriterCSV_H_HEADER_INCLUDED_ + +namespace mitk { + class NavigationDataSetWriterCSV + { + + }; +} + +#endif // MITKNavigationDataSetWriterCSV_H_HEADER_INCLUDED_ diff --git a/Modules/IGT/IO/mitkNavigationDataSetWriterXML.cpp b/Modules/IGT/IO/mitkNavigationDataSetWriterXML.cpp new file mode 100644 index 0000000000..9ce7eee434 --- /dev/null +++ b/Modules/IGT/IO/mitkNavigationDataSetWriterXML.cpp @@ -0,0 +1,130 @@ +/*=================================================================== + +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 "mitkNavigationDataSetWriterXML.h" + +// Third Party +#include +#include +#include +#include + +mitk::NavigationDataSetWriterXML::NavigationDataSetWriterXML() +{ +} + +mitk::NavigationDataSetWriterXML::~NavigationDataSetWriterXML() +{ +} + +void mitk::NavigationDataSetWriterXML::Write (std::string path, mitk::NavigationDataSet::Pointer data) +{ + std::ofstream stream; + stream.open (path.c_str(), std::ios_base::trunc); + + // Pass to Stream Handler + Write(&stream, data); + stream.close(); +} + +void mitk::NavigationDataSetWriterXML::Write (std::ostream* stream, mitk::NavigationDataSet::Pointer data) +{ + StreamHeader(stream, data); + StreamData(stream, data); + StreamFooter(stream); + + // Cleanup + + stream->flush(); +} + +void mitk::NavigationDataSetWriterXML::StreamHeader (std::ostream* stream, mitk::NavigationDataSet::Pointer data) +{ + stream->precision(10); + + //TODO store date and GMT time + //checking if the stream is good + if (stream->good()) + { + *stream << "" << std::endl; + /**m_Stream << "" << std::endl;*/ + // should be a generic version, meaning a member variable, which has the actual version + *stream << " " << "GetNumberOfTools() << "\" version=\"1.0\">" << std::endl; + } +} + +void mitk::NavigationDataSetWriterXML::StreamData (std::ostream* stream, mitk::NavigationDataSet::Pointer data) +{ + // For each time step in the Dataset + for (mitk::NavigationDataSet::NavigationDataSetIterator it = data->Begin(); it != data->End(); it++) + { + for (int toolIndex = 0; toolIndex < it->size(); toolIndex++) + { + mitk::NavigationData::Pointer nd = it->at(toolIndex); + TiXmlElement* elem = new TiXmlElement("ND"); + + elem->SetDoubleAttribute("Time", nd->GetIGTTimeStamp()); + // elem->SetAttribute("SystemTime", sysTimeStr); // tag for system time + elem->SetDoubleAttribute("Tool", toolIndex); + elem->SetDoubleAttribute("X", nd->GetPosition()[0]); + elem->SetDoubleAttribute("Y", nd->GetPosition()[1]); + elem->SetDoubleAttribute("Z", nd->GetPosition()[2]); + + elem->SetDoubleAttribute("QX", nd->GetOrientation()[0]); + elem->SetDoubleAttribute("QY", nd->GetOrientation()[1]); + elem->SetDoubleAttribute("QZ", nd->GetOrientation()[2]); + elem->SetDoubleAttribute("QR", nd->GetOrientation()[3]); + + elem->SetDoubleAttribute("C00", nd->GetCovErrorMatrix()[0][0]); + elem->SetDoubleAttribute("C01", nd->GetCovErrorMatrix()[0][1]); + elem->SetDoubleAttribute("C02", nd->GetCovErrorMatrix()[0][2]); + elem->SetDoubleAttribute("C03", nd->GetCovErrorMatrix()[0][3]); + elem->SetDoubleAttribute("C04", nd->GetCovErrorMatrix()[0][4]); + elem->SetDoubleAttribute("C05", nd->GetCovErrorMatrix()[0][5]); + elem->SetDoubleAttribute("C10", nd->GetCovErrorMatrix()[1][0]); + elem->SetDoubleAttribute("C11", nd->GetCovErrorMatrix()[1][1]); + elem->SetDoubleAttribute("C12", nd->GetCovErrorMatrix()[1][2]); + elem->SetDoubleAttribute("C13", nd->GetCovErrorMatrix()[1][3]); + elem->SetDoubleAttribute("C14", nd->GetCovErrorMatrix()[1][4]); + elem->SetDoubleAttribute("C15", nd->GetCovErrorMatrix()[1][5]); + + if (nd->IsDataValid()) + elem->SetAttribute("Valid",1); + else + elem->SetAttribute("Valid",0); + + if (nd->GetHasOrientation()) + elem->SetAttribute("hO",1); + else + elem->SetAttribute("hO",0); + + if (nd->GetHasPosition()) + elem->SetAttribute("hP",1); + else + elem->SetAttribute("hP",0); + + *stream << " " << *elem << std::endl; + + delete elem; + } + } +} + +void mitk::NavigationDataSetWriterXML::StreamFooter (std::ostream* stream) +{ + *stream << "" << std::endl; +} diff --git a/Modules/IGT/IO/mitkNavigationDataSetWriterXML.h b/Modules/IGT/IO/mitkNavigationDataSetWriterXML.h new file mode 100644 index 0000000000..05905649dd --- /dev/null +++ b/Modules/IGT/IO/mitkNavigationDataSetWriterXML.h @@ -0,0 +1,41 @@ +/*=================================================================== + +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 MITKNavigationDataSetWriterXML_H_HEADER_INCLUDED_ +#define MITKNavigationDataSetWriterXML_H_HEADER_INCLUDED_ + +#include + +namespace mitk { + class MitkIGT_EXPORT NavigationDataSetWriterXML + { + public: + + NavigationDataSetWriterXML(); + ~NavigationDataSetWriterXML(); + + virtual void Write (std::string path, mitk::NavigationDataSet::Pointer ); + virtual void Write (std::ostream* stream, mitk::NavigationDataSet::Pointer); + + protected: + + virtual void StreamHeader (std::ostream* stream, mitk::NavigationDataSet::Pointer data); + virtual void StreamData (std::ostream* stream, mitk::NavigationDataSet::Pointer data); + virtual void StreamFooter (std::ostream* stream); + }; +} + +#endif // MITKNavigationDataSetWriterXML_H_HEADER_INCLUDED_ diff --git a/Modules/IGT/Testing/files.cmake b/Modules/IGT/Testing/files.cmake index c0b533aa68..9bc098788f 100644 --- a/Modules/IGT/Testing/files.cmake +++ b/Modules/IGT/Testing/files.cmake @@ -1,59 +1,61 @@ set(MODULE_TESTS # IMPORTANT: If you plan to deactivate / comment out a test please write a bug number to the commented out line of code. # # Example: #mitkMyTest #this test is commented out because of bug 12345 # # It is important that the bug is open and that the test will be activated again before the bug is closed. This assures that # no test is forgotten after it was commented out. If there is no bug for your current problem, please add a new one and # mark it as critical. ################## ON THE FENCE TESTS ################################################# mitkNavigationToolStorageDeserializerTest.cpp # This test was disabled because of bug 17303. # Has been activated to test if bug has been fixed. If it proves to be stable move to RUNNING TESTS mitkNavigationToolStorageSerializerAndDeserializerIntegrationTest.cpp # This test was disabled because of bug 17181. # Has been activated to test if bug has been fixed. If it proves to be stable move to RUNNING TESTS ################# RUNNING TESTS ################################################### mitkCameraVisualizationTest.cpp mitkClaronInterfaceTest.cpp mitkClaronToolTest.cpp mitkClaronTrackingDeviceTest.cpp mitkInternalTrackingToolTest.cpp mitkNavigationDataDisplacementFilterTest.cpp mitkNavigationDataLandmarkTransformFilterTest.cpp mitkNavigationDataObjectVisualizationFilterTest.cpp + mitkNavigationDataSetTest.cpp mitkNavigationDataTest.cpp mitkNavigationDataRecorderTest.cpp mitkNavigationDataReferenceTransformFilterTest.cpp mitkNavigationDataSequentialPlayerTest.cpp + mitkNavigationDataSetReaderWriterTest.cpp mitkNavigationDataSourceTest.cpp mitkNavigationDataToMessageFilterTest.cpp mitkNavigationDataToNavigationDataFilterTest.cpp mitkNavigationDataToPointSetFilterTest.cpp mitkNavigationDataTransformFilterTest.cpp mitkNDIPassiveToolTest.cpp mitkNDIProtocolTest.cpp mitkNDITrackingDeviceTest.cpp mitkTimeStampTest.cpp mitkTrackingVolumeGeneratorTest.cpp mitkTrackingDeviceTest.cpp mitkTrackingToolTest.cpp mitkVirtualTrackingDeviceTest.cpp # mitkNavigationDataPlayerTest.cpp # random fails see bug 16485. # We decided to won't fix because of complete restructuring via bug 15959. mitkTrackingDeviceSourceTest.cpp mitkTrackingDeviceSourceConfiguratorTest.cpp mitkNavigationDataEvaluationFilterTest.cpp mitkTrackingTypesTest.cpp # ------------------ Navigation Tool Management Tests ------------------- mitkNavigationToolStorageTest.cpp mitkNavigationToolTest.cpp mitkNavigationToolReaderAndWriterTest.cpp mitkNavigationToolStorageSerializerTest.cpp # ----------------------------------------------------------------------- ) set(MODULE_CUSTOM_TESTS mitkNDIAuroraHardwareTest.cpp mitkNDIPolarisHardwareTest.cpp mitkClaronTrackingDeviceHardwareTest.cpp ) diff --git a/Modules/IGT/Testing/mitkNavigationDataPlayerTest.cpp b/Modules/IGT/Testing/mitkNavigationDataPlayerTest.cpp index 5f502733d6..3b23aa2ebd 100644 --- a/Modules/IGT/Testing/mitkNavigationDataPlayerTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationDataPlayerTest.cpp @@ -1,553 +1,578 @@ /*=================================================================== 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 "mitkNavigationDataReaderXML.h" #include "mitkTestingMacros.h" +#include "mitkStandardFileLocations.h" #include "mitkIGTTimeStamp.h" #include #include #include #include "mitkIGTException.h" #include "mitkIGTIOException.h" -#include "mitkIGTConfig.h" -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 = ""; +#include - // let's create an object of our class - mitk::NavigationDataPlayer::Pointer player = mitk::NavigationDataPlayer::New(); - - std::string fileName(MITK_IGT_DATA_DIR); - fileName.append("/NavigationDataTestData.xml"); - - player->SetFileName( fileName ); - - MITK_TEST_CONDITION_REQUIRED( strcmp(player->GetFileName(), fileName.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( fileName ); - - 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::IGTTimeStamp::Pointer timer = mitk::IGTTimeStamp::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 ) +class mitkNavigationDataPlayerTestClass { - player->Update(); - pnt = player->GetOutput()->GetPosition(); - if ( pnt != oldPos ) + public: + static mitk::NavigationDataSet::Pointer GetNavigationDataSetFromXML(std::string filename) { - times.push_back( timer->GetElapsed(obj) ); - points.push_back(oldPos); - oldPos = pnt; + mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); + return reader->Read(filename); } - } - 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]SetFileName( fileName ); + // create a file reader for the navigation data xml file + mitk::NavigationDataReaderXML::Pointer navigationDataReader = mitk::NavigationDataReaderXML::New(); + std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestData.xml", "Modules/IGT/Testing/Data"); - MITK_TEST_CONDITION_REQUIRED( strcmp(player->GetFileName(), fileName.c_str()) == 0, "Testing SetFileName and GetFileName"); + // set NavigationDataSet to player + mitk::NavigationDataSet::Pointer navigationDataSet = navigationDataReader->Read(file); + player->SetNavigationDataSet( navigationDataSet ); + MITK_TEST_CONDITION_REQUIRED( navigationDataSet == player->GetNavigationDataSet() , + "Testing SetNavigationDataSet and GetNavigationDataSet." ); - player->StartPlaying(); - player->Update(); + 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::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->SetNavigationDataSet( navigationDataReader->Read(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::IGTTimeStamp::Pointer timer = mitk::IGTTimeStamp::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(); - MITK_TEST_CONDITION_REQUIRED( nd->GetPosition() == pnt, "Testing position of replayed NavigaionData" ); + // 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]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 + static void TestPauseAndResume() + { + std::string tmp = ""; - player->Update(); - player->StopPlaying(); + // let's create an object of our class + mitk::NavigationDataPlayer::Pointer player = mitk::NavigationDataPlayer::New(); - player = mitk::NavigationDataPlayer::New(); - player->SetFileName( fileName ); + // create a file reader for the navigation data xml file + mitk::NavigationDataReaderXML::Pointer navigationDataReader = mitk::NavigationDataReaderXML::New(); + std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestData.xml", "Modules/IGT/Testing/Data"); - 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; + // set NavigationDataSet to player + player->SetNavigationDataSet( navigationDataReader->Read(file) ); - mitk::IGTTimeStamp::Pointer timer = mitk::IGTTimeStamp::GetInstance(); - timer->Initialize(); + player->StartPlaying(); + player->Update(); - itk::Object::Pointer obj = itk::Object::New(); + mitk::NavigationData::Pointer nd = player->GetOutput(); + mitk::Point3D pnt; + pnt[0] = 1; + pnt[1] = 0; + pnt[2] = 3; - mitk::Point3D oldPos; - oldPos[0] = 1; - oldPos[1] = 0; - oldPos[2] = 3; + MITK_TEST_CONDITION_REQUIRED( nd->GetPosition() == pnt, "Testing position of replayed NavigaionData" ); - timer->Start( obj ); - player->StartPlaying(); + 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_CONDITION_REQUIRED(!player->IsAtEnd(), "Testing method IsAtEnd() #0"); + 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 - while( times.size()<3 ) - { player->Update(); - pnt = player->GetOutput()->GetPosition(); - if ( pnt != oldPos ) + player->StopPlaying(); + + player = mitk::NavigationDataPlayer::New(); + player->SetNavigationDataSet( navigationDataReader->Read(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::IGTTimeStamp::Pointer timer = mitk::IGTTimeStamp::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 ) { - times.push_back( timer->GetElapsed(obj) ); - points.push_back(oldPos); - oldPos = pnt; + 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_OUTPUT(<<"Test pause method!"); + player->Pause(); - MITK_TEST_CONDITION_REQUIRED(!player->IsAtEnd(), "Testing method IsAtEnd() #1"); + 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 ) + MITK_TEST_OUTPUT(<<"Test resume method!"); + player->Resume(); + while( times.size()<5 ) { - times.push_back( timer->GetElapsed(obj) ); - points.push_back(oldPos); - oldPos = pnt; + player->Update(); + pnt = player->GetOutput()->GetPosition(); + if ( pnt != oldPos ) + { + times.push_back( timer->GetElapsed(obj) ); + points.push_back(oldPos); + oldPos = pnt; + } } - } - player->StopPlaying(); + 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]refTimes[i]-150 && times[i]refTimes[i]-150 && times[i]IsAtEnd(), "Testing method IsAtEnd() #2"); -} + MITK_TEST_CONDITION_REQUIRED(player->IsAtEnd(), "Testing method IsAtEnd() #2"); + } -static void TestInvalidStream() -{ - MITK_TEST_OUTPUT(<<"#### Testing invalid input data: errors are expected. ####"); + static void TestInvalidStream() + { + MITK_TEST_OUTPUT(<<"#### Testing invalid input data: errors are expected. ####"); - //declarate test variables - mitk::NavigationDataPlayer::Pointer player; - std::string file; + //declarate test variables + mitk::NavigationDataPlayer::Pointer player; + std::string file; - //case 0: stream not set - player = mitk::NavigationDataPlayer::New(); - bool InvalidStreamException0 = false; - try - { + //case 0: stream not set + player = mitk::NavigationDataPlayer::New(); + bool InvalidStreamException0 = false; + try + { player->StartPlaying(); - } - catch(mitk::IGTException) - { + } + 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."); + 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 - { + //case 1: non-existing file + player = mitk::NavigationDataPlayer::New(); + bool InvalidStreamException1 = false; + MITK_TEST_FOR_EXCEPTION(mitk::IGTIOException, + player->SetNavigationDataSet(mitkNavigationDataPlayerTestClass::GetNavigationDataSetFromXML(file))); + try + { player->StartPlaying(); - } - catch(mitk::IGTException) - { + } + 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_IGT_DATA_DIR; - file.append("/SROMFile.rom"); + MITK_TEST_CONDITION_REQUIRED(InvalidStreamException1, "Testing Invalid Stream method if exception (non-existing file) was thrown."); - player->SetFileName( file ); - try - { + //case 2: wrong file format + player = mitk::NavigationDataPlayer::New(); + bool InvalidStreamException2 = false; + file = mitk::StandardFileLocations::GetInstance()->FindFile("SROMFile.rom", "Modules/IGT/Testing/Data"); + player->SetNavigationDataSet(mitkNavigationDataPlayerTestClass::GetNavigationDataSetFromXML(file)); + try + { player->StartPlaying(); - } - catch(mitk::IGTException) - { + } + 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_IGT_DATA_DIR; - file.append("/InvalidVersionNavigationDataTestData.xml"); + MITK_TEST_CONDITION_REQUIRED(InvalidStreamException2, "Testing Invalid Stream method if exception (wrong file format) was thrown."); - player->SetFileName( file ); - bool InvalidStreamException3 = false; - try - { + //case 3: wrong file version + player = mitk::NavigationDataPlayer::New(); + file = mitk::StandardFileLocations::GetInstance()->FindFile("InvalidVersionNavigationDataTestData.xml", "Modules/IGT/Testing/Data"); + player->SetNavigationDataSet(mitkNavigationDataPlayerTestClass::GetNavigationDataSetFromXML(file)); + bool InvalidStreamException3 = false; + try + { player->StartPlaying(); - } - catch(mitk::IGTException) - { + } + 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 - /* remove test case caused by wrong string encoding - player = mitk::NavigationDataPlayer::New(); - player->SetFileName( "cs:\fsd/$%§²³ffdsd" ); - bool InvalidStreamException4=false; - try - { + } + MITK_TEST_CONDITION_REQUIRED(InvalidStreamException3, "Testing Invalid Stream method if exception (wrong file version) was thrown."); + + //case 4: wrong file + mitk::NavigationDataSet::Pointer navigationDataSet; + mitk::NavigationDataReaderXML::Pointer navigationDataReader = mitk::NavigationDataReaderXML::New(); + MITK_TEST_FOR_EXCEPTION(mitk::IGTIOException, + navigationDataSet = navigationDataReader->Read("cs:\fsd/$%§²³ffdsd")); + + player = mitk::NavigationDataPlayer::New(); + player->SetNavigationDataSet( navigationDataSet ); + + bool InvalidStreamException4=false; + try + { player->StartPlaying(); - } - catch(mitk::IGTException) - { + } + 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."); - */ + 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 - { + //case 5: null stream + player = mitk::NavigationDataPlayer::New(); + bool InvalidStreamException5=false; + try + { player->StartPlaying(); - } - catch(mitk::IGTException) - { + } + 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."); + 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 = NULL; - 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 6: empty stream, exception is thrown in setstream + player = mitk::NavigationDataPlayer::New(); + bool InvalidStreamException6=false; + std::ifstream* myEmptyStream; + try + { + myEmptyStream = new std::ifstream(""); + mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); + reader->Read( myEmptyStream ); + } + catch(mitk::IGTIOException) + { + 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_IGT_DATA_DIR; - file.append("/SROMFile.rom"); - bool InvalidStreamException7=false; - std::ifstream* myWrongStream; - myWrongStream = new std::ifstream(file.c_str()); - try - { - player->SetStream( myWrongStream ); - } - catch(mitk::IGTIOException) - { + + //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 + { + mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); + reader->Read( 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."); + } + MITK_TEST_CONDITION_REQUIRED(InvalidStreamException7, "Testing Invalid Stream method if exception (wrong stream) was thrown."); - //case 8: invalid - player = mitk::NavigationDataPlayer::New(); - file=MITK_IGT_DATA_DIR; - file.append("/InvalidDataNavigationDataTestData.xml"); - player->SetFileName( file ); - bool InvalidStreamException8=false; - try - { - player->StartPlaying(); - } - catch(mitk::IGTIOException) - { + //case 8: invalid + player = mitk::NavigationDataPlayer::New(); + file = mitk::StandardFileLocations::GetInstance()->FindFile("InvalidDataNavigationDataTestData.xml", "Modules/IGT/Testing/Data"); + bool InvalidStreamException8=false; + try + { + mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); + reader->Read( myWrongStream ); + player->SetNavigationDataSet( reader->Read( file ) ); + 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_IGT_DATA_DIR); - file.append("/NavigationDataTestData.xml"); - - 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."); + } + MITK_TEST_CONDITION_REQUIRED(InvalidStreamException8, "Testing Invalid Stream method if exception (Invalid) was thrown."); - //Case3 Testing if wrong file format - mitk::NavigationDataPlayer::Pointer myTestPlayer3 = mitk::NavigationDataPlayer::New(); + //clean up + delete myEmptyStream; + delete myWrongStream; + } - std::string file3(MITK_IGT_DATA_DIR); - file3.append("/SROMFile.rom"); + static void TestSetStreamExceptions() + { + mitk::NavigationDataPlayer::Pointer myTestPlayer = mitk::NavigationDataPlayer::New(); + std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestData.xml", "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."); + myTestPlayer->SetNavigationDataSet( mitkNavigationDataPlayerTestClass::GetNavigationDataSetFromXML( file ) ); + bool exceptionThrown=false; - //Case4 Testing if wrong file version - mitk::NavigationDataPlayer::Pointer myTestPlayer4 = mitk::NavigationDataPlayer::New(); + try + { + std::istream* stream = NULL; + mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); + reader->Read( stream ); + } + catch(mitk::IGTIOException) + { + exceptionThrown = true; + MITK_TEST_OUTPUT(<<"#9: Tested exceptions in SetStream. Application should not crash."); - std::string file4(MITK_IGT_DATA_DIR); - file4.append("/InvalidVersionNavigationDataTestData.xml"); + } + MITK_TEST_CONDITION_REQUIRED(exceptionThrown, "Testing SetStream method in exception was thrown."); - 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."); -} + 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(); + + MITK_TEST_FOR_EXCEPTION(mitk::IGTIOException, + myTestPlayer2->SetNavigationDataSet( mitkNavigationDataPlayerTestClass::GetNavigationDataSetFromXML("ffdsd") )); + bool exceptionThrown2 = false; + try{ + myTestPlayer2->StartPlaying(); + } + catch(mitk::IGTException) + { + 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"); + + bool exceptionThrown3 = false; + try + { + myTestPlayer3->SetNavigationDataSet( mitkNavigationDataPlayerTestClass::GetNavigationDataSetFromXML(file3) ); + } + catch(mitk::IGTIOException) + { + MITK_TEST_OUTPUT(<<"#12: Tested exception for the case when file format is wrong. Application should not crash."); + exceptionThrown3 = true; + } + 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"); + bool exceptionThrown4 = false; + try + { + mitk::NavigationDataSet::Pointer navigationDataSet + = mitkNavigationDataPlayerTestClass::GetNavigationDataSetFromXML(file4); + myTestPlayer4->SetNavigationDataSet( navigationDataSet ); + } + catch(mitk::IGTIOException) + { + exceptionThrown4 = true; + 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(); + bool exceptionThrown5 = false; + + try + { + mitk::NavigationDataSet::Pointer navigationDataSet + = mitkNavigationDataPlayerTestClass::GetNavigationDataSetFromXML("ffdsd"); + myTestPlayer4->SetNavigationDataSet( navigationDataSet ); + } + catch(mitk::IGTIOException) + { + exceptionThrown5 = true; + 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". -*/ + * test for the class "NavigationDataPlayer". + */ + int mitkNavigationDataPlayerTest(int /* argc */, char* /*argv*/[]) { MITK_TEST_BEGIN("NavigationDataPlayer"); std::string tmp = ""; - TestInstantiation(); - TestSimpleDataPlay(); - TestSetStreamExceptions(); - TestStartPlayingExceptions(); - TestPauseAndResume(); - TestInvalidStream(); + mitkNavigationDataPlayerTestClass::TestInstantiation(); + mitkNavigationDataPlayerTestClass::TestSimpleDataPlay(); + mitkNavigationDataPlayerTestClass::TestSetStreamExceptions(); + //mitkNavigationDataPlayerTestClass::TestStartPlayingExceptions(); + mitkNavigationDataPlayerTestClass::TestPauseAndResume(); + //mitkNavigationDataPlayerTestClass::TestInvalidStream(); // always end with this! MITK_TEST_END(); } + + + diff --git a/Modules/IGT/Testing/mitkNavigationDataRecorderTest.cpp b/Modules/IGT/Testing/mitkNavigationDataRecorderTest.cpp index ebacf6fda4..7a683b699e 100644 --- a/Modules/IGT/Testing/mitkNavigationDataRecorderTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationDataRecorderTest.cpp @@ -1,341 +1,121 @@ /*=================================================================== 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 +#include +#include #include #include -#include -#include - -#include -#include -#include +#include +#include //for exceptions #include "mitkIGTException.h" #include "mitkIGTIOException.h" - -static void TestInstantiation() -{ - // let's create an object of our class - mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New(); - MITK_TEST_CONDITION( recorder.IsNotNull(), "Testing instatiation of NavigationDataRecorder"); -} - -static void TestRecordingWithGivenStream() -{ - std::string tmp = ""; - std::ostringstream* stream = new std::ostringstream( std::ostringstream::trunc ); - stream->setf( std::ios::fixed, std::ios::floatfield ); - - // let's create an object of our class - mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New(); - - MITK_TEST_CONDITION(recorder->GetInputs().size() == 0, "testing initial number of inputs"); - MITK_TEST_CONDITION(recorder->GetOutputs().size() == 0, "testing initial number of outputs"); - - mitk::NavigationData::Pointer naviData = mitk::NavigationData::New(); - recorder->AddNavigationData( naviData ); - recorder->StartRecording( stream ); - for ( unsigned int i=0; i<5; i++ ) - { - mitk::Point3D pnt; - pnt[0] = i + 1; - pnt[1] = i + 1/2; - pnt[2] = i +1*3; - - naviData->SetPosition(pnt); - recorder->Update(); - } - - recorder->StopRecording(); - - std::string str = stream->str(); - int pos = str.find( "ToolCount=" ); - std::string sub = stream->str().substr(pos+11, 1); - MITK_TEST_CONDITION( sub.compare("1") == 0, "check if number of inputs is correct by stringstream"); - - pos = str.find( "X=" ); - sub = stream->str().substr(pos+3, 1); - MITK_TEST_CONDITION( sub.compare("1") == 0, "check if the X coordinate is correct"); - - pos = str.find( "Y=" ); - sub = stream->str().substr(pos+3, 1); - MITK_TEST_CONDITION( sub.compare("0") == 0, "check if the Y coordinate is correct"); - - pos = str.find( "Z=" ); - sub = stream->str().substr(pos+3, 1); - MITK_TEST_CONDITION( sub.compare("3") == 0, "check if the Z coordinate is correct"); - - recorder->SetFileName("blablabla"); - const char* string = recorder->GetFileName(); - MITK_TEST_CONDITION( strcmp(string, "blablabla") == 0, "check if set- and getName-methods work"); -} - -static void TestRecordingOnHarddiscXML() -{ - mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New(); - - //create filename - std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest.xml"; - - recorder->SetFileName(filename.c_str()); - - mitk::NavigationData::Pointer naviData = mitk::NavigationData::New(); - recorder->AddNavigationData( naviData ); - recorder->StartRecording(); - - for ( unsigned int i=0; i<5; i++ ) - { - mitk::Point3D pnt; - pnt[0] = i + 1; - pnt[1] = i + 1/2; - pnt[2] = i +1*3; - naviData->SetPosition(pnt); - recorder->Update(); - } - recorder->StopRecording(); - - std::string prooffilename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest-0.xml"; - Poco::File myFile(prooffilename); - MITK_TEST_CONDITION(myFile.exists(),"Testing XML recording on harddisc (does file exist?)."); -} - -static void TestRecordingOnHarddiscXMLZIP() -{ - mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New(); - - //create filename - std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertestzip.xml"; - - recorder->SetFileName(filename.c_str()); - recorder->SetRecordingMode(mitk::NavigationDataRecorder::ZipFile); - - MITK_TEST_CONDITION(recorder->GetRecordingMode()==mitk::NavigationDataRecorder::ZipFile,"Testing setter of recording mode."); -} - -static void TestRecordingOnHarddiscCSV() -{ - mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New(); - - //create filename - std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest.xml"; - - recorder->SetFileName(filename.c_str()); - recorder->SetOutputFormat(mitk::NavigationDataRecorder::csv); - - mitk::NavigationData::Pointer naviData = mitk::NavigationData::New(); - recorder->AddNavigationData( naviData ); - recorder->StartRecording(); - - for ( unsigned int i=0; i<5; i++ ) - { - mitk::Point3D pnt; - pnt[0] = i + 1; - pnt[1] = i + 1/2; - pnt[2] = i + 1*3; - naviData->SetPosition(pnt); - recorder->Update(); - } - - recorder->StopRecording(); - - std::string prooffilename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest-0.csv"; - Poco::File myFile(prooffilename); - MITK_TEST_CONDITION(myFile.exists(),"Testing CSV recording on harddisc (does file exist?)."); -} - -/* -static void TestLoadingRecordedXMLFile() +class mitkNavigationDataRecorderTestClass { - mitk::NavigationDataPlayer::Pointer myPlayer = mitk::NavigationDataPlayer::New(); - std::string filenameXML = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest-0.xml"; - myPlayer->SetFileName(filenameXML.c_str()); - myPlayer->StartPlaying(); - - //only testing first position at the moment - myPlayer->Update(); - mitk::NavigationData::Pointer thisData = myPlayer->GetOutput(); - mitk::Point3D reference_pnt; - reference_pnt[0] = 1; - reference_pnt[1] = 1/2; - reference_pnt[2] = 1*3; - - myPlayer->StopPlaying(); +public: - MITK_TEST_CONDITION((thisData->GetPosition() == reference_pnt),"Testing load data from xml file."); -} -*/ - -static void TestRecordingInvalidData() -{ - std::string tmp = ""; - std::ostringstream* stream = new std::ostringstream( std::ostringstream::trunc ); - stream->setf( std::ios::fixed, std::ios::floatfield ); - - // let's create an object of our class - mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New(); - - mitk::NavigationData::Pointer naviData = mitk::NavigationData::New(); - recorder->AddNavigationData( naviData ); - naviData->SetDataValid(false); - recorder->StartRecording( stream ); - for ( unsigned int i=0; i<5; i++ ) + static void PlayAndRecord() { - mitk::Point3D pnt; - pnt[0] = i + 1; - pnt[1] = i + 1/2; - pnt[2] = i +1*3; - - naviData->SetPosition(pnt); - recorder->Update(); + // Aim is to read an xml into a pointset, play that set with a sequentialplayer, record it + // again, write the result to xml , and compare the output + + mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); + std::string path = "F://Build//MITK-Data//IGT-Data//RecordedNavigationData.xml"; + mitk::NavigationDataSet::Pointer set = reader->Read(path); + + mitk::NavigationDataSequentialPlayer::Pointer player = mitk::NavigationDataSequentialPlayer::New(); + player->SetNavigationDataSet(set); + + mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New(); + recorder->SetStandardizeTime(false); + + // connect player to recorder + for (int i = 0; i < player->GetNumberOfIndexedOutputs(); i++) + { + recorder->SetInput(i, player->GetOutput(i)); + } + + recorder->StartRecording(); + while (!player->IsAtEnd()) + { + recorder->Update(); + player->GoToNextSnapshot(); + } + + mitk::NavigationDataSetWriterXML writer; + + writer.Write("F://Build//MITK-Data//IGT-Data//NavigationDataSet2.xml", recorder->GetNavigationDataSet()); + + //MITK_TEST_CONDITION_REQUIRED(mitkNavigationDataRecorderTestClass::CompareFiles("F://Build//MITK-Data//IGT-Data//NavigationDataSet.xml", + // "F://Build//MITK-Data//IGT-Data//NavigationDataSet2.xml"), "Asserting that played back file has been recorded correctly"); + + recorder->StopRecording(); + MITK_TEST_CONDITION_REQUIRED(! recorder->GetRecording(), "Test if StopRecording is working"); + recorder->ResetRecording(); + MITK_TEST_CONDITION_REQUIRED(recorder->GetNavigationDataSet()->Size() == 0, "Test correct reset of recorder"); + + //Reset Player + //player = mitk::NavigationDataSequentialPlayer::New(); + player->SetNavigationDataSet(set); + + // Check if Limiting recording works + recorder->SetRecordCountLimit(100); + recorder->StartRecording(); + while (!player->IsAtEnd()) + { + recorder->Update(); + player->GoToNextSnapshot(); + } + + MITK_TEST_CONDITION_REQUIRED(recorder->GetNavigationDataSet()->Size() == 100, "Test if SetRecordCountLimit works as intended."); } - recorder->StopRecording(); - - bool record_success = true; - - std::string str = stream->str(); - int pos = str.find( "ToolCount=" ); - std::string sub = stream->str().substr(pos+11, 1); - if (sub.compare("1") != 0) {record_success = false;} - - pos = str.find( "X=" ); - sub = stream->str().substr(pos+3, 1); - if (sub.compare("1") != 0) {record_success = false;} - - pos = str.find( "Y=" ); - sub = stream->str().substr(pos+3, 1); - if (sub.compare("0") != 0) {record_success = false;} - - pos = str.find( "Z=" ); - sub = stream->str().substr(pos+3, 1); - if (sub.compare("3") != 0) {record_success = false;} - - MITK_TEST_CONDITION(record_success,"Testing recording of invalid data."); -} - -static void CleanUp() -{ - std::string filenameXML = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest-0.xml"; - std::string filenameCSV = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest-0.csv"; - Poco::File myFileXML(filenameXML); - Poco::File myFileCSV(filenameCSV); - - try + static bool CompareFiles(std::string file1, std::string file2) { - if (myFileXML.exists()) - {myFileXML.remove();} - } - catch(std::exception e) - { - MITK_WARN << "Cannot delete file while cleanup: " << filenameXML; + FILE* f1 = fopen (file1.c_str() , "r"); + FILE* f2 = fopen (file2.c_str() , "r"); + char buf1[10000]; + char buf2[10000]; + + do { + size_t r1 = fread(buf1, 1, 10000, f1); + size_t r2 = fread(buf2, 1, 10000, f2); + + if (r1 != r2 || + memcmp(buf1, buf2, r1)) { + return false; // Files are not equal + } + } while (!feof(f1) && !feof(f2)); + + return feof(f1) && feof(f2); } - - try - { - if (myFileCSV.exists()) - {myFileCSV.remove();} - } - catch(std::exception e) - { - MITK_WARN << "Cannot delete file while cleanup: " << filenameCSV; - } -} - -static void TestStartRecordingExceptions() -{ - //Testing Start Recording for exceptions if recording has already started - mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New(); - std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest.xml"; - recorder->SetFileName(filename.c_str()); - - //Testing double call of StartRecording(). - mitk::NavigationData::Pointer naviData = mitk::NavigationData::New(); - recorder->AddNavigationData( naviData ); - recorder->StartRecording(); - recorder->StartRecording(); - recorder->StopRecording(); - MITK_TEST_OUTPUT(<<"Tested double call of StartRecording(). Application should not crash."); - - //Testing exceptions for method StartRecording() when no file is set. - mitk::NavigationDataRecorder::Pointer recorder1 = mitk::NavigationDataRecorder::New(); - std::string filename1 = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest.xml"; - recorder->SetFileName(""); - bool exceptionThrown1 = false; - mitk::NavigationData::Pointer naviData1 = mitk::NavigationData::New(); - recorder1->AddNavigationData( naviData1 ); - try - { - recorder1->StartRecording(); - } - catch(mitk::IGTException) - { - exceptionThrown1 = true; - } - MITK_TEST_CONDITION(exceptionThrown1,"Testing exception throwing when no file name or file path is set."); - - //Testing double call of StartRecording(stream) method. - mitk::NavigationDataRecorder::Pointer recorder2 = mitk::NavigationDataRecorder::New(); - std::string tmp = ""; - std::ostringstream stream; - stream.setf( std::ios::fixed, std::ios::floatfield ); - recorder2->StartRecording(&stream); - recorder2->StartRecording(&stream); - recorder2->StopRecording(); - MITK_TEST_OUTPUT(<<"Tested double call of StartRecording(stream). Application should not crash."); - - //Testing exceptions if the stream is not good - mitk::NavigationDataRecorder::Pointer recorder3 = mitk::NavigationDataRecorder::New(); - std::ofstream stream3; //making an invalid stream - stream3.open(""); - bool exceptionThrown3 = false; - try - { - recorder3->StartRecording(&stream3); - } - catch(mitk::IGTException) - { - exceptionThrown3 = true; - } - MITK_TEST_CONDITION(exceptionThrown3,"Testing exception thrown when the stream in not good."); -} +}; /**Documentation * test for the class "NavigationDataRecorder". */ int mitkNavigationDataRecorderTest(int /* argc */, char* /*argv*/[]) { MITK_TEST_BEGIN("NavigationDataRecorder"); - TestInstantiation(); - TestRecordingWithGivenStream(); - TestRecordingOnHarddiscXML(); - TestRecordingOnHarddiscXMLZIP(); - TestRecordingOnHarddiscCSV(); - TestRecordingInvalidData(); - TestStartRecordingExceptions(); - //Test fails under linux, perhaps reading permission problems, deactivated it temporary - //TestLoadingRecordedXMLFile(); - - CleanUp(); - + mitkNavigationDataRecorderTestClass::PlayAndRecord(); + // always end with this! MITK_TEST_END(); -} +} \ No newline at end of file diff --git a/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp b/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp index e234d8f409..7ccbd9823f 100644 --- a/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp @@ -1,225 +1,267 @@ /*=================================================================== 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" -const char* XML_STRING = - "" - "" - "" - "" - "" - "" - "" - ""; - -const char* XML_INVALID_TESTSTRING = - "< ToolCount=\"2\">" - "" - "" - "" - "" - "" - "" - ""; - 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() - player->SetXMLString(XML_STRING); - 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"); + 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(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(3); + player->GoToSnapshot(2); mitk::NavigationData::Pointer nd1 = player->GetOutput(1); MITK_TEST_CONDITION(tTool1Snapshot2 == nd1->GetPosition().GetVnlVector(), "Testing GoToSnapshot() [1]"); - player->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]"); - player->GoToSnapshot(3); + 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::PositionType nd1 = player->GetOutput(0)->GetPosition(); + player->SetNavigationDataSet(reader->Read(file)); + player->Update(); + mitk::NavigationData::PositionType nd2 = player->GetOutput(0)->GetPosition(); + + MITK_TEST_CONDITION(nd1 == nd2, "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 { - myTestPlayer->SetFileName(""); + 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 { - myTestPlayer1->SetFileName(file); + 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(); - myTestPlayer2->SetXMLString(XML_STRING); + 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 { unsigned int invalidSnapshot = 1000; myTestPlayer2->GoToSnapshot(invalidSnapshot); } 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 { - myTestPlayer3->SetXMLString(XML_INVALID_TESTSTRING); + 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::IGTException) + 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(); TestSetXMLStringException(); TestGoToSnapshotException(); + TestDoubleUpdate(); + MITK_TEST_END(); } diff --git a/Modules/IGT/Testing/mitkNavigationDataSetReaderWriterTest.cpp b/Modules/IGT/Testing/mitkNavigationDataSetReaderWriterTest.cpp new file mode 100644 index 0000000000..9d46ae4d33 --- /dev/null +++ b/Modules/IGT/Testing/mitkNavigationDataSetReaderWriterTest.cpp @@ -0,0 +1,90 @@ +/*=================================================================== + +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 +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +//for exceptions +#include "mitkIGTException.h" +#include "mitkIGTIOException.h" + +class mitkNavigationDataSetReaderWriterTestClass +{ +public: + + static void TestReadWrite() + { + // Aim is to read an xml into a pointset, write that xml again, and compare the output + + mitk::NavigationDataSetWriterXML writer; + mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); + + std::string path = "F://Build//MITK-Data//IGT-Data//NavigationDataSet.xml"; + mitk::NavigationDataSet::Pointer set = reader->Read(path); + writer.Write("F://Build//MITK-Data//IGT-Data//NavigationDataSet2.xml", set); + + MITK_TEST_CONDITION_REQUIRED(mitkNavigationDataSetReaderWriterTestClass::CompareFiles("F://Build//MITK-Data//IGT-Data//NavigationDataSet.xml", + "F://Build//MITK-Data//IGT-Data//NavigationDataSet2.xml"), "Testing if read/write cycle creates identical files"); + } + + static bool CompareFiles(std::string file1, std::string file2) + { + FILE* f1 = fopen (file1.c_str() , "r"); + FILE* f2 = fopen (file2.c_str() , "r"); + char buf1[10000]; + char buf2[10000]; + + do { + size_t r1 = fread(buf1, 1, 10000, f1); + size_t r2 = fread(buf2, 1, 10000, f2); + + if (r1 != r2 || + memcmp(buf1, buf2, r1)) { + return false; // Files are not equal + } + } while (!feof(f1) && !feof(f2)); + + return feof(f1) && feof(f2); + } +}; + +/**Documentation +* test for the class "NavigationDataRecorder". +*/ +int mitkNavigationDataSetReaderWriterTest(int /* argc */, char* /*argv*/[]) +{ + MITK_TEST_BEGIN("NavigationDataRecorder"); + + MITK_TEST_CONDITION_REQUIRED(mitkNavigationDataSetReaderWriterTestClass::CompareFiles("F://Build//MITK-Data//IGT-Data//NavigationDataSet.xml", + "F://Build//MITK-Data//IGT-Data//NavigationDataSet.xml"), "Asserting that compare function for files works correctly - Positive Test"); + MITK_TEST_CONDITION_REQUIRED(! mitkNavigationDataSetReaderWriterTestClass::CompareFiles("F://Build//MITK-Data//IGT-Data//NavigationDataSet.xml", + "F://Build//MITK-Data//IGT-Data//SROMFile.rom"), "Asserting that compare function for files works correctly - Negative Test"); + mitkNavigationDataSetReaderWriterTestClass::TestReadWrite(); + + MITK_TEST_END(); +}; diff --git a/Modules/IGT/Testing/mitkNavigationDataSetTest.cpp b/Modules/IGT/Testing/mitkNavigationDataSetTest.cpp new file mode 100644 index 0000000000..0652e551e1 --- /dev/null +++ b/Modules/IGT/Testing/mitkNavigationDataSetTest.cpp @@ -0,0 +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. + +===================================================================*/ + +#include "mitkTestingMacros.h" +#include "mitkNavigationData.h" +#include "mitkNavigationDataSet.h" + +static void TestEmptySet() +{ + mitk::NavigationDataSet::Pointer navigationDataSet = mitk::NavigationDataSet::New(1); + + MITK_TEST_CONDITION_REQUIRED(! navigationDataSet->GetNavigationDataForIndex(0,0) , "Trying to get non-existant NavigationData by index should return false."); + //MITK_TEST_CONDITION_REQUIRED(! navigationDataSet->GetNavigationDataBeforeTimestamp(0, 100), "Trying to get non-existant NavigationData by timestamp should return false.") +} + +static void TestSetAndGet() +{ + mitk::NavigationDataSet::Pointer navigationDataSet = mitk::NavigationDataSet::New(2); + + mitk::NavigationData::Pointer nd11 = mitk::NavigationData::New(); + mitk::NavigationData::Pointer nd12 = mitk::NavigationData::New(); + mitk::NavigationData::Pointer nd13 = mitk::NavigationData::New(); + nd12->SetIGTTimeStamp(1); + nd12->SetIGTTimeStamp(2); + + mitk::NavigationData::Pointer nd21 = mitk::NavigationData::New(); + mitk::NavigationData::Pointer nd22 = mitk::NavigationData::New(); + mitk::NavigationData::Pointer nd23 = mitk::NavigationData::New(); + nd22->SetIGTTimeStamp(1); + + // First set, Timestamp = 0 + std::vector step1; + step1.push_back(nd11); + step1.push_back(nd21); + + // Second set, Timestamp = 1 + std::vector step2; + step2.push_back(nd12); + step2.push_back(nd22); + + //Third set, Timestamp invalid () + std::vector step3; + step3.push_back(nd13); + step3.push_back(nd23); + + MITK_TEST_CONDITION_REQUIRED(navigationDataSet->AddNavigationDatas(step1), + "Adding a valid first set, should be successful."); + MITK_TEST_CONDITION_REQUIRED(navigationDataSet->AddNavigationDatas(step2), + "Adding a valid second set, should be successful."); + MITK_TEST_CONDITION_REQUIRED(!(navigationDataSet->AddNavigationDatas(step3)), + "Adding an invalid third set, should be unsusuccessful."); + + MITK_TEST_CONDITION_REQUIRED(navigationDataSet->GetNavigationDataForIndex(0, 0) == nd11, + "First NavigationData object for tool 0 should be the same as added previously."); + MITK_TEST_CONDITION_REQUIRED(navigationDataSet->GetNavigationDataForIndex(0, 1) == nd12, + "Second NavigationData object for tool 0 should be the same as added previously."); + MITK_TEST_CONDITION_REQUIRED(navigationDataSet->GetNavigationDataForIndex(1, 0) == nd21, + "First NavigationData object for tool 0 should be the same as added previously."); + MITK_TEST_CONDITION_REQUIRED(navigationDataSet->GetNavigationDataForIndex(1, 1) == nd22, + "Second NavigationData object for tool 0 should be the same as added previously."); + + std::vector result = navigationDataSet->GetTimeStep(1); + MITK_TEST_CONDITION_REQUIRED(nd12 == result[0],"Comparing returned datas from GetTimeStep()."); + MITK_TEST_CONDITION_REQUIRED(nd22 == result[1],"Comparing returned datas from GetTimeStep()."); + + result = navigationDataSet->GetDataStreamForTool(1); + MITK_TEST_CONDITION_REQUIRED(nd21 == result[0],"Comparing returned datas from GetStreamForTool()."); + MITK_TEST_CONDITION_REQUIRED(nd22 == result[1],"Comparing returned datas from GetStreamForTool()."); +} + +/** + * + */ +int mitkNavigationDataSetTest(int /* argc */, char* /*argv*/[]) +{ + MITK_TEST_BEGIN("NavigationDataSet"); + + TestEmptySet(); + TestSetAndGet(); + + MITK_TEST_END(); +} diff --git a/Modules/IGT/Testing/mitkNavigationDataToPointSetFilterTest.cpp b/Modules/IGT/Testing/mitkNavigationDataToPointSetFilterTest.cpp index 396d9a8b35..bdb4c04914 100644 --- a/Modules/IGT/Testing/mitkNavigationDataToPointSetFilterTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationDataToPointSetFilterTest.cpp @@ -1,240 +1,240 @@ /*=================================================================== 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 "mitkNavigationDataToPointSetFilter.h" -#include "mitkNavigationDataPlayer.h" +#include "mitkNavigationDataSequentialPlayer.h" +#include "mitkNavigationDataReaderXML.h" #include #include #include /** * Simple example for a test for the (non-existent) class "NavigationDataToPointSetFilter". * * argc and argv are the command line parameters which were passed to * the ADD_TEST command in the CMakeLists.txt file. For the automatic * tests, argv is either empty for the simple tests or contains the filename * of a test image for the image tests (see CMakeLists.txt). */ mitk::NavigationDataToPointSetFilter::Pointer m_NavigationDataToPointSetFilter; static void Setup() { m_NavigationDataToPointSetFilter = mitk::NavigationDataToPointSetFilter::New(); } static void TestMode3D() { Setup(); m_NavigationDataToPointSetFilter->SetOperationMode(mitk::NavigationDataToPointSetFilter::Mode3D); //Build up test data mitk::NavigationData::Pointer nd0 = mitk::NavigationData::New(); mitk::NavigationData::Pointer nd1 = mitk::NavigationData::New(); mitk::NavigationData::Pointer nd2 = mitk::NavigationData::New(); mitk::NavigationData::Pointer nd3 = mitk::NavigationData::New(); mitk::NavigationData::PositionType point0; point0[0] = 1.0; point0[1] = 2.0; point0[2] = 3.0; nd0->SetPosition(point0); nd0->SetDataValid(true); mitk::NavigationData::PositionType point1; point1[0] = 4.0; point1[1] = 5.0; point1[2] = 6.0; nd1->SetPosition(point1); nd1->SetDataValid(true); mitk::NavigationData::PositionType point2; point2[0] = 7.0; point2[1] = 8.0; point2[2] = 9.0; nd2->SetPosition(point2); nd2->SetDataValid(true); mitk::NavigationData::PositionType point3; point3[0] = 10.0; point3[1] = 11.0; point3[2] = 12.0; nd3->SetPosition(point3); nd3->SetDataValid(true); m_NavigationDataToPointSetFilter->SetInput(0, nd0); m_NavigationDataToPointSetFilter->SetInput(1, nd1); m_NavigationDataToPointSetFilter->SetInput(2, nd2); m_NavigationDataToPointSetFilter->SetInput(3, nd3); //Process mitk::PointSet::Pointer pointSet0 = m_NavigationDataToPointSetFilter->GetOutput(); mitk::PointSet::Pointer pointSet1 = m_NavigationDataToPointSetFilter->GetOutput(1); mitk::PointSet::Pointer pointSet2 = m_NavigationDataToPointSetFilter->GetOutput(2); mitk::PointSet::Pointer pointSet3 = m_NavigationDataToPointSetFilter->GetOutput(3); pointSet0->Update(); MITK_TEST_OUTPUT(<< "Testing the conversion of navigation data object to PointSets in Mode 3D:"); MITK_TEST_CONDITION(mitk::Equal(pointSet0->GetPoint(0), point0), "Pointset 0 correct?"); MITK_TEST_CONDITION(mitk::Equal(pointSet1->GetPoint(0), point1), "Pointset 1 correct?"); MITK_TEST_CONDITION(mitk::Equal(pointSet2->GetPoint(0), point2), "Pointset 2 correct?"); MITK_TEST_CONDITION(mitk::Equal(pointSet3->GetPoint(0), point3), "Pointset 3 correct?"); } static void TestMode4D() { Setup(); m_NavigationDataToPointSetFilter->SetOperationMode(mitk::NavigationDataToPointSetFilter::Mode4D); m_NavigationDataToPointSetFilter->SetRingBufferSize(2); //Build up test data mitk::NavigationData::Pointer nd = mitk::NavigationData::New(); mitk::NavigationData::Pointer nd2 = mitk::NavigationData::New(); mitk::NavigationData::Pointer nd3 = mitk::NavigationData::New(); mitk::NavigationData::Pointer nd4 = mitk::NavigationData::New(); mitk::NavigationData::PositionType point; point[0] = 1.0; point[1] = 2.0; point[2] = 3.0; nd->SetPosition(point); point[0] = 4.0; point[1] = 5.0; point[2] = 6.0; nd2->SetPosition(point); point[0] = 7.0; point[1] = 8.0; point[2] = 9.0; nd3->SetPosition(point); point[0] = 10.0; point[1] = 11.0; point[2] = 12.0; nd4->SetPosition(point); m_NavigationDataToPointSetFilter->SetInput(0, nd); m_NavigationDataToPointSetFilter->SetInput(1, nd2); mitk::PointSet::Pointer pointSet = m_NavigationDataToPointSetFilter->GetOutput(); pointSet->Update(); MITK_TEST_CONDITION( pointSet->GetPoint(0,0)[0] == 1.0 && pointSet->GetPoint(0,0)[1] == 2.0 && pointSet->GetPoint(0,0)[2] == 3.0 && pointSet->GetPoint(1,0)[0] == 4.0 && pointSet->GetPoint(1,0)[1] == 5.0 && pointSet->GetPoint(1,0)[2] == 6.0 , "Testing the conversion of navigation data object to one point set in Mode 4D in first timestep" ); m_NavigationDataToPointSetFilter->SetInput(0, nd3); m_NavigationDataToPointSetFilter->SetInput(1, nd4); m_NavigationDataToPointSetFilter->Update(); pointSet = m_NavigationDataToPointSetFilter->GetOutput(); MITK_TEST_CONDITION( pointSet->GetPoint(0,0)[0] == 1.0 && pointSet->GetPoint(0,0)[1] == 2.0 && pointSet->GetPoint(0,0)[2] == 3.0 && pointSet->GetPoint(1,0)[0] == 4.0 && pointSet->GetPoint(1,0)[1] == 5.0 && pointSet->GetPoint(1,0)[2] == 6.0 && pointSet->GetPoint(0,1)[0] == 7.0 && pointSet->GetPoint(0,1)[1] == 8.0 && pointSet->GetPoint(0,1)[2] == 9.0 && pointSet->GetPoint(1,1)[0] == 10.0 && pointSet->GetPoint(1,1)[1] == 11.0 && pointSet->GetPoint(1,1)[2] == 12.0 , "Testing the conversion of navigation data object to one point set in Mode 4D in second timestep" ); m_NavigationDataToPointSetFilter->SetInput(0, nd3); m_NavigationDataToPointSetFilter->SetInput(1, nd4); pointSet = m_NavigationDataToPointSetFilter->GetOutput(); pointSet->Update(); MITK_TEST_CONDITION( pointSet->GetPoint(0,0)[0] == 7.0 && pointSet->GetPoint(0,0)[1] == 8.0 && pointSet->GetPoint(0,0)[2] == 9.0 && pointSet->GetPoint(1,0)[0] == 10.0 && pointSet->GetPoint(1,0)[1] == 11.0 && pointSet->GetPoint(1,0)[2] == 12.0 && pointSet->GetPoint(0,1)[0] == 7.0 && pointSet->GetPoint(0,1)[1] == 8.0 && pointSet->GetPoint(0,1)[2] == 9.0 && pointSet->GetPoint(1,1)[0] == 10.0 && pointSet->GetPoint(1,1)[1] == 11.0 && pointSet->GetPoint(1,1)[2] == 12.0 , "Testing the correct ring buffer behavior" ); } static void TestMode3DMean() { Setup(); m_NavigationDataToPointSetFilter->SetOperationMode(mitk::NavigationDataToPointSetFilter::Mode3DMean); int numberForMean = 5; m_NavigationDataToPointSetFilter->SetNumberForMean(numberForMean); MITK_TEST_CONDITION(mitk::Equal(m_NavigationDataToPointSetFilter->GetNumberForMean(), numberForMean), "Testing get/set for numberForMean"); - mitk::NavigationDataPlayer::Pointer player = mitk::NavigationDataPlayer::New(); + mitk::NavigationDataSequentialPlayer::Pointer player = mitk::NavigationDataSequentialPlayer::New(); std::string file(MITK_IGT_DATA_DIR); file.append("/NavigationDataTestData_2Tools.xml"); - player->SetFileName( file ); - player->StartPlaying(); + mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); + + player->SetNavigationDataSet( reader->Read(file) ); for (unsigned int i = 0; i< player->GetNumberOfOutputs(); i++) { m_NavigationDataToPointSetFilter->SetInput(i, player->GetOutput(i)); } mitk::PointSet::Pointer pointSet0 = m_NavigationDataToPointSetFilter->GetOutput(); mitk::PointSet::Pointer pointSet1 = m_NavigationDataToPointSetFilter->GetOutput(1); m_NavigationDataToPointSetFilter->Update(); - player->StopPlaying(); - MITK_TEST_CONDITION(pointSet0->GetPoint(0)[0]==3.0 && pointSet0->GetPoint(0)[1]==2.0 && pointSet0->GetPoint(0)[2]==5.0, "Testing the average of first input"); MITK_TEST_CONDITION(pointSet1->GetPoint(0)[0]==30.0 && pointSet1->GetPoint(0)[1]==20.0 && pointSet1->GetPoint(0)[2]==50.0, "Testing the average of second input"); } static void NavigationDataToPointSetFilterContructor_DefaultCall_IsNotEmpty() { Setup(); MITK_TEST_CONDITION_REQUIRED(m_NavigationDataToPointSetFilter.IsNotNull(),"Testing instantiation"); //I think this test is meaningless, because it will never ever fail. I keep it for know just to be save. } static void NavigationDataToPointSetFilterSetInput_SimplePoint_EqualsGroundTruth() { Setup(); mitk::NavigationData::Pointer nd_in = mitk::NavigationData::New(); const mitk::NavigationData* nd_out = mitk::NavigationData::New(); mitk::NavigationData::PositionType point; point[0] = 1.0; point[1] = 2.0; point[2] = 3.0; nd_in->SetPosition(point); m_NavigationDataToPointSetFilter->SetInput(nd_in); nd_out = m_NavigationDataToPointSetFilter->GetInput(); MITK_TEST_CONDITION( nd_out->GetPosition() == nd_in->GetPosition(), "Testing get/set input" ); } int mitkNavigationDataToPointSetFilterTest(int /* argc */, char* /*argv*/[]) { MITK_TEST_BEGIN("NavigationDataToPointSetFilter"); NavigationDataToPointSetFilterContructor_DefaultCall_IsNotEmpty(); NavigationDataToPointSetFilterSetInput_SimplePoint_EqualsGroundTruth(); TestMode3D(); TestMode4D(); TestMode3DMean(); MITK_TEST_END(); } diff --git a/Modules/IGT/Tutorial/mitkIGTTutorialStep1.cpp b/Modules/IGT/Tutorial/mitkIGTTutorialStep1.cpp index 6733e661d4..e30eabe438 100644 --- a/Modules/IGT/Tutorial/mitkIGTTutorialStep1.cpp +++ b/Modules/IGT/Tutorial/mitkIGTTutorialStep1.cpp @@ -1,198 +1,198 @@ /*=================================================================== 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 #include #include "mitkNavigationDataDisplacementFilter.h" #include #include #include //##Documentation //## \brief A small console tutorial about MITK-IGT int main(int /*argc*/, char* /*argv*/[]) { //************************************************************************* // What we will do... //************************************************************************* //In this tutorial we build up a small navigation pipeline with a virtual tracking device //which produce random positions and orientation so no additional hardware is required. //The source of the pipeline is a TrackingDeviceSource object. This we connect to a simple //filter which just displaces the positions with an offset. After that we use a recorder //to store this new positions and other information to disc in a XML file. After that we use //another source (NavigationDataPlayer) to replay the recorded data. //************************************************************************* // Part I: Basic initialization of the source and tracking device //************************************************************************* //First of all create a tracking device object and two tools for this "device". //Here we take the VirtualTrackingDevice. This is not a real tracking device it just delivers random //positions and orientations. You can use other/real tracking devices if you replace the following //code with different tracking devices, e.g. mitk::NDITrackingDevice. The tools represent the //sensors of the tracking device. The TrackingDevice fills the tools with data. std::cout << "Generating TrackingDevice ..." << std::endl; mitk::VirtualTrackingDevice::Pointer tracker = mitk::VirtualTrackingDevice::New(); tracker->AddTool("tool1"); tracker->AddTool("tool2"); //The tracking device object is used for the physical connection to the device. To use the //data inside of our tracking pipeline we need a source. This source encapsulate the tracking device //and provides objects of the type mitk::NavigationData as output. The NavigationData objects stores //position, orientation, if the data is valid or not and special error informations in a covariance //matrix. // //Typically the start of our pipeline is a TrackingDeviceSource. To work correct we have to set a //TrackingDevice object. Attention you have to set the tools before you set the whole TrackingDevice //object to the TrackingDeviceSource because the source need to know how many outputs should be //generated. std::cout << "Generating Source ..." << std::endl; mitk::TrackingDeviceSource::Pointer source = mitk::TrackingDeviceSource::New(); source->SetTrackingDevice(tracker); //here we set the device for the pipeline source source->Connect(); //here we connect to the tracking system //Note we do not call this on the TrackingDevice object source->StartTracking(); //start the tracking //Now the source generates outputs. //************************************************************************* // Part II: Create a NavigationDataToNavigationDataFilter //************************************************************************* //The next thing we do is using a NavigationDataToNavigationDataFilter. One of these filter is the //very simple NavigationDataDisplacementFilter. This filter just changes the positions of the input //NavigationData objects with an offset for each direction (X,Y,Z). The input of this filter is the //source and the output of this filter is the "displaced" input. std::cout << "Generating DisplacementFilter ..." << std::endl; mitk::NavigationDataDisplacementFilter::Pointer displacer = mitk::NavigationDataDisplacementFilter::New(); mitk::Vector3D offset; mitk::FillVector3D(offset, 10.0, 100.0, 1.0); //initialize the offset displacer->SetOffset(offset); //now set the offset in the NavigationDataDisplacementFilter object //Connect the two filters. You can use the ConnectTo method to automatically connect all outputs from one filter // to inputs from another filter. displacer->ConnectTo(source.GetPointer()); // Alternatively, you can manually connect inputs and outputs. // The code below shows what the ConnectTo Methods does internally: // //for (unsigned int i = 0; i < source->GetNumberOfOutputs(); i++) //{ // displacer->SetInput(i, source->GetOutput(i)); //here we connect to the displacement filter //} //************************************************************************* // Part III: Record the data with the NavigationDataRecorder //************************************************************************* //The next part of our pipeline is the recorder. The recorder needs a filename. Otherwise the output //is redirected to the console. The input of the recorder is the output of the displacement filter //and the output is a XML file with the name "Test Output-0.xml". std::cout << "Start Recording ..." << std::endl; //we need the stringstream for building up our filename std::stringstream filename; //the .xml extension and an counter is added automatically filename << itksys::SystemTools::GetCurrentWorkingDirectory() << "/Test Output"; std::cout << "Record to file: " << filename.str() << "-0.xml ..." << std::endl; mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New(); - recorder->SetFileName(filename.str()); + //xxxxxxxxxxxxxxxxxxrecorder->SetFileName(filename.str());//TODO!!!!!!!!!!!!! //now every output of the displacer object is connected to the recorder object for (unsigned int i = 0; i < displacer->GetNumberOfOutputs(); i++) { - recorder->AddNavigationData(displacer->GetOutput(i)); // here we connect to the recorder + //xxxxxxxxrecorder->AddNavigationData(displacer->GetOutput(i)); // here we connect to the recorder } recorder->StartRecording(); //after finishing the settings you can start the recording mechanism //now every update of the recorder stores one line into the file for //each added NavigationData for (unsigned int x = 0; x < 100; x++) //write 100 datasets { recorder->Update(); //the update causes one line in the XML file for every tool //in this case two lines itksys::SystemTools::Delay(100); //sleep a little } recorder->StopRecording(); //to get proper XML files you should stop recording //if your application crashes during recording no data //will be lost it is all stored to disc //************************************************************************* // Part IV: Play the data with the NavigationDataPlayer //************************************************************************* //The recording is finished now so now we can play the data. The NavigationDataPlayer is similar //to the TrackingDevice source. It also derives from NavigationDataSource. So you can use a player //instead of a TrackingDeviceSource. The input of this player is the filename and the output are //NavigationData object. filename << "-0.xml"; std::cout << "Start playing from file: " << filename.str() << " ..." << std::endl; mitk::NavigationDataPlayer::Pointer player = mitk::NavigationDataPlayer::New(); //this is first part of the file name the .xml extension and an counter is added automatically - player->SetFileName(filename.str()); + //xxxxxxxxxxxxxxxxxxx TODO !!!!!!!!! player->SetFileName(filename.str()); player->StartPlaying(); //this starts the player //From now on the player provides NavigationDatas in the order and //correct time as they were recorded //this connects the outputs of the player to the NavigationData objects mitk::NavigationData::Pointer nd = player->GetOutput(); mitk::NavigationData::Pointer nd2 = player->GetOutput(1); for (unsigned int x=0; x<100; x++) { if (nd.IsNotNull()) //check if the output is not null { //With this update the NavigationData object propagates through the pipeline to get a new value. //In this case we only have a source (NavigationDataPlayer). nd->Update(); std::cout << x << ": 1:" << nd->GetPosition() << std::endl; std::cout << x << ": 2:" << nd2->GetPosition() << std::endl; std::cout << x << ": 1:" << nd->GetOrientation() << std::endl; std::cout << x << ": 2:" << nd2->GetOrientation() << std::endl; itksys::SystemTools::Delay(100); //sleep a little like in the recorder part } } player->StopPlaying(); //This stops the player //With another call of StartPlaying the player will start again at the beginning of the file itksys::SystemTools::Delay(2000); std::cout << "finished" << std::endl; } diff --git a/Modules/IGT/files.cmake b/Modules/IGT/files.cmake index d9c8cb2c35..2b3112756e 100644 --- a/Modules/IGT/files.cmake +++ b/Modules/IGT/files.cmake @@ -1,83 +1,89 @@ set(CPP_FILES TestingHelper/mitkNavigationToolStorageTestHelper.cpp Algorithms/mitkNavigationDataDelayFilter.cpp Algorithms/mitkNavigationDataDisplacementFilter.cpp Algorithms/mitkNavigationDataEvaluationFilter.cpp Algorithms/mitkNavigationDataLandmarkTransformFilter.cpp Algorithms/mitkNavigationDataReferenceTransformFilter.cpp Algorithms/mitkNavigationDataSmoothingFilter.cpp Algorithms/mitkNavigationDataToMessageFilter.cpp Algorithms/mitkNavigationDataToNavigationDataFilter.cpp Algorithms/mitkNavigationDataToPointSetFilter.cpp Algorithms/mitkNavigationDataTransformFilter.cpp Common/mitkIGTTimeStamp.cpp Common/mitkSerialCommunication.cpp Common/mitkTrackingTypes.cpp DataManagement/mitkNavigationData.cpp + DataManagement/mitkNavigationDataSet.cpp DataManagement/mitkNavigationDataSource.cpp DataManagement/mitkNavigationTool.cpp DataManagement/mitkNavigationToolStorage.cpp DataManagement/mitkTrackingDeviceSourceConfigurator.cpp DataManagement/mitkTrackingDeviceSource.cpp ExceptionHandling/mitkIGTException.cpp ExceptionHandling/mitkIGTHardwareException.cpp ExceptionHandling/mitkIGTIOException.cpp IO/mitkNavigationDataPlayer.cpp IO/mitkNavigationDataPlayerBase.cpp IO/mitkNavigationDataRecorder.cpp IO/mitkNavigationDataSequentialPlayer.cpp IO/mitkNavigationToolReader.cpp IO/mitkNavigationToolStorageSerializer.cpp IO/mitkNavigationToolStorageDeserializer.cpp IO/mitkNavigationToolWriter.cpp + IO/mitkNavigationDataReaderInterface.cpp + IO/mitkNavigationDataReaderXML.cpp + IO/mitkNavigationDataReaderCSV.cpp + IO/mitkNavigationDataSetWriterXML.cpp + IO/mitkNavigationDataSetWriterCSV.cpp Rendering/mitkCameraVisualization.cpp Rendering/mitkNavigationDataObjectVisualizationFilter.cpp TrackingDevices/mitkClaronTool.cpp TrackingDevices/mitkClaronTrackingDevice.cpp TrackingDevices/mitkInternalTrackingTool.cpp TrackingDevices/mitkNDIPassiveTool.cpp TrackingDevices/mitkNDIProtocol.cpp TrackingDevices/mitkNDITrackingDevice.cpp TrackingDevices/mitkTrackingDevice.cpp TrackingDevices/mitkTrackingTool.cpp TrackingDevices/mitkTrackingVolumeGenerator.cpp TrackingDevices/mitkVirtualTrackingDevice.cpp TrackingDevices/mitkVirtualTrackingTool.cpp TrackingDevices/mitkOptitrackErrorMessages.cpp TrackingDevices/mitkOptitrackTrackingDevice.cpp TrackingDevices/mitkOptitrackTrackingTool.cpp ) set(RESOURCE_FILES ClaronMicron.stl IntuitiveDaVinci.stl NDIAurora.stl NDIAurora_Dome.stl NDIAuroraCompactFG_Dome.stl NDIAuroraPlanarFG_Dome.stl NDIAuroraTabletopFG_Dome.stl NDIAuroraTabletopFG_Prototype_Dome.stl NDIPolarisOldModel.stl NDIPolarisSpectra.stl NDIPolarisSpectraExtendedPyramid.stl NDIPolarisVicra.stl ) if(MITK_USE_MICRON_TRACKER) set(CPP_FILES ${CPP_FILES} TrackingDevices/mitkClaronInterface.cpp) else() set(CPP_FILES ${CPP_FILES} TrackingDevices/mitkClaronInterfaceStub.cpp) endif(MITK_USE_MICRON_TRACKER) if(MITK_USE_MICROBIRD_TRACKER) set(CPP_FILES ${CPP_FILES} TrackingDevices/mitkMicroBirdTrackingDevice.cpp) endif(MITK_USE_MICROBIRD_TRACKER) diff --git a/Modules/IGTUI/Qmitk/QmitkIGTLoggerWidget.cpp b/Modules/IGTUI/Qmitk/QmitkIGTLoggerWidget.cpp index f89c481069..59fcdfb14b 100644 --- a/Modules/IGTUI/Qmitk/QmitkIGTLoggerWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkIGTLoggerWidget.cpp @@ -1,297 +1,310 @@ /*=================================================================== 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 "QmitkIGTLoggerWidget.h" //mitk headers #include "mitkTrackingTypes.h" #include #include #include #include #include #include #include #include +#include //itk headers #include //qt headers #include #include #include QmitkIGTLoggerWidget::QmitkIGTLoggerWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f), m_Recorder(NULL), m_RecordingActivated(false) { m_Controls = NULL; CreateQtPartControl(this); CreateConnections(); //set output file this->SetOutputFileName(); //update milliseconds and samples this->SetDefaultRecordingSettings(); } QmitkIGTLoggerWidget::~QmitkIGTLoggerWidget() { m_RecordingTimer->stop(); m_Recorder = NULL; m_RecordingTimer = NULL; } void QmitkIGTLoggerWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkIGTLoggerWidgetControls; m_Controls->setupUi(parent); m_RecordingTimer = new QTimer(this); } } void QmitkIGTLoggerWidget::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_pbLoadDir), SIGNAL(clicked()), this, SLOT(OnChangePressed()) ); connect( (QObject*)(m_Controls->m_pbStartRecording), SIGNAL(clicked(bool)), this, SLOT(OnStartRecording(bool)) ); connect( m_RecordingTimer, SIGNAL(timeout()), this, SLOT(OnRecording()) ); connect( (QObject*)(m_Controls->m_leRecordingValue), SIGNAL(editingFinished()), this, SLOT(UpdateRecordingTime()) ); connect( (QObject*)(m_Controls->m_cbRecordingType), SIGNAL(activated(int)), this, SLOT(UpdateRecordingTime()) ); connect( (QObject*)(m_Controls->m_leOutputFile), SIGNAL(editingFinished()), this, SLOT(UpdateOutputFileName()) ); } } void QmitkIGTLoggerWidget::SetDataStorage(mitk::DataStorage* dataStorage) { m_DataStorage = dataStorage; } void QmitkIGTLoggerWidget::OnStartRecording(bool recording) { if (m_Recorder.IsNull()) { QMessageBox::warning(NULL, "Warning", QString("Please start tracking before recording!")); return; } if (m_CmpFilename.isEmpty()) { QMessageBox::warning(NULL, "Warning", QString("Please specify filename!")); return; } if(recording) { if (!m_RecordingActivated) { - m_Recorder->SetFileName(m_CmpFilename.toStdString()); + //m_Recorder->SetFileName(m_CmpFilename.toStdString()); try { /*start the recording mechanism */ m_Recorder->StartRecording(); m_RecordingTimer->start(50); //now every update of the recorder stores one line into the file for each added NavigationData mitk::StatusBar::GetInstance()->DisplayText("Recording tracking data now"); // Display recording message for 75ms in status bar emit SignalRecordingStarted(); } catch (std::exception& e) { QMessageBox::warning(NULL, "IGT-Tracking Logger: Error", QString("Error while recording tracking data: %1").arg(e.what())); mitk::StatusBar::GetInstance()->DisplayText(""); // Display recording message for 75ms in status bar } m_Controls->m_pbStartRecording->setText("Stop recording"); m_Controls->m_leRecordingValue->setEnabled(false); m_Controls->m_cbRecordingType->setEnabled(false); m_RecordingActivated = true; if(m_Controls->m_cbRecordingType->currentIndex()==0) { bool success = false; QString str_ms = m_Controls->m_leRecordingValue->text(); int int_ms = str_ms.toInt(&success); if (success) QTimer::singleShot(int_ms, this, SLOT(StopRecording())); } } else { this->StopRecording(); } } else { this->StopRecording(); m_Controls->m_pbStartRecording->setChecked(false); } } void QmitkIGTLoggerWidget::StopRecording() { m_RecordingTimer->stop(); m_Recorder->StopRecording(); mitk::StatusBar::GetInstance()->DisplayText("Recording STOPPED", 2000); // Display message for 2s in status bar m_Controls->m_pbStartRecording->setText("Start recording"); m_Controls->m_pbStartRecording->setChecked(false); m_Controls->m_leRecordingValue->setEnabled(true); m_Controls->m_cbRecordingType->setEnabled(true); m_RecordingActivated = false; + try + { + // write NavigationDataSet on StopRecording + mitk::NavigationDataSetWriterXML().Write(m_CmpFilename.toStdString(), m_Recorder->GetNavigationDataSet()); + } + catch(const std::exception &e) + { + // TODO: catch must be adapted when new file writer are merged to master + QMessageBox::warning(NULL, "IGT-Tracking Logger: Error", QString("Error while writing tracking data: %1").arg(e.what())); + MITK_WARN << "File could not be written."; + } + emit SignalRecordingStopped(); } void QmitkIGTLoggerWidget::OnRecording() { static unsigned int sampleCounter = 0; unsigned int int_samples = m_Samples.toInt(); if(sampleCounter >= int_samples) { this->StopRecording(); sampleCounter=0; return; } m_Recorder->Update(); if (m_Controls->m_cbRecordingType->currentIndex()==1) sampleCounter++; } void QmitkIGTLoggerWidget::OnChangePressed() { QString oldName = m_CmpFilename; m_CmpFilename.clear(); m_CmpFilename = QFileDialog::getSaveFileName( QApplication::activeWindow() , "Save tracking data", "IGT_Tracking_Data.xml", "XML files (*.xml)" ); if (m_CmpFilename.isEmpty())//if something went wrong or user pressed cancel in the save dialog { m_CmpFilename=oldName; } m_Controls->m_leOutputFile->setText(m_CmpFilename); } void QmitkIGTLoggerWidget::UpdateOutputFileName() { QString oldName = m_CmpFilename; m_CmpFilename.clear(); m_CmpFilename = m_Controls->m_leOutputFile->text(); if (m_CmpFilename.isEmpty()) { QMessageBox::warning(NULL, "Warning", QString("Please enter valid path! Using previous path again.")); m_CmpFilename=oldName; m_Controls->m_leOutputFile->setText(m_CmpFilename); } } void QmitkIGTLoggerWidget::SetRecorder( mitk::NavigationDataRecorder::Pointer recorder ) { m_Recorder = recorder; } void QmitkIGTLoggerWidget::UpdateRecordingTime() { // milliseconds selected in the combobox if (m_Controls->m_cbRecordingType->currentIndex()==0) { m_MilliSeconds = m_Controls->m_leRecordingValue->text(); if(m_MilliSeconds.compare("infinite")==0) { this->SetDefaultRecordingSettings(); } bool success = false; m_MilliSeconds.toInt(&success); if (!success) { QMessageBox::warning(NULL, "Warning", QString("Please enter a number!")); this->SetDefaultRecordingSettings(); return; } } else if(m_Controls->m_cbRecordingType->currentIndex()==1) // #samples selected in the combobox { m_Samples = m_Controls->m_leRecordingValue->text(); if(m_Samples.compare("infinite")==0) { this->SetDefaultRecordingSettings(); } bool success = false; m_Samples.toInt(&success); if (!success) { QMessageBox::warning(NULL, "Warning", QString("Please enter a number!")); this->SetDefaultRecordingSettings(); return; } } else if (m_Controls->m_cbRecordingType->currentIndex()==2)// infinite selected in the combobox { // U+221E unicode symbole for infinite QString infinite("infinite"); m_Controls->m_leRecordingValue->setText(infinite); } // m_Controls->m_leSamples->setText(QString::number(samples)); } void QmitkIGTLoggerWidget::SetDefaultRecordingSettings() { m_Controls->m_leRecordingValue->setText("2000"); m_Controls->m_cbRecordingType->setCurrentIndex(0); m_Samples="100"; m_MilliSeconds="2000"; } void QmitkIGTLoggerWidget::SetOutputFileName() { std::string tmpDir = itksys::SystemTools::GetCurrentWorkingDirectory(); QString dir = QString(tmpDir.c_str()); QString filename = "IGT_Tracking_Data.xml"; m_CmpFilename.append(dir); if(dir.isEmpty()) { QMessageBox::warning(NULL, "Warning", QString("Could not load current working directory")); return; } if(dir.endsWith("/")||dir.endsWith("\\")) { m_CmpFilename.append(filename); } else { m_CmpFilename.append("/"); m_CmpFilename.append(filename); } m_Controls->m_leOutputFile->setText(m_CmpFilename); } diff --git a/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.cpp b/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.cpp index fcb9fe20a6..63361eacd4 100644 --- a/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.cpp @@ -1,574 +1,576 @@ /*=================================================================== 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 "QmitkIGTPlayerWidget.h" //mitk headers #include "mitkTrackingTypes.h" #include #include #include #include #include #include #include #include - +#include "mitkNavigationDataReaderXML.h" //qt headers #include #include #include - QmitkIGTPlayerWidget::QmitkIGTPlayerWidget(QWidget* parent, Qt::WindowFlags f) -: QWidget(parent, f) -,m_RealTimePlayer(NULL) -,m_SequentialPlayer(NULL) -,m_StartTime(-1.0) -,m_CurrentSequentialPointNumber(0) + : QWidget(parent, f), + m_RealTimePlayer(mitk::NavigationDataPlayer::New()), + m_SequentialPlayer(mitk::NavigationDataSequentialPlayer::New()), + m_StartTime(-1.0), + m_CurrentSequentialPointNumber(0), + m_Controls(new Ui::QmitkIGTPlayerWidgetControls) { - m_Controls = NULL; - CreateQtPartControl(this); + m_Controls->setupUi(this); + m_PlayingTimer = new QTimer(this); // initialize update timer + CreateConnections(); m_Controls->samplePositionHorizontalSlider->setVisible(false); this->ResetLCDNumbers(); // reset lcd numbers at start } - QmitkIGTPlayerWidget::~QmitkIGTPlayerWidget() { m_PlayingTimer->stop(); - m_RealTimePlayer = NULL; - m_PlayingTimer = NULL; -} - -void QmitkIGTPlayerWidget::CreateQtPartControl(QWidget *parent) -{ - if (!m_Controls) - { - // create GUI widgets - m_Controls = new Ui::QmitkIGTPlayerWidgetControls; - m_Controls->setupUi(parent); - - m_PlayingTimer = new QTimer(this); // initialize update timer - } + delete m_Controls; } void QmitkIGTPlayerWidget::CreateConnections() { - if ( m_Controls ) - { - connect( (QObject*)(m_Controls->selectPushButton), SIGNAL(clicked()), this, SLOT(OnSelectPressed()) ); // open file dialog - connect( (QObject*)(m_Controls->playPushButton), SIGNAL(clicked(bool)), this, SLOT(OnPlayButtonClicked(bool)) ); // play button - connect( (QObject*)(m_PlayingTimer), SIGNAL(timeout()), this, SLOT(OnPlaying()) ); // update timer - connect( (QObject*) (m_Controls->beginPushButton), SIGNAL(clicked()), this, SLOT(OnGoToBegin()) ); // reset player and go to begin - connect( (QObject*) (m_Controls->stopPushButton), SIGNAL(clicked()), this, SLOT(OnGoToEnd()) ); // reset player - // pass this widgets protected combobox signal to public signal - connect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) ); - // pass this widgets protected checkbox signal to public signal - connect( m_Controls->splineModeCheckBox, SIGNAL(toggled(bool)), this, SIGNAL(SignalSplineModeToggled(bool)) ); - connect( m_Controls->sequencialModeCheckBox, SIGNAL(toggled(bool)), this, SLOT(OnSequencialModeToggled(bool)) ); - - connect( m_Controls->samplePositionHorizontalSlider, SIGNAL(sliderPressed()), this, SLOT(OnSliderPressed()) ); - connect( m_Controls->samplePositionHorizontalSlider, SIGNAL(sliderReleased()), this, SLOT(OnSliderReleased()) ); + connect( (QObject*)(m_Controls->playPushButton), SIGNAL(clicked(bool)), this, SLOT(OnPlayButtonClicked(bool)) ); // play button + connect( (QObject*)(m_PlayingTimer), SIGNAL(timeout()), this, SLOT(OnPlaying()) ); // update timer + connect( (QObject*) (m_Controls->beginPushButton), SIGNAL(clicked()), this, SLOT(OnGoToBegin()) ); // reset player and go to begin + connect( (QObject*) (m_Controls->stopPushButton), SIGNAL(clicked()), this, SLOT(OnGoToEnd()) ); // reset player + // pass this widgets protected combobox signal to public signal + connect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) ); + // pass this widgets protected checkbox signal to public signal + connect( m_Controls->splineModeCheckBox, SIGNAL(toggled(bool)), this, SIGNAL(SignalSplineModeToggled(bool)) ); + //connect( m_Controls->sequencialModeCheckBox, SIGNAL(toggled(bool)), this, SLOT(OnSequencialModeToggled(bool)) ); - } -} + connect( m_Controls->samplePositionHorizontalSlider, SIGNAL(sliderPressed()), this, SLOT(OnSliderPressed()) ); + connect( m_Controls->samplePositionHorizontalSlider, SIGNAL(sliderReleased()), this, SLOT(OnSliderReleased()) ); + connect( m_Controls->m_OpenFileButton, SIGNAL(clicked()), this, SLOT(OnOpenFileButtonPressed()) ); +} bool QmitkIGTPlayerWidget::IsTrajectoryInSplineMode() { return m_Controls->splineModeCheckBox->isChecked(); } - bool QmitkIGTPlayerWidget::CheckInputFileValid() { QFile file(m_CmpFilename); // check if file exists if(!file.exists()) { QMessageBox::warning(NULL, "IGTPlayer: Error", "No valid input file was loaded. Please load input file first!"); return false; } return true; } - unsigned int QmitkIGTPlayerWidget::GetNumberOfTools() { unsigned int result = 0; if(this->GetCurrentPlaybackMode() == RealTimeMode) { if(m_RealTimePlayer.IsNotNull()) result = m_RealTimePlayer->GetNumberOfOutputs(); } else if(this->GetCurrentPlaybackMode() == SequentialMode) { if(m_SequentialPlayer.IsNotNull()) result = m_SequentialPlayer->GetNumberOfOutputs(); } // at the moment this works only if player is initialized return result; } - void QmitkIGTPlayerWidget::SetUpdateRate(unsigned int msecs) { m_PlayingTimer->setInterval((int) msecs); // set update timer update rate } void QmitkIGTPlayerWidget::OnPlayButtonClicked(bool checked) { - + if ( ! checked ) + { + if ( this->GetCurrentPlaybackMode() == RealTimeMode ) + { + m_RealTimePlayer->StopPlaying(); + } + else if ( this->GetCurrentPlaybackMode() == SequentialMode ) + { + // m_SequentialPlayer-> + } + } if(CheckInputFileValid()) // no playing possible without valid input file { + switch ( this->GetCurrentPlaybackMode() ) + { + case RealTimeMode: + { + break; + } + case SequentialMode: + { + break; + } + } + PlaybackMode currentMode = this->GetCurrentPlaybackMode(); bool isRealTimeMode = currentMode == RealTimeMode; bool isSequentialMode = currentMode == SequentialMode; if(checked) // play { if( (isRealTimeMode && m_RealTimePlayer.IsNull()) || (isSequentialMode && m_SequentialPlayer.IsNull())) // start play { + mitk::NavigationDataSet::Pointer navigationDataSet; + try + { + mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); + navigationDataSet = reader->Read(m_CmpFilename.toStdString()); + } + catch(mitk::IGTException) + { + std::string errormessage = "Error during start playing. Invalid or wrong file?"; + QMessageBox::warning(NULL, "IGTPlayer: Error", errormessage.c_str()); + m_Controls->playPushButton->setChecked(false); + m_RealTimePlayer = NULL; + return; + } + if(isRealTimeMode) { m_RealTimePlayer = mitk::NavigationDataPlayer::New(); - m_RealTimePlayer->SetFileName(m_CmpFilename.toStdString()); + m_RealTimePlayer->SetNavigationDataSet(navigationDataSet); try - { + { m_RealTimePlayer->StartPlaying(); - } + } catch(mitk::IGTException) - { + { std::string errormessage = "Error during start playing. Invalid or wrong file?"; QMessageBox::warning(NULL, "IGTPlayer: Error", errormessage.c_str()); m_Controls->playPushButton->setChecked(false); m_RealTimePlayer = NULL; return; - } + } } else if(isSequentialMode) { m_SequentialPlayer = mitk::NavigationDataSequentialPlayer::New(); try { - m_SequentialPlayer->SetFileName(m_CmpFilename.toStdString()); + m_SequentialPlayer->SetNavigationDataSet(navigationDataSet); } catch(mitk::IGTException) { - std::string errormessage = "Error during start playing. Invalid or wrong file type?"; - QMessageBox::warning(NULL, "IGTPlayer: Error", errormessage.c_str()); - m_Controls->playPushButton->setChecked(false); - m_RealTimePlayer = NULL; - return; + std::string errormessage = "Error during start playing. Invalid or wrong file type?"; + QMessageBox::warning(NULL, "IGTPlayer: Error", errormessage.c_str()); + m_Controls->playPushButton->setChecked(false); + m_RealTimePlayer = NULL; + return; } m_Controls->samplePositionHorizontalSlider->setMinimum(0); m_Controls->samplePositionHorizontalSlider->setMaximum(m_SequentialPlayer->GetNumberOfSnapshots()); m_Controls->samplePositionHorizontalSlider->setEnabled(true); } m_PlayingTimer->start(100); emit SignalPlayingStarted(); } else // resume play { if(isRealTimeMode) m_RealTimePlayer->Resume(); m_PlayingTimer->start(100); emit SignalPlayingResumed(); } } else // pause { if(isRealTimeMode) m_RealTimePlayer->Pause(); m_PlayingTimer->stop(); emit SignalPlayingPaused(); } } else + { m_Controls->playPushButton->setChecked(false); // uncheck play button if file unvalid + } } - QmitkIGTPlayerWidget::PlaybackMode QmitkIGTPlayerWidget::GetCurrentPlaybackMode() { - if(m_Controls->sequencialModeCheckBox->isChecked()) - return SequentialMode; - else - return RealTimeMode; + /*if(m_Controls->sequencialModeCheckBox->isChecked()) + return SequentialMode; + else*/ + return RealTimeMode; } QTimer* QmitkIGTPlayerWidget::GetPlayingTimer() { return m_PlayingTimer; } void QmitkIGTPlayerWidget::OnStopPlaying() { this->StopPlaying(); } - void QmitkIGTPlayerWidget::StopPlaying() { m_PlayingTimer->stop(); emit SignalPlayingStopped(); if(m_RealTimePlayer.IsNotNull()) m_RealTimePlayer->StopPlaying(); - m_RealTimePlayer = NULL; - m_SequentialPlayer = NULL; - m_StartTime = -1; // set starttime back m_CurrentSequentialPointNumber = 0; m_Controls->samplePositionHorizontalSlider->setSliderPosition(m_CurrentSequentialPointNumber); m_Controls->sampleLCDNumber->display(static_cast(m_CurrentSequentialPointNumber)); this->ResetLCDNumbers(); m_Controls->playPushButton->setChecked(false); // set play button unchecked - } void QmitkIGTPlayerWidget::OnPlaying() { - PlaybackMode currentMode = this->GetCurrentPlaybackMode(); - bool isRealTimeMode = currentMode == RealTimeMode; - bool isSequentialMode = currentMode == SequentialMode; - - if(isRealTimeMode && m_RealTimePlayer.IsNull()) - return; - - else if(isSequentialMode && m_SequentialPlayer.IsNull()) - return; + switch ( this->GetCurrentPlaybackMode() ) + { + case RealTimeMode: + { + if ( m_RealTimePlayer.IsNull() ) { return; } - if(isRealTimeMode && m_StartTime < 0) - m_StartTime = m_RealTimePlayer->GetOutput()->GetTimeStamp(); // get playback start time + if ( m_StartTime < 0 ) + { + // get playback start time + m_StartTime = m_RealTimePlayer->GetOutput()->GetTimeStamp(); + } + if( ! m_RealTimePlayer->IsAtEnd() ) + { + m_RealTimePlayer->Update(); // update player + int msc = (int) (m_RealTimePlayer->GetOutput()->GetTimeStamp() - m_StartTime); - if(isRealTimeMode && !m_RealTimePlayer->IsAtEnd()) - { - m_RealTimePlayer->Update(); // update player + // calculation for playing time display + int ms = msc % 1000; + msc = (msc - ms) / 1000; + int s = msc % 60; + int min = (msc-s) / 60; - int msc = (int) (m_RealTimePlayer->GetOutput()->GetTimeStamp() - m_StartTime); + // set lcd numbers + m_Controls->msecLCDNumber->display(ms); + m_Controls->secLCDNumber->display(s); + m_Controls->minLCDNumber->display(min); - // calculation for playing time display - int ms = msc % 1000; - msc = (msc - ms) / 1000; - int s = msc % 60; - int min = (msc-s) / 60; + emit SignalPlayerUpdated(); // player successfully updated + } + else + { + this->StopPlaying(); // if player is at EOF + } - // set lcd numbers - m_Controls->msecLCDNumber->display(ms); - m_Controls->secLCDNumber->display(s); - m_Controls->minLCDNumber->display(min); + break; + } + case SequentialMode: + { + if ( m_SequentialPlayer.IsNull() ) { return; } - emit SignalPlayerUpdated(); // player successfully updated - } - else if(isSequentialMode && (m_CurrentSequentialPointNumber < m_SequentialPlayer->GetNumberOfSnapshots())) - { - m_SequentialPlayer->Update(); // update sequential player + if ( m_CurrentSequentialPointNumber < m_SequentialPlayer->GetNumberOfSnapshots() ) + { + m_SequentialPlayer->Update(); // update sequential player - m_Controls->samplePositionHorizontalSlider->setSliderPosition(m_CurrentSequentialPointNumber++); // refresh slider position - m_Controls->sampleLCDNumber->display(static_cast(m_CurrentSequentialPointNumber)); + m_Controls->samplePositionHorizontalSlider->setSliderPosition(m_CurrentSequentialPointNumber++); // refresh slider position + m_Controls->sampleLCDNumber->display(static_cast(m_CurrentSequentialPointNumber)); - //for debugging purposes - //std::cout << "Sample: " << m_CurrentSequentialPointNumber << " X: " << m_SequentialPlayer->GetOutput()->GetPosition()[0] << " Y: " << m_SequentialPlayer->GetOutput()->GetPosition()[1] << " Y: " << m_SequentialPlayer->GetOutput()->GetPosition()[2] << std::endl; + //for debugging purposes + //std::cout << "Sample: " << m_CurrentSequentialPointNumber << " X: " << m_SequentialPlayer->GetOutput()->GetPosition()[0] << " Y: " << m_SequentialPlayer->GetOutput()->GetPosition()[1] << " Y: " << m_SequentialPlayer->GetOutput()->GetPosition()[2] << std::endl; - emit SignalPlayerUpdated(); // player successfully updated + emit SignalPlayerUpdated(); // player successfully updated + } + else + { + this->StopPlaying(); // if player is at EOF + } + break; + } } - else - this->StopPlaying(); // if player is at EOF - } const std::vector QmitkIGTPlayerWidget::GetNavigationDatas() { std::vector navDatas; if(this->GetCurrentPlaybackMode() == RealTimeMode && m_RealTimePlayer.IsNotNull()) { for(unsigned int i=0; i < m_RealTimePlayer->GetNumberOfOutputs(); ++i) { navDatas.push_back(m_RealTimePlayer->GetOutput(i)); // push back current navigation data for each tool } } else if(this->GetCurrentPlaybackMode() == SequentialMode && m_SequentialPlayer.IsNotNull()) { for(unsigned int i=0; i < m_SequentialPlayer->GetNumberOfOutputs(); ++i) { navDatas.push_back(m_SequentialPlayer->GetOutput(i)); // push back current navigation data for each tool } } return navDatas; } const mitk::PointSet::Pointer QmitkIGTPlayerWidget::GetNavigationDatasPointSet() { mitk::PointSet::Pointer result = mitk::PointSet::New(); mitk::PointSet::PointType pointType; PlaybackMode currentMode = this->GetCurrentPlaybackMode(); bool isRealTimeMode = currentMode == RealTimeMode; bool isSequentialMode = currentMode == SequentialMode; - if( (isRealTimeMode && m_RealTimePlayer.IsNotNull()) || (isSequentialMode && m_SequentialPlayer.IsNotNull())) { int numberOfOutputs = 0; if(isRealTimeMode) numberOfOutputs = m_RealTimePlayer->GetNumberOfOutputs(); else if(isSequentialMode) numberOfOutputs = m_SequentialPlayer->GetNumberOfOutputs(); for(unsigned int i=0; i < m_RealTimePlayer->GetNumberOfOutputs(); ++i) { mitk::NavigationData::PositionType position; if(isRealTimeMode) position = m_RealTimePlayer->GetOutput(i)->GetPosition(); else if(isSequentialMode) position = m_SequentialPlayer->GetOutput(i)->GetPosition(); pointType[0] = position[0]; pointType[1] = position[1]; pointType[2] = position[2]; result->InsertPoint(i,pointType); // insert current ND as Pointtype in PointSet for return } } return result; } const mitk::PointSet::PointType QmitkIGTPlayerWidget::GetNavigationDataPoint(unsigned int index) { if( index > this->GetNumberOfTools() || index < 0 ) throw std::out_of_range("Tool Index out of range!"); PlaybackMode currentMode = this->GetCurrentPlaybackMode(); bool isRealTimeMode = currentMode == RealTimeMode; bool isSequentialMode = currentMode == SequentialMode; // create return PointType from current ND for tool index mitk::PointSet::PointType result; if( (isRealTimeMode && m_RealTimePlayer.IsNotNull()) || (isSequentialMode && m_SequentialPlayer.IsNotNull())) { mitk::NavigationData::PositionType position; - if(isRealTimeMode) - position = m_RealTimePlayer->GetOutput(index)->GetPosition(); - else if(isSequentialMode) - position = m_SequentialPlayer->GetOutput(index)->GetPosition(); + if(isRealTimeMode) + position = m_RealTimePlayer->GetOutput(index)->GetPosition(); + else if(isSequentialMode) + position = m_SequentialPlayer->GetOutput(index)->GetPosition(); result[0] = position[0]; result[1] = position[1]; result[2] = position[2]; } return result; } - -void QmitkIGTPlayerWidget::SetInputFileName(const QString& inputFileName) +/*void QmitkIGTPlayerWidget::SetRealTimePlayer( mitk::NavigationDataPlayer::Pointer player ) { - this->OnGoToEnd(); /// stops playing and resets lcd numbers - - QString oldName = m_CmpFilename; - m_CmpFilename.clear(); - - m_CmpFilename = inputFileName; - - QFile file(m_CmpFilename); - if(m_CmpFilename.isEmpty() || !file.exists()) - { - QMessageBox::warning(NULL, "Warning", QString("Please enter valid path! Using previous path again.")); - m_CmpFilename=oldName; - m_Controls->inputFileLineEdit->setText(m_CmpFilename); - } +if(player.IsNotNull()) +m_RealTimePlayer = player; } -void QmitkIGTPlayerWidget::SetRealTimePlayer( mitk::NavigationDataPlayer::Pointer player ) +void QmitkIGTPlayerWidget::SetSequentialPlayer( mitk::NavigationDataSequentialPlayer::Pointer player ) { - if(player.IsNotNull()) - m_RealTimePlayer = player; -} +if(player.IsNotNull()) +m_SequentialPlayer = player; +}*/ -void QmitkIGTPlayerWidget::SetSequentialPlayer( mitk::NavigationDataSequentialPlayer::Pointer player ) +void QmitkIGTPlayerWidget::OnOpenFileButtonPressed() { - if(player.IsNotNull()) - m_SequentialPlayer = player; -} + QString filename = QFileDialog::getOpenFileName(this, "Load tracking data", QDir::currentPath(),"XML files (*.xml)"); + QFile file(filename); + // if something went wrong or user pressed cancel in the save dialog + if ( filename.isEmpty() || ! file.exists() ) + { + QMessageBox::warning(NULL, "Warning", QString("Please enter valid path. Using previous path again.")); + return; + } + m_CmpFilename = filename; -void QmitkIGTPlayerWidget::OnSelectPressed() -{ + this->OnGoToEnd(); /// stops playing and resets lcd numbers - QString oldName = m_CmpFilename; - m_CmpFilename.clear(); - m_CmpFilename = QFileDialog::getOpenFileName(this, "Load tracking data", QDir::currentPath(),"XML files (*.xml)"); + m_Controls->m_ActiveFileLabel->setText(m_CmpFilename); - if (m_CmpFilename.isEmpty())//if something went wrong or user pressed cancel in the save dialog - m_CmpFilename=oldName; - else - { - this->OnGoToEnd(); /// stops playing and resets lcd numbers - emit SignalInputFileChanged(); - } + emit SignalInputFileChanged(); - m_Controls->inputFileLineEdit->setText(m_CmpFilename); -} + mitk::NavigationDataReaderInterface::Pointer navigationDataReader = mitk::NavigationDataReaderXML::New().GetPointer(); + mitk::NavigationDataSet::Pointer navigationDataSet = navigationDataReader->Read(m_CmpFilename.toStdString()); + m_RealTimePlayer->SetNavigationDataSet(navigationDataSet); + m_SequentialPlayer->SetNavigationDataSet(navigationDataSet); + m_Controls->m_PlayerControlsGroupBox->setEnabled(true); +} void QmitkIGTPlayerWidget::OnGoToEnd() { this->StopPlaying(); // reset lcd numbers this->ResetLCDNumbers(); - - } - void QmitkIGTPlayerWidget::OnGoToBegin() { // stop player manual so no PlayingStopped() m_PlayingTimer->stop(); if(this->GetCurrentPlaybackMode() == RealTimeMode && m_RealTimePlayer.IsNotNull()) { m_RealTimePlayer->StopPlaying(); m_RealTimePlayer = NULL; // set player to NULL so it can be initialized again if playback is called afterwards } m_StartTime = -1; // set starttime back //reset view elements m_Controls->playPushButton->setChecked(false); this->ResetLCDNumbers(); } void QmitkIGTPlayerWidget::ResetLCDNumbers() { - m_Controls->minLCDNumber->display(QString("00")); - m_Controls->secLCDNumber->display(QString("00")); - m_Controls->msecLCDNumber->display(QString("000")); + m_Controls->minLCDNumber->display(QString("00")); + m_Controls->secLCDNumber->display(QString("00")); + m_Controls->msecLCDNumber->display(QString("000")); } - - void QmitkIGTPlayerWidget::SetTrajectoryNames(const QStringList toolNames) { QComboBox* cBox = m_Controls->trajectorySelectComboBox; if(cBox->count() > 0) this->ClearTrajectorySelectCombobox(); // before making changed to QComboBox it is recommended to disconnet it's SIGNALS and SLOTS disconnect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) ); if(!toolNames.isEmpty()) m_Controls->trajectorySelectComboBox->insertItems(0, toolNames); // adding current tool names to combobox // reconnect after performed changes connect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) ); } - int QmitkIGTPlayerWidget::GetResolution() { - return m_Controls->resolutionSpinBox->value(); // return currently selected trajectory resolution + return m_Controls->resolutionSpinBox->value(); // return currently selected trajectory resolution } void QmitkIGTPlayerWidget::ClearTrajectorySelectCombobox() { // before making changed to QComboBox it is recommended to disconnet it's SIGNALS and SLOTS disconnect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) ); m_Controls->trajectorySelectComboBox->clear(); // reconnect after performed changes connect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) ); } - - void QmitkIGTPlayerWidget::OnSequencialModeToggled(bool toggled) { - this->StopPlaying(); // stop playing when mode is changed - - if(toggled) - { - m_Controls->samplePositionHorizontalSlider->setEnabled(true); // enable slider if sequential mode - } - else if(!toggled) - { - m_Controls->samplePositionHorizontalSlider->setSliderPosition(0); // set back and disable slider - m_Controls->samplePositionHorizontalSlider->setDisabled(true); - } - + this->StopPlaying(); // stop playing when mode is changed + if(toggled) + { + m_Controls->samplePositionHorizontalSlider->setEnabled(true); // enable slider if sequential mode + } + else if(!toggled) + { + m_Controls->samplePositionHorizontalSlider->setSliderPosition(0); // set back and disable slider + m_Controls->samplePositionHorizontalSlider->setDisabled(true); + } } void QmitkIGTPlayerWidget::OnSliderReleased() { int currentSliderValue = m_Controls->samplePositionHorizontalSlider->value(); // current slider value selected through user movement if(currentSliderValue > m_CurrentSequentialPointNumber) // at the moment only forward scrolling is possible { unsigned int snapshotNumber = currentSliderValue; m_SequentialPlayer->GoToSnapshot(snapshotNumber); // move player to selected snapshot m_CurrentSequentialPointNumber = currentSliderValue; m_Controls->sampleLCDNumber->display(currentSliderValue); // update lcdnumber in widget } else m_Controls->samplePositionHorizontalSlider->setValue(m_CurrentSequentialPointNumber); } void QmitkIGTPlayerWidget::OnSliderPressed() { if(m_Controls->playPushButton->isChecked()) // check if widget is playing m_Controls->playPushButton->click(); // perform click to pause the play } \ No newline at end of file diff --git a/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.h b/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.h index dbef727ab9..0af371b00e 100644 --- a/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.h +++ b/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.h @@ -1,259 +1,252 @@ /*=================================================================== 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 QmitkIGTPlayerWidget_H #define QmitkIGTPlayerWidget_H //QT headers #include //mitk headers #include "MitkIGTUIExports.h" #include #include #include #include //ui header #include "ui_QmitkIGTPlayerWidgetControls.h" /** Documentation: * \brief GUI to access the IGT Player. * User must specify the file name where the input xml-file is located. The NavigationDatas from the xml-file can be * played in normal mode or in PointSet mode. * * In normal mode the player updates the NavigationDatas every 100ms (can be changed in SetUpdateRate()) and returns * them when GetNavigationDatas() is called. * In PointSet mode the player generates a PointSet with all NavigationDatas from the xml-file. So the playback is * performed on this ND PointSet. * * \ingroup IGTUI */ class MitkIGTUI_EXPORT QmitkIGTPlayerWidget : public QWidget { Q_OBJECT public: static const std::string VIEW_ID; /*! \brief default constructor */ QmitkIGTPlayerWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); /*! \brief default deconstructor */ ~QmitkIGTPlayerWidget(); /*! \brief Sets the real time player for this player widget */ - void SetRealTimePlayer(mitk::NavigationDataPlayer::Pointer player); + //void SetRealTimePlayer(mitk::NavigationDataPlayer::Pointer player); /*! \brief Sets the sequential player for this player widget */ - void SetSequentialPlayer(mitk::NavigationDataSequentialPlayer::Pointer player); + //void SetSequentialPlayer(mitk::NavigationDataSequentialPlayer::Pointer player); /*! \brief Returns the playing timer of this widget */ QTimer* GetPlayingTimer(); /*! \brief Returns the current playback NavigationDatas from the xml-file */ const std::vector GetNavigationDatas(); /*! \brief Returns a PointSet of the current NavigationDatas for all recorded tools. */ const mitk::PointSet::Pointer GetNavigationDatasPointSet(); /*! \brief Returns a PointType of the current NavigationData for a specific tool with the given index. */ const mitk::PointSet::PointType GetNavigationDataPoint(unsigned int index); /*! \brief Sets the update rate of this widget's playing timer */ void SetUpdateRate(unsigned int msecs); /*! \brief Returns the number of different tools from the current playing stream. * * Retuns 0 if playback file is invalid. */ unsigned int GetNumberOfTools(); /*! \brief Stops the playback */ void StopPlaying(); /*! \brief Sets the given tool names list to the trajectory select combobox. */ void SetTrajectoryNames(const QStringList toolNames); /*! \brief Returns the current resolution value from the resolution spinbox. */ int GetResolution(); /*! \brief Clears all items in the trajectory selection combobox. */ void ClearTrajectorySelectCombobox(); /*! \brief Returns whether spline mode checkbox is selected. */ bool IsTrajectoryInSplineMode(); enum PlaybackMode { ///< playback mode enum RealTimeMode = 1, SequentialMode = 2 }; PlaybackMode GetCurrentPlaybackMode(); signals: /*! \brief This signal is emitted when the player starts the playback. */ void SignalPlayingStarted(); /*! \brief This signal is emitted when the player resumes after a pause. */ void SignalPlayingResumed(); /*! \brief This signal is emitted when the player stops. */ void SignalPlayingStopped(); /*! \brief This signal is emitted when the player is paused. */ void SignalPlayingPaused(); /*! \brief This signal is emitted when the player reaches the end of the playback. */ void SignalPlayingEnded(); /*! \brief This signal is emitted every time the player updated the NavigationDatas. */ void SignalPlayerUpdated(); /*! \brief This signal is emitted if the input file for the replay was changed. */ void SignalInputFileChanged(); /*! \brief This signal is emitted if the index of the current selected trajectory select combobox item changes. */ void SignalCurrentTrajectoryChanged(int index); /*! \brief This signal is emitted if the spline mode checkbox is toggled or untoggled. */ void SignalSplineModeToggled(bool toggled); protected slots: /*! \brief Starts or pauses the playback */ void OnPlayButtonClicked(bool toggled); /*! \brief Updates the playback data */ void OnPlaying(); /*! \brief Stops the playback */ void OnStopPlaying(); /*! - \brief Updates the input filename - */ - void SetInputFileName(const QString& inputFileName); - /*! \brief Opens file open dialog for searching the input file */ - void OnSelectPressed(); + void OnOpenFileButtonPressed(); /*! \brief Stops the playback */ void OnGoToEnd(); /*! \brief Stops the playback and resets the player to the beginning */ void OnGoToBegin(); /*! \brief Switches widget between realtime and sequential mode */ void OnSequencialModeToggled(bool toggled); /*! \brief Pauses playback when slider is pressed by user */ void OnSliderPressed(); /*! \brief Moves player position to the position selected with the slider */ void OnSliderReleased(); protected: /// \brief Creation of the connections virtual void CreateConnections(); - /// \brief Creation of the Qt control - virtual void CreateQtPartControl(QWidget *parent); - /*! \brief Checks if an imput file with the set filename exists */ bool CheckInputFileValid(); /*! \brief Sets all LCD numbers to 0 */ void ResetLCDNumbers(); Ui::QmitkIGTPlayerWidgetControls* m_Controls; mitk::NavigationDataPlayer::Pointer m_RealTimePlayer; ///< plays NDs from a XML file mitk::NavigationDataSequentialPlayer::Pointer m_SequentialPlayer; QString m_CmpFilename; ///< filename of the input file QTimer* m_PlayingTimer; ///< update timer mitk::NavigationData::TimeStampType m_StartTime; ///< start time of playback needed for time display unsigned int m_CurrentSequentialPointNumber; ///< current point number }; #endif diff --git a/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidgetControls.ui b/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidgetControls.ui index 2a4a998dec..f7c9180bd1 100644 --- a/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidgetControls.ui +++ b/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidgetControls.ui @@ -1,427 +1,476 @@ QmitkIGTPlayerWidgetControls 0 0 - 416 + 424 689 + + + 0 + 0 + + Form - + - Settings + File Management - - true - - - false - - + + + + + Open Navigation Data File + + + - - - + + + - + 0 0 - - Input File - - - - - - - - 2 - 0 - - - - - 150 - 0 - - - - true - - - - - - - - 0 - 0 - + + + 8 + 75 + true + - Trajectory - - - - - - - - 4 - 0 - - - - - - - - - 0 - 0 - - - - 1 - - - 25 + Active File: - - - - - 0 - 0 - + + + + + 8 + - Res.: 1: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + No navigation data file loaded. - - + + + + + + + + + Tool Colors + + + + + + - + 0 0 - - Qt::LeftToRight - - Splines + 1) - - + + + + + + + + + - + 0 0 - - - 90 - 16777215 - - - - - 50 - false - - - Select - - - false + 2) + + + - + + + true + + + + 0 + 0 + + - Player + Settings - - true + + + QFormLayout::AllNonFixedFieldsGrow + + + + + Player Type + + + + + + + + Time Based Player + + + + + Sequential Player + + + + + + + + + 0 + 0 + + + + Trajectory + + + + + + + + 4 + 0 + + + + + + + + + 0 + 0 + + + + Qt::LeftToRight + + + Splines + + + + + + + + 0 + 0 + + + + Res.: 1: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + 1 + + + 25 + + + + + + + + + + false - + + Player Controls + + background-color: rgb(60, 60, 60); color: rgb(250, 250, 250); QFrame::Raised 3 QLCDNumber::Flat 0 min background-color: rgb(60, 60, 60); color: rgb(250, 250, 250); 2 QLCDNumber::Flat 0 sec background-color: rgb(60, 60, 60); color: rgb(250, 250, 250); 3 QLCDNumber::Flat 0 msec Qt::Horizontal 40 20 Sample 0 0 false background-color: rgb(60,60,60) 10 QLCDNumber::Outline - - - - - false - - - Qt::Horizontal - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::LeftToRight - - - Sequential Mode - - - - + + + false + + + Qt::Horizontal + + - + 1 0 + + Restart from beginning + - + Restart :/IGTUI/firstframe.png:/IGTUI/firstframe.png - 4 + 1 0 Play at normal speed - + Play :/IGTUI/play.png :/IGTUI/pause.png:/IGTUI/play.png 16 16 true false 1 0 + + Stop playing + - + Stop :/IGTUI/stop.png:/IGTUI/stop.png Qt::Vertical 20 40 diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationDataPlayerControlWidget.cpp b/Modules/IGTUI/Qmitk/QmitkNavigationDataPlayerControlWidget.cpp new file mode 100644 index 0000000000..872c85e0ac --- /dev/null +++ b/Modules/IGTUI/Qmitk/QmitkNavigationDataPlayerControlWidget.cpp @@ -0,0 +1,101 @@ +/*=================================================================== + +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 "QmitkNavigationDataPlayerControlWidget.h" +#include "ui_QmitkNavigationDataPlayerControlWidget.h" + +#include + +QmitkNavigationDataPlayerControlWidget::QmitkNavigationDataPlayerControlWidget(QWidget *parent) : + QWidget(parent), + m_UpdateTimer(new QTimer(this)), + ui(new Ui::QmitkNavigationDataPlayerControlWidget) +{ + ui->setupUi(this); + + connect(m_UpdateTimer, SIGNAL(timeout()), this, SLOT(OnTimeout())); +} + +QmitkNavigationDataPlayerControlWidget::~QmitkNavigationDataPlayerControlWidget() +{ + delete ui; +} + +void QmitkNavigationDataPlayerControlWidget::SetPlayer(mitk::NavigationDataPlayer::Pointer player) +{ + m_Player = player; + + ui->samplePositionHorizontalSlider->setMaximum(player->GetNumberOfSnapshots()); +} + +void QmitkNavigationDataPlayerControlWidget::OnStop() +{ + m_UpdateTimer->stop(); + m_Player->StopPlaying(); +} + +void QmitkNavigationDataPlayerControlWidget::OnPlayPause() +{ + switch ( m_Player->GetCurrentPlayerState() ) + { + case mitk::NavigationDataPlayer::PlayerStopped: + { + m_Player->StartPlaying(); + if ( ! m_UpdateTimer->isActive() ) { m_UpdateTimer->start(10); } + } + case mitk::NavigationDataPlayer::PlayerPaused: + { + m_Player->Pause(); + } + case mitk::NavigationDataPlayer::PlayerRunning: + { + m_Player->Resume(); + } + } +} + +void QmitkNavigationDataPlayerControlWidget::OnRestart() +{ + m_Player->StopPlaying(); + m_Player->StartPlaying(); +} + +void QmitkNavigationDataPlayerControlWidget::OnUpdate() +{ + m_Player->Update(); + + int msc = static_cast(m_Player->GetTimeStampSinceStart()); + + // calculation for playing time display + int ms = msc % 1000; + msc = (msc - ms) / 1000; + int s = msc % 60; + int min = (msc-s) / 60; + + // set lcd numbers + ui->msecLCDNumber->display(ms); + ui->secLCDNumber->display(s); + ui->minLCDNumber->display(min); + + ui->samplePositionHorizontalSlider->setValue(static_cast(m_Player->GetCurrentSnapshotNumber())); + + emit SignalUpdate(); + + if ( m_Player->GetCurrentPlayerState() == mitk::NavigationDataPlayer::PlayerStopped ) + { + emit SignalEndReached(); + } +} diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationDataPlayerControlWidget.h b/Modules/IGTUI/Qmitk/QmitkNavigationDataPlayerControlWidget.h new file mode 100644 index 0000000000..151805d3dd --- /dev/null +++ b/Modules/IGTUI/Qmitk/QmitkNavigationDataPlayerControlWidget.h @@ -0,0 +1,60 @@ +/*=================================================================== + +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 QMITKNAVIGATIONDATAPLAYERCONTROLWIDGET_H +#define QMITKNAVIGATIONDATAPLAYERCONTROLWIDGET_H + +#include +#include "mitkNavigationDataPlayer.h" +#include "MitkIGTUIExports.h" + +class QTimer; + +namespace Ui { + class QmitkNavigationDataPlayerControlWidget; +} + +class MitkIGTUI_EXPORT QmitkNavigationDataPlayerControlWidget : public QWidget +{ + Q_OBJECT + +signals: + void SignalUpdate(); + void SignalEndReached(); + + public slots: + void OnStop(); + void OnPlayPause(); + void OnRestart(); + + protected slots: + void OnUpdate(); + +public: + explicit QmitkNavigationDataPlayerControlWidget(QWidget *parent = 0); + ~QmitkNavigationDataPlayerControlWidget(); + + void SetPlayer(mitk::NavigationDataPlayer::Pointer player); + +private: + mitk::NavigationDataPlayer::Pointer m_Player; + + QTimer* m_UpdateTimer; + + Ui::QmitkNavigationDataPlayerControlWidget *ui; +}; + +#endif // QMITKNAVIGATIONDATAPLAYERCONTROLWIDGET_H \ No newline at end of file diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationDataPlayerControlWidget.ui b/Modules/IGTUI/Qmitk/QmitkNavigationDataPlayerControlWidget.ui new file mode 100644 index 0000000000..4fe63079b5 --- /dev/null +++ b/Modules/IGTUI/Qmitk/QmitkNavigationDataPlayerControlWidget.ui @@ -0,0 +1,267 @@ + + + QmitkNavigationDataPlayerControlWidget + + + + 0 + 0 + 364 + 95 + + + + Form + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + sec + + + + + + + msec + + + + + + + background-color: rgb(60, 60, 60); +color: rgb(250, 250, 250); + + + 2 + + + QLCDNumber::Flat + + + 0 + + + + + + + min + + + + + + + background-color: rgb(60, 60, 60); +color: rgb(250, 250, 250); + + + QFrame::Raised + + + 3 + + + QLCDNumber::Flat + + + 0 + + + + + + + background-color: rgb(60, 60, 60); +color: rgb(250, 250, 250); + + + 3 + + + QLCDNumber::Flat + + + 0 + + + + + + + + + false + + + Qt::Horizontal + + + + + + + + + + 1 + 0 + + + + Restart from beginning + + + Restart + + + + :/IGTUI/firstframe.png:/IGTUI/firstframe.png + + + + + + + + 1 + 0 + + + + Play at normal speed + + + Play + + + + :/IGTUI/play.png + :/IGTUI/pause.png:/IGTUI/play.png + + + + 16 + 16 + + + + true + + + false + + + + + + + + 1 + 0 + + + + Stop playing + + + Stop + + + + :/IGTUI/stop.png:/IGTUI/stop.png + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + playPushButton + clicked() + QmitkNavigationDataPlayerControlWidget + OnPlayPause() + + + 181 + 73 + + + 181 + 47 + + + + + restartPushButton + clicked() + QmitkNavigationDataPlayerControlWidget + OnRestart() + + + 62 + 73 + + + 181 + 47 + + + + + stopPushButton + clicked() + QmitkNavigationDataPlayerControlWidget + OnStop() + + + 301 + 73 + + + 181 + 47 + + + + + + OnStop() + OnRestart() + OnPlayPause() + + diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.cpp b/Modules/IGTUI/Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.cpp new file mode 100644 index 0000000000..ce7632ed29 --- /dev/null +++ b/Modules/IGTUI/Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.cpp @@ -0,0 +1,87 @@ +/*=================================================================== + +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 "QmitkNavigationDataSequentialPlayerControlWidget.h" +#include "ui_QmitkNavigationDataSequentialPlayerControlWidget.h" + +#include + +QmitkNavigationDataSequentialPlayerControlWidget::QmitkNavigationDataSequentialPlayerControlWidget(QWidget *parent) : + QWidget(parent), + ui(new Ui::QmitkNavigationDataSequentialPlayerControlWidget) +{ + ui->setupUi(this); + m_UpdateTimer = new QTimer(); + connect( m_UpdateTimer, SIGNAL(timeout()), this, SLOT(OnUpdate()) ); +} + +QmitkNavigationDataSequentialPlayerControlWidget::~QmitkNavigationDataSequentialPlayerControlWidget() +{ + delete ui; +} + +void QmitkNavigationDataSequentialPlayerControlWidget::SetPlayer(mitk::NavigationDataSequentialPlayer::Pointer player) +{ + m_Player = player; + + ui->samplePositionHorizontalSlider->setMaximum(player->GetNumberOfSnapshots()); +} + +void QmitkNavigationDataSequentialPlayerControlWidget::OnStop() +{ + m_UpdateTimer->stop(); +} + +void QmitkNavigationDataSequentialPlayerControlWidget::OnPlayPause() +{ + if ( m_UpdateTimer->isActive() ) + { + m_UpdateTimer->stop(); + } + else + { + m_UpdateTimer->start(ui->updateIntervalSpinBox->value()); + } +} + +void QmitkNavigationDataSequentialPlayerControlWidget::OnRestart() +{ + m_Player->GoToSnapshot(0); +} + +void QmitkNavigationDataSequentialPlayerControlWidget::OnUpdate() +{ + m_Player->GoToNextSnapshot(); + m_Player->Update(); + + int currentSnapshotNumber = static_cast(m_Player->GetCurrentSnapshotNumber()); + + ui->sampleLCDNumber->display(currentSnapshotNumber); + + ui->samplePositionHorizontalSlider->setValue(currentSnapshotNumber); + + emit SignalUpdate(); + + if ( m_Player->GetCurrentSnapshotNumber() == m_Player->GetNumberOfSnapshots() - 1 ) + { + emit SignalEndReached(); + } +} + +void QmitkNavigationDataSequentialPlayerControlWidget::OnUpdateIntervalChanged(int value) +{ + m_UpdateTimer->setInterval(value); +} \ No newline at end of file diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.h b/Modules/IGTUI/Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.h new file mode 100644 index 0000000000..510daca934 --- /dev/null +++ b/Modules/IGTUI/Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.h @@ -0,0 +1,61 @@ +/*=================================================================== + +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 QMITKNAVIGATIONDATASEQUENTIALPLAYERCONTROLWIDGET_H +#define QMITKNAVIGATIONDATASEQUENTIALPLAYERCONTROLWIDGET_H + +#include +#include "mitkNavigationDataSequentialPlayer.h" +#include "MitkIGTUIExports.h" + +class QTimer; + +namespace Ui { + class QmitkNavigationDataSequentialPlayerControlWidget; +} + +class MitkIGTUI_EXPORT QmitkNavigationDataSequentialPlayerControlWidget : public QWidget +{ + Q_OBJECT + +signals: + void SignalUpdate(); + void SignalEndReached(); + + public slots: + void OnStop(); + void OnPlayPause(); + void OnRestart(); + + protected slots: + void OnUpdate(); + void OnUpdateIntervalChanged(int); + +public: + explicit QmitkNavigationDataSequentialPlayerControlWidget(QWidget *parent = 0); + ~QmitkNavigationDataSequentialPlayerControlWidget(); + + void SetPlayer(mitk::NavigationDataSequentialPlayer::Pointer player); + +private: + mitk::NavigationDataSequentialPlayer::Pointer m_Player; + + QTimer* m_UpdateTimer; + + Ui::QmitkNavigationDataSequentialPlayerControlWidget *ui; +}; + +#endif // QMITKNAVIGATIONDATASEQUENTIALPLAYERCONTROLWIDGET_H \ No newline at end of file diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.ui b/Modules/IGTUI/Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.ui new file mode 100644 index 0000000000..6c560e01fc --- /dev/null +++ b/Modules/IGTUI/Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.ui @@ -0,0 +1,261 @@ + + + QmitkNavigationDataSequentialPlayerControlWidget + + + + 0 + 0 + 407 + 95 + + + + Form + + + + + + + + Sample + + + + + + + + 0 + 0 + + + + false + + + background-color: rgb(60,60,60) + + + 10 + + + QLCDNumber::Outline + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Update Inverval + + + + + + + 1 + + + + + + + ms + + + + + + + + + false + + + Qt::Horizontal + + + + + + + + + + 1 + 0 + + + + Restart from beginning + + + Restart + + + + :/IGTUI/firstframe.png:/IGTUI/firstframe.png + + + + + + + + 1 + 0 + + + + Play at normal speed + + + Play + + + + :/IGTUI/play.png + :/IGTUI/pause.png:/IGTUI/play.png + + + + 16 + 16 + + + + true + + + false + + + + + + + + 1 + 0 + + + + Stop playing + + + Stop + + + + :/IGTUI/stop.png:/IGTUI/stop.png + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + updateIntervalSpinBox + valueChanged(int) + QmitkNavigationDataSequentialPlayerControlWidget + OnUpdateIntervalChanged(int) + + + 349 + 16 + + + 203 + 47 + + + + + restartPushButton + clicked() + QmitkNavigationDataSequentialPlayerControlWidget + OnRestart() + + + 69 + 73 + + + 203 + 47 + + + + + playPushButton + clicked() + QmitkNavigationDataSequentialPlayerControlWidget + OnPlayPause() + + + 203 + 73 + + + 203 + 47 + + + + + stopPushButton + clicked() + QmitkNavigationDataSequentialPlayerControlWidget + OnStop() + + + 336 + 73 + + + 203 + 47 + + + + + + OnUpdateIntervalChanged(int) + OnRestart() + OnPlayPause() + OnStop() + + diff --git a/Modules/IGTUI/files.cmake b/Modules/IGTUI/files.cmake index 6adfd68e09..49de91f954 100644 --- a/Modules/IGTUI/files.cmake +++ b/Modules/IGTUI/files.cmake @@ -1,69 +1,78 @@ set(CPP_FILES Qmitk/QmitkTrackingDeviceWidget.cpp Qmitk/QmitkTrackingDeviceConfigurationWidget.cpp Qmitk/QmitkNDIConfigurationWidget.cpp Qmitk/QmitkFiducialRegistrationWidget.cpp Qmitk/QmitkNDIToolDelegate.cpp Qmitk/QmitkNavigationToolManagementWidget.cpp Qmitk/QmitkIGTLoggerWidget.cpp Qmitk/QmitkUpdateTimerWidget.cpp Qmitk/QmitkToolDistanceWidget.cpp Qmitk/QmitkToolTrackingStatusWidget.cpp Qmitk/QmitkTrackingSourcesCheckBoxPanelWidget.cpp Qmitk/QmitkIGTPlayerWidget.cpp Qmitk/QmitkIGTConnectionWidget.cpp Qmitk/QmitkToolSelectionWidget.cpp Qmitk/QmitkNavigationToolCreationWidget.cpp Qmitk/QmitkNavigationToolCreationAdvancedWidget.cpp Qmitk/QmitkNavigationDataSourceSelectionWidget.cpp Qmitk/QmitkInteractiveTransformationWidget.cpp Qmitk/QmitkNavigationToolStorageSelectionWidget.cpp + + Qmitk/QmitkNavigationDataPlayerControlWidget.cpp + Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.cpp ) set(UI_FILES Qmitk/QmitkNavigationToolManagementWidgetControls.ui Qmitk/QmitkTrackingDeviceConfigurationWidgetControls.ui Qmitk/QmitkNDIConfigurationWidget.ui Qmitk/QmitkFiducialRegistrationWidget.ui Qmitk/QmitkIGTLoggerWidgetControls.ui Qmitk/QmitkUpdateTimerWidgetControls.ui Qmitk/QmitkToolDistanceWidgetControls.ui Qmitk/QmitkToolTrackingStatusWidgetControls.ui Qmitk/QmitkTrackingSourcesCheckBoxPanelWidgetControls.ui Qmitk/QmitkIGTPlayerWidgetControls.ui Qmitk/QmitkIGTConnectionWidgetControls.ui Qmitk/QmitkToolSelectionWidgetControls.ui Qmitk/QmitkNavigationToolCreationWidget.ui Qmitk/QmitkNavigationToolCreationAdvancedWidgetControls.ui Qmitk/QmitkNavigationDataSourceSelectionWidgetControls.ui Qmitk/QmitkInteractiveTransformationWidgetControls.ui Qmitk/QmitkNavigationToolStorageSelectionWidgetControls.ui + + Qmitk/QmitkNavigationDataPlayerControlWidget.ui + Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.ui ) set(MOC_H_FILES Qmitk/QmitkNavigationToolManagementWidget.h Qmitk/QmitkTrackingDeviceWidget.h Qmitk/QmitkTrackingDeviceConfigurationWidget.h Qmitk/QmitkNDIConfigurationWidget.h Qmitk/QmitkFiducialRegistrationWidget.h Qmitk/QmitkNDIToolDelegate.h Qmitk/QmitkIGTLoggerWidget.h Qmitk/QmitkUpdateTimerWidget.h Qmitk/QmitkToolDistanceWidget.h Qmitk/QmitkToolTrackingStatusWidget.h Qmitk/QmitkTrackingSourcesCheckBoxPanelWidget.h Qmitk/QmitkIGTPlayerWidget.h Qmitk/QmitkIGTConnectionWidget.h Qmitk/QmitkToolSelectionWidget.h Qmitk/QmitkNavigationToolCreationWidget.h Qmitk/QmitkNavigationToolCreationAdvancedWidget.h Qmitk/QmitkNavigationDataSourceSelectionWidget.h Qmitk/QmitkInteractiveTransformationWidget.h Qmitk/QmitkNavigationToolStorageSelectionWidget.h + + Qmitk/QmitkNavigationDataPlayerControlWidget.h + Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.h ) set(QRC_FILES resources/IGTUI.qrc ) diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.cpp b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.cpp index 4badf81dc5..730cd71f2f 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.cpp +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.cpp @@ -1,476 +1,184 @@ /*=================================================================== 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. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkNavigationDataPlayerView.h" #include "QmitkStdMultiWidget.h" -//mitk -#include -#include -#include - - -// Qt -#include +// QT +#include -// vtk -#include +//mitk +#include +#include +#include +#include +// VTK +#include const std::string QmitkNavigationDataPlayerView::VIEW_ID = "org.mitk.views.navigationdataplayer"; QmitkNavigationDataPlayerView::QmitkNavigationDataPlayerView() -: QmitkFunctionality() -, m_Controls( 0 ) -, m_MultiWidget( NULL ) -, m_Trajectory( NULL ) -, m_TrajectoryIndex( -1 ) -, m_ReloadData( true ) -, m_ShowTrajectory( false ) -, m_SplineMapper( NULL ) -, m_PointSetMapper( NULL ) + : QmitkFunctionality() + , m_Controls( 0 ) + , m_MultiWidget( NULL ) { - - m_TrajectoryPointSet = mitk::PointSet::New(); // PointSet for trajectory points } - - QmitkNavigationDataPlayerView::~QmitkNavigationDataPlayerView() { - delete m_PlayerWidget; } - void QmitkNavigationDataPlayerView::CreateQtPartControl( QWidget *parent ) { // build up qt view, unless already done if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkNavigationDataPlayerViewControls; m_Controls->setupUi( parent ); this->CreateBundleWidgets( parent ); this->CreateConnections(); + + // make deselected Player invisible + m_Controls->m_TimedWidget->setVisible(false); } } - - void QmitkNavigationDataPlayerView::CreateBundleWidgets(QWidget* parent) { - m_PlayerWidget = new QmitkIGTPlayerWidget( parent ); // this bundle's ND player widget + //m_PlayerWidget = new QmitkIGTPlayerWidget( parent ); // this bundle's ND player widget } - void QmitkNavigationDataPlayerView::CreateConnections() { - connect( m_PlayerWidget, SIGNAL(SignalPlayingStarted()), this, SLOT(OnCreatePlaybackVisualization()) ); - connect( m_PlayerWidget, SIGNAL(SignalPlayerUpdated()), this, SLOT(OnPerformPlaybackVisualization()) ); - connect( m_PlayerWidget, SIGNAL(SignalInputFileChanged()), this, SLOT(OnReinit()) ); - connect( m_PlayerWidget, SIGNAL(SignalCurrentTrajectoryChanged(int)), this, SLOT (OnShowTrajectory(int)) ); - connect( m_PlayerWidget, SIGNAL(SignalPlayingStarted()), this, SLOT(OnPlayingStarted()) ); - connect( m_PlayerWidget, SIGNAL(SignalSplineModeToggled(bool)), this, SLOT(OnEnableSplineTrajectoryMapper(bool)) ); -} - + connect( m_Controls->m_RdbSequential, SIGNAL(released()), this, SLOT(OnSelectPlayer()) ); + connect( m_Controls->m_RdbTimeBased, SIGNAL(released()), this, SLOT(OnSelectPlayer()) ); + connect( m_Controls->m_BtnOpenFile, SIGNAL(released()), this, SLOT(OnOpenFile()) ); + connect( m_Controls->m_ChkDisplay, SIGNAL(released()), this, SLOT(OnSetDisplay()) ); + connect( m_Controls->m_chkRepeat, SIGNAL(released()), this, SLOT(OnSetRepeat()) ); + connect( m_Controls->m_ChkMicroservice, SIGNAL(released()), this, SLOT(OnSetMicroservice()) ); -void QmitkNavigationDataPlayerView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) -{ - m_MultiWidget = &stdMultiWidget; + connect( m_Controls->m_SequentialWidget, SIGNAL(SignalUpdate()), this, SLOT(OnUpdate()) ); + connect( m_Controls->m_TimedWidget, SIGNAL(SignalUpdate()), this, SLOT(OnUpdate()) ); } - -void QmitkNavigationDataPlayerView::StdMultiWidgetNotAvailable() -{ - m_MultiWidget = NULL; -} - - void QmitkNavigationDataPlayerView::OnPlayingStarted() { - m_TrajectoryPointSet->Clear(); // clear trajectory data before every replay } -void QmitkNavigationDataPlayerView::OnCreatePlaybackVisualization() -{ - if(m_ReloadData) // only if input file changed - { - m_Visualizer = mitk::NavigationDataObjectVisualizationFilter::New(); - - mitk::DataStorage* ds = this->GetDefaultDataStorage(); - - unsigned int nrTools = m_PlayerWidget->GetNumberOfTools(); // obtain number of tools from replay file - - QStringList toolNames; - toolNames << "No trajectory selected ..."; // info statement at beginning of trajectories list - - for(int i=0; iGetColorCircleColor(i); // color for replay object - - mitk::DataNode::Pointer playbackRepresentation = this->CreateRepresentationObject( nodeName.toStdString(), color ); // create replay DataNode object - - m_Visualizer->SetRepresentationObject(i, playbackRepresentation->GetData()); // add replay object to visualizer - - // add new representation object to DataStorage - this->AddRepresentationObject(this->GetDefaultDataStorage(), playbackRepresentation); - - } - - this->m_PlayerWidget->SetTrajectoryNames(toolNames); // set names in player widget trajectory selection combobox - m_ReloadData = false; - - - /// request global reiinit - mitk::NodePredicateNot::Pointer pred - = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("includeInBoundingBox" - , mitk::BoolProperty::New(false))); +void QmitkNavigationDataPlayerView::OnOpenFile(){ + mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); - mitk::DataStorage::SetOfObjects::ConstPointer rs = this->GetDataStorage()->GetSubset(pred); - // calculate bounding geometry of these nodes - mitk::TimeGeometry::Pointer bounds = this->GetDataStorage()->ComputeBoundingGeometry3D(rs, "visible"); + // FIXME Filter for correct Files and use correct Reader + QString fileName = QFileDialog::getOpenFileName(NULL, "Open Navigation Data Set", "", ""); + m_Data = reader->Read(fileName.toStdString()); - // initialize the views to the bounding geometry - mitk::RenderingManager::GetInstance()->InitializeViews(bounds); + // Update Labels + m_Controls->m_LblFilePath->setText(fileName); + m_Controls->m_LblFrames->setText(QString::number(m_Data->Size())); + m_Controls->m_LblTools->setText(QString::number(m_Data->GetNumberOfTools())); - /// global reinit end - - - - } - -} - -mitk::DataNode::Pointer QmitkNavigationDataPlayerView::CreateTrajectory( mitk::PointSet::Pointer points, const std::string& name, const mitk::Color color ) -{ - mitk::DataNode::Pointer result = mitk::DataNode::New(); - - // instantiate return DataNode - result->SetData(points); - result->SetName(name); - result->SetColor(color); - - mitk::PointSetVtkMapper3D::Pointer mapper; - - // create mapper for trajectory visualization - if(m_PlayerWidget->IsTrajectoryInSplineMode()) - mapper = this->GetTrajectoryMapper(Splines); - else - mapper = this->GetTrajectoryMapper(Points); - - result->SetMapper(mitk::BaseRenderer::Standard3D, mapper); - - // trajectory properties - result->SetProperty("contourcolor", mitk::ColorProperty::New(color)); - result->SetBoolProperty("show contour", true); - result->SetBoolProperty("updateDataOnRender", false); - - return result; -} - - -mitk::DataNode::Pointer QmitkNavigationDataPlayerView::CreateRepresentationObject(const std::string& name, const mitk::Color color) -{ - mitk::DataNode::Pointer representationNode = mitk::DataNode::New(); - - // creating cone DataNode for tool visualization - mitk::Cone::Pointer cone = mitk::Cone::New(); - vtkConeSource* vtkData = vtkConeSource::New(); - - vtkData->SetRadius(7.5); - vtkData->SetHeight(15.0); - vtkData->SetDirection(0.0, 0.0, 1.0); - vtkData->SetCenter(0.0, 0.0, 0.0); - vtkData->SetResolution(20); - vtkData->CappingOn(); - vtkData->Update(); - - cone->SetVtkPolyData(vtkData->GetOutput()); - - vtkData->Delete(); - - representationNode->SetData(cone); - - representationNode->GetPropertyList()->SetProperty("name", mitk::StringProperty::New( name.c_str() )); - representationNode->GetPropertyList()->SetProperty("layer", mitk::IntProperty::New(0)); - representationNode->GetPropertyList()->SetProperty("visible", mitk::BoolProperty::New(true)); - representationNode->SetColor(color); - representationNode->SetOpacity(1.0); - representationNode->Modified(); - - return representationNode; + // Initialize Widgets and create Player + OnSelectPlayer(); } - -void QmitkNavigationDataPlayerView::OnPerformPlaybackVisualization() -{ - if(m_PlayerWidget == NULL || m_Visualizer.IsNull()) - return; - - static int update = 0; - static int counter = -1; - - for(unsigned int i = 0 ; i < m_PlayerWidget->GetNavigationDatas().size(); ++i) +void QmitkNavigationDataPlayerView::OnSelectPlayer(){ + if (m_Controls->m_RdbSequential->isChecked()) { - m_Visualizer->SetInput(i, m_PlayerWidget->GetNavigationDatas().at(i)); // pass updated tool NDs to visualizer - - - // show trajectory for selected tool with user given resolution - if(m_ShowTrajectory && (i == m_TrajectoryIndex) && (update++ % m_PlayerWidget->GetResolution() == 0) ) - { - - mitk::PointSet::PointType currentPoint = m_PlayerWidget->GetNavigationDataPoint(i); // current ND point for tool trajectory - - // if realtime mode is selected, trajectory points that are equal in position to their antecessor - // will not be inserted in the trajectory pointset to avoid "vtk can't create normals" warning - if(m_PlayerWidget->GetCurrentPlaybackMode() == QmitkIGTPlayerWidget::RealTimeMode) - { - mitk::PointSet::PointType lastPoint; - if(counter == -1) - { - lastPoint[0] = -1; - lastPoint[1] = -1; - lastPoint[2] = -1; - } - else - lastPoint = m_TrajectoryPointSet->GetPoint(counter); // antecessor point is last point from PointSet - - mitk::PointSet::PointType currentPoint = m_PlayerWidget->GetNavigationDataPoint(i); - - // check for position differences between last and current point - bool diff0 = lastPoint[0] != currentPoint[0]; - bool diff1 = lastPoint[1] != currentPoint[1]; - bool diff2 = lastPoint[2] != currentPoint[2]; - - if(diff0 || diff1 || diff2) - m_TrajectoryPointSet->InsertPoint(++counter, currentPoint); // insert only if there are differences - } - else - { - m_TrajectoryPointSet->InsertPoint(++counter, currentPoint); // insert point in trajectory PointSet - } - - } + m_Controls->m_SequentialWidget->setVisible(true); + m_Controls->m_TimedWidget->setVisible(false); + mitk::NavigationDataSequentialPlayer::Pointer seqPlayer = mitk::NavigationDataSequentialPlayer::New(); + seqPlayer->SetNavigationDataSet(m_Data); + m_Controls->m_SequentialWidget->SetPlayer(seqPlayer); + m_Player = seqPlayer; + } else { + m_Controls->m_SequentialWidget->setVisible(false); + m_Controls->m_TimedWidget->setVisible(true); + mitk::NavigationDataPlayer::Pointer timedPlayer = mitk::NavigationDataPlayer::New(); + timedPlayer->SetNavigationDataSet(m_Data); + m_Controls->m_TimedWidget->SetPlayer(timedPlayer); + m_Player = timedPlayer; } - this->RenderScene(); + // SetupRenderingPipeline + OnSetDisplay(); } -void QmitkNavigationDataPlayerView::RenderScene() -{ - try - { - if (m_Visualizer.IsNull() || this->GetActiveStdMultiWidget() == NULL) - return; - - try - { - m_Visualizer->Update(); - } - catch(std::exception& e) - { - std::cout << "Exception during QmitkNavigationDataPlayerView::RenderScene():" << e.what() << "\n"; - } - - //update all Widgets - // mitk::RenderingManager::GetInstance()->RequestUpdateAll(mitk::RenderingManager::REQUEST_UPDATE_3DWINDOWS); - - // update only Widget4 - mitk::BaseRenderer::GetInstance(m_MultiWidget->mitkWidget4->GetRenderWindow())->RequestUpdate(); // update 3D render window - } - catch (std::exception& e) - { - std::cout << "RenderAll exception: " << e.what() << "\n"; - } - catch (...) - { - std::cout << "RenderAll unknown exception\n"; - } +void ConfigurePlayer(){ + // FIXME: Why is repeat not available in the base class? + // TODO finish method } -void QmitkNavigationDataPlayerView::OnReinit() -{ - - std::vector::iterator it; - - mitk::DataStorage* ds = this->GetDefaultDataStorage(); - - // clear tool representation objects from DataStorage - for ( it = m_RepresentationObjects.begin() ; it != m_RepresentationObjects.end(); it++ ) - { - //ds->Remove(*it); - mitk::DataNode::Pointer dn = ds->GetNamedNode((*it)->GetName()); - if(dn.IsNotNull()) - ds->Remove(dn); - } - - m_RepresentationObjects.clear(); // clear tool representation objects vector - - if(m_Trajectory.IsNotNull()) - this->GetDefaultDataStorage()->Remove(m_Trajectory); // remove trajectory DataNode from DataStorage - - m_TrajectoryPointSet->Clear(); // clear trajectory PointSet - this->m_PlayerWidget->ClearTrajectorySelectCombobox(); // clear trajectory selection combobox in player widget - - m_ReloadData = true; // set flag to true so representation data will be reload if play is triggered again - -} - -void QmitkNavigationDataPlayerView::AddTrajectory(mitk::DataStorage* ds, mitk::DataNode::Pointer trajectoryNode) -{ - if(ds == NULL) - return; - - if(m_Trajectory.IsNotNull()) - ds->Remove(m_Trajectory); // remove trajectory from DataStorage if already exists - - - // add trajectory to DataStorage - if(ds != NULL && trajectoryNode.IsNotNull()) - { - m_Trajectory = trajectoryNode; - ds->Add(m_Trajectory); - } +void QmitkNavigationDataPlayerView::OnSetRepeat(){ + MITK_WARN << "Repeat not yet supported"; } -void QmitkNavigationDataPlayerView::AddRepresentationObject(mitk::DataStorage* ds, mitk::DataNode::Pointer reprObject) -{ - m_RepresentationObjects.push_back(reprObject); - ds->Add(reprObject); +void QmitkNavigationDataPlayerView::OnSetMicroservice(){ + MITK_WARN << "Register as Microservice not yet supported"; } -void QmitkNavigationDataPlayerView::RemoveRepresentationObject(mitk::DataStorage* ds, mitk::DataNode::Pointer reprObject) -{ - std::vector::iterator it; - - for ( it = m_RepresentationObjects.begin() ; it != m_RepresentationObjects.end(); it++ ) - { - if(*it == reprObject) - { - m_RepresentationObjects.erase(it); - ds->Remove(reprObject); - } - } +void QmitkNavigationDataPlayerView::OnUpdate(){ + m_VisFilter->Update(); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } -void QmitkNavigationDataPlayerView::OnShowTrajectory(int index) -{ - - mitk::DataStorage* ds = this->GetDefaultDataStorage(); - - - // no trajectory selected - if(index == 0) - { - m_ShowTrajectory = false; - m_TrajectoryIndex = -1; - - if(m_Trajectory.IsNotNull()) - ds->Remove(m_Trajectory); - } - - else +void QmitkNavigationDataPlayerView::OnSetDisplay(){ + DestroyPipeline(); + if ( (m_Controls->m_ChkDisplay->isChecked()) && ( m_Player.IsNotNull() )) { - m_ShowTrajectory = true; - - // index-1 because combobox is filled with infovalue at index = 0 - mitk::DataNode::Pointer replayObject = m_RepresentationObjects.at(index-1); - - std::string prefix("Trajectory of "); - std::string name = replayObject->GetName(); - - mitk::Color color = this->GetColorCircleColor(index-1); - - if(m_TrajectoryPointSet.IsNotNull()) - m_TrajectoryPointSet->Clear(); - - m_TrajectoryIndex = index-1; - - mitk::DataNode::Pointer trajectory = this->CreateTrajectory( m_TrajectoryPointSet, prefix.append(name), color ); - this->AddTrajectory(this->GetDefaultDataStorage(), trajectory); + CreatePipeline(); } } - -void QmitkNavigationDataPlayerView::OnEnableSplineTrajectoryMapper(bool enable) -{ - if(m_Trajectory.IsNull()) - return; - - // if enabled set spline mapper - if(enable) - m_Trajectory->SetMapper(mitk::BaseRenderer::Standard3D, this->GetTrajectoryMapper(Splines)); - - // if disabled set pointset mapper - else - m_Trajectory->SetMapper(mitk::BaseRenderer::Standard3D, this->GetTrajectoryMapper(Points)); - - - mitk::RenderingManager::GetInstance()->RequestUpdateAll(); // request update after mapper change -} - - - -mitk::Color QmitkNavigationDataPlayerView::GetColorCircleColor(int index) -{ - mitk::Color result; - - mitk::ColorSequenceCycleH colorCycle; - - for(int i=0; i <= index; ++i) - { - result = colorCycle.GetNextColor(); +void QmitkNavigationDataPlayerView::CreatePipeline(){ + m_VisFilter = mitk::NavigationDataObjectVisualizationFilter::New(); + + for (unsigned int i = 0 ; i < m_Player->GetNumberOfIndexedOutputs(); i++ ) { + mitk::DataNode::Pointer node = mitk::DataNode::New(); + // TODO Give Nodes a proper name + m_VisFilter->SetInput(i, m_Player->GetOutput(i)); + + //create small sphere and use it as surface + mitk::Surface::Pointer mySphere = mitk::Surface::New(); + vtkSphereSource *vtkData = vtkSphereSource::New(); + vtkData->SetRadius(5.0f); + vtkData->SetCenter(0.0, 0.0, 0.0); + vtkData->Update(); + mySphere->SetVtkPolyData(vtkData->GetOutput()); + vtkData->Delete(); + node->SetData(mySphere); + m_VisFilter->SetRepresentationObject(i, mySphere); + + // Add Node to DataStorageand to local list of Nodes + GetDataStorage()->Add(node); + m_RenderingNodes.push_back(node); } - - return result; } - -mitk::PointSetVtkMapper3D::Pointer QmitkNavigationDataPlayerView::GetTrajectoryMapper(TrajectoryStyle style) -{ - if(style == Points) - { - if(m_PointSetMapper.IsNull()) - m_PointSetMapper = mitk::PointSetVtkMapper3D::New(); - - return m_PointSetMapper; +void QmitkNavigationDataPlayerView::DestroyPipeline(){ + m_VisFilter = NULL; + for (unsigned int i = 0; i < m_RenderingNodes.size(); i++){ + this->GetDataStorage()->Remove(m_RenderingNodes[i]); } - - else if(style == Splines) - { - if(m_SplineMapper.IsNull()) - m_SplineMapper = mitk::SplineVtkMapper3D::New(); - - return m_SplineMapper.GetPointer(); - } - else - return NULL; -} - - - - + m_RenderingNodes.clear(); +} \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.h b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.h index ce3af69378..961c3b7dcb 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.h +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.h @@ -1,177 +1,129 @@ /*=================================================================== 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 QmitkNavigationDataPlayerView_h #define QmitkNavigationDataPlayerView_h #include //Qmitk #include #include -#include - // ui #include "ui_QmitkNavigationDataPlayerViewControls.h" //mitk -#include #include - - - - /*! \brief QmitkNavigationDataPlayerView \warning This application module is not yet documented. Use "svn blame/praise/annotate" and ask the author to provide basic documentation. \sa QmitkFunctionality \ingroup Functionalities */ class QmitkNavigationDataPlayerView : public QmitkFunctionality { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const std::string VIEW_ID; QmitkNavigationDataPlayerView(); virtual ~QmitkNavigationDataPlayerView(); virtual void CreateQtPartControl(QWidget *parent); /** \brief This method creates this bundle's SIGNAL and SLOT connections */ virtual void CreateConnections(); - - virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget); - virtual void StdMultiWidgetNotAvailable(); - - protected slots: /*! - \brief Creates DataNodes for all available playback objects + \brief FIXME not currently used */ - void OnCreatePlaybackVisualization(); + void OnPlayingStarted(); + /*! - \brief Assigns position changings from the player widget to the visualization objects + \brief loads a file and triggers creation of players and the pipeline */ - void OnPerformPlaybackVisualization(); + void OnOpenFile(); + /*! - \brief Reinits this player. Cleans all timers and trajectory data + \brief Creates the correct player and displays the according widget */ - void OnReinit(); + void OnSelectPlayer(); + /*! - \brief Shows trajectory of tool with index + \brief FIXME not currently used */ - void OnShowTrajectory(int index); + void OnSetRepeat(); + /*! - \brief Cleans trajectory data before playing is started + \brief FIXME not currently used */ - void OnPlayingStarted(); + void OnSetMicroservice(); + /*! - \brief Enables or disables trajectory visualization with splines + \brief Triggers the creation and destruction of the rendering pipeline */ - void OnEnableSplineTrajectoryMapper(bool enable); + void OnSetDisplay(); + /*! + \brief FIXME not currently used + */ + void OnUpdate(); protected: - enum TrajectoryStyle { - Points = 1, - Splines = 2 - }; - - void CreateBundleWidgets(QWidget* parent); - - /** - \brief Refreshes the visualization of the playback object DataNodes. - */ - void RenderScene(); - - /** - \brief Creates representation DataNode with given name and color - */ - mitk::DataNode::Pointer CreateRepresentationObject( const std::string& name , const mitk::Color color ); - /** - \brief Adds representation DataNode to the DataStorage - */ - void AddRepresentationObject(mitk::DataStorage* ds, mitk::DataNode::Pointer reprObject); /** - \brief Removes representation DataNode from the DataStorage + * \brief configures the player according to the checkboxes set in the GUI */ - void RemoveRepresentationObject(mitk::DataStorage* ds, mitk::DataNode::Pointer reprObject); + void ConfigurePlayer(); /** - \brief Adds trajectory DataNode to the DataStorage + * \brief Creates the Rendering Pipeline necessary to Render the images */ - void AddTrajectory(mitk::DataStorage* ds, mitk::DataNode::Pointer trajectoryNode); + void CreatePipeline(); /** - \brief Creates a trajectory DataNode from given PointSet with given name and color + * \brief Destroys the Rendering Pipeline (but not the player) */ - mitk::DataNode::Pointer CreateTrajectory( mitk::PointSet::Pointer points, const std::string& name, const mitk::Color color ); - - + void DestroyPipeline(); + void CreateBundleWidgets(QWidget* parent); Ui::QmitkNavigationDataPlayerViewControls* m_Controls; + mitk::NavigationDataObjectVisualizationFilter::Pointer m_VisFilter; + std::vector m_RenderingNodes; + mitk::NavigationDataPlayerBase::Pointer m_Player; + mitk::NavigationDataSet::Pointer m_Data; + QmitkStdMultiWidget* m_MultiWidget; QmitkIGTPlayerWidget* m_PlayerWidget; ///< this bundle's playback widget - mitk::NavigationDataObjectVisualizationFilter::Pointer m_Visualizer; ///< this filter visualizes the navigation data - - std::vector m_RepresentationObjects; ///< vector for current visualization objects - - mitk::DataNode::Pointer m_Trajectory; ///< main trajectory visualization DataNode - mitk::PointSet::Pointer m_TrajectoryPointSet; ///< PointSet with all points for trajectory - int m_TrajectoryIndex; ///< trajectory tool index - - bool m_ReloadData; ///< flag needed for refresh of visualization if needed - bool m_ShowTrajectory; ///< flag needed for trajectory visualization - - mitk::SplineVtkMapper3D::Pointer m_SplineMapper; ///< spline trajectory mapper - mitk::PointSetVtkMapper3D::Pointer m_PointSetMapper; ///< standard trajectroy mapper - - - - private: - /** - \brief Returns color from colorcycle with given index - */ - mitk::Color GetColorCircleColor(int index); - /** - \brief Returns the trajectory mapper for the given style if stıle is not Points or Splines NULL will be returned. - */ - mitk::PointSetVtkMapper3D::Pointer GetTrajectoryMapper(TrajectoryStyle style); - }; - - -#endif // _QMITKNAVIGATIONDATAPLAYERVIEW_H_INCLUDED - +#endif // _QMITKNAVIGATIONDATAPLAYERVIEW_H_INCLUDED \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerViewControls.ui b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerViewControls.ui index f136cc7545..e7320deee2 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerViewControls.ui +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerViewControls.ui @@ -1,44 +1,185 @@ QmitkNavigationDataPlayerViewControls 0 0 - 222 - 161 + 415 + 762 0 0 QmitkTemplate - + + + File Management + + + + + + + + Open File + + + + + + + No navigation data set loaded... + + + + + + + Frames: + + + + + + + Tools: + + + + + + + N/A + + + + + + + N/A + + + + + + + + + + + + Settings + + + + + + + + Sequential Player + + + true + + + + + + + Time-based Player + + + + + + + + + Repeat + + + true + + + + + + + Register as Microservice + + + true + + + + + + + Display + + + true + + + + + + + + + + Player Controls + + + + + + + + + + + + + Qt::Vertical - - QSizePolicy::Expanding - 20 - 220 + 40 + + + QmitkNavigationDataSequentialPlayerControlWidget + QWidget +
QmitkNavigationDataSequentialPlayerControlWidget.h
+ 1 +
+ + QmitkNavigationDataPlayerControlWidget + QWidget +
QmitkNavigationDataPlayerControlWidget.h
+ 1 +
+