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 eddacc6619..9c7a0c1c56 100644 --- a/Modules/IGT/IO/mitkNavigationDataPlayer.cpp +++ b/Modules/IGT/IO/mitkNavigationDataPlayer.cpp @@ -1,550 +1,152 @@ /*=================================================================== 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_NumberOfOutputs = 0; - m_Pause = false; - m_Playing = false; - m_Stream = NULL; - m_PlayerMode = NormalFile; - m_FileName = ""; - m_FileVersion = 1; - m_Playing = false; - m_Pause = false; - m_NumberOfOutputs = 0; - m_StartPlayingTimeStamp = 0.0; - m_PauseTimeStamp = 0.0; - m_parentElement = NULL; - m_currentNode = NULL; - m_StreamEnd = false; - m_StreamSetOutsideFromClass = false; - - //To get a start time + // 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(); + // get elapsed time since start of playing + TimeStampType timeSinceStart = + mitk::IGTTimeStamp::GetInstance()->GetElapsed() - m_StartPlayingTimeStamp; - //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)); - - 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() > timeSinceStart) { - 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++) + // first element was greater than timestamp -> return null + if ( m_NavigationDataSetIterator == m_NavigationDataSet->Begin() ) { - mitk::NavigationData* output = this->GetOutput(index); - assert(output); - output->Graft(lastCandidates.at(index)); - m_NextToPlayNavigationData[index] = nextCandidates.at(index); - } -} + MITK_WARN("NavigationDataSet") << "No NavigationData was recorded before given timestamp."; - -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?"); + //The output is not at this time + this->GraftEmptyOutput(); 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) - { - StreamInvalid("Playing not possible. Invalid file version!"); - return; - } - - if(m_NumberOfOutputs == 0) {m_NumberOfOutputs = GetNumberOfNavigationDatas(m_Stream);} - - //with the information about the tracked tool number we can generate the output - if (m_NumberOfOutputs > 0) - { - //Generate the output only if there are changes to the amount of outputs - //This happens when the player is stopped and start again with different file - if (this->GetNumberOfOutputs() != m_NumberOfOutputs) {SetNumberOfOutputs(m_NumberOfOutputs);} - //initialize the player with first data - GetFirstData(); - //set stream valid - m_ErrorMessage = ""; - m_StreamValid = true; - } - else - { - StreamInvalid("The input stream seems to have NavigationData incompatible format"); - return; - } - -} - -unsigned int mitk::NavigationDataPlayer::GetFileVersion(std::istream* stream) -{ - if (stream==NULL) - { - MITK_ERROR << "No input stream set!"; - mitkThrowException(mitk::IGTException)<<"No input stream set!"; - } - if (!stream->good()) - { - MITK_ERROR << "Stream 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); - } + mitk::NavigationDataSet::NavigationDataSetIterator curIterator = m_NavigationDataSetIterator-1; + output->Graft(curIterator->at(index)); } - else - { - m_parentElement->QueryIntAttribute("Ver",&version); - } - - if (version > 0) - return version; - else - return 0; -} - - -unsigned int mitk::NavigationDataPlayer::GetNumberOfNavigationDatas(std::istream* stream) -{ - if (stream == NULL) - { - MITK_ERROR << "No input stream set!"; - mitkThrowException(mitk::IGTException)<<"No input stream set!"; - } - if (!stream->good()) + // stop playing if the last NavigationData objects were grafted + if (m_NavigationDataSetIterator == m_NavigationDataSet->End()) { - 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; + this->StopPlaying(); } - 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() -{ + m_CurPlayerState = PlayerStopped; - //Here we read the first lines of input (dependend on the number of inputs) - for (unsigned int index=0; index < m_NumberOfOutputs; index++) - { - //Here we init the vector for later use - m_NextToPlayNavigationData.push_back(NULL); - m_StartTimeOfData.push_back(0.0); - mitk::NavigationData::Pointer nd = this->GetOutput(index); - - switch(m_FileVersion) - { - case 1: - m_NextToPlayNavigationData[index] = ReadVersion1(); - //check if there is valid data in it - - if (m_NextToPlayNavigationData[index].IsNull()) - { - m_StreamEnd = true; - StopPlaying(); - 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() -{ - 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(); -} - -bool mitk::NavigationDataPlayer::IsAtEnd() -{ - return this->m_StreamEnd; -} - -void mitk::NavigationDataPlayer::StreamInvalid(std::string message) -{ - m_StreamEnd = true; - StopPlaying(); - m_ErrorMessage = message; - m_StreamValid = false; - mitkThrowException(mitk::IGTIOException) << "Invalid stream!"; -} \ No newline at end of file diff --git a/Modules/IGT/IO/mitkNavigationDataPlayer.h b/Modules/IGT/IO/mitkNavigationDataPlayer.h index 0ea226f904..7c00898a54 100644 --- a/Modules/IGT/IO/mitkNavigationDataPlayer.h +++ b/Modules/IGT/IO/mitkNavigationDataPlayer.h @@ -1,225 +1,103 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKNavigationDataPlayer_H_HEADER_INCLUDED_ #define MITKNavigationDataPlayer_H_HEADER_INCLUDED_ #include -#include -#include //for the Recording Mode enum -#include "mitkTrackingDevice.h" #include -#include "tinyxml.h" -#include - namespace mitk { /**Documentation * \brief This class is used to play recorded (see mitkNavigationDataRecorder class) files. * * If you want to play a file you have to set an input stream. This can be an own one (use StartPlaying(std::istream*)) * or a preset (use StartPlaying()). The presets are NormalFile and ZipFile and can be set with the method * SetPlayerMode(PlayerMode). The presets need a FileName. Therefore the FileName must be set before the preset. * For pausing the player call Pause(). A call of Resume() will continue the playing. * * * \ingroup IGT */ class MitkIGT_EXPORT NavigationDataPlayer : public NavigationDataPlayerBase { public: mitkClassMacro(NavigationDataPlayer, NavigationDataPlayerBase); itkNewMacro(Self); - /** - * \brief sets the file name and path for the PlayerMode NormalFile and ZipFile - */ - itkSetStringMacro(FileName); - - /** - * \brief returns the file name and path for the PlayerMode NormalFile and ZipFile - */ - itkGetStringMacro(FileName); - - /** * \brief Used for pipeline update just to tell the pipeline that we always have to update */ virtual void UpdateOutputInformation(); /** * \brief This method starts the player. * - * Before the stream has to be set. Either with a PlayingMode (SetStream(PlayerMode)) and FileName. Or - * with an own inputstream (SetStream(istream*)). + * 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(); - - /** - * \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); - 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(); + enum PlayerState { PlayerStopped, PlayerRunning, PlayerPaused }; + PlayerState m_CurPlayerState; - /** - * \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(); + typedef mitk::NavigationData::TimeStampType TimeStampType; /** - * \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(); + * \brief The start time of the playing. Set in the method mitk::NavigationDataPlayer::StartPlaying(). + */ + TimeStampType m_StartPlayingTimeStamp; /** - * \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 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; }; } // namespace mitk #endif /* MITKNavigationDataPlayer_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/IO/mitkNavigationDataPlayerBase.cpp b/Modules/IGT/IO/mitkNavigationDataPlayerBase.cpp index 8edca1fb68..84e87b6b6b 100644 --- a/Modules/IGT/IO/mitkNavigationDataPlayerBase.cpp +++ b/Modules/IGT/IO/mitkNavigationDataPlayerBase.cpp @@ -1,118 +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. ===================================================================*/ #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; +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..01d12e6d7f 100644 --- a/Modules/IGT/IO/mitkNavigationDataPlayerBase.h +++ b/Modules/IGT/IO/mitkNavigationDataPlayerBase.h @@ -1,78 +1,104 @@ /*=================================================================== 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. - */ - itkGetStringMacro(ErrorMessage); + 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); - /** @return Retruns if the current stream is valid or not. */ - itkGetMacro(StreamValid,bool); + /** + * \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. + */ + unsigned int GetNumberOfSnapshots(); - /** - * \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(); + + NavigationDataSet::Pointer m_NavigationDataSet; - 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 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 bbd1d4f191..8d013cdf9d 100644 --- a/Modules/IGT/IO/mitkNavigationDataRecorder.h +++ b/Modules/IGT/IO/mitkNavigationDataRecorder.h @@ -1,219 +1,119 @@ /*=================================================================== 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 ); itkNewMacro( 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 df453b3da1..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->SetNumberOfOutputs(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 389634b835..bbabaf757d 100644 --- a/Modules/IGT/IO/mitkNavigationDataSequentialPlayer.h +++ b/Modules/IGT/IO/mitkNavigationDataSequentialPlayer.h @@ -1,122 +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); itkNewMacro(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); - - /** - * @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; - 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 8fc4665475..274b641bde 100644 --- a/Modules/IGT/Testing/files.cmake +++ b/Modules/IGT/Testing/files.cmake @@ -1,45 +1,47 @@ set(MODULE_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 # see bug 11636 (extend this test by microservices) mitkTrackingDeviceSourceTest.cpp mitkTrackingDeviceSourceConfiguratorTest.cpp mitkNavigationDataEvaluationFilterTest.cpp mitkTrackingTypesTest.cpp # ------------------ Navigation Tool Management Tests ------------------- mitkNavigationToolStorageTest.cpp mitkNavigationToolTest.cpp mitkNavigationToolReaderAndWriterTest.cpp mitkNavigationToolStorageSerializerAndDeserializerTest.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 c76bacec5b..3b23aa2ebd 100644 --- a/Modules/IGT/Testing/mitkNavigationDataPlayerTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationDataPlayerTest.cpp @@ -1,550 +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."); + } + MITK_TEST_CONDITION_REQUIRED(InvalidStreamException3, "Testing Invalid Stream method if exception (wrong file version) was thrown."); - //case 4: wrong file - player = mitk::NavigationDataPlayer::New(); - player->SetFileName( "cs:\fsd/$%§²³ffdsd" ); - bool InvalidStreamException4=false; - try - { + //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; - 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 2d13f8f2bb..7a683b699e 100644 --- a/Modules/IGT/Testing/mitkNavigationDataRecorderTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationDataRecorderTest.cpp @@ -1,339 +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() +class mitkNavigationDataRecorderTestClass { - 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"); +public: - mitk::NavigationData::Pointer naviData = mitk::NavigationData::New(); - recorder->AddNavigationData( naviData ); - 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(); - - 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++ ) + static bool CompareFiles(std::string file1, std::string file2) { - mitk::Point3D pnt; - pnt[0] = i + 1; - pnt[1] = i + 1/2; - pnt[2] = i +1*3; - naviData->SetPosition(pnt); - recorder->Update(); + 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); } - 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() -{ - 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(); - - 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++ ) - { - mitk::Point3D pnt; - pnt[0] = i + 1; - pnt[1] = i + 1/2; - pnt[2] = i +1*3; - - naviData->SetPosition(pnt); - recorder->Update(); - } - - 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 - { - if (myFileXML.exists()) - {myFileXML.remove();} - } - catch(std::exception e) - { - MITK_WARN << "Cannot delete file while cleanup: " << filenameXML; - } - - 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 b92650d64a..b1571c0af6 100644 --- a/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp @@ -1,224 +1,266 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include "mitkTestingMacros.h" +#include "mitkNavigationDataReaderXML.h" #include #include //foe exceptions #include "mitkIGTException.h" #include "mitkIGTIOException.h" -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 { myTestPlayer2->GoToSnapshot(1000); } catch(mitk::IGTException) { exceptionThrown2=true; } - MITK_TEST_CONDITION_REQUIRED(exceptionThrown2, "Testing if exception is thrown when GoToSnapShot method is called with an index that doesn't exist."); + MITK_TEST_CONDITION(exceptionThrown2, "Testing if exception is thrown when GoToSnapShot method is called with an index that doesn't exist."); } void TestSetXMLStringException() { mitk::NavigationDataSequentialPlayer::Pointer myTestPlayer3 = mitk::NavigationDataSequentialPlayer::New(); bool exceptionThrown3=false; //The string above XML_INVALID_TESTSTRING is a wrong string, some element were deleted in above try { - 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/files.cmake b/Modules/IGT/files.cmake index 57360ee6aa..3620d42933 100644 --- a/Modules/IGT/files.cmake +++ b/Modules/IGT/files.cmake @@ -1,74 +1,80 @@ set(CPP_FILES Algorithms/mitkNavigationDataDisplacementFilter.cpp Algorithms/mitkNavigationDataEvaluationFilter.cpp Algorithms/mitkNavigationDataLandmarkTransformFilter.cpp Algorithms/mitkNavigationDataReferenceTransformFilter.cpp Algorithms/mitkNavigationDataToMessageFilter.cpp Algorithms/mitkNavigationDataToNavigationDataFilter.cpp Algorithms/mitkNavigationDataToPointSetFilter.cpp Algorithms/mitkNavigationDataTransformFilter.cpp Common/mitkIGTTimeStamp.cpp Common/mitkSerialCommunication.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 ) 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 45438a4e01..d8b26355e4 100644 --- a/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.cpp @@ -1,573 +1,590 @@ /*=================================================================== 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) { m_Controls = NULL; CreateQtPartControl(this); 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 } } 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()) ); } } 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(CheckInputFileValid()) // no playing possible without valid input file { 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; } 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; } 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; if(isRealTimeMode && m_StartTime < 0) m_StartTime = m_RealTimePlayer->GetOutput()->GetTimeStamp(); // get playback start time if(isRealTimeMode && !m_RealTimePlayer->IsAtEnd()) { m_RealTimePlayer->Update(); // update player int msc = (int) (m_RealTimePlayer->GetOutput()->GetTimeStamp() - m_StartTime); // 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 m_Controls->msecLCDNumber->display(ms); m_Controls->secLCDNumber->display(s); m_Controls->minLCDNumber->display(min); emit SignalPlayerUpdated(); // player successfully updated } else if(isSequentialMode && (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)); //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 } 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(); result[0] = position[0]; result[1] = position[1]; result[2] = position[2]; } return result; } void QmitkIGTPlayerWidget::SetInputFileName(const QString& inputFileName) { 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); } } void QmitkIGTPlayerWidget::SetRealTimePlayer( mitk::NavigationDataPlayer::Pointer player ) { if(player.IsNotNull()) m_RealTimePlayer = player; } void QmitkIGTPlayerWidget::SetSequentialPlayer( mitk::NavigationDataSequentialPlayer::Pointer player ) { if(player.IsNotNull()) m_SequentialPlayer = player; } void QmitkIGTPlayerWidget::OnSelectPressed() { QString oldName = m_CmpFilename; m_CmpFilename.clear(); m_CmpFilename = QFileDialog::getOpenFileName(this, "Load tracking data", QDir::currentPath(),"XML files (*.xml)"); 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(); } m_Controls->inputFileLineEdit->setText(m_CmpFilename); } 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")); } 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 } 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); } } 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 { m_SequentialPlayer->GoToSnapshot(currentSliderValue); // 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/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp index d0d65b173e..dedb886e9b 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp @@ -1,726 +1,747 @@ /*=================================================================== 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 "QmitkMITKIGTTrackingToolboxView.h" #include "QmitkStdMultiWidget.h" // Qt #include #include // MITK #include #include #include #include #include #include #include +#include +#include // vtk #include //for exceptions #include #include const std::string QmitkMITKIGTTrackingToolboxView::VIEW_ID = "org.mitk.views.mitkigttrackingtoolbox"; QmitkMITKIGTTrackingToolboxView::QmitkMITKIGTTrackingToolboxView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget( NULL ) { m_TrackingTimer = new QTimer(this); m_tracking = false; m_logging = false; m_loggedFrames = 0; } QmitkMITKIGTTrackingToolboxView::~QmitkMITKIGTTrackingToolboxView() { //remove the tracking volume this->GetDataStorage()->Remove(m_TrackingVolumeNode); //remove the tool storage m_toolStorage->UnRegisterMicroservice(); } void QmitkMITKIGTTrackingToolboxView::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::QmitkMITKIGTTrackingToolboxViewControls; m_Controls->setupUi( parent ); //create connections connect( m_Controls->m_LoadTools, SIGNAL(clicked()), this, SLOT(OnLoadTools()) ); connect( m_Controls->m_Connect, SIGNAL(clicked()), this, SLOT(OnConnect()) ); connect( m_Controls->m_Disconnect, SIGNAL(clicked()), this, SLOT(OnDisconnect()) ); connect( m_Controls->m_StartTracking, SIGNAL(clicked()), this, SLOT(OnStartTracking()) ); connect( m_Controls->m_StopTracking, SIGNAL(clicked()), this, SLOT(OnStopTracking()) ); connect( m_TrackingTimer, SIGNAL(timeout()), this, SLOT(UpdateTrackingTimer())); connect( m_Controls->m_ChooseFile, SIGNAL(clicked()), this, SLOT(OnChooseFileClicked())); connect( m_Controls->m_StartLogging, SIGNAL(clicked()), this, SLOT(StartLogging())); connect( m_Controls->m_StopLogging, SIGNAL(clicked()), this, SLOT(StopLogging())); connect( m_Controls->m_configurationWidget, SIGNAL(TrackingDeviceSelectionChanged()), this, SLOT(OnTrackingDeviceChanged())); connect( m_Controls->m_VolumeSelectionBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(OnTrackingVolumeChanged(QString))); connect( m_Controls->m_ShowTrackingVolume, SIGNAL(clicked()), this, SLOT(OnShowTrackingVolumeChanged())); connect( m_Controls->m_AutoDetectTools, SIGNAL(clicked()), this, SLOT(OnAutoDetectTools())); connect( m_Controls->m_ResetTools, SIGNAL(clicked()), this, SLOT(OnResetTools())); connect( m_Controls->m_AddSingleTool, SIGNAL(clicked()), this, SLOT(OnAddSingleTool())); connect( m_Controls->m_NavigationToolCreationWidget, SIGNAL(NavigationToolFinished()), this, SLOT(OnAddSingleToolFinished())); connect( m_Controls->m_NavigationToolCreationWidget, SIGNAL(Canceled()), this, SLOT(OnAddSingleToolCanceled())); //initialize widgets m_Controls->m_configurationWidget->EnableAdvancedUserControl(false); m_Controls->m_TrackingToolsStatusWidget->SetShowPositions(true); m_Controls->m_TrackingToolsStatusWidget->SetTextAlignment(Qt::AlignLeft); //initialize tracking volume node m_TrackingVolumeNode = mitk::DataNode::New(); m_TrackingVolumeNode->SetName("TrackingVolume"); m_TrackingVolumeNode->SetOpacity(0.25); m_TrackingVolumeNode->SetBoolProperty("Backface Culling",true); mitk::Color red; red.SetRed(1); m_TrackingVolumeNode->SetColor(red); GetDataStorage()->Add(m_TrackingVolumeNode); //initialize buttons m_Controls->m_Connect->setEnabled(true); m_Controls->m_Disconnect->setEnabled(false); m_Controls->m_StartTracking->setEnabled(false); m_Controls->m_StopTracking->setEnabled(false); m_Controls->m_AutoDetectTools->setVisible(false); //only visible if tracking device is Aurora //Update List of available models for selected tool. std::vector Compatibles = mitk::GetDeviceDataForLine( m_Controls->m_configurationWidget->GetTrackingDevice()->GetType()); m_Controls->m_VolumeSelectionBox->clear(); for(int i = 0; i < Compatibles.size(); i++) { m_Controls->m_VolumeSelectionBox->addItem(Compatibles[i].Model.c_str()); } //initialize tool storage m_toolStorage = mitk::NavigationToolStorage::New(GetDataStorage()); m_toolStorage->SetName("TrackingToolbox Default Storage"); m_toolStorage->RegisterAsMicroservice("no tracking device"); } } void QmitkMITKIGTTrackingToolboxView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkMITKIGTTrackingToolboxView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkMITKIGTTrackingToolboxView::OnLoadTools() { //read in filename QString filename = QFileDialog::getOpenFileName(NULL,tr("Open Tool Storage"), "/", tr("Tool Storage Files (*.IGTToolStorage)")); if (filename.isNull()) return; //read tool storage from disk std::string errorMessage = ""; mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(GetDataStorage()); // try-catch block for exceptions try { this->ReplaceCurrentToolStorage(myDeserializer->Deserialize(filename.toStdString()),filename.toStdString()); } catch(mitk::IGTException) { std::string errormessage = "Error during deserializing. Problems with file,please check the file?"; QMessageBox::warning(NULL, "IGTPlayer: Error", errormessage.c_str()); return; } if(m_toolStorage->isEmpty()) { errorMessage = myDeserializer->GetErrorMessage(); MessageBox(errorMessage); return; } //update label Poco::Path myPath = Poco::Path(filename.toStdString()); //use this to seperate filename from path QString toolLabel = QString("Loaded Tools: ") + QString::number(m_toolStorage->GetToolCount()) + " Tools from " + myPath.getFileName().c_str(); m_Controls->m_toolLabel->setText(toolLabel); //update tool preview m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); } void QmitkMITKIGTTrackingToolboxView::OnResetTools() { this->ReplaceCurrentToolStorage(mitk::NavigationToolStorage::New(GetDataStorage()),"TrackingToolbox Default Storage"); m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); QString toolLabel = QString("Loaded Tools: "); m_Controls->m_toolLabel->setText(toolLabel); } void QmitkMITKIGTTrackingToolboxView::OnConnect() { //check if everything is ready to start tracking if (this->m_toolStorage.IsNull()) { MessageBox("Error: No Tools Loaded Yet!"); return; } else if (this->m_toolStorage->GetToolCount() == 0) { MessageBox("Error: No Way To Track Without Tools!"); return; } //build the IGT pipeline mitk::TrackingDevice::Pointer trackingDevice = this->m_Controls->m_configurationWidget->GetTrackingDevice(); //set device to rotation mode transposed becaus we are working with VNL style quaternions if(m_Controls->m_InverseMode->isChecked()) trackingDevice->SetRotationMode(mitk::TrackingDevice::RotationTransposed); //Get Tracking Volume Data mitk::TrackingDeviceData data = mitk::DeviceDataUnspecified; QString qstr = m_Controls->m_VolumeSelectionBox->currentText(); if ( (! qstr.isNull()) || (! qstr.isEmpty()) ) { std::string str = qstr.toStdString(); data = mitk::GetDeviceDataByName(str); //Data will be set later, after device generation } //Create Navigation Data Source with the factory class mitk::TrackingDeviceSourceConfigurator::Pointer myTrackingDeviceSourceFactory = mitk::TrackingDeviceSourceConfigurator::New(this->m_toolStorage,trackingDevice); m_TrackingDeviceSource = myTrackingDeviceSourceFactory->CreateTrackingDeviceSource(this->m_ToolVisualizationFilter); MITK_INFO << "Number of tools: " << m_TrackingDeviceSource->GetNumberOfOutputs(); //set filter to rotation mode transposed becaus we are working with VNL style quaternions if(m_Controls->m_InverseMode->isChecked()) m_ToolVisualizationFilter->SetRotationMode(mitk::NavigationDataObjectVisualizationFilter::RotationTransposed); //First check if the created object is valid if (m_TrackingDeviceSource.IsNull()) { MessageBox(myTrackingDeviceSourceFactory->GetErrorMessage()); return; } //The tools are maybe reordered after initialization, e.g. in case of auto-detected tools of NDI Aurora mitk::NavigationToolStorage::Pointer toolsInNewOrder = myTrackingDeviceSourceFactory->GetUpdatedNavigationToolStorage(); if ((toolsInNewOrder.IsNotNull()) && (toolsInNewOrder->GetToolCount() > 0)) { //so delete the old tools in wrong order and add them in the right order //we cannot simply replace the tool storage because the new storage is //not correctly initialized with the right data storage m_toolStorage->DeleteAllTools(); for (int i=0; i < toolsInNewOrder->GetToolCount(); i++) {m_toolStorage->AddTool(toolsInNewOrder->GetTool(i));} } //connect to device try { m_TrackingDeviceSource->Connect(); //Microservice registration: m_TrackingDeviceSource->RegisterAsMicroservice(); m_toolStorage->UnRegisterMicroservice(); m_toolStorage->RegisterAsMicroservice(m_TrackingDeviceSource->GetMicroserviceID()); m_toolStorage->LockStorage(); } catch (...) //todo: change to mitk::IGTException { MessageBox("Error while starting the tracking device!"); return; } //enable/disable Buttons m_Controls->m_Disconnect->setEnabled(true); m_Controls->m_StartTracking->setEnabled(true); m_Controls->m_StopTracking->setEnabled(false); m_Controls->m_Connect->setEnabled(false); DisableOptionsButtons(); DisableTrackingConfigurationButtons(); m_Controls->m_configurationWidget->ConfigurationFinished(); m_Controls->m_TrackingControlLabel->setText("Status: connected"); } void QmitkMITKIGTTrackingToolboxView::OnDisconnect() { if (m_tracking) this->OnStopTracking(); m_TrackingDeviceSource->Disconnect(); m_TrackingDeviceSource->UnRegisterMicroservice(); m_toolStorage->UnLockStorage(); //enable/disable Buttons m_Controls->m_Disconnect->setEnabled(false); m_Controls->m_StartTracking->setEnabled(false); m_Controls->m_StopTracking->setEnabled(false); m_Controls->m_Connect->setEnabled(true); EnableOptionsButtons(); EnableTrackingConfigurationButtons(); m_Controls->m_configurationWidget->Reset(); m_Controls->m_TrackingControlLabel->setText("Status: disconnected"); } void QmitkMITKIGTTrackingToolboxView::OnStartTracking() { try { m_TrackingDeviceSource->StartTracking(); } catch (...) //todo: change to mitk::IGTException { MessageBox("Error while starting the tracking device!"); return; } m_TrackingTimer->start(1000/(m_Controls->m_UpdateRate->value())); m_Controls->m_TrackingControlLabel->setText("Status: tracking"); //connect the tool visualization widget for(int i=0; iGetNumberOfOutputs(); i++) { m_Controls->m_TrackingToolsStatusWidget->AddNavigationData(m_TrackingDeviceSource->GetOutput(i)); } m_Controls->m_TrackingToolsStatusWidget->ShowStatusLabels(); if (m_Controls->m_ShowToolQuaternions->isChecked()) {m_Controls->m_TrackingToolsStatusWidget->SetShowQuaternions(true);} else {m_Controls->m_TrackingToolsStatusWidget->SetShowQuaternions(false);} //show tracking volume this->OnTrackingVolumeChanged(m_Controls->m_VolumeSelectionBox->currentText()); //enable/disable Buttons m_Controls->m_Disconnect->setEnabled(true); m_Controls->m_StartTracking->setEnabled(false); m_Controls->m_StopTracking->setEnabled(true); m_Controls->m_Connect->setEnabled(false); m_tracking = true; this->GlobalReinit(); } void QmitkMITKIGTTrackingToolboxView::OnStopTracking() { if (!m_tracking) return; m_TrackingTimer->stop(); m_TrackingDeviceSource->StopTracking(); m_Controls->m_TrackingControlLabel->setText("Status: connected"); if (m_logging) StopLogging(); m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); m_tracking = false; //enable/disable Buttons m_Controls->m_Disconnect->setEnabled(true); m_Controls->m_StartTracking->setEnabled(true); m_Controls->m_StopTracking->setEnabled(false); m_Controls->m_Connect->setEnabled(false); this->GlobalReinit(); } void QmitkMITKIGTTrackingToolboxView::OnTrackingDeviceChanged() { mitk::TrackingDeviceType Type = m_Controls->m_configurationWidget->GetTrackingDevice()->GetType(); // Code to enable/disable device specific buttons if (Type == mitk::NDIAurora) //Aurora { m_Controls->m_AutoDetectTools->setVisible(true); m_Controls->m_AddSingleTool->setEnabled(false); } else //Polaris or Microntracker { m_Controls->m_AutoDetectTools->setVisible(false); m_Controls->m_AddSingleTool->setEnabled(true); } // Code to select appropriate tracking volume for current type std::vector Compatibles = mitk::GetDeviceDataForLine(Type); m_Controls->m_VolumeSelectionBox->clear(); for(int i = 0; i < Compatibles.size(); i++) { m_Controls->m_VolumeSelectionBox->addItem(Compatibles[i].Model.c_str()); } } void QmitkMITKIGTTrackingToolboxView::OnTrackingVolumeChanged(QString qstr) { if (qstr.isNull()) return; if (qstr.isEmpty()) return; if (m_Controls->m_ShowTrackingVolume->isChecked()) { mitk::TrackingVolumeGenerator::Pointer volumeGenerator = mitk::TrackingVolumeGenerator::New(); std::string str = qstr.toStdString(); mitk::TrackingDeviceData data = mitk::GetDeviceDataByName(str); volumeGenerator->SetTrackingDeviceData(data); volumeGenerator->Update(); mitk::Surface::Pointer volumeSurface = volumeGenerator->GetOutput(); m_TrackingVolumeNode->SetData(volumeSurface); GlobalReinit(); } } void QmitkMITKIGTTrackingToolboxView::OnShowTrackingVolumeChanged() { if (m_Controls->m_ShowTrackingVolume->isChecked()) { OnTrackingVolumeChanged(m_Controls->m_VolumeSelectionBox->currentText()); GetDataStorage()->Add(m_TrackingVolumeNode); } else { GetDataStorage()->Remove(m_TrackingVolumeNode); GlobalReinit(); } } void QmitkMITKIGTTrackingToolboxView::OnAutoDetectTools() { if (m_Controls->m_configurationWidget->GetTrackingDevice()->GetType() == mitk::NDIAurora) { DisableTrackingConfigurationButtons(); mitk::NDITrackingDevice::Pointer currentDevice = dynamic_cast(m_Controls->m_configurationWidget->GetTrackingDevice().GetPointer()); currentDevice->OpenConnection(); currentDevice->StartTracking(); mitk::NavigationToolStorage::Pointer autoDetectedStorage = mitk::NavigationToolStorage::New(this->GetDataStorage()); for (int i=0; iGetToolCount(); i++) { //create a navigation tool with sphere as surface std::stringstream toolname; toolname << "AutoDetectedTool" << i; mitk::NavigationTool::Pointer newTool = mitk::NavigationTool::New(); newTool->SetSerialNumber(dynamic_cast(currentDevice->GetTool(i))->GetSerialNumber()); newTool->SetIdentifier(toolname.str()); newTool->SetTrackingDeviceType(mitk::NDIAurora); mitk::DataNode::Pointer newNode = mitk::DataNode::New(); mitk::Surface::Pointer mySphere = mitk::Surface::New(); vtkSphereSource *vtkData = vtkSphereSource::New(); vtkData->SetRadius(3.0f); vtkData->SetCenter(0.0, 0.0, 0.0); vtkData->Update(); mySphere->SetVtkPolyData(vtkData->GetOutput()); vtkData->Delete(); newNode->SetData(mySphere); newNode->SetName(toolname.str()); newTool->SetDataNode(newNode); autoDetectedStorage->AddTool(newTool); } //save detected tools this->ReplaceCurrentToolStorage(autoDetectedStorage,"Autodetected NDI Aurora Storage"); //update label QString toolLabel = QString("Loaded Tools: ") + QString::number(m_toolStorage->GetToolCount()) + " Tools (Auto Detected)"; m_Controls->m_toolLabel->setText(toolLabel); //update tool preview m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); currentDevice->StopTracking(); currentDevice->CloseConnection(); EnableTrackingConfigurationButtons(); if (m_toolStorage->GetToolCount()>0) { //ask the user if he wants to save the detected tools QMessageBox msgBox; switch(m_toolStorage->GetToolCount()) { case 1: msgBox.setText("Found one tool!"); break; default: msgBox.setText("Found " + QString::number(m_toolStorage->GetToolCount()) + " tools!"); } msgBox.setInformativeText("Do you want to save this tools as tool storage, so you can load them again?"); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No); int ret = msgBox.exec(); if (ret == 16384) //yes { //ask the user for a filename QString fileName = QFileDialog::getSaveFileName(NULL, tr("Save File"),"/",tr("*.IGTToolStorage")); //check for empty filename if(fileName == "") {return;} mitk::NavigationToolStorageSerializer::Pointer mySerializer = mitk::NavigationToolStorageSerializer::New(); //when Serialize method is used exceptions are thrown, need to be adapted //try-catch block for exception handling in Serializer try { mySerializer->Serialize(fileName.toStdString(),m_toolStorage); } catch(mitk::IGTException) { std::string errormessage = "Error during serialization. Please check the Zip file."; QMessageBox::warning(NULL, "IGTPlayer: Error", errormessage.c_str());} return; } else if (ret == 65536) //no { return; } } } } void QmitkMITKIGTTrackingToolboxView::MessageBox(std::string s) { QMessageBox msgBox; msgBox.setText(s.c_str()); msgBox.exec(); } void QmitkMITKIGTTrackingToolboxView::UpdateTrackingTimer() { m_ToolVisualizationFilter->Update(); MITK_DEBUG << "Number of outputs ToolVisualizationFilter: " << m_ToolVisualizationFilter->GetNumberOfIndexedOutputs(); MITK_DEBUG << "Number of inputs ToolVisualizationFilter: " << m_ToolVisualizationFilter->GetNumberOfIndexedInputs(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); if (m_logging) { this->m_loggingFilter->Update(); - m_loggedFrames = this->m_loggingFilter->GetRecordCounter(); + m_loggedFrames = this->m_loggingFilter->GetNumberOfRecordedSteps(); this->m_Controls->m_LoggedFramesLabel->setText("Logged Frames: "+QString::number(m_loggedFrames)); //check if logging stopped automatically if((m_loggedFrames>1)&&(!m_loggingFilter->GetRecording())){StopLogging();} } m_Controls->m_TrackingToolsStatusWidget->Refresh(); } void QmitkMITKIGTTrackingToolboxView::OnChooseFileClicked() { QString filename = QFileDialog::getSaveFileName(NULL,tr("Choose Logging File"), "/", "*.*"); if (filename == "") return; this->m_Controls->m_LoggingFileName->setText(filename); } void QmitkMITKIGTTrackingToolboxView::StartLogging() { if (!m_logging) { //initialize logging filter m_loggingFilter = mitk::NavigationDataRecorder::New(); - m_loggingFilter->SetRecordingMode(mitk::NavigationDataRecorder::NormalFile); - if (m_Controls->m_xmlFormat->isChecked()) m_loggingFilter->SetOutputFormat(mitk::NavigationDataRecorder::xml); - else if (m_Controls->m_csvFormat->isChecked()) m_loggingFilter->SetOutputFormat(mitk::NavigationDataRecorder::csv); - std::string filename = m_Controls->m_LoggingFileName->text().toStdString().c_str(); - // this part has been changed in order to prevent crash of the program - if(!filename.empty()) - m_loggingFilter->SetFileName(filename); - else if(filename.empty()){ - std::string errormessage = "File name has not been set, please set the file name"; - mitkThrowException(mitk::IGTIOException)<SetFileName(filename); - } if (m_Controls->m_LoggingLimit->isChecked()){m_loggingFilter->SetRecordCountLimit(m_Controls->m_LoggedFramesLimit->value());} //connect filter - for(int i=0; iGetNumberOfOutputs(); i++){m_loggingFilter->AddNavigationData(m_ToolVisualizationFilter->GetOutput(i));} + for(int i=0; iGetNumberOfIndexedOutputs(); i++) + { + m_loggingFilter->SetInput(i, m_ToolVisualizationFilter->GetOutput(i)); + } //start filter with try-catch block for exceptions try { m_loggingFilter->StartRecording(); } catch(mitk::IGTException) { std::string errormessage = "Error during start recording. Recorder already started recording?"; QMessageBox::warning(NULL, "IGTPlayer: Error", errormessage.c_str()); m_loggingFilter->StopRecording(); return; } //update labels / logging variables this->m_Controls->m_LoggingLabel->setText("Logging ON"); this->m_Controls->m_LoggedFramesLabel->setText("Logged Frames: 0"); m_loggedFrames = 0; m_logging = true; DisableLoggingButtons(); } } void QmitkMITKIGTTrackingToolboxView::StopLogging() - { +{ if (m_logging) - { + { //update label this->m_Controls->m_LoggingLabel->setText("Logging OFF"); m_loggingFilter->StopRecording(); m_logging = false; EnableLoggingButtons(); + + std::string filename = m_Controls->m_LoggingFileName->text().toStdString().c_str(); + // this part has been changed in order to prevent crash of the program + if(filename.empty()) + { + std::string errormessage = "File name has not been set, please set the file name"; + mitkThrowException(mitk::IGTIOException)<m_xmlFormat->isChecked()) + { + mitk::NavigationDataSetWriterXML().Write(filename, m_loggingFilter->GetNavigationDataSet()); + } + else if (m_Controls->m_csvFormat->isChecked()) + { + //mitk::NavigationDataSetWriterCSV().Write(filename, m_loggingFilter->GetNavigationDataSet()); + mitkThrowException(mitk::Exception) << "CSV writer not implemented, yet."; + } + } + catch (const std::exception &e) // TODO: error handling has to be adapted when the new writers are merged + { + MITK_WARN << "IGTPlayer: Error", e.what(); + QMessageBox::warning(NULL, "IGTPlayer: Error", e.what()); + return; + } + } +} void QmitkMITKIGTTrackingToolboxView::OnAddSingleTool() { QString Identifier = "Tool#"; if (m_toolStorage.IsNotNull()) Identifier += QString::number(m_toolStorage->GetToolCount()); else Identifier += "0"; m_Controls->m_NavigationToolCreationWidget->Initialize(GetDataStorage(),Identifier.toStdString()); m_Controls->m_NavigationToolCreationWidget->SetTrackingDeviceType(m_Controls->m_configurationWidget->GetTrackingDevice()->GetType(),false); m_Controls->m_TrackingToolsWidget->setCurrentIndex(1); //disable tracking volume during tool editing lastTrackingVolumeState = m_Controls->m_ShowTrackingVolume->isChecked(); if (lastTrackingVolumeState) m_Controls->m_ShowTrackingVolume->click(); GlobalReinit(); } void QmitkMITKIGTTrackingToolboxView::OnAddSingleToolFinished() { m_Controls->m_TrackingToolsWidget->setCurrentIndex(0); if (this->m_toolStorage.IsNull()) { //this shouldn't happen! MITK_WARN << "No ToolStorage available, cannot add tool, aborting!"; return; } m_toolStorage->AddTool(m_Controls->m_NavigationToolCreationWidget->GetCreatedTool()); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); QString toolLabel = QString("Loaded Tools: "); //enable tracking volume again if (lastTrackingVolumeState) m_Controls->m_ShowTrackingVolume->click(); GlobalReinit(); } void QmitkMITKIGTTrackingToolboxView::OnAddSingleToolCanceled() { m_Controls->m_TrackingToolsWidget->setCurrentIndex(0); //enable tracking volume again if (lastTrackingVolumeState) m_Controls->m_ShowTrackingVolume->click(); GlobalReinit(); } void QmitkMITKIGTTrackingToolboxView::GlobalReinit() { // get all nodes that have not set "includeInBoundingBox" to false mitk::NodePredicateNot::Pointer pred = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("includeInBoundingBox", mitk::BoolProperty::New(false))); mitk::DataStorage::SetOfObjects::ConstPointer rs = this->GetDataStorage()->GetSubset(pred); // calculate bounding geometry of these nodes mitk::TimeSlicedGeometry::Pointer bounds = this->GetDataStorage()->ComputeBoundingGeometry3D(rs, "visible"); // initialize the views to the bounding geometry mitk::RenderingManager::GetInstance()->InitializeViews(bounds); } void QmitkMITKIGTTrackingToolboxView::DisableLoggingButtons() { m_Controls->m_StartLogging->setEnabled(false); m_Controls->m_LoggingFileName->setEnabled(false); m_Controls->m_ChooseFile->setEnabled(false); m_Controls->m_LoggingLimit->setEnabled(false); m_Controls->m_LoggedFramesLimit->setEnabled(false); m_Controls->m_csvFormat->setEnabled(false); m_Controls->m_xmlFormat->setEnabled(false); m_Controls->m_StopLogging->setEnabled(true); } void QmitkMITKIGTTrackingToolboxView::EnableLoggingButtons() { m_Controls->m_StartLogging->setEnabled(true); m_Controls->m_LoggingFileName->setEnabled(true); m_Controls->m_ChooseFile->setEnabled(true); m_Controls->m_LoggingLimit->setEnabled(true); m_Controls->m_LoggedFramesLimit->setEnabled(true); m_Controls->m_csvFormat->setEnabled(true); m_Controls->m_xmlFormat->setEnabled(true); m_Controls->m_StopLogging->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::DisableOptionsButtons() { m_Controls->m_ShowTrackingVolume->setEnabled(false); m_Controls->m_UpdateRate->setEnabled(false); m_Controls->m_ShowToolQuaternions->setEnabled(false); m_Controls->m_OptionsUpdateRateLabel->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::EnableOptionsButtons() { m_Controls->m_ShowTrackingVolume->setEnabled(true); m_Controls->m_UpdateRate->setEnabled(true); m_Controls->m_ShowToolQuaternions->setEnabled(true); m_Controls->m_OptionsUpdateRateLabel->setEnabled(true); } void QmitkMITKIGTTrackingToolboxView::EnableTrackingConfigurationButtons() { m_Controls->m_AutoDetectTools->setEnabled(true); if (m_Controls->m_configurationWidget->GetTrackingDevice()->GetType() != mitk::NDIAurora) m_Controls->m_AddSingleTool->setEnabled(true); m_Controls->m_LoadTools->setEnabled(true); m_Controls->m_ResetTools->setEnabled(true); } void QmitkMITKIGTTrackingToolboxView::DisableTrackingConfigurationButtons() { m_Controls->m_AutoDetectTools->setEnabled(false); if (m_Controls->m_configurationWidget->GetTrackingDevice()->GetType() != mitk::NDIAurora) m_Controls->m_AddSingleTool->setEnabled(false); m_Controls->m_LoadTools->setEnabled(false); m_Controls->m_ResetTools->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::ReplaceCurrentToolStorage(mitk::NavigationToolStorage::Pointer newStorage, std::string newStorageName) { //first: get rid of the old one m_toolStorage->UnLockStorage(); //only to be sure... m_toolStorage->UnRegisterMicroservice(); m_toolStorage = NULL; //now: replace by the new one m_toolStorage = newStorage; m_toolStorage->SetName(newStorageName); m_toolStorage->RegisterAsMicroservice("no tracking device"); } 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 5f154a8535..954b1a5bfc 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,439 @@ /*=================================================================== 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 // 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_Trajectory( NULL ) + , m_TrajectoryIndex( -1 ) + , m_ReloadData( true ) + , m_ShowTrajectory( false ) + , m_SplineMapper( NULL ) + , m_PointSetMapper( 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(); } } - - void QmitkNavigationDataPlayerView::CreateBundleWidgets(QWidget* parent) { 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)) ); } - void QmitkNavigationDataPlayerView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } - 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))); mitk::DataStorage::SetOfObjects::ConstPointer rs = this->GetDataStorage()->GetSubset(pred); // calculate bounding geometry of these nodes mitk::TimeSlicedGeometry::Pointer bounds = this->GetDataStorage()->ComputeBoundingGeometry3D(rs, "visible"); // initialize the views to the bounding geometry mitk::RenderingManager::GetInstance()->InitializeViews(bounds); /// 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; } - 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) { 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 } - } } this->RenderScene(); } 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 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::AddRepresentationObject(mitk::DataStorage* ds, mitk::DataNode::Pointer reprObject) { m_RepresentationObjects.push_back(reprObject); ds->Add(reprObject); } 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::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 { 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); } } - 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(); } return result; } - mitk::PointSetVtkMapper3D::Pointer QmitkNavigationDataPlayerView::GetTrajectoryMapper(TrajectoryStyle style) { if(style == Points) { if(m_PointSetMapper.IsNull()) m_PointSetMapper = mitk::PointSetVtkMapper3D::New(); return m_PointSetMapper; } else if(style == Splines) { if(m_SplineMapper.IsNull()) m_SplineMapper = mitk::SplineVtkMapper3D::New(); return m_SplineMapper.GetPointer(); } else return NULL; -} - - - - +} \ 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 5cbeb8f463..4353289411 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.h +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.h @@ -1,178 +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. ===================================================================*/ #ifndef QmitkNavigationDataPlayerView_h #define QmitkNavigationDataPlayerView_h #include //Qmitk #include #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 */ void OnCreatePlaybackVisualization(); /*! \brief Assigns position changings from the player widget to the visualization objects */ void OnPerformPlaybackVisualization(); /*! \brief Reinits this player. Cleans all timers and trajectory data */ void OnReinit(); /*! \brief Shows trajectory of tool with index */ void OnShowTrajectory(int index); /*! \brief Cleans trajectory data before playing is started */ void OnPlayingStarted(); /*! \brief Enables or disables trajectory visualization with splines */ void OnEnableSplineTrajectoryMapper(bool enable); - protected: enum TrajectoryStyle { Points = 1, Splines = 2 }; void CreateBundleWidgets(QWidget* parent); - /** - \brief Refreshes the visualization of the playback object DataNodes. - */ + /** + \brief Refreshes the visualization of the playback object DataNodes. + */ void RenderScene(); /** - \brief Creates representation DataNode with given name and color + \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 + \brief Adds representation DataNode to the DataStorage */ void AddRepresentationObject(mitk::DataStorage* ds, mitk::DataNode::Pointer reprObject); /** - \brief Removes representation DataNode from the DataStorage + \brief Removes representation DataNode from the DataStorage */ void RemoveRepresentationObject(mitk::DataStorage* ds, mitk::DataNode::Pointer reprObject); /** - \brief Adds trajectory DataNode to the DataStorage + \brief Adds trajectory DataNode to the DataStorage */ void AddTrajectory(mitk::DataStorage* ds, mitk::DataNode::Pointer trajectoryNode); /** - \brief Creates a trajectory DataNode from given PointSet with given name and color + \brief Creates a trajectory DataNode from given PointSet with given name and color */ mitk::DataNode::Pointer CreateTrajectory( mitk::PointSet::Pointer points, const std::string& name, const mitk::Color color ); - - - Ui::QmitkNavigationDataPlayerViewControls* m_Controls; 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 + \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. + \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