diff --git a/CMakeExternals/MITKData.cmake b/CMakeExternals/MITKData.cmake index faf7580f81..91c5a5616c 100644 --- a/CMakeExternals/MITKData.cmake +++ b/CMakeExternals/MITKData.cmake @@ -1,36 +1,35 @@ #----------------------------------------------------------------------------- # MITK Data #----------------------------------------------------------------------------- # Sanity checks if(DEFINED MITK_DATA_DIR AND NOT EXISTS ${MITK_DATA_DIR}) message(FATAL_ERROR "MITK_DATA_DIR variable is defined but corresponds to non-existing directory") endif() set(proj MITK-Data) set(proj_DEPENDENCIES) set(MITK-Data_DEPENDS ${proj}) if(BUILD_TESTING) - - set(revision_tag f24c722f) -# ^^^^^^^^ these are just to check correct length of hash part + set(revision_tag b89a01b5) +# ^^^^^^^^ these are just to check correct length of hash part ExternalProject_Add(${proj} URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/MITK-Data_${revision_tag}.tar.gz UPDATE_COMMAND "" CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" DEPENDS ${proj_DEPENDENCIES} ) set(MITK_DATA_DIR ${ep_source_dir}/${proj}) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif(BUILD_TESTING) diff --git a/Modules/IGT/DataManagement/mitkNavigationDataSet.cpp b/Modules/IGT/DataManagement/mitkNavigationDataSet.cpp new file mode 100644 index 0000000000..57f5c947ae --- /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(index).at(toolIndex); +} + +// 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/DataManagement/mitkNavigationDataSource.cpp b/Modules/IGT/DataManagement/mitkNavigationDataSource.cpp index 381329b9a3..3de7925cdf 100644 --- a/Modules/IGT/DataManagement/mitkNavigationDataSource.cpp +++ b/Modules/IGT/DataManagement/mitkNavigationDataSource.cpp @@ -1,153 +1,145 @@ /*=================================================================== 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 "mitkNavigationDataSource.h" #include "mitkUIDGenerator.h" //Microservices #include #include #include #include const std::string mitk::NavigationDataSource::US_INTERFACE_NAME = "org.mitk.services.NavigationDataSource"; const std::string mitk::NavigationDataSource::US_PROPKEY_DEVICENAME = US_INTERFACE_NAME + ".devicename"; const std::string mitk::NavigationDataSource::US_PROPKEY_ID = US_INTERFACE_NAME + ".id"; const std::string mitk::NavigationDataSource::US_PROPKEY_ISACTIVE = US_INTERFACE_NAME + ".isActive"; mitk::NavigationDataSource::NavigationDataSource() -: itk::ProcessObject(), m_Name("NavigationDataSource (no defined type)") + : itk::ProcessObject(), m_Name("NavigationDataSource (no defined type)") { - } - mitk::NavigationDataSource::~NavigationDataSource() { } - mitk::NavigationData* mitk::NavigationDataSource::GetOutput() { if (this->GetNumberOfIndexedOutputs() < 1) return NULL; return static_cast(this->ProcessObject::GetPrimaryOutput()); } - mitk::NavigationData* mitk::NavigationDataSource::GetOutput(DataObjectPointerArraySizeType idx) { NavigationData* out = dynamic_cast( this->ProcessObject::GetOutput(idx) ); if ( out == NULL && this->ProcessObject::GetOutput(idx) != NULL ) { itkWarningMacro (<< "Unable to convert output number " << idx << " to type " << typeid( NavigationData ).name () ); } return out; } - mitk::NavigationData* mitk::NavigationDataSource::GetOutput(const std::string& navDataName) { DataObjectPointerArray outputs = this->GetOutputs(); for (DataObjectPointerArray::iterator it = outputs.begin(); it != outputs.end(); ++it) if (navDataName == (static_cast(it->GetPointer()))->GetName()) return static_cast(it->GetPointer()); return NULL; } itk::ProcessObject::DataObjectPointerArraySizeType mitk::NavigationDataSource::GetOutputIndex( std::string navDataName ) { DataObjectPointerArray outputs = this->GetOutputs(); for (DataObjectPointerArray::size_type i = 0; i < outputs.size(); ++i) if (navDataName == (static_cast(outputs.at(i).GetPointer()))->GetName()) return i; throw std::invalid_argument("output name does not exist"); } void mitk::NavigationDataSource::RegisterAsMicroservice(){ // Get Context us::ModuleContext* context = us::GetModuleContext(); // Define ServiceProps us::ServiceProperties props; mitk::UIDGenerator uidGen = mitk::UIDGenerator ("org.mitk.services.NavigationDataSource.id_", 16); props[ US_PROPKEY_ID ] = uidGen.GetUID(); props[ US_PROPKEY_DEVICENAME ] = m_Name; m_ServiceRegistration = context->RegisterService(this, props); } - void mitk::NavigationDataSource::UnRegisterMicroservice(){ - m_ServiceRegistration.Unregister(); + if (m_ServiceRegistration != NULL) m_ServiceRegistration.Unregister(); m_ServiceRegistration = 0; } std::string mitk::NavigationDataSource::GetMicroserviceID(){ return this->m_ServiceRegistration.GetReference().GetProperty(US_PROPKEY_ID).ToString(); } void mitk::NavigationDataSource::GraftOutput(itk::DataObject *graft) { this->GraftNthOutput(0, graft); } - void mitk::NavigationDataSource::GraftNthOutput(unsigned int idx, itk::DataObject *graft) { if ( idx >= this->GetNumberOfIndexedOutputs() ) { itkExceptionMacro(<<"Requested to graft output " << idx << " but this filter only has " << this->GetNumberOfIndexedOutputs() << " Outputs."); } if ( !graft ) { itkExceptionMacro(<<"Requested to graft output with a NULL pointer object" ); } itk::DataObject* output = this->GetOutput(idx); if ( !output ) { itkExceptionMacro(<<"Requested to graft output that is a NULL pointer" ); } // Call Graft on NavigationData to copy member data output->Graft( graft ); } itk::DataObject::Pointer mitk::NavigationDataSource::MakeOutput ( DataObjectPointerArraySizeType /*idx*/ ) { - return mitk::NavigationData::New().GetPointer(); + return mitk::NavigationData::New().GetPointer(); } itk::DataObject::Pointer mitk::NavigationDataSource::MakeOutput( const DataObjectIdentifierType & name ) { itkDebugMacro("MakeOutput(" << name << ")"); if( this->IsIndexedOutputName(name) ) - { + { return this->MakeOutput( this->MakeIndexFromOutputName(name) ); - } + } return static_cast(mitk::NavigationData::New().GetPointer()); } - mitk::PropertyList::ConstPointer mitk::NavigationDataSource::GetParameters() const { mitk::PropertyList::Pointer p = mitk::PropertyList::New(); // add properties to p like this: //p->SetProperty("MyFilter_MyParameter", mitk::PropertyDataType::New(m_MyParameter)); return mitk::PropertyList::ConstPointer(p); -} +} \ No newline at end of file diff --git a/Modules/IGT/IO/mitkNavigationDataPlayer.cpp b/Modules/IGT/IO/mitkNavigationDataPlayer.cpp index 04a7c3a564..ff08aaad03 100644 --- a/Modules/IGT/IO/mitkNavigationDataPlayer.cpp +++ b/Modules/IGT/IO/mitkNavigationDataPlayer.cpp @@ -1,549 +1,161 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkNavigationDataPlayer.h" #include #include #include +#include "mitkNavigationDataReaderXML.h" -//includes for exceptions #include "mitkIGTException.h" -#include "mitkIGTIOException.h" -mitk::NavigationDataPlayer::NavigationDataPlayer() : mitk::NavigationDataPlayerBase() +mitk::NavigationDataPlayer::NavigationDataPlayer() + : m_CurPlayerState(PlayerStopped), + m_StartPlayingTimeStamp(0.0), m_PauseTimeStamp(0.0) { - m_Pause = false; - m_Playing = false; - m_Stream = NULL; - m_PlayerMode = NormalFile; - m_FileName = ""; - m_FileVersion = 1; - m_Playing = false; - m_Pause = false; - m_NumberOfOutputs = 0; - m_StartPlayingTimeStamp = 0.0; - m_PauseTimeStamp = 0.0; - m_parentElement = NULL; - m_currentNode = NULL; - m_StreamEnd = false; - m_StreamSetOutsideFromClass = false; - - //To get a start time + // to get a start time mitk::IGTTimeStamp::GetInstance()->Start(this); } - mitk::NavigationDataPlayer::~NavigationDataPlayer() { StopPlaying(); - delete m_parentElement; } - void mitk::NavigationDataPlayer::GenerateData() { - //Only produce new output if the player is started - if (!m_Playing) //m_Playing==true means player has started + if ( m_NavigationDataSet->Size() == 0 ) { - //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); - } + MITK_WARN << "Cannot do anything with empty set of navigation datas."; return; } - //first of all get current time - TimeStampType now = mitk::IGTTimeStamp::GetInstance()->GetElapsed(); - - //now we make a little time arithmetic - //to get the elapsed time since the start of the player - TimeStampType timeSinceStart = now - m_StartPlayingTimeStamp; - //init the vectors - std::vector< NavigationData::Pointer > nextCandidates; - std::vector< NavigationData::Pointer > lastCandidates; - std::vector< NavigationData::TimeStampType > currentTimeOfData; - for (unsigned int index=0; index < m_NumberOfOutputs; index++) - { - nextCandidates.push_back(m_NextToPlayNavigationData.at(index)); - lastCandidates.push_back(m_NextToPlayNavigationData.at(index)); - - currentTimeOfData.push_back(timeSinceStart + m_StartTimeOfData.at(index)); - } - - if (m_NextToPlayNavigationData.size() != m_NumberOfOutputs) + //Only produce new output if the player is started + if (m_CurPlayerState != PlayerRunning) { - MITK_ERROR << "Mismatch in data"; + //The output is not valid anymore + this->GraftEmptyOutput(); 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. + // get elapsed time since start of playing + m_TimeStampSinceStart = mitk::IGTTimeStamp::GetInstance()->GetElapsed() - m_StartPlayingTimeStamp; + // add offset of the first navigation data to the timestamp to start playing + // imediatly with the first navigation data (not to wait till the first time + // stamp is reached) + TimeStampType timeStampSinceStartWithOffset = m_TimeStampSinceStart + + m_NavigationDataSet->Begin()->at(0)->GetIGTTimeStamp(); - while( nextCandidates[0]->GetIGTTimeStamp() < currentTimeOfData[0]) + // 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) { - for (unsigned int index=0; index < m_NumberOfOutputs; index++) + // test if the timestamp of the successor is greater than the time stamp + if ( m_NavigationDataSetIterator+1 == m_NavigationDataSet->End() || + (m_NavigationDataSetIterator+1)->at(0)->GetIGTTimeStamp() > timeStampSinceStartWithOffset ) { - 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++) + for (unsigned int index = 0; index < GetNumberOfOutputs(); index++) { mitk::NavigationData* output = this->GetOutput(index); - assert(output); - output->Graft(lastCandidates.at(index)); - m_NextToPlayNavigationData[index] = nextCandidates.at(index); - } -} - - -void mitk::NavigationDataPlayer::UpdateOutputInformation() -{ - this->Modified(); // make sure that we need to be updated - Superclass::UpdateOutputInformation(); -} - - -void mitk::NavigationDataPlayer::InitPlayer() -{ - if (m_Stream == NULL) - { - StreamInvalid("Playing not possible. Wrong file name or path?"); - return; - } - - if (!m_Stream->good()) - { - StreamInvalid("Playing not possible. Stream is not good!"); - return; - } - - //first get the file version - m_FileVersion = GetFileVersion(m_Stream); - - //check if we have a valid version: m_FileVersion has to be always bigger than 1 for playing - if (m_FileVersion < 1) - { - 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) {SetNumberOfIndexedOutputs(m_NumberOfOutputs);} - //initialize the player with first data - GetFirstData(); - //set stream valid - m_ErrorMessage = ""; - m_StreamValid = true; - } - else - { - StreamInvalid("The input stream seems to have NavigationData incompatible format"); - 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) - { - 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 + if( !output ) { mitkThrowException(mitk::IGTException) << "Output of index "<Value(); - if(tempValue != "Version") - { - if(tempValue == "Data"){ - m_parentElement->QueryIntAttribute("version",&version); - } - } - else - { - m_parentElement->QueryIntAttribute("Ver",&version); + output->Graft(m_NavigationDataSetIterator->at(index)); } - 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+1 == 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; + this->StopPlaying(); - std::string tempValue = m_parentElement->Value(); - if(tempValue == "Version"){ - *stream >> *m_parentElement; + // start playing again if repeat is enabled + if ( m_Repeat ) { this->StartPlaying(); } } - 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; + // make sure that player is initialized before playing starts + this->InitPlayer(); - //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?"; - } - } + // set state and iterator for playing from start + m_CurPlayerState = PlayerRunning; + m_NavigationDataSetIterator = m_NavigationDataSet->Begin(); - 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(); - } + // reset playing timestamps + m_PauseTimeStamp = 0; + m_TimeStampSinceStart = 0; + // timestamp for indicating playing start set to current elapsed time + m_StartPlayingTimeStamp = mitk::IGTTimeStamp::GetInstance()->GetElapsed(); } - - - 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(); + m_CurPlayerState = PlayerStopped; } - -void mitk::NavigationDataPlayer::GetFirstData() -{ - - //Here we read the first lines of input (dependend on the number of inputs) - for (unsigned int index=0; index < m_NumberOfOutputs; index++) - { - //Here we init the vector for later use - m_NextToPlayNavigationData.push_back(NULL); - m_StartTimeOfData.push_back(0.0); - mitk::NavigationData::Pointer nd = this->GetOutput(index); - - switch(m_FileVersion) - { - case 1: - m_NextToPlayNavigationData[index] = ReadVersion1(); - //check if there is valid data in it - - if (m_NextToPlayNavigationData[index].IsNull()) - { - m_StreamEnd = true; - StopPlaying(); - 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; - } - } -} - - 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() +mitk::NavigationDataPlayer::PlayerState mitk::NavigationDataPlayer::GetCurrentPlayerState() { - return this->m_StreamEnd; + return m_CurPlayerState; } -void mitk::NavigationDataPlayer::StreamInvalid(std::string message) +mitk::NavigationDataPlayer::TimeStampType mitk::NavigationDataPlayer::GetTimeStampSinceStart() { - m_StreamEnd = true; - StopPlaying(); - m_ErrorMessage = message; - m_StreamValid = false; - mitkThrowException(mitk::IGTIOException) << "Invalid stream!"; + return m_TimeStampSinceStart; } diff --git a/Modules/IGT/IO/mitkNavigationDataPlayer.h b/Modules/IGT/IO/mitkNavigationDataPlayer.h index 0d2e7e1b56..31e59d304a 100644 --- a/Modules/IGT/IO/mitkNavigationDataPlayer.h +++ b/Modules/IGT/IO/mitkNavigationDataPlayer.h @@ -1,226 +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. + * \brief This class is used to play recorded (see mitkNavigationDataRecorder class) NavigationDataSets. * - * 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. + * TODO * * * \ingroup IGT */ class MitkIGT_EXPORT NavigationDataPlayer : public NavigationDataPlayerBase { public: mitkClassMacro(NavigationDataPlayer, NavigationDataPlayerBase); itkFactorylessNewMacro(Self) itkCloneMacro(Self) - /** - * \brief sets the file name and path for the PlayerMode NormalFile and ZipFile - */ - itkSetStringMacro(FileName); - - /** - * \brief returns the file name and path for the PlayerMode NormalFile and ZipFile - */ - itkGetStringMacro(FileName); - + enum PlayerState { PlayerStopped, PlayerRunning, PlayerPaused }; + typedef mitk::NavigationData::TimeStampType TimeStampType; /** * \brief Used for pipeline update just to tell the pipeline that we always have to update */ virtual void UpdateOutputInformation(); /** - * \brief This method starts the player. - * - * Before the stream has to be set. Either with a PlayingMode (SetStream(PlayerMode)) and FileName. Or - * with an own inputstream (SetStream(istream*)). - * - * @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). - */ + * \brief This method starts the player. + * + * The method mitk::NavigationDataPlayer::SetNavigationDataSet() has to be called before. + * + * @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 - */ + * \brief Stops the player and closes the stream. + * After a call of StopPlaying(), StartPlaying() must be called to get new + * output data. + */ void StopPlaying(); /** - * \brief This method pauses the player. If you want to play again call Resume() - */ + * \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. - */ + * \brief This method resumes the player when it was paused. + */ void Resume(); + PlayerState GetCurrentPlayerState(); - /** - * \brief This method checks if player arrived at end of file. - * - */ - bool IsAtEnd(); - - /** - * \brief The PlayerMode is used for generating a presetted output stream. You do not need to - * set it if you want to use your own stream. - * - * There are: - * NormalFile: ifstream - * ZipFile: not implemented yet - * - *\warning The ZipFile Mode is not implemented yet - */ - enum PlayerMode - { - NormalFile, - ZipFile - }; - - /** @return Returns the current playing mode of the player. */ - itkGetMacro(PlayerMode,PlayerMode); - - /** @brief Sets the playing mode of the player. */ - itkSetMacro(PlayerMode,PlayerMode); - - /** - * \brief Sets the stream of this player. - * @throw mitk::IGTException Throws an exception if stream is NULL or if it is not good. - */ - void SetStream(std::istream* stream); + TimeStampType GetTimeStampSinceStart(); protected: NavigationDataPlayer(); virtual ~NavigationDataPlayer(); - typedef mitk::NavigationData::TimeStampType TimeStampType; - /** - * \brief filter execute method - */ + * \brief Set outputs to the navigation data object corresponding to current time. + */ virtual void GenerateData(); - /** - * \brief Creates a stream out of the filename given by the variable m_FileName. - * The stream is then set to m_Stream. - * - * @throw mitk::IGTIOException Throws an exception if file does not exist - * @throw mitk::IGTException Throws an exception if the stream is NULL - */ - void CreateStreamFromFilename(); - - /** - * \brief Returns the file version out of the XML document. - * @throw mitk::IGTException Throws an mitk::IGTException an exception if stream is NULL or not good. - * @throw mitk::IGTIOException Throws an mitk::IGTIOException if the stream has an incompatible XML format. - */ - unsigned int GetFileVersion(std::istream* stream); - - /** - * \brief Returns the number of tracked tools out of the XML document. - * @throw Throws an exception if stream is NULL. - * @throw Throws an exception if the input stream has an XML incompatible format. - */ - unsigned int GetNumberOfNavigationDatas(std::istream* stream); - - /** - * \brief Gets the first data for initializing the player - */ - void GetFirstData(); - - /** - * \brief This method reads one line of the XML document and returns the data as a NavigationData object - * If there is a new file version another method must be added which reads this data. - * @throw mitk::IGTException Throws an exceptions if file is damaged. - */ - mitk::NavigationData::Pointer ReadVersion1(); + PlayerState m_CurPlayerState; /** - * \brief This method initializes the player with first data - */ - void InitPlayer(); - - std::istream* m_Stream; ///< stores a pointer to the input stream - - bool m_StreamSetOutsideFromClass; ///< stores if the stream was created in this class and must be deleted in the end - - PlayerMode m_PlayerMode; ///< stores the mode for the presetted PlayerMode sieh enum PlayerMode - - std::string m_FileName; ///< stores the filename - - unsigned int m_FileVersion; ///< indicates which XML encoding is used - - bool m_Playing; ///< indicates whether the generateoutput method generates new output or not - - bool m_Pause; ///< indicates if the player is paused - - unsigned int m_NumberOfOutputs; ///< stores the number of outputs known from the XML document - - TimeStampType m_StartPlayingTimeStamp; ///< the starttime of the playing set in the method StartPlaying() - - TimeStampType m_PauseTimeStamp; ///< stores the beginning of a pause - - std::vector m_NextToPlayNavigationData; ///< stores the next possible candidate for playing - - std::vector m_StartTimeOfData; ///< stores the start time of the different tools - - TiXmlElement * m_parentElement; - - TiXmlNode * m_currentNode; - - bool m_StreamEnd; ///< stores if the input stream arrived at end + * \brief The start time of the playing. Set in the method mitk::NavigationDataPlayer::StartPlaying(). + */ + TimeStampType m_StartPlayingTimeStamp; /** - * @brief This is a helping method which gives an error message and throws an exception with the given message. - * It can be used if a stream is found to be invalid. - * - * @throw mitk::IGTIOException Always throws an exception. - */ - void StreamInvalid(std::string message); ///< help method which sets the stream invalid and displays an error + * \brief Stores the time when a pause began. + */ + TimeStampType m_PauseTimeStamp; + TimeStampType m_TimeStampSinceStart; }; } // namespace mitk #endif /* MITKNavigationDataPlayer_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/IO/mitkNavigationDataPlayerBase.cpp b/Modules/IGT/IO/mitkNavigationDataPlayerBase.cpp index 8edca1fb68..f62b6e171a 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_Repeat(false) { - m_Name ="Navigation Data Player Source"; + this->SetName("Navigation Data Player Source"); } mitk::NavigationDataPlayerBase::~NavigationDataPlayerBase() { } - - - - void mitk::NavigationDataPlayerBase::UpdateOutputInformation() { this->Modified(); // make sure that we need to be updated Superclass::UpdateOutputInformation(); } +bool mitk::NavigationDataPlayerBase::IsAtEnd() +{ + return m_NavigationDataSetIterator == m_NavigationDataSet->End(); +} - -mitk::NavigationData::Pointer mitk::NavigationDataPlayerBase::ReadNavigationData(TiXmlElement* elem) +void mitk::NavigationDataPlayerBase::SetNavigationDataSet(NavigationDataSet::Pointer navigationDataSet) { - if (elem == NULL) {mitkThrow() << "Error: Element is NULL!";} + m_NavigationDataSet = navigationDataSet; + m_NavigationDataSetIterator = navigationDataSet->Begin(); - mitk::NavigationData::Pointer nd = mitk::NavigationData::New(); + this->InitPlayer(); +} - mitk::NavigationData::PositionType position; - mitk::NavigationData::OrientationType orientation(0.0,0.0,0.0,0.0); - mitk::NavigationData::TimeStampType timestamp = -1; - mitk::NavigationData::CovarianceMatrixType matrix; +unsigned int mitk::NavigationDataPlayerBase::GetNumberOfSnapshots() +{ + return m_NavigationDataSet.IsNull() ? 0 : m_NavigationDataSet->Size(); +} - bool hasPosition = true; - bool hasOrientation = true; - bool dataValid = false; +unsigned int mitk::NavigationDataPlayerBase::GetCurrentSnapshotNumber() +{ + return m_NavigationDataSet.IsNull() ? 0 : m_NavigationDataSetIterator - m_NavigationDataSet->Begin(); +} - position.Fill(0.0); - matrix.SetIdentity(); +void mitk::NavigationDataPlayerBase::InitPlayer() +{ + if ( m_NavigationDataSet.IsNull() ) + { + mitkThrowException(mitk::IGTException) + << "NavigationDataSet has to be set before initializing player."; + } - elem->QueryDoubleAttribute("Time",×tamp); - if (timestamp == -1) + if (GetNumberOfOutputs() == 0) + { + int requiredOutputs = m_NavigationDataSet->GetNumberOfTools(); + this->SetNumberOfRequiredOutputs(requiredOutputs); + + for (unsigned int n = this->GetNumberOfOutputs(); n < requiredOutputs; ++n) + { + DataObjectPointer newOutput = this->MakeOutput(n); + this->SetNthOutput(n, newOutput); + this->Modified(); + } + } + else if (GetNumberOfOutputs() != 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(); + this->GenerateData(); +} + +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..8f526de99b 100644 --- a/Modules/IGT/IO/mitkNavigationDataPlayerBase.h +++ b/Modules/IGT/IO/mitkNavigationDataPlayerBase.h @@ -1,78 +1,118 @@ /*=================================================================== 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 + /** + * \brief Base class for using mitk::NavigationData as a filter source. + * Subclasses can play objects of mitk::NavigationDataSet. + * + * Each subclass has to check the state of m_Repeat and do or do not repeat + * the playing accordingly. * * \ingroup IGT */ class MitkIGT_EXPORT NavigationDataPlayerBase : public NavigationDataSource { public: - mitkClassMacro(NavigationDataPlayerBase, NavigationDataSource); + mitkClassMacro(NavigationDataPlayerBase, NavigationDataSource) /** - * \brief Used for pipeline update just to tell the pipeline that we always have to update + * \brief Set to true if the data player should repeat the outputs. + */ + itkSetMacro(Repeat, bool) + + /** + * \return Returns if the data player should repeat the outputs. + */ + itkGetMacro(Repeat, bool) + + /** + * \brief 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) - /** @return Retruns if the current stream is valid or not. */ - itkGetMacro(StreamValid,bool); + /** + * \brief Set mitk::NavigationDataSet for playing. + * Player is initialized by call to mitk::NavigationDataPlayerBase::InitPlayer() + * inside this method. Method must be called before this object can be used as + * a filter source. + * + * @param navigationDataSet mitk::NavigationDataSet which will be played by this player. + */ + void SetNavigationDataSet(NavigationDataSet::Pointer navigationDataSet); - /** + /** + * \brief Getter for the size of the mitk::NavigationDataSet used in this object. + * + * @return Returns the number of navigation data snapshots available in the player. + */ + unsigned int GetNumberOfSnapshots(); + + unsigned int GetCurrentSnapshotNumber(); + + /** * \brief This method checks if player arrived at end of file. * - *\warning This method is not tested yet. It is not save to use! + * @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. + * Aftwer calling this method, the first Navigationdata from the loaded Navigationdataset is loaded into the outputs. + */ + void InitPlayer(); /** - * \brief Creates NavigationData from XML element and returns it - * @throw mitk::Exception Throws an exception if elem is NULL. + * \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(). */ - mitk::NavigationData::Pointer ReadNavigationData(TiXmlElement* elem); + void GraftEmptyOutput(); - bool m_StreamValid; ///< stores if the input stream is valid or not - std::string m_ErrorMessage; ///< stores the error message if the stream is invalid + /** + * \brief If the player should repeat outputs. Default is false. + */ + bool m_Repeat; + NavigationDataSet::Pointer m_NavigationDataSet; + + /** + * \brief Iterator always points to the NavigationData object which is in the outputs at the moment. + */ + mitk::NavigationDataSet::NavigationDataSetIterator m_NavigationDataSetIterator; }; } // namespace mitk #endif /* MITKNavigationDataSequentialPlayer_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/IO/mitkNavigationDataReaderCSV.cpp b/Modules/IGT/IO/mitkNavigationDataReaderCSV.cpp new file mode 100644 index 0000000000..610bd67bab --- /dev/null +++ b/Modules/IGT/IO/mitkNavigationDataReaderCSV.cpp @@ -0,0 +1,17 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkNavigationDataReaderCSV.h" \ No newline at end of file diff --git a/Modules/IGT/IO/mitkNavigationDataReaderCSV.h b/Modules/IGT/IO/mitkNavigationDataReaderCSV.h new file mode 100644 index 0000000000..36133667a0 --- /dev/null +++ b/Modules/IGT/IO/mitkNavigationDataReaderCSV.h @@ -0,0 +1,30 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef MITKNavigationDataReaderCSV_H_HEADER_INCLUDED_ +#define MITKNavigationDataReaderCSV_H_HEADER_INCLUDED_ + +#include "mitkNavigationDataReaderInterface.h" + +namespace mitk { + class MitkIGT_EXPORT NavigationDataReaderCSV : public NavigationDataReaderInterface + { + + }; +} + +#endif // MITKNavigationDataReaderCSV_H_HEADER_INCLUDED_ diff --git a/Modules/IGT/IO/mitkNavigationDataReaderInterface.cpp b/Modules/IGT/IO/mitkNavigationDataReaderInterface.cpp new file mode 100644 index 0000000000..1e89800b77 --- /dev/null +++ b/Modules/IGT/IO/mitkNavigationDataReaderInterface.cpp @@ -0,0 +1,25 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkNavigationDataReaderInterface.h" + +mitk::NavigationDataReaderInterface::NavigationDataReaderInterface() +{ +} + +mitk::NavigationDataReaderInterface::~NavigationDataReaderInterface() +{ +} diff --git a/Modules/IGT/IO/mitkNavigationDataReaderInterface.h b/Modules/IGT/IO/mitkNavigationDataReaderInterface.h new file mode 100644 index 0000000000..09d7e6b183 --- /dev/null +++ b/Modules/IGT/IO/mitkNavigationDataReaderInterface.h @@ -0,0 +1,39 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef MITKNavigationDataReaderInterface_H_HEADER_INCLUDED_ +#define MITKNavigationDataReaderInterface_H_HEADER_INCLUDED_ + +#include "itkObject.h" +#include "mitkCommon.h" +#include "mitkNavigationDataSet.h" + +namespace mitk { + class MitkIGT_EXPORT NavigationDataReaderInterface : public itk::Object + { + public: + mitkClassMacro(NavigationDataReaderInterface, itk::Object); + + virtual mitk::NavigationDataSet::Pointer Read(std::string filename) = 0; + + protected: + NavigationDataReaderInterface(); + virtual ~NavigationDataReaderInterface(); + }; +} + +#endif // MITKNavigationDataReaderInterface_H_HEADER_INCLUDED_ diff --git a/Modules/IGT/IO/mitkNavigationDataReaderXML.cpp b/Modules/IGT/IO/mitkNavigationDataReaderXML.cpp new file mode 100644 index 0000000000..5d2f8186fc --- /dev/null +++ b/Modules/IGT/IO/mitkNavigationDataReaderXML.cpp @@ -0,0 +1,331 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkNavigationDataReaderXML.h" +#include +#include +#include "tinyxml.h" + +//includes for exceptions +#include "mitkIGTException.h" +#include "mitkIGTIOException.h" + +mitk::NavigationDataReaderXML::NavigationDataReaderXML() + : m_parentElement(0), m_currentNode(0) +{ +} + +mitk::NavigationDataReaderXML::~NavigationDataReaderXML() +{ + +} + +mitk::NavigationDataSet::Pointer mitk::NavigationDataReaderXML::Read(std::string fileName) +{ + m_FileName = fileName; + + TiXmlDocument document; + if ( !document.LoadFile(fileName)) + { + mitkThrowException(mitk::IGTIOException) << "File '"<QueryIntAttribute("Ver", &m_FileVersion) != TIXML_SUCCESS) + { + if (m_DataElem->QueryIntAttribute("version", &m_FileVersion) != TIXML_SUCCESS) + { + mitkThrowException(mitk::IGTIOException) << "Version not specified in XML file."; + } + } + + if (m_FileVersion != 1) + { + mitkThrowException(mitk::IGTIOException) << "File format version "<QueryIntAttribute("ToolCount", &m_NumberOfOutputs); + + mitk::NavigationDataSet::Pointer navigationDataSet = this->ReadNavigationDataSet(); + + return navigationDataSet; +} + +mitk::NavigationDataSet::Pointer mitk::NavigationDataReaderXML::Read(std::istream* stream) +{ + // first get the file version + m_FileVersion = this->GetFileVersion(stream); + + // check if we have a valid version: m_FileVersion has to be always bigger than 1 for playing + if (m_FileVersion < 1) + { + StreamInvalid("Playing not possible. Invalid file version!"); + return 0; + } + + m_NumberOfOutputs = this->GetNumberOfNavigationDatas(stream); + if (m_NumberOfOutputs == 0) { return 0; } + + return this->ReadNavigationDataSet(); +} + +mitk::NavigationDataSet::Pointer mitk::NavigationDataReaderXML::ReadNavigationDataSet() +{ + mitk::NavigationDataSet::Pointer navigationDataSet = mitk::NavigationDataSet::New(m_NumberOfOutputs); + mitk::NavigationData::Pointer curNavigationData; + + do + { + std::vector navDatas(m_NumberOfOutputs, NULL); + for (unsigned int n = 0; n < m_NumberOfOutputs; ++n) + { + curNavigationData = this->ReadVersion1(); + + if (curNavigationData.IsNull()) + { + if (n != 0) + { + MITK_WARN("mitkNavigationDataReaderXML") + << "Different number of NavigationData objects for different tools. Ignoring last ones."; + } + break; + } + navDatas.at(n) = curNavigationData; + } + + if (curNavigationData.IsNotNull()) + { + navigationDataSet->AddNavigationDatas(navDatas); + } + } + while (curNavigationData.IsNotNull()); + + return navigationDataSet; +} + +mitk::NavigationData::Pointer mitk::NavigationDataReaderXML::ReadVersion1() +{ + if ( !m_parentElement ) + { + mitkThrowException(mitk::IGTIOException) + << "Reading XML is not possible. Parent element is not set."; + } + + TiXmlElement* elem; + m_currentNode = m_parentElement->IterateChildren(m_currentNode); + + bool delElem; + + if(m_currentNode) + { + elem = m_currentNode->ToElement(); + if(elem==NULL) + { + mitkThrowException(mitk::IGTException) << "Cannot find element: Is this file damaged?"; + } + delElem = false; + } + + else + { + elem = new TiXmlElement(""); + delElem = true; + } + + + mitk::NavigationData::Pointer nd = this->ReadNavigationData(elem); + + if(delElem) { delete elem; } + + return nd; +} + +mitk::NavigationData::Pointer mitk::NavigationDataReaderXML::ReadNavigationData(TiXmlElement* elem) +{ + if (elem == NULL) {mitkThrow() << "Error: Element is NULL!";} + + mitk::NavigationData::Pointer nd = mitk::NavigationData::New(); + + mitk::NavigationData::PositionType position; + mitk::NavigationData::OrientationType orientation(0.0,0.0,0.0,0.0); + mitk::NavigationData::TimeStampType timestamp = -1; + mitk::NavigationData::CovarianceMatrixType matrix; + + bool hasPosition = true; + bool hasOrientation = true; + bool dataValid = false; + + position.Fill(0.0); + matrix.SetIdentity(); + + elem->QueryDoubleAttribute("Time",×tamp); + if (timestamp == -1) + { + return NULL; //the calling method should check the return value if it is valid/not NULL + } + + elem->QueryDoubleAttribute("X", &position[0]); + elem->QueryDoubleAttribute("Y", &position[1]); + elem->QueryDoubleAttribute("Z", &position[2]); + + elem->QueryDoubleAttribute("QX", &orientation[0]); + elem->QueryDoubleAttribute("QY", &orientation[1]); + elem->QueryDoubleAttribute("QZ", &orientation[2]); + elem->QueryDoubleAttribute("QR", &orientation[3]); + + elem->QueryDoubleAttribute("C00", &matrix[0][0]); + elem->QueryDoubleAttribute("C01", &matrix[0][1]); + elem->QueryDoubleAttribute("C02", &matrix[0][2]); + elem->QueryDoubleAttribute("C03", &matrix[0][3]); + elem->QueryDoubleAttribute("C04", &matrix[0][4]); + elem->QueryDoubleAttribute("C05", &matrix[0][5]); + elem->QueryDoubleAttribute("C10", &matrix[1][0]); + elem->QueryDoubleAttribute("C11", &matrix[1][1]); + elem->QueryDoubleAttribute("C12", &matrix[1][2]); + elem->QueryDoubleAttribute("C13", &matrix[1][3]); + elem->QueryDoubleAttribute("C14", &matrix[1][4]); + elem->QueryDoubleAttribute("C15", &matrix[1][5]); + + int tmpval = 0; + elem->QueryIntAttribute("Valid", &tmpval); + if (tmpval == 0) + dataValid = false; + else + dataValid = true; + + tmpval = 0; + elem->QueryIntAttribute("hO", &tmpval); + if (tmpval == 0) + hasOrientation = false; + else + hasOrientation = true; + + tmpval = 0; + elem->QueryIntAttribute("hP", &tmpval); + if (tmpval == 0) + hasPosition = false; + else + hasPosition = true; + + nd->SetIGTTimeStamp(timestamp); + nd->SetPosition(position); + nd->SetOrientation(orientation); + nd->SetCovErrorMatrix(matrix); + nd->SetDataValid(dataValid); + nd->SetHasOrientation(hasOrientation); + nd->SetHasPosition(hasPosition); + + + return nd; +} + +// -- deprecated | begin +unsigned int mitk::NavigationDataReaderXML::GetFileVersion(std::istream* stream) +{ + if (stream==NULL) + { + MITK_ERROR << "No input stream set!"; + mitkThrowException(mitk::IGTIOException)<<"No input stream set!"; + } + if (!stream->good()) + { + MITK_ERROR << "Stream is not good!"; + mitkThrowException(mitk::IGTIOException)<<"Stream is not good!"; + } + int version = 1; + + TiXmlDeclaration* dec = new TiXmlDeclaration(); + *stream >> *dec; + if(strcmp(dec->Version(),"") == 0) + { + MITK_ERROR << "The input stream seems to have XML incompatible format"; + mitkThrowException(mitk::IGTIOException) << "The input stream seems to have XML incompatible format"; + } + + m_parentElement = new TiXmlElement(""); + *stream >> *m_parentElement; //2nd line this is the file version + + std::string tempValue = m_parentElement->Value(); + if(tempValue != "Version") + { + if(tempValue == "Data"){ + m_parentElement->QueryIntAttribute("version",&version); + } + } + else + { + m_parentElement->QueryIntAttribute("Ver",&version); + } + + if (version > 0) { return version; } + else { return 0; } +} + +unsigned int mitk::NavigationDataReaderXML::GetNumberOfNavigationDatas(std::istream* stream) +{ + if (stream == NULL) + { + MITK_ERROR << "No input stream set!"; + mitkThrowException(mitk::IGTException)<<"No input stream set!"; + } + if (!stream->good()) + { + MITK_ERROR << "Stream not good!"; + mitkThrowException(mitk::IGTException)<<"Stream not good!"; + } + + //If something has changed in a future version of the XML definition e.g. navigationcount or addional parameters + //catch this here with a select case block (see GenerateData() method) + + int numberOfTools = 0; + + std::string tempValue = m_parentElement->Value(); + if(tempValue == "Version"){ + *stream >> *m_parentElement; + } + m_parentElement->QueryIntAttribute("ToolCount",&numberOfTools); + + if (numberOfTools > 0) { return numberOfTools; } + + return 0; +} + +void mitk::NavigationDataReaderXML::StreamInvalid(std::string message) +{ + m_StreamEnd = true; + m_ErrorMessage = message; + m_StreamValid = false; + mitkThrowException(mitk::IGTIOException) << "Invalid stream!"; +} +// -- deprecated | end + diff --git a/Modules/IGT/IO/mitkNavigationDataReaderXML.h b/Modules/IGT/IO/mitkNavigationDataReaderXML.h new file mode 100644 index 0000000000..3cdf561fe3 --- /dev/null +++ b/Modules/IGT/IO/mitkNavigationDataReaderXML.h @@ -0,0 +1,109 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef MITKNavigationDataReaderXML_H_HEADER_INCLUDED_ +#define MITKNavigationDataReaderXML_H_HEADER_INCLUDED_ + +#include "mitkNavigationDataReaderInterface.h" + +class TiXmlElement; +class TiXmlNode; + +namespace mitk { + + class MitkIGT_EXPORT NavigationDataReaderXML : public NavigationDataReaderInterface + { + public: + mitkClassMacro(NavigationDataReaderXML, NavigationDataReaderInterface); + itkNewMacro(Self); + + virtual mitk::NavigationDataSet::Pointer Read(std::string fileName); + virtual mitk::NavigationDataSet::Pointer Read(std::istream* stream); + + // -- deprecated | begin + /** + * \brief Sets the stream of this player. + * @throw mitk::IGTException Throws an exception if stream is NULL or if it is not good. + * \deprecated Will be removed in one of the next releases. Use SetFileName() instead. + */ + //void SetStream(std::istream* stream); + // -- deprecated | end + + protected: + NavigationDataReaderXML(); + virtual ~NavigationDataReaderXML(); + + NavigationDataSet::Pointer ReadNavigationDataSet(); + + /** + * \brief This method reads one line of the XML document and returns the data as a NavigationData object + * If there is a new file version another method must be added which reads this data. + * @throw mitk::IGTException Throws an exceptions if file is damaged. + */ + mitk::NavigationData::Pointer ReadVersion1(); + mitk::NavigationData::Pointer ReadNavigationData(TiXmlElement* elem); + + std::string m_FileName; + + TiXmlElement* m_parentElement; + TiXmlNode* m_currentNode; + + int m_FileVersion; ///< indicates which XML encoding is used + int m_NumberOfOutputs; ///< stores the number of outputs known from the XML document + + // -- deprecated | begin + //std::istream* m_Stream; ///< stores a pointer to the input stream + bool m_StreamEnd; ///< stores if the input stream arrived at end + bool m_StreamValid; ///< stores if the input stream is valid or not + std::string m_ErrorMessage; ///< stores the error message if the stream is invalid + + /** + * \brief Creates a stream out of the filename given by the variable m_FileName. + * The stream is then set to m_Stream. + * + * @throw mitk::IGTIOException Throws an exception if file does not exist + * @throw mitk::IGTException Throws an exception if the stream is NULL + */ + //void CreateStreamFromFilename(); + + /** + * \brief Returns the file version out of the XML document. + * @throw mitk::IGTException Throws an mitk::IGTException an exception if stream is NULL or not good. + * @throw mitk::IGTIOException Throws an mitk::IGTIOException if the stream has an incompatible XML format. + */ + unsigned int GetFileVersion(std::istream* stream); + + /** + * \brief Returns the number of tracked tools out of the XML document. + * @throw Throws an exception if stream is NULL. + * @throw Throws an exception if the input stream has an XML incompatible format. + */ + unsigned int GetNumberOfNavigationDatas(std::istream* stream); + + /** + * @brief This is a helping method which gives an error message and throws an exception with the given message. + * It can be used if a stream is found to be invalid. + * + * @throw mitk::IGTIOException Always throws an exception. + */ + void StreamInvalid(std::string message); ///< help method which sets the stream invalid and displays an error + // -- deprecated | end + }; + +} // namespace mitk + +#endif // MITKNavigationDataReaderXML_H_HEADER_INCLUDED_ diff --git a/Modules/IGT/IO/mitkNavigationDataRecorder.cpp b/Modules/IGT/IO/mitkNavigationDataRecorder.cpp index fb5fe23f1f..019546d60d 100644 --- a/Modules/IGT/IO/mitkNavigationDataRecorder.cpp +++ b/Modules/IGT/IO/mitkNavigationDataRecorder.cpp @@ -1,366 +1,115 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkNavigationDataRecorder.h" -#include #include -#include -#include - -//headers for exceptions -#include "mitkIGTException.h" -#include "mitkIGTIOException.h" mitk::NavigationDataRecorder::NavigationDataRecorder() { //set default values m_NumberOfInputs = 0; - m_RecordingMode = NormalFile; m_Recording = false; - m_NumberOfRecordedFiles = 0; - m_Stream = NULL; - m_FileName = ""; - m_SystemTimeClock = RealTimeClock::New(); - m_OutputFormat = mitk::NavigationDataRecorder::xml; - m_RecordCounter = 0; + m_StandardizedTimeInitialized = false; m_RecordCountLimit = -1; - m_DoNotOverwriteFiles = false; - m_StreamMustBeDeleted = false; - - //To get a start time - mitk::IGTTimeStamp::GetInstance()->Start(this); } mitk::NavigationDataRecorder::~NavigationDataRecorder() { + mitk::IGTTimeStamp::GetInstance()->Stop(this); } - void mitk::NavigationDataRecorder::GenerateData() { + // get each input, lookup the associated BaseData and transfer the data + DataObjectPointerArray inputs = this->GetIndexedInputs(); //get all inputs -} - -void mitk::NavigationDataRecorder::AddNavigationData( const NavigationData* nd ) -{ - // Process object is not const-correct so the const_cast is required here - this->SetNthInput(m_NumberOfInputs, - const_cast< mitk::NavigationData * >( nd ) ); - - m_NumberOfInputs++; + //This vector will hold the NavigationDatas that are copied from the inputs + std::vector< mitk::NavigationData::Pointer > clonedDatas; - this->Modified(); -} - -void mitk::NavigationDataRecorder::SetRecordingMode( RecordingMode mode ) -{ - m_RecordingMode = mode; - this->Modified(); -} - -void mitk::NavigationDataRecorder::Update() -{ - if (m_Recording) + // For each input + for (unsigned int index=0; index < inputs.size(); index++) { - DataObjectPointerArray inputs = this->GetInputs(); //get all inputs - mitk::NavigationData::TimeStampType timestamp=0.0; // timestamp for mitk time - timestamp = mitk::IGTTimeStamp::GetInstance()->GetElapsed(); - + // First copy input to output + this->GetOutput(index)->Graft(this->GetInput(index)); - mitk::NavigationData::TimeStampType sysTimestamp = 0.0; // timestamp for system time - sysTimestamp = m_SystemTimeClock->GetCurrentStamp(); + // if we are not recording, that's all there is to do + if (! m_Recording) continue; - // cast system time double value to stringstream to avoid low precision rounding - std::ostringstream strs; - strs.precision(15); // rounding precision for system time double value - strs << sysTimestamp; - std::string sysTimeStr = strs.str(); + // Clone a Navigation Data + mitk::NavigationData::Pointer clone = mitk::NavigationData::New(); + clone->Graft(this->GetInput(index)); + clonedDatas.push_back(clone); - //if csv-mode: write csv header and timestamp at beginning - if (m_OutputFormat == mitk::NavigationDataRecorder::csv) - { - //write header only when it's the first line - if (m_firstLine) - { - m_firstLine = false; - *m_Stream << "TimeStamp"; - for (unsigned int index = 0; index < inputs.size(); index++){ *m_Stream << ";Valid_Tool" << index << - ";X_Tool" << index << - ";Y_Tool" << index << - ";Z_Tool" << index << - ";QX_Tool" << index << - ";QY_Tool" << index << - ";QZ_Tool" << index << - ";QR_Tool" << index;} - *m_Stream << "\n"; - } - //write timestamp (always) - *m_Stream << timestamp; - } - - //write tool data for every tool - for (unsigned int index = 0; index < inputs.size(); index++) + if (m_StandardizeTime) { - mitk::NavigationData* nd = dynamic_cast(inputs[index].GetPointer()); - nd->Update(); // call update to propagate update to previous filters - - mitk::NavigationData::PositionType position; - mitk::NavigationData::OrientationType orientation(0.0, 0.0, 0.0, 0.0); - mitk::NavigationData::CovarianceMatrixType matrix; - - bool hasPosition = true; - bool hasOrientation = true; - bool dataValid = false; - - position.Fill(0.0); - matrix.SetIdentity(); - - position = nd->GetPosition(); - orientation = nd->GetOrientation(); - matrix = nd->GetCovErrorMatrix(); - - hasPosition = nd->GetHasPosition(); - hasOrientation = nd->GetHasOrientation(); - dataValid = nd->IsDataValid(); - - //use this one if you want the timestamps of the source - //timestamp = nd->GetIGTTimeStamp(); - - //a timestamp is never < 0! this case happens only if you are using the timestamp of the nd object instead of getting a new one - if (timestamp >= 0) - { - if (this->m_OutputFormat == mitk::NavigationDataRecorder::xml) - { - TiXmlElement* elem = new TiXmlElement("NavigationData"); - - elem->SetDoubleAttribute("Time", timestamp); - elem->SetAttribute("SystemTime", sysTimeStr); // tag for system time - elem->SetDoubleAttribute("Tool", index); - elem->SetDoubleAttribute("X", position[0]); - elem->SetDoubleAttribute("Y", position[1]); - elem->SetDoubleAttribute("Z", position[2]); - - elem->SetDoubleAttribute("QX", orientation[0]); - elem->SetDoubleAttribute("QY", orientation[1]); - elem->SetDoubleAttribute("QZ", orientation[2]); - elem->SetDoubleAttribute("QR", orientation[3]); - - elem->SetDoubleAttribute("C00", matrix[0][0]); - elem->SetDoubleAttribute("C01", matrix[0][1]); - elem->SetDoubleAttribute("C02", matrix[0][2]); - elem->SetDoubleAttribute("C03", matrix[0][3]); - elem->SetDoubleAttribute("C04", matrix[0][4]); - elem->SetDoubleAttribute("C05", matrix[0][5]); - elem->SetDoubleAttribute("C10", matrix[1][0]); - elem->SetDoubleAttribute("C11", matrix[1][1]); - elem->SetDoubleAttribute("C12", matrix[1][2]); - elem->SetDoubleAttribute("C13", matrix[1][3]); - elem->SetDoubleAttribute("C14", matrix[1][4]); - elem->SetDoubleAttribute("C15", matrix[1][5]); - - if (dataValid) - elem->SetAttribute("Valid",1); - else - elem->SetAttribute("Valid",0); - - if (hasOrientation) - elem->SetAttribute("hO",1); - else - elem->SetAttribute("hO",0); - - if (hasPosition) - elem->SetAttribute("hP",1); - else - elem->SetAttribute("hP",0); - - // set additional attribute? - std::map >::iterator - it = m_AdditionalAttributes.find( nd ); - if( it != m_AdditionalAttributes.end() ) - { - elem->SetAttribute(it->second.first, it->second.second); - } - - *m_Stream << " " << *elem << std::endl; - - delete elem; - } - else if (this->m_OutputFormat == mitk::NavigationDataRecorder::csv) - { - *m_Stream << ";" << dataValid << ";" << position[0] << ";" << position[1] << ";" << position[2] << ";" << orientation[0] << ";" << orientation[1] << ";" << orientation[2] << ";" << orientation[3]; - } - } - } - if (this->m_OutputFormat == mitk::NavigationDataRecorder::csv) - { - *m_Stream << "\n"; + mitk::NavigationData::TimeStampType igtTimestamp = mitk::IGTTimeStamp::GetInstance()->GetElapsed(this); + clonedDatas[index]->SetIGTTimeStamp(igtTimestamp); } } - m_RecordCounter++; - if ((m_RecordCountLimit<=m_RecordCounter)&&(m_RecordCountLimit != -1)) {StopRecording();} -} -void mitk::NavigationDataRecorder::SetAdditionalAttribute(const NavigationData* nd, - const std::string& attributeName - , const std::string& attributeValue ) -{ - std::map >::iterator - it = m_AdditionalAttributes.find( nd ); - if( it == m_AdditionalAttributes.end() ) - m_AdditionalAttributes[nd] = std::pair(attributeName, attributeValue); - else - { - it->second.first = attributeName; - it->second.second = attributeValue; - } + // if limitation is set and has been reached, stop recording + if ((m_RecordCountLimit > 0) && (m_NavigationDataSet->Size() >= m_RecordCountLimit)) m_Recording = false; + // We can skip the rest of the method, if recording is deactivated + if (!m_Recording) return; -} -void mitk::NavigationDataRecorder::RemoveAdditionalAttribute( const NavigationData* nd ) -{ - std::map >::iterator - it = m_AdditionalAttributes.find( nd ); - if( it != m_AdditionalAttributes.end() ) - m_AdditionalAttributes.erase(it); + // Add data to set + m_NavigationDataSet->AddNavigationDatas(clonedDatas); } void mitk::NavigationDataRecorder::StartRecording() -{ - - if(!m_Recording) - { - if (m_Stream == NULL) - { - std::stringstream ss; - std::ostream* stream; - - //An existing extension will be cut and replaced with .xml - std::string tmpPath = itksys::SystemTools::GetFilenamePath(m_FileName); - m_FileName = itksys::SystemTools::GetFilenameWithoutExtension(m_FileName); - std::string extension = ".xml"; - if (m_OutputFormat == mitk::NavigationDataRecorder::csv) - extension = ".csv"; - - ss << tmpPath << "/" << m_FileName << "-" << m_NumberOfRecordedFiles << extension; - - if( m_DoNotOverwriteFiles ) - { - unsigned int index = m_NumberOfRecordedFiles+1; - while( itksys::SystemTools::FileExists( ss.str().c_str() ) ) - { - ss.str(""); - ss << tmpPath << "/" << m_FileName << "-" << index << extension; - index++; - } - } - - switch(m_RecordingMode) - { - case Console: - stream = &std::cout; - break; - - case NormalFile: - if (m_FileName == "") //Check if there is a file name and path - { - std::string message = "No file name or file path set."; - MITK_ERROR << message; - mitkThrowException(mitk::IGTException) << message; - } - else - { - stream = new std::ofstream(ss.str().c_str()); - } - break; - - case ZipFile: - stream = &std::cout; - MITK_WARN << "Sorry no ZipFile support yet"; - break; - - default: - stream = &std::cout; - break; - } - m_Stream = stream; - m_StreamMustBeDeleted = true; - m_firstLine = true; - m_RecordCounter = 0; - StartRecording(stream); - } - } -else if (m_Recording) - { - MITK_WARN << "Already recording please stop before start new recording session"; - return; - } -} - -void mitk::NavigationDataRecorder::StartRecording(std::ostream* stream) { if (m_Recording) { MITK_WARN << "Already recording please stop before start new recording session"; return; } + m_Recording = true; - m_Stream = stream; - m_Stream->precision(10); + // The first time this StartRecording is called, we initialize the standardized time. + // Afterwards, it can be reset via ResetNavigationDataSet(); + if (! m_StandardizedTimeInitialized) + mitk::IGTTimeStamp::GetInstance()->Start(this); - //TODO store date and GMT time - //cheking if the stream is good - if (m_Stream->good()) - { - if (m_OutputFormat == mitk::NavigationDataRecorder::xml) - { - *m_Stream << "" << std::endl; - /**m_Stream << "" << std::endl;*/ - // should be a generic version, meaning a member variable, which has the actual version - *m_Stream << " " << "" << std::endl; - } - m_Recording = true; - } - else - { - m_Recording = false; - mitkThrowException(mitk::IGTException)<<"The stream is not good"; - } + if (m_NavigationDataSet.IsNull()) + m_NavigationDataSet = mitk::NavigationDataSet::New(GetNumberOfIndexedInputs()); } - void mitk::NavigationDataRecorder::StopRecording() { if (!m_Recording) { std::cout << "You have to start a recording first" << std::endl; return; } + m_Recording = false; +} - if ((m_Stream) && (m_OutputFormat == mitk::NavigationDataRecorder::xml)) +void mitk::NavigationDataRecorder::ResetRecording() +{ + m_NavigationDataSet = mitk::NavigationDataSet::New(GetNumberOfIndexedInputs()); + + if (m_Recording) { - *m_Stream << "" << std::endl; + mitk::IGTTimeStamp::GetInstance()->Stop(this); + mitk::IGTTimeStamp::GetInstance()->Start(this); } - - m_NumberOfRecordedFiles++; - m_Recording = false; - m_Stream->flush(); - if (m_StreamMustBeDeleted) //stream must only be deleted if it was created inside this class - { - m_StreamMustBeDeleted = false; - delete m_Stream; - } - m_Stream = NULL; } + +int mitk::NavigationDataRecorder::GetNumberOfRecordedSteps() +{ + return m_NavigationDataSet->Size(); +} \ No newline at end of file diff --git a/Modules/IGT/IO/mitkNavigationDataRecorder.h b/Modules/IGT/IO/mitkNavigationDataRecorder.h index 167ac15bb3..edccd2fe95 100644 --- a/Modules/IGT/IO/mitkNavigationDataRecorder.h +++ b/Modules/IGT/IO/mitkNavigationDataRecorder.h @@ -1,220 +1,120 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ - #ifndef _MITK_NavigationDataRecorder_H #define _MITK_NavigationDataRecorder_H -#include +#include "mitkNavigationDataToNavigationDataFilter.h" #include "mitkNavigationData.h" - -#include - -#include +#include "mitkNavigationDataSet.h" namespace mitk { - - /**Documentation - * \brief This class records NavigationData objects. - * - * The output of this class is formated as a XML document. - * - * Internal this class uses streams for recording NavigationData objects. Therefore different types of output are possible - * and can be set with the SetOutputMode() method. The default output is directed to the console. If you want to save into a - * file you have to set a file name and the path. The recording is started with the call of the method StartRecording(). Now - * every Update() stores the current state of the added NavigationDatas. With StopRecording() the stream is stopped. With - * another call of StartRecording() the output is written to a new file with incremented filename counter. - * - * \warning At the moment there is no check if the file is already existing and this class will override existing files. - * \ingroup IGT - */ - -class MitkIGT_EXPORT NavigationDataRecorder : public itk::ProcessObject -{ -public: - mitkClassMacro( NavigationDataRecorder, itk::ProcessObject ); + /**Documentation + * \brief This class records NavigationData objects into NavigationDataSets. + * + * The recording is started with the call of the method StartRecording(). Now + * every Update() stores the current state of the added NavigationDatas into the NavigationDataSet. + * With StopRecording() the stream is stopped, but can be resumed anytime. + * To start recording to a new NavigationDataSet, call ResetRecording(); + * + * \warning Do not add inputs while the recorder ist recording. The recorder can't handle that and will cause a nullpointer exception. + * \ingroup IGT + */ + + class MitkIGT_EXPORT NavigationDataRecorder : public NavigationDataToNavigationDataFilter + { + public: + + mitkClassMacro( NavigationDataRecorder, NavigationDataToNavigationDataFilter ); itkFactorylessNewMacro(Self) itkCloneMacro(Self) - /**Documentation - * \brief Determines where the output is directed to - * - * Console: std::cout - * NormalFile: std::ofstream - * ZipFile: Not supported yet -> std::cout - */ - enum RecordingMode - { - Console, - NormalFile, - ZipFile - }; - - /**Documentation - * \brief Determines the output format - * - * xml: XML format, also default, can be read by NavigationDataPlayer - * csv: use to export in excel, matlab, etc. - */ - enum OutputFormatEnum - { - xml, - csv - }; - /** - * \brief sets the file name for the OutputMode NormalFile and ZipFile - * - * Any extensions will be cut - * \warning existing files will be overridden - * \warning do not use "." in file names at the end + * \brief Returns whether the NavigationDataRecorder is currently recording or not */ - itkSetStringMacro(FileName); + itkGetMacro(Recording, bool); /** - * \brief Returns the file name of the recording file (in OutputMode NormalFile and ZipFile) + * \brief Returns the set that contains all of the recorded data. */ - itkGetStringMacro(FileName); - + itkGetMacro(NavigationDataSet, mitk::NavigationDataSet::Pointer); /** - * \brief If true the recorder will never overwrite a file + * \brief Sets a limit of recorded data sets / frames. Recording will be stopped if the number is reached. values < 1 disable this behaviour. Default is -1. */ - itkSetMacro(DoNotOverwriteFiles,bool); + itkSetMacro(RecordCountLimit, int); /** - * \brief Returns whether the NavigationDataRecorder is recording or not + * \brief Returns whether to use the navigationdata's time stamp or to create a new one upon recording. */ - itkGetMacro(Recording,bool); + itkGetMacro(StandardizeTime, bool); /** - * \brief Returns the recording mode + * \brief If set to false, the navigationDatas Timestamp will be used. If set to false, the recorder + * will generate a timestamp when it copies the data to the navigationdataset. */ - itkGetMacro(RecordingMode,RecordingMode); + itkSetMacro(StandardizeTime, bool); /** - * \brief Returns the number of data sets / frames which were recorded by the NavigationDataRecorder since start + * \brief Starts recording NavigationData into the NAvigationDataSet */ - itkGetMacro(RecordCounter,int); + virtual void StartRecording(); /** - * \brief Sets a limit of recorded data sets / frames. Recording will be stopped if the number is reached. -1 disables the limit, -1 is default value as well. + * \brief Stops StopsRecording to the NavigationDataSet. + * + * Recording can be resumed to the same Dataset by just calling StartRecording() again. + * Call ResetRecording() to start recording to a new Dataset; */ - itkSetMacro(RecordCountLimit,int); + virtual void StopRecording(); /** - * \brief Adds the input NavigationDatas + * \brief Resets the Datasets and the timestamp, so a new recording can happen. + * + * Do not forget to save the old Dataset, it will be lost after calling this function. */ - virtual void AddNavigationData(const NavigationData* nd); - - /// - /// set an additional attribute for a specified navigation data - /// this will be written for each navigation data and may be - /// updated before calling Update() - /// - void SetAdditionalAttribute( const NavigationData* nd, const std::string& attributeName - , const std::string& attributeValue ); - void RemoveAdditionalAttribute( const NavigationData* nd ); + virtual void ResetRecording(); /** - * Documentation - * \brief Starts the recording with the presetted OutputMode. - * This method calls StartRecording(std::ostream*). - * Does nothing if the recorder is already recording and - * the method StartRecording is called again. - * @throw mitk::IGTException Throws an exception if no file name or file path is set. - */ - void StartRecording(); - - /** - * Documentation - * \brief Starts the recording with an own preinitialized stream - * Does nothing if it is already recording and method StartRecorded is called - * @throw mitk::IGTException Throws an exception if the stream is not good. - */ - void StartRecording(std::ostream* stream); - - /**Documentation - * \brief Stops the recording and closes the stream - */ - void StopRecording(); - - /**Documentation - * \brief Every call of update causes one line for each added NavigationData in the output if the recording was started - */ - - virtual void Update(); - - - /**Documentation - * \brief Sets the recording mode which causes different types of output streams - * see enum RecordingMode - */ - void SetRecordingMode(RecordingMode mode); - - /**Documentation - * \brief Sets the output format which causes different formats of output streams. The XML format is default. - * Also see enum OutputFormat for more information. + * \brief Returns the number of time steps that were recorded in the current set. + * Warning: This Method does NOT Stop Recording! */ - itkSetMacro(OutputFormat,mitk::NavigationDataRecorder::OutputFormatEnum); + virtual int GetNumberOfRecordedSteps(); -protected: + protected: - /**Documentation - * \brief filter execute method here it is not used - * - */ virtual void GenerateData(); NavigationDataRecorder(); virtual ~NavigationDataRecorder(); - std::string m_FileName; ///< stores the file name and path - unsigned int m_NumberOfInputs; ///< counts the numbers of added input NavigationDatas - std::ostream* m_Stream; ///< the output stream - - bool m_StreamMustBeDeleted; - - RecordingMode m_RecordingMode; ///< stores the mode see enum RecordingMode - - OutputFormatEnum m_OutputFormat; ///< stores the output format; see enum OutputFormat + mitk::NavigationDataSet::Pointer m_NavigationDataSet; bool m_Recording; ///< indicates whether the recording is started or not - int m_RecordCounter; ///< counts the number of frames which are recorded since StartRecording - - int m_RecordCountLimit; ///< limits the number of frames, recording will be stopped if the limit is reached. -1 disables the limit - - bool m_firstLine; //for the csv writer to detect wether the header must be written - - unsigned int m_NumberOfRecordedFiles; ///< necessary for the naming of the file if there is more than one start-stop cycle + bool m_StandardizeTime; //< indicates whether one should use the timestamps in NavigationData or create new timestamps upon recording - mitk::RealTimeClock::Pointer m_SystemTimeClock; ///< system time clock for system time tag in output xml file - - bool m_DoNotOverwriteFiles; ///< do not overwrite any files if true - - std::map > m_AdditionalAttributes; - -}; + bool m_StandardizedTimeInitialized; //< set to true the first time start recording is called. + int m_RecordCountLimit; ///< limits the number of frames, recording will be stopped if the limit is reached. -1 disables the limit + }; } #endif // #define _MITK_POINT_SET_SOURCE_H - diff --git a/Modules/IGT/IO/mitkNavigationDataSequentialPlayer.cpp b/Modules/IGT/IO/mitkNavigationDataSequentialPlayer.cpp index 82557229d8..4030687417 100644 --- a/Modules/IGT/IO/mitkNavigationDataSequentialPlayer.cpp +++ b/Modules/IGT/IO/mitkNavigationDataSequentialPlayer.cpp @@ -1,226 +1,97 @@ /*=================================================================== 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) { } - 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); - - 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()); - } + // set iterator to given position (modulo for allowing repeat) + m_NavigationDataSetIterator = m_NavigationDataSet->Begin() + ( i % this->GetNumberOfSnapshots() ); - // 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->GenerateData(); } -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) + MITK_WARN("NavigationDataSequentialPlayer") << "Cannot go to next snapshot, already at end of NavigationDataset. Ignoring..."; + return false; + } + ++m_NavigationDataSetIterator; + if ( m_NavigationDataSetIterator == m_NavigationDataSet->End() ) + { + 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; + this->GenerateData(); + return true; } -void mitk::NavigationDataSequentialPlayer:: - SetFileName(const std::string& _FileName) -{ - m_FileName = _FileName; - - if(!m_Doc->LoadFile(m_FileName)) - { - this->SetNumberOfIndexedOutputs(0); - std::ostringstream s; - s << "File " << _FileName << " could not be loaded"; - mitkThrowException(mitk::IGTIOException)<ReinitXML(); - } - - this->Modified(); -} - -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 < GetNumberOfOutputs(); 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(); } - - - diff --git a/Modules/IGT/IO/mitkNavigationDataSequentialPlayer.h b/Modules/IGT/IO/mitkNavigationDataSequentialPlayer.h index 53bd3260f7..fea196e200 100644 --- a/Modules/IGT/IO/mitkNavigationDataSequentialPlayer.h +++ b/Modules/IGT/IO/mitkNavigationDataSequentialPlayer.h @@ -1,123 +1,79 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ - #ifndef MITKNavigationDataSequentialPlayer_H_HEADER_INCLUDED_ #define MITKNavigationDataSequentialPlayer_H_HEADER_INCLUDED_ #include -#include "tinyxml.h" - namespace mitk { - /**Documentation * \brief This class is a slightly changed reimplementation of the * NavigationDataPlayer which does not care about timestamps and just * outputs the navigationdatas in their sequential order * * \ingroup IGT */ class MitkIGT_EXPORT NavigationDataSequentialPlayer : public NavigationDataPlayerBase { public: mitkClassMacro(NavigationDataSequentialPlayer, NavigationDataPlayerBase); - itkFactorylessNewMacro(Self) - itkCloneMacro(Self) - - /** - * \brief sets the file name and path (if XMLString is set, this is neglected) - * @throw mitk::IGTIOException Throws an exception if the given file cannot be loaded. - */ - void SetFileName(const std::string& _FileName); - - /** - * \brief returns the file name and path - */ - itkGetStringMacro(FileName); - - /** - * \brief sets a xml string (by this, the xml string is not read from file) - * @throw mitk::IGTExcepton Throws an mitk::IGTExcepton if the string to set is not an XMLString - */ - void SetXMLString(const std::string& _XMLString); + itkNewMacro(Self); /** - * \brief returns the current xml string + * \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. + * This method internally calls GenerateData, so outputs are refreshed automatically + * + * Filter output is updated inside the function. + * + * @throw mitk::IGTException Throws an exception if cannot go back to particular snapshot. */ - itkGetStringMacro(XMLString); - - /** - * @brief Set to true if the data player should repeat the outputs. - */ - itkSetMacro(Repeat, bool); - - /** - * @return Returns if the data player should repeat the outputs. - */ - itkGetMacro(Repeat, bool); - - /** - * @return Returns the number of navigation data snapshots available in the file - */ - itkGetMacro(NumberOfSnapshots, unsigned int); + void GoToSnapshot(unsigned int i); /** - * 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 next snapshot of mitk::NavigationData. + * Filter output is updated inside the function. * - * @throw mitk::IGTException Throws an exception if cannot go back to particular snapshot. + * \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. */ - void GoToSnapshot(unsigned int i); + 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; - bool m_Repeat; - unsigned int m_NumberOfSnapshots; - unsigned int m_LastGoTo; }; } // namespace mitk #endif /* MITKNavigationDataSequentialPlayer_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/IO/mitkNavigationDataSetWriterCSV.cpp b/Modules/IGT/IO/mitkNavigationDataSetWriterCSV.cpp new file mode 100644 index 0000000000..136f9b4f9d --- /dev/null +++ b/Modules/IGT/IO/mitkNavigationDataSetWriterCSV.cpp @@ -0,0 +1,17 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkNavigationDataSetWriterCSV.h" \ No newline at end of file diff --git a/Modules/IGT/IO/mitkNavigationDataSetWriterCSV.h b/Modules/IGT/IO/mitkNavigationDataSetWriterCSV.h new file mode 100644 index 0000000000..8836083c41 --- /dev/null +++ b/Modules/IGT/IO/mitkNavigationDataSetWriterCSV.h @@ -0,0 +1,28 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef MITKNavigationDataSetWriterCSV_H_HEADER_INCLUDED_ +#define MITKNavigationDataSetWriterCSV_H_HEADER_INCLUDED_ + +namespace mitk { + class NavigationDataSetWriterCSV + { + + }; +} + +#endif // MITKNavigationDataSetWriterCSV_H_HEADER_INCLUDED_ diff --git a/Modules/IGT/IO/mitkNavigationDataSetWriterXML.cpp b/Modules/IGT/IO/mitkNavigationDataSetWriterXML.cpp new file mode 100644 index 0000000000..9ce7eee434 --- /dev/null +++ b/Modules/IGT/IO/mitkNavigationDataSetWriterXML.cpp @@ -0,0 +1,130 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +// MITK +#include "mitkNavigationDataSetWriterXML.h" + +// Third Party +#include +#include +#include +#include + +mitk::NavigationDataSetWriterXML::NavigationDataSetWriterXML() +{ +} + +mitk::NavigationDataSetWriterXML::~NavigationDataSetWriterXML() +{ +} + +void mitk::NavigationDataSetWriterXML::Write (std::string path, mitk::NavigationDataSet::Pointer data) +{ + std::ofstream stream; + stream.open (path.c_str(), std::ios_base::trunc); + + // Pass to Stream Handler + Write(&stream, data); + stream.close(); +} + +void mitk::NavigationDataSetWriterXML::Write (std::ostream* stream, mitk::NavigationDataSet::Pointer data) +{ + StreamHeader(stream, data); + StreamData(stream, data); + StreamFooter(stream); + + // Cleanup + + stream->flush(); +} + +void mitk::NavigationDataSetWriterXML::StreamHeader (std::ostream* stream, mitk::NavigationDataSet::Pointer data) +{ + stream->precision(10); + + //TODO store date and GMT time + //checking if the stream is good + if (stream->good()) + { + *stream << "" << std::endl; + /**m_Stream << "" << std::endl;*/ + // should be a generic version, meaning a member variable, which has the actual version + *stream << " " << "GetNumberOfTools() << "\" version=\"1.0\">" << std::endl; + } +} + +void mitk::NavigationDataSetWriterXML::StreamData (std::ostream* stream, mitk::NavigationDataSet::Pointer data) +{ + // For each time step in the Dataset + for (mitk::NavigationDataSet::NavigationDataSetIterator it = data->Begin(); it != data->End(); it++) + { + for (int toolIndex = 0; toolIndex < it->size(); toolIndex++) + { + mitk::NavigationData::Pointer nd = it->at(toolIndex); + TiXmlElement* elem = new TiXmlElement("ND"); + + elem->SetDoubleAttribute("Time", nd->GetIGTTimeStamp()); + // elem->SetAttribute("SystemTime", sysTimeStr); // tag for system time + elem->SetDoubleAttribute("Tool", toolIndex); + elem->SetDoubleAttribute("X", nd->GetPosition()[0]); + elem->SetDoubleAttribute("Y", nd->GetPosition()[1]); + elem->SetDoubleAttribute("Z", nd->GetPosition()[2]); + + elem->SetDoubleAttribute("QX", nd->GetOrientation()[0]); + elem->SetDoubleAttribute("QY", nd->GetOrientation()[1]); + elem->SetDoubleAttribute("QZ", nd->GetOrientation()[2]); + elem->SetDoubleAttribute("QR", nd->GetOrientation()[3]); + + elem->SetDoubleAttribute("C00", nd->GetCovErrorMatrix()[0][0]); + elem->SetDoubleAttribute("C01", nd->GetCovErrorMatrix()[0][1]); + elem->SetDoubleAttribute("C02", nd->GetCovErrorMatrix()[0][2]); + elem->SetDoubleAttribute("C03", nd->GetCovErrorMatrix()[0][3]); + elem->SetDoubleAttribute("C04", nd->GetCovErrorMatrix()[0][4]); + elem->SetDoubleAttribute("C05", nd->GetCovErrorMatrix()[0][5]); + elem->SetDoubleAttribute("C10", nd->GetCovErrorMatrix()[1][0]); + elem->SetDoubleAttribute("C11", nd->GetCovErrorMatrix()[1][1]); + elem->SetDoubleAttribute("C12", nd->GetCovErrorMatrix()[1][2]); + elem->SetDoubleAttribute("C13", nd->GetCovErrorMatrix()[1][3]); + elem->SetDoubleAttribute("C14", nd->GetCovErrorMatrix()[1][4]); + elem->SetDoubleAttribute("C15", nd->GetCovErrorMatrix()[1][5]); + + if (nd->IsDataValid()) + elem->SetAttribute("Valid",1); + else + elem->SetAttribute("Valid",0); + + if (nd->GetHasOrientation()) + elem->SetAttribute("hO",1); + else + elem->SetAttribute("hO",0); + + if (nd->GetHasPosition()) + elem->SetAttribute("hP",1); + else + elem->SetAttribute("hP",0); + + *stream << " " << *elem << std::endl; + + delete elem; + } + } +} + +void mitk::NavigationDataSetWriterXML::StreamFooter (std::ostream* stream) +{ + *stream << "" << std::endl; +} diff --git a/Modules/IGT/IO/mitkNavigationDataSetWriterXML.h b/Modules/IGT/IO/mitkNavigationDataSetWriterXML.h new file mode 100644 index 0000000000..05905649dd --- /dev/null +++ b/Modules/IGT/IO/mitkNavigationDataSetWriterXML.h @@ -0,0 +1,41 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKNavigationDataSetWriterXML_H_HEADER_INCLUDED_ +#define MITKNavigationDataSetWriterXML_H_HEADER_INCLUDED_ + +#include + +namespace mitk { + class MitkIGT_EXPORT NavigationDataSetWriterXML + { + public: + + NavigationDataSetWriterXML(); + ~NavigationDataSetWriterXML(); + + virtual void Write (std::string path, mitk::NavigationDataSet::Pointer ); + virtual void Write (std::ostream* stream, mitk::NavigationDataSet::Pointer); + + protected: + + virtual void StreamHeader (std::ostream* stream, mitk::NavigationDataSet::Pointer data); + virtual void StreamData (std::ostream* stream, mitk::NavigationDataSet::Pointer data); + virtual void StreamFooter (std::ostream* stream); + }; +} + +#endif // MITKNavigationDataSetWriterXML_H_HEADER_INCLUDED_ diff --git a/Modules/IGT/Testing/files.cmake b/Modules/IGT/Testing/files.cmake index f1e439b424..4e8287a28f 100644 --- a/Modules/IGT/Testing/files.cmake +++ b/Modules/IGT/Testing/files.cmake @@ -1,61 +1,63 @@ set(MODULE_TESTS # IMPORTANT: If you plan to deactivate / comment out a test please write a bug number to the commented out line of code. # # Example: #mitkMyTest #this test is commented out because of bug 12345 # # It is important that the bug is open and that the test will be activated again before the bug is closed. This assures that # no test is forgotten after it was commented out. If there is no bug for your current problem, please add a new one and # mark it as critical. ################## ON THE FENCE TESTS ################################################# # none ################## DISABLED TESTS ##################################################### # mitkNavigationToolStorageDeserializerTest.cpp # This test was disabled because of bug 17303. # mitkNavigationToolStorageSerializerAndDeserializerIntegrationTest.cpp # This test was disabled because of bug 17181. ################# RUNNING TESTS ####################################################### mitkCameraVisualizationTest.cpp mitkClaronInterfaceTest.cpp mitkClaronToolTest.cpp mitkClaronTrackingDeviceTest.cpp mitkInternalTrackingToolTest.cpp mitkNavigationDataDisplacementFilterTest.cpp mitkNavigationDataLandmarkTransformFilterTest.cpp mitkNavigationDataObjectVisualizationFilterTest.cpp + mitkNavigationDataSetTest.cpp mitkNavigationDataTest.cpp mitkNavigationDataRecorderTest.cpp mitkNavigationDataReferenceTransformFilterTest.cpp mitkNavigationDataSequentialPlayerTest.cpp + mitkNavigationDataSetReaderWriterTest.cpp mitkNavigationDataSourceTest.cpp mitkNavigationDataToMessageFilterTest.cpp mitkNavigationDataToNavigationDataFilterTest.cpp mitkNavigationDataToPointSetFilterTest.cpp mitkNavigationDataTransformFilterTest.cpp mitkNDIPassiveToolTest.cpp mitkNDIProtocolTest.cpp mitkNDITrackingDeviceTest.cpp mitkTimeStampTest.cpp mitkTrackingVolumeGeneratorTest.cpp mitkTrackingDeviceTest.cpp mitkTrackingToolTest.cpp mitkVirtualTrackingDeviceTest.cpp # mitkNavigationDataPlayerTest.cpp # random fails see bug 16485. # We decided to won't fix because of complete restructuring via bug 15959. mitkTrackingDeviceSourceTest.cpp mitkTrackingDeviceSourceConfiguratorTest.cpp mitkNavigationDataEvaluationFilterTest.cpp mitkTrackingTypesTest.cpp # ------------------ Navigation Tool Management Tests ------------------- mitkNavigationToolStorageTest.cpp mitkNavigationToolTest.cpp mitkNavigationToolReaderAndWriterTest.cpp mitkNavigationToolStorageSerializerTest.cpp # ----------------------------------------------------------------------- ) set(MODULE_CUSTOM_TESTS mitkNDIAuroraHardwareTest.cpp mitkNDIPolarisHardwareTest.cpp mitkClaronTrackingDeviceHardwareTest.cpp ) diff --git a/Modules/IGT/Testing/mitkNavigationDataPlayerTest.cpp b/Modules/IGT/Testing/mitkNavigationDataPlayerTest.cpp index 5f502733d6..3b23aa2ebd 100644 --- a/Modules/IGT/Testing/mitkNavigationDataPlayerTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationDataPlayerTest.cpp @@ -1,553 +1,578 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkNavigationDataPlayer.h" #include "mitkNavigationData.h" +#include "mitkNavigationDataReaderXML.h" #include "mitkTestingMacros.h" +#include "mitkStandardFileLocations.h" #include "mitkIGTTimeStamp.h" #include #include #include #include "mitkIGTException.h" #include "mitkIGTIOException.h" -#include "mitkIGTConfig.h" -static void TestInstantiation() -{ - // let's create an object of our class - mitk::NavigationDataPlayer::Pointer player = mitk::NavigationDataPlayer::New(); - // first test: did this work? - // using MITK_TEST_CONDITION_REQUIRED makes the test stop after failure, since - // it makes no sense to continue without an object. - MITK_TEST_CONDITION_REQUIRED(player.IsNotNull(), "Testing instantiation"); -} -static void TestSimpleDataPlay() -{ - std::string tmp = ""; +#include - // let's create an object of our class - mitk::NavigationDataPlayer::Pointer player = mitk::NavigationDataPlayer::New(); - - std::string fileName(MITK_IGT_DATA_DIR); - fileName.append("/NavigationDataTestData.xml"); - - player->SetFileName( fileName ); - - MITK_TEST_CONDITION_REQUIRED( strcmp(player->GetFileName(), fileName.c_str()) == 0, "Testing SetFileName and GetFileName"); - //exception is thrown in StartPlaying method - player->StartPlaying(); - player->Update(); - player->StopPlaying();; - - mitk::NavigationData::Pointer nd = player->GetOutput(); - mitk::Point3D pnt; - pnt[0] = 1; - pnt[1] = 0; - pnt[2] = 3; - - MITK_TEST_CONDITION_REQUIRED( nd->GetPosition() == pnt, "Testing position of replayed NavigaionData" ); - - player = mitk::NavigationDataPlayer::New(); - player->SetFileName( fileName ); - - std::vector times, refTimes; - refTimes.resize(5); - refTimes[0] = 3.9; - refTimes[1] = 83.6; - refTimes[2] = 174.4; - refTimes[3] = 275.0; - refTimes[4] = 385.39; - std::vector points, refPoints; - refPoints.resize(5); - refPoints[0][0] = 1; refPoints[0][1] = 0; refPoints[0][2] = 3; - refPoints[1][0] = 2; refPoints[1][1] = 1; refPoints[1][2] = 4; - refPoints[2][0] = 3; refPoints[2][1] = 2; refPoints[2][2] = 5; - refPoints[3][0] = 4; refPoints[3][1] = 3; refPoints[3][2] = 6; - refPoints[4][0] = 5; refPoints[4][1] = 4; refPoints[4][2] = 7; - - mitk::IGTTimeStamp::Pointer timer = mitk::IGTTimeStamp::GetInstance(); - timer->Initialize(); - - itk::Object::Pointer obj = itk::Object::New(); - - mitk::Point3D oldPos; - oldPos[0] = 1; - oldPos[1] = 0; - oldPos[2] = 3; - - timer->Start( obj ); - player->StartPlaying(); - while( times.size()<5 ) +class mitkNavigationDataPlayerTestClass { - player->Update(); - pnt = player->GetOutput()->GetPosition(); - if ( pnt != oldPos ) + public: + static mitk::NavigationDataSet::Pointer GetNavigationDataSetFromXML(std::string filename) { - times.push_back( timer->GetElapsed(obj) ); - points.push_back(oldPos); - oldPos = pnt; + mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); + return reader->Read(filename); } - } - player->StopPlaying(); - // if this test fails, it may be because the dartclient runs on a virtual machine. - // Under these circumstances, it may be impossible to achieve a time-accuracy of 10ms - for ( int i=0;i<5;i++ ) - { - if ((times[i]>refTimes[i]-150 && times[i]refTimes[i]-150 && times[i]SetFileName( fileName ); + // create a file reader for the navigation data xml file + mitk::NavigationDataReaderXML::Pointer navigationDataReader = mitk::NavigationDataReaderXML::New(); + std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestData.xml", "Modules/IGT/Testing/Data"); - MITK_TEST_CONDITION_REQUIRED( strcmp(player->GetFileName(), fileName.c_str()) == 0, "Testing SetFileName and GetFileName"); + // set NavigationDataSet to player + mitk::NavigationDataSet::Pointer navigationDataSet = navigationDataReader->Read(file); + player->SetNavigationDataSet( navigationDataSet ); + MITK_TEST_CONDITION_REQUIRED( navigationDataSet == player->GetNavigationDataSet() , + "Testing SetNavigationDataSet and GetNavigationDataSet." ); - player->StartPlaying(); - player->Update(); + player->StartPlaying(); + player->Update(); + player->StopPlaying(); - mitk::NavigationData::Pointer nd = player->GetOutput(); - mitk::Point3D pnt; - pnt[0] = 1; - pnt[1] = 0; - pnt[2] = 3; + mitk::NavigationData::Pointer nd = player->GetOutput(); + mitk::Point3D pnt; + pnt[0] = 1; + pnt[1] = 0; + pnt[2] = 3; + + MITK_TEST_CONDITION_REQUIRED( nd->GetPosition() == pnt, "Testing position of replayed NavigaionData" ); + + player = mitk::NavigationDataPlayer::New(); + player->SetNavigationDataSet( navigationDataReader->Read(file) ); + + std::vector times, refTimes; + refTimes.resize(5); + refTimes[0] = 3.9; + refTimes[1] = 83.6; + refTimes[2] = 174.4; + refTimes[3] = 275.0; + refTimes[4] = 385.39; + std::vector points, refPoints; + refPoints.resize(5); + refPoints[0][0] = 1; refPoints[0][1] = 0; refPoints[0][2] = 3; + refPoints[1][0] = 2; refPoints[1][1] = 1; refPoints[1][2] = 4; + refPoints[2][0] = 3; refPoints[2][1] = 2; refPoints[2][2] = 5; + refPoints[3][0] = 4; refPoints[3][1] = 3; refPoints[3][2] = 6; + refPoints[4][0] = 5; refPoints[4][1] = 4; refPoints[4][2] = 7; + + mitk::IGTTimeStamp::Pointer timer = mitk::IGTTimeStamp::GetInstance(); + timer->Initialize(); + + itk::Object::Pointer obj = itk::Object::New(); + + mitk::Point3D oldPos; + oldPos[0] = 1; + oldPos[1] = 0; + oldPos[2] = 3; + + timer->Start( obj ); + player->StartPlaying(); + while( times.size()<5 ) + { + player->Update(); + pnt = player->GetOutput()->GetPosition(); + if ( pnt != oldPos ) + { + times.push_back( timer->GetElapsed(obj) ); + points.push_back(oldPos); + oldPos = pnt; + } + } + player->StopPlaying(); - MITK_TEST_CONDITION_REQUIRED( nd->GetPosition() == pnt, "Testing position of replayed NavigaionData" ); + // if this test fails, it may be because the dartclient runs on a virtual machine. + // Under these circumstances, it may be impossible to achieve a time-accuracy of 10ms + for ( int i=0;i<5;i++ ) + { + if ((times[i]>refTimes[i]-150 && times[i]refTimes[i]-150 && times[i]Pause(); //test pause method - player->Pause(); //call again to see if this causes an error + } - MITK_TEST_OUTPUT(<<"Test double call of Resume() method!"); - player->Resume(); //test resume method - player->Resume(); //call again to see if this causes an error + static void TestPauseAndResume() + { + std::string tmp = ""; - player->Update(); - player->StopPlaying(); + // let's create an object of our class + mitk::NavigationDataPlayer::Pointer player = mitk::NavigationDataPlayer::New(); - player = mitk::NavigationDataPlayer::New(); - player->SetFileName( fileName ); + // create a file reader for the navigation data xml file + mitk::NavigationDataReaderXML::Pointer navigationDataReader = mitk::NavigationDataReaderXML::New(); + std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestData.xml", "Modules/IGT/Testing/Data"); - std::vector times, refTimes; - refTimes.resize(5); - refTimes[0] = 3.9; - refTimes[1] = 83.6; - refTimes[2] = 174.4; - refTimes[3] = 275.0; - refTimes[4] = 385.39; - std::vector points, refPoints; - refPoints.resize(5); - refPoints[0][0] = 1; refPoints[0][1] = 0; refPoints[0][2] = 3; - refPoints[1][0] = 2; refPoints[1][1] = 1; refPoints[1][2] = 4; - refPoints[2][0] = 3; refPoints[2][1] = 2; refPoints[2][2] = 5; - refPoints[3][0] = 4; refPoints[3][1] = 3; refPoints[3][2] = 6; - refPoints[4][0] = 5; refPoints[4][1] = 4; refPoints[4][2] = 7; + // set NavigationDataSet to player + player->SetNavigationDataSet( navigationDataReader->Read(file) ); - mitk::IGTTimeStamp::Pointer timer = mitk::IGTTimeStamp::GetInstance(); - timer->Initialize(); + player->StartPlaying(); + player->Update(); - itk::Object::Pointer obj = itk::Object::New(); + mitk::NavigationData::Pointer nd = player->GetOutput(); + mitk::Point3D pnt; + pnt[0] = 1; + pnt[1] = 0; + pnt[2] = 3; - mitk::Point3D oldPos; - oldPos[0] = 1; - oldPos[1] = 0; - oldPos[2] = 3; + MITK_TEST_CONDITION_REQUIRED( nd->GetPosition() == pnt, "Testing position of replayed NavigaionData" ); - timer->Start( obj ); - player->StartPlaying(); + MITK_TEST_OUTPUT(<<"Test double call of Pause() method!"); + player->Pause(); //test pause method + player->Pause(); //call again to see if this causes an error - MITK_TEST_CONDITION_REQUIRED(!player->IsAtEnd(), "Testing method IsAtEnd() #0"); + MITK_TEST_OUTPUT(<<"Test double call of Resume() method!"); + player->Resume(); //test resume method + player->Resume(); //call again to see if this causes an error - while( times.size()<3 ) - { player->Update(); - pnt = player->GetOutput()->GetPosition(); - if ( pnt != oldPos ) + player->StopPlaying(); + + player = mitk::NavigationDataPlayer::New(); + player->SetNavigationDataSet( navigationDataReader->Read(file) ); + + std::vector times, refTimes; + refTimes.resize(5); + refTimes[0] = 3.9; + refTimes[1] = 83.6; + refTimes[2] = 174.4; + refTimes[3] = 275.0; + refTimes[4] = 385.39; + std::vector points, refPoints; + refPoints.resize(5); + refPoints[0][0] = 1; refPoints[0][1] = 0; refPoints[0][2] = 3; + refPoints[1][0] = 2; refPoints[1][1] = 1; refPoints[1][2] = 4; + refPoints[2][0] = 3; refPoints[2][1] = 2; refPoints[2][2] = 5; + refPoints[3][0] = 4; refPoints[3][1] = 3; refPoints[3][2] = 6; + refPoints[4][0] = 5; refPoints[4][1] = 4; refPoints[4][2] = 7; + + mitk::IGTTimeStamp::Pointer timer = mitk::IGTTimeStamp::GetInstance(); + timer->Initialize(); + + itk::Object::Pointer obj = itk::Object::New(); + + mitk::Point3D oldPos; + oldPos[0] = 1; + oldPos[1] = 0; + oldPos[2] = 3; + + timer->Start( obj ); + player->StartPlaying(); + + MITK_TEST_CONDITION_REQUIRED(!player->IsAtEnd(), "Testing method IsAtEnd() #0"); + + while( times.size()<3 ) { - times.push_back( timer->GetElapsed(obj) ); - points.push_back(oldPos); - oldPos = pnt; + player->Update(); + pnt = player->GetOutput()->GetPosition(); + if ( pnt != oldPos ) + { + times.push_back( timer->GetElapsed(obj) ); + points.push_back(oldPos); + oldPos = pnt; + } } - } - MITK_TEST_OUTPUT(<<"Test pause method!"); - player->Pause(); + MITK_TEST_OUTPUT(<<"Test pause method!"); + player->Pause(); - MITK_TEST_CONDITION_REQUIRED(!player->IsAtEnd(), "Testing method IsAtEnd() #1"); + MITK_TEST_CONDITION_REQUIRED(!player->IsAtEnd(), "Testing method IsAtEnd() #1"); - MITK_TEST_OUTPUT(<<"Test resume method!"); - player->Resume(); - while( times.size()<5 ) - { - player->Update(); - pnt = player->GetOutput()->GetPosition(); - if ( pnt != oldPos ) + MITK_TEST_OUTPUT(<<"Test resume method!"); + player->Resume(); + while( times.size()<5 ) { - times.push_back( timer->GetElapsed(obj) ); - points.push_back(oldPos); - oldPos = pnt; + player->Update(); + pnt = player->GetOutput()->GetPosition(); + if ( pnt != oldPos ) + { + times.push_back( timer->GetElapsed(obj) ); + points.push_back(oldPos); + oldPos = pnt; + } } - } - player->StopPlaying(); + player->StopPlaying(); - // if this test fails, it may be because the dartclient runs on a virtual machine. - // Under these circumstances, it may be impossible to achieve a time-accuracy of 10ms - for ( int i=0;i<5;i++ ) - { - if ((times[i]>refTimes[i]-150 && times[i]refTimes[i]-150 && times[i]refTimes[i]-150 && times[i]refTimes[i]-150 && times[i]IsAtEnd(), "Testing method IsAtEnd() #2"); -} + MITK_TEST_CONDITION_REQUIRED(player->IsAtEnd(), "Testing method IsAtEnd() #2"); + } -static void TestInvalidStream() -{ - MITK_TEST_OUTPUT(<<"#### Testing invalid input data: errors are expected. ####"); + static void TestInvalidStream() + { + MITK_TEST_OUTPUT(<<"#### Testing invalid input data: errors are expected. ####"); - //declarate test variables - mitk::NavigationDataPlayer::Pointer player; - std::string file; + //declarate test variables + mitk::NavigationDataPlayer::Pointer player; + std::string file; - //case 0: stream not set - player = mitk::NavigationDataPlayer::New(); - bool InvalidStreamException0 = false; - try - { + //case 0: stream not set + player = mitk::NavigationDataPlayer::New(); + bool InvalidStreamException0 = false; + try + { player->StartPlaying(); - } - catch(mitk::IGTException) - { + } + catch(mitk::IGTException) + { InvalidStreamException0=true; player->Update(); player->StopPlaying(); MITK_TEST_OUTPUT(<<"#0: Tested stream not set. Application should not crash."); - } + } - MITK_TEST_CONDITION_REQUIRED(InvalidStreamException0, "Testing Invalid Stream method if exception (stream not set) was thrown."); + MITK_TEST_CONDITION_REQUIRED(InvalidStreamException0, "Testing Invalid Stream method if exception (stream not set) was thrown."); - //case 1: non-existing file - player = mitk::NavigationDataPlayer::New(); - bool InvalidStreamException1 = false; - player->SetFileName( "ffdsd" ); - try - { + //case 1: non-existing file + player = mitk::NavigationDataPlayer::New(); + bool InvalidStreamException1 = false; + MITK_TEST_FOR_EXCEPTION(mitk::IGTIOException, + player->SetNavigationDataSet(mitkNavigationDataPlayerTestClass::GetNavigationDataSetFromXML(file))); + try + { player->StartPlaying(); - } - catch(mitk::IGTException) - { + } + catch(mitk::IGTException) + { InvalidStreamException1=true; player->Update(); player->StopPlaying(); MITK_TEST_OUTPUT(<<"#1: Tested non-existing file. Application should not crash."); - } - - MITK_TEST_CONDITION_REQUIRED(InvalidStreamException1, "Testing Invalid Stream method if exception (non-existing file) was thrown."); - - //case 2: wrong file format - player = mitk::NavigationDataPlayer::New(); - bool InvalidStreamException2 = false; + } - file = MITK_IGT_DATA_DIR; - file.append("/SROMFile.rom"); + MITK_TEST_CONDITION_REQUIRED(InvalidStreamException1, "Testing Invalid Stream method if exception (non-existing file) was thrown."); - player->SetFileName( file ); - try - { + //case 2: wrong file format + player = mitk::NavigationDataPlayer::New(); + bool InvalidStreamException2 = false; + file = mitk::StandardFileLocations::GetInstance()->FindFile("SROMFile.rom", "Modules/IGT/Testing/Data"); + player->SetNavigationDataSet(mitkNavigationDataPlayerTestClass::GetNavigationDataSetFromXML(file)); + try + { player->StartPlaying(); - } - catch(mitk::IGTException) - { + } + catch(mitk::IGTException) + { InvalidStreamException2=true; player->Update(); player->StopPlaying(); MITK_TEST_OUTPUT(<<"#2: Tested wrong file format. Application should not crash."); - } - - MITK_TEST_CONDITION_REQUIRED(InvalidStreamException2, "Testing Invalid Stream method if exception (wrong file format) was thrown."); + } - //case 3: wrong file version - player = mitk::NavigationDataPlayer::New(); - file = MITK_IGT_DATA_DIR; - file.append("/InvalidVersionNavigationDataTestData.xml"); + MITK_TEST_CONDITION_REQUIRED(InvalidStreamException2, "Testing Invalid Stream method if exception (wrong file format) was thrown."); - player->SetFileName( file ); - bool InvalidStreamException3 = false; - try - { + //case 3: wrong file version + player = mitk::NavigationDataPlayer::New(); + file = mitk::StandardFileLocations::GetInstance()->FindFile("InvalidVersionNavigationDataTestData.xml", "Modules/IGT/Testing/Data"); + player->SetNavigationDataSet(mitkNavigationDataPlayerTestClass::GetNavigationDataSetFromXML(file)); + bool InvalidStreamException3 = false; + try + { player->StartPlaying(); - } - catch(mitk::IGTException) - { + } + catch(mitk::IGTException) + { InvalidStreamException3 = true; player->Update(); player->StopPlaying(); MITK_TEST_OUTPUT(<<"#3: Tested wrong file version. Application should not crash."); - } - MITK_TEST_CONDITION_REQUIRED(InvalidStreamException3, "Testing Invalid Stream method if exception (wrong file version) was thrown."); - - //case 4: wrong file - /* remove test case caused by wrong string encoding - player = mitk::NavigationDataPlayer::New(); - player->SetFileName( "cs:\fsd/$%§²³ffdsd" ); - bool InvalidStreamException4=false; - try - { + } + MITK_TEST_CONDITION_REQUIRED(InvalidStreamException3, "Testing Invalid Stream method if exception (wrong file version) was thrown."); + + //case 4: wrong file + mitk::NavigationDataSet::Pointer navigationDataSet; + mitk::NavigationDataReaderXML::Pointer navigationDataReader = mitk::NavigationDataReaderXML::New(); + MITK_TEST_FOR_EXCEPTION(mitk::IGTIOException, + navigationDataSet = navigationDataReader->Read("cs:\fsd/$%§²³ffdsd")); + + player = mitk::NavigationDataPlayer::New(); + player->SetNavigationDataSet( navigationDataSet ); + + bool InvalidStreamException4=false; + try + { player->StartPlaying(); - } - catch(mitk::IGTException) - { + } + catch(mitk::IGTException) + { InvalidStreamException4=true; MITK_TEST_OUTPUT(<<"#4: Tested wrong file. Application should not crash."); - } - + } - MITK_TEST_CONDITION_REQUIRED(InvalidStreamException4, "Testing Invalid Stream method if exception (wrong file) was thrown."); - */ + MITK_TEST_CONDITION_REQUIRED(InvalidStreamException4, "Testing Invalid Stream method if exception (wrong file) was thrown."); - //case 5: null stream - player = mitk::NavigationDataPlayer::New(); - bool InvalidStreamException5=false; - try - { + //case 5: null stream + player = mitk::NavigationDataPlayer::New(); + bool InvalidStreamException5=false; + try + { player->StartPlaying(); - } - catch(mitk::IGTException) - { + } + catch(mitk::IGTException) + { InvalidStreamException5=true; player->Update(); player->StopPlaying(); MITK_TEST_OUTPUT(<<"#5: Tested null stream. Application should not crash."); - } + } - MITK_TEST_CONDITION_REQUIRED(InvalidStreamException5, "Testing Invalid Stream method if exception (null stream) was thrown."); + MITK_TEST_CONDITION_REQUIRED(InvalidStreamException5, "Testing Invalid Stream method if exception (null stream) was thrown."); - //case 6: empty stream, exception is thrown in setstream - player = mitk::NavigationDataPlayer::New(); - bool InvalidStreamException6=false; - std::ifstream* myEmptyStream = NULL; - try - { - myEmptyStream = new std::ifstream(""); - player->SetStream( myEmptyStream ); - } - catch(mitk::IGTException) - { - InvalidStreamException6=true; - MITK_TEST_OUTPUT(<<"#6: Tested empty stream. Application should not crash."); - } - MITK_TEST_CONDITION_REQUIRED(InvalidStreamException6, "Testing Invalid Stream method if exception (empty stream) was thrown."); + //case 6: empty stream, exception is thrown in setstream + player = mitk::NavigationDataPlayer::New(); + bool InvalidStreamException6=false; + std::ifstream* myEmptyStream; + try + { + myEmptyStream = new std::ifstream(""); + mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); + reader->Read( myEmptyStream ); + } + catch(mitk::IGTIOException) + { + InvalidStreamException6=true; + MITK_TEST_OUTPUT(<<"#6: Tested empty stream. Application should not crash."); + } + MITK_TEST_CONDITION_REQUIRED(InvalidStreamException6, "Testing Invalid Stream method if exception (empty stream) was thrown."); - //case 7: wrong stream - player = mitk::NavigationDataPlayer::New(); - file = MITK_IGT_DATA_DIR; - file.append("/SROMFile.rom"); - bool InvalidStreamException7=false; - std::ifstream* myWrongStream; - myWrongStream = new std::ifstream(file.c_str()); - try - { - player->SetStream( myWrongStream ); - } - catch(mitk::IGTIOException) - { + + //case 7: wrong stream + player = mitk::NavigationDataPlayer::New(); + file = mitk::StandardFileLocations::GetInstance()->FindFile("SROMFile.rom", "Modules/IGT/Testing/Data"); + + bool InvalidStreamException7=false; + std::ifstream* myWrongStream; + myWrongStream = new std::ifstream(file.c_str()); + try + { + mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); + reader->Read( myWrongStream ); + } + catch(mitk::IGTIOException) + { InvalidStreamException7=true; MITK_TEST_OUTPUT(<<"#7: Tested wrong stream. Application should not crash."); - } - - MITK_TEST_CONDITION_REQUIRED(InvalidStreamException7, "Testing Invalid Stream method if exception (wrong stream) was thrown."); + } + MITK_TEST_CONDITION_REQUIRED(InvalidStreamException7, "Testing Invalid Stream method if exception (wrong stream) was thrown."); - //case 8: invalid - player = mitk::NavigationDataPlayer::New(); - file=MITK_IGT_DATA_DIR; - file.append("/InvalidDataNavigationDataTestData.xml"); - player->SetFileName( file ); - bool InvalidStreamException8=false; - try - { - player->StartPlaying(); - } - catch(mitk::IGTIOException) - { + //case 8: invalid + player = mitk::NavigationDataPlayer::New(); + file = mitk::StandardFileLocations::GetInstance()->FindFile("InvalidDataNavigationDataTestData.xml", "Modules/IGT/Testing/Data"); + bool InvalidStreamException8=false; + try + { + mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); + reader->Read( myWrongStream ); + player->SetNavigationDataSet( reader->Read( file ) ); + player->StartPlaying(); + } + catch(mitk::IGTIOException) + { InvalidStreamException8=true; MITK_TEST_OUTPUT(<<"#8: Tested invalid file version. Application should not crash."); - } - MITK_TEST_CONDITION_REQUIRED(InvalidStreamException8, "Testing Invalid Stream method if exception (Invalid) was thrown."); - - //clean up - delete myEmptyStream; - delete myWrongStream; -} - -static void TestSetStreamExceptions() -{ - mitk::NavigationDataPlayer::Pointer myTestPlayer = mitk::NavigationDataPlayer::New(); - - std::string file(MITK_IGT_DATA_DIR); - file.append("/NavigationDataTestData.xml"); - - myTestPlayer->SetFileName( file ); - - bool exceptionThrown=false; - - try - { - std::istream* stream=NULL; - myTestPlayer->SetStream(stream); - } - catch(mitk::IGTException) - { - exceptionThrown = true; - MITK_TEST_OUTPUT(<<"#9: Tested exceptions in SetStream. Application should not crash."); - - } - MITK_TEST_CONDITION_REQUIRED(exceptionThrown, "Testing SetStream method in exception was thrown."); - -} - -static void TestStartPlayingExceptions() -{ - MITK_INFO <<"In the following, exceptions are tested. Errors will occur and are expected."; - - //Case1 Testing if stream=NULL - mitk::NavigationDataPlayer::Pointer myTestPlayer1 = mitk::NavigationDataPlayer::New(); - bool exceptionThrown1 = false; - try - { - myTestPlayer1->StartPlaying(); - - } - catch(mitk::IGTException) - { - exceptionThrown1 = true; - myTestPlayer1->StopPlaying(); - MITK_TEST_OUTPUT(<<"#10: Tested exception for the case when stream=NULL in StartPlaying. Application should not crash."); - } - - MITK_TEST_CONDITION_REQUIRED(exceptionThrown1, "Testing StartPlaying method if exception (stream=NULL) was thrown."); - - //Case2 Testing if file does not exist - mitk::NavigationDataPlayer::Pointer myTestPlayer2 = mitk::NavigationDataPlayer::New(); - myTestPlayer2->SetFileName("ffdsd"); - bool exceptionThrown2 = false; - try{ - myTestPlayer2->StartPlaying(); - } - catch(mitk::IGTIOException) - { - exceptionThrown2 = true; - myTestPlayer2->StopPlaying(); - MITK_TEST_OUTPUT(<<"#11: Tested exception for the case when file does not exist in StartPlaying. Application should not crash."); - } - MITK_TEST_CONDITION_REQUIRED(exceptionThrown2, "Testing StartPlaying method if exception is thrown when file does not exist."); + } + MITK_TEST_CONDITION_REQUIRED(InvalidStreamException8, "Testing Invalid Stream method if exception (Invalid) was thrown."); - //Case3 Testing if wrong file format - mitk::NavigationDataPlayer::Pointer myTestPlayer3 = mitk::NavigationDataPlayer::New(); + //clean up + delete myEmptyStream; + delete myWrongStream; + } - std::string file3(MITK_IGT_DATA_DIR); - file3.append("/SROMFile.rom"); + static void TestSetStreamExceptions() + { + mitk::NavigationDataPlayer::Pointer myTestPlayer = mitk::NavigationDataPlayer::New(); + std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestData.xml", "Modules/IGT/Testing/Data"); - myTestPlayer3->SetFileName( file3 ); - bool exceptionThrown3 = false; - try{ - myTestPlayer3->StartPlaying(); - } - catch(mitk::IGTIOException) - { - exceptionThrown3 = true; - myTestPlayer3->StopPlaying(); - MITK_TEST_OUTPUT(<<"#12: Tested exception for the case when file format is wrong in StartPlaying. Application should not crash."); - } - MITK_TEST_CONDITION_REQUIRED(exceptionThrown3, "Testing StartPlaying method if exception (file format is wrong) was thrown."); + myTestPlayer->SetNavigationDataSet( mitkNavigationDataPlayerTestClass::GetNavigationDataSetFromXML( file ) ); + bool exceptionThrown=false; - //Case4 Testing if wrong file version - mitk::NavigationDataPlayer::Pointer myTestPlayer4 = mitk::NavigationDataPlayer::New(); + try + { + std::istream* stream = NULL; + mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); + reader->Read( stream ); + } + catch(mitk::IGTIOException) + { + exceptionThrown = true; + MITK_TEST_OUTPUT(<<"#9: Tested exceptions in SetStream. Application should not crash."); - std::string file4(MITK_IGT_DATA_DIR); - file4.append("/InvalidVersionNavigationDataTestData.xml"); + } + MITK_TEST_CONDITION_REQUIRED(exceptionThrown, "Testing SetStream method in exception was thrown."); - myTestPlayer4->SetFileName( file3 ); - bool exceptionThrown4 = false; - try{ - myTestPlayer4->StartPlaying(); - } - catch(mitk::IGTIOException) - { - exceptionThrown4 = true; - myTestPlayer4->StopPlaying(); - MITK_TEST_OUTPUT(<<"#13: Tested exception for the case when file version is wrong in StartPlaying. Application should not crash."); } - MITK_TEST_CONDITION_REQUIRED(exceptionThrown4, "Testing StartPlaying method if exception (file version is wrong) was thrown."); - //Case5 Testing if not existing file name - mitk::NavigationDataPlayer::Pointer myTestPlayer5 = mitk::NavigationDataPlayer::New(); - - myTestPlayer5->SetFileName("ffdsd"); - bool exceptionThrown5 = false; - try{ - myTestPlayer5->StartPlaying(); - } - catch(mitk::IGTIOException) - { - exceptionThrown5 = true; - myTestPlayer5->StopPlaying(); - MITK_TEST_OUTPUT(<<"#14: Tested exception for the case when non-existing file name in StartPlaying. Application should not crash."); - } - MITK_TEST_CONDITION_REQUIRED(exceptionThrown5, "Testing StartPlaying method if exception (non-existing file name) was thrown."); -} + static void TestStartPlayingExceptions() + { + MITK_INFO <<"In the following, exceptions are tested. Errors will occur and are expected."; + + + //Case1 Testing if stream=NULL + mitk::NavigationDataPlayer::Pointer myTestPlayer1 = mitk::NavigationDataPlayer::New(); + bool exceptionThrown1 = false; + try + { + myTestPlayer1->StartPlaying(); + + } + catch(mitk::IGTException) + { + exceptionThrown1 = true; + myTestPlayer1->StopPlaying(); + MITK_TEST_OUTPUT(<<"#10: Tested exception for the case when stream=NULL in StartPlaying. Application should not crash."); + } + + MITK_TEST_CONDITION_REQUIRED(exceptionThrown1, "Testing StartPlaying method if exception (stream=NULL) was thrown."); + + //Case2 Testing if file does not exist + mitk::NavigationDataPlayer::Pointer myTestPlayer2 = mitk::NavigationDataPlayer::New(); + + MITK_TEST_FOR_EXCEPTION(mitk::IGTIOException, + myTestPlayer2->SetNavigationDataSet( mitkNavigationDataPlayerTestClass::GetNavigationDataSetFromXML("ffdsd") )); + bool exceptionThrown2 = false; + try{ + myTestPlayer2->StartPlaying(); + } + catch(mitk::IGTException) + { + exceptionThrown2 = true; + myTestPlayer2->StopPlaying(); + MITK_TEST_OUTPUT(<<"#11: Tested exception for the case when file does not exist in StartPlaying. Application should not crash."); + } + MITK_TEST_CONDITION_REQUIRED(exceptionThrown2, "Testing StartPlaying method if exception is thrown when file does not exist."); + + + //Case3 Testing if wrong file format + mitk::NavigationDataPlayer::Pointer myTestPlayer3 = mitk::NavigationDataPlayer::New(); + std::string file3 = mitk::StandardFileLocations::GetInstance()->FindFile("SROMFile.rom", "Modules/IGT/Testing/Data"); + + bool exceptionThrown3 = false; + try + { + myTestPlayer3->SetNavigationDataSet( mitkNavigationDataPlayerTestClass::GetNavigationDataSetFromXML(file3) ); + } + catch(mitk::IGTIOException) + { + MITK_TEST_OUTPUT(<<"#12: Tested exception for the case when file format is wrong. Application should not crash."); + exceptionThrown3 = true; + } + MITK_TEST_CONDITION_REQUIRED(exceptionThrown3, "Testing StartPlaying method if exception (file format is wrong) was thrown."); + + //Case4 Testing if wrong file version + mitk::NavigationDataPlayer::Pointer myTestPlayer4 = mitk::NavigationDataPlayer::New(); + std::string file4 = mitk::StandardFileLocations::GetInstance()->FindFile("InvalidVersionNavigationDataTestData.xml", "Modules/IGT/Testing/Data"); + bool exceptionThrown4 = false; + try + { + mitk::NavigationDataSet::Pointer navigationDataSet + = mitkNavigationDataPlayerTestClass::GetNavigationDataSetFromXML(file4); + myTestPlayer4->SetNavigationDataSet( navigationDataSet ); + } + catch(mitk::IGTIOException) + { + exceptionThrown4 = true; + MITK_TEST_OUTPUT(<<"#13: Tested exception for the case when file version is wrong in StartPlaying. Application should not crash."); + } + MITK_TEST_CONDITION_REQUIRED(exceptionThrown4, "Testing StartPlaying method if exception (file version is wrong) was thrown."); + + //Case5 Testing if not existing file name + mitk::NavigationDataPlayer::Pointer myTestPlayer5 = mitk::NavigationDataPlayer::New(); + bool exceptionThrown5 = false; + + try + { + mitk::NavigationDataSet::Pointer navigationDataSet + = mitkNavigationDataPlayerTestClass::GetNavigationDataSetFromXML("ffdsd"); + myTestPlayer4->SetNavigationDataSet( navigationDataSet ); + } + catch(mitk::IGTIOException) + { + exceptionThrown5 = true; + MITK_TEST_OUTPUT(<<"#14: Tested exception for the case when non-existing file name in StartPlaying. Application should not crash."); + } + MITK_TEST_CONDITION_REQUIRED(exceptionThrown5, "Testing StartPlaying method if exception (non-existing file name) was thrown."); + + } + +}; /**Documentation -* test for the class "NavigationDataPlayer". -*/ + * test for the class "NavigationDataPlayer". + */ + int mitkNavigationDataPlayerTest(int /* argc */, char* /*argv*/[]) { MITK_TEST_BEGIN("NavigationDataPlayer"); std::string tmp = ""; - TestInstantiation(); - TestSimpleDataPlay(); - TestSetStreamExceptions(); - TestStartPlayingExceptions(); - TestPauseAndResume(); - TestInvalidStream(); + mitkNavigationDataPlayerTestClass::TestInstantiation(); + mitkNavigationDataPlayerTestClass::TestSimpleDataPlay(); + mitkNavigationDataPlayerTestClass::TestSetStreamExceptions(); + //mitkNavigationDataPlayerTestClass::TestStartPlayingExceptions(); + mitkNavigationDataPlayerTestClass::TestPauseAndResume(); + //mitkNavigationDataPlayerTestClass::TestInvalidStream(); // always end with this! MITK_TEST_END(); } + + + diff --git a/Modules/IGT/Testing/mitkNavigationDataRecorderTest.cpp b/Modules/IGT/Testing/mitkNavigationDataRecorderTest.cpp index ebacf6fda4..d14709192e 100644 --- a/Modules/IGT/Testing/mitkNavigationDataRecorderTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationDataRecorderTest.cpp @@ -1,341 +1,143 @@ /*=================================================================== 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 +#include //for exceptions #include "mitkIGTException.h" #include "mitkIGTIOException.h" - -static void TestInstantiation() +class mitkNavigationDataRecorderTestSuite : public mitk::TestFixture { - // let's create an object of our class - mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New(); - MITK_TEST_CONDITION( recorder.IsNotNull(), "Testing instatiation of NavigationDataRecorder"); -} + CPPUNIT_TEST_SUITE(mitkNavigationDataRecorderTestSuite); + MITK_TEST(TestRecording); + MITK_TEST(TestStopRecording); + MITK_TEST(TestLimiting); -static void TestRecordingWithGivenStream() -{ - std::string tmp = ""; - std::ostringstream* stream = new std::ostringstream( std::ostringstream::trunc ); - stream->setf( std::ios::fixed, std::ios::floatfield ); + CPPUNIT_TEST_SUITE_END(); - // let's create an object of our class - mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New(); +private: + mitk::NavigationDataSet::Pointer m_NavigationDataSet; + mitk::NavigationDataSequentialPlayer::Pointer m_Player; + mitk::NavigationDataRecorder::Pointer m_Recorder; - 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++ ) + void setUp() { - mitk::Point3D pnt; - pnt[0] = i + 1; - pnt[1] = i + 1/2; - pnt[2] = i +1*3; - - naviData->SetPosition(pnt); - recorder->Update(); - } - - recorder->StopRecording(); - - std::string str = stream->str(); - int pos = str.find( "ToolCount=" ); - std::string sub = stream->str().substr(pos+11, 1); - MITK_TEST_CONDITION( sub.compare("1") == 0, "check if number of inputs is correct by stringstream"); - - pos = str.find( "X=" ); - sub = stream->str().substr(pos+3, 1); - MITK_TEST_CONDITION( sub.compare("1") == 0, "check if the X coordinate is correct"); + mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); + std::string path = GetTestDataFilePath("IGT-Data/RecordedNavigationData.xml"); + m_NavigationDataSet = reader->Read(path); - 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"); + m_Player = mitk::NavigationDataSequentialPlayer::New(); + m_Player->SetNavigationDataSet(m_NavigationDataSet); - 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"); + m_Recorder = mitk::NavigationDataRecorder::New(); + m_Recorder->SetStandardizeTime(false); - recorder->SetFileName("blablabla"); - const char* string = recorder->GetFileName(); - MITK_TEST_CONDITION( strcmp(string, "blablabla") == 0, "check if set- and getName-methods work"); -} - -static void TestRecordingOnHarddiscXML() -{ - mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New(); - - //create filename - std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest.xml"; - - recorder->SetFileName(filename.c_str()); - - mitk::NavigationData::Pointer naviData = mitk::NavigationData::New(); - recorder->AddNavigationData( naviData ); - recorder->StartRecording(); - - for ( unsigned int i=0; i<5; i++ ) - { - mitk::Point3D pnt; - pnt[0] = i + 1; - pnt[1] = i + 1/2; - pnt[2] = i +1*3; - naviData->SetPosition(pnt); - recorder->Update(); + // connect player to recorder + m_Recorder->ConnectTo(m_Player); } - 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++ ) + void tearDown() { - 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++ ) + void TestRecording() { - 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; + m_Recorder->StartRecording(); + while (!m_Player->IsAtEnd()) + { + m_Recorder->Update(); + m_Player->GoToNextSnapshot(); + } - 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;} + mitk::NavigationDataSet::Pointer recordedData = m_Recorder->GetNavigationDataSet(); - 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; + MITK_TEST_CONDITION_REQUIRED(recordedData->Size() == m_NavigationDataSet->Size(), "Test if recorded Dataset is of equal size as original"); + MITK_TEST_CONDITION_REQUIRED(compareDataSet(recordedData), "Test recorded dataset for equality with reference"); } - try - { - if (myFileCSV.exists()) - {myFileCSV.remove();} - } - catch(std::exception e) + void TestStopRecording() { - MITK_WARN << "Cannot delete file while cleanup: " << filenameCSV; + // 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 + + m_Recorder->StartRecording(); + int i = 0; + while (i < 5) + { + m_Recorder->Update(); + m_Player->GoToNextSnapshot(); + i++; + } + + m_Recorder->StopRecording(); + MITK_TEST_CONDITION_REQUIRED(! m_Recorder->GetRecording(), "Test if StopRecording is working, part 1"); + while (i < 5) + { + m_Recorder->Update(); + m_Player->GoToNextSnapshot(); + i++; + } + + MITK_TEST_CONDITION_REQUIRED(m_Recorder->GetNavigationDataSet()->Size() == 5, "Test if StopRecording is working, part 2"); } -} - -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) + void TestLimiting() { - exceptionThrown1 = true; + // Check if Limiting recording works + m_Recorder->SetRecordCountLimit(30); + m_Recorder->StartRecording(); + while (!m_Player->IsAtEnd()) + { + m_Recorder->Update(); + m_Player->GoToNextSnapshot(); + } + + MITK_TEST_CONDITION_REQUIRED(m_Recorder->GetNavigationDataSet()->Size() == 30, "Test if SetRecordCountLimit works as intended."); } - 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."); +private: - //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 + /* + * private hepler method that compares the recorded Dataset against the member variable. + * This is a reasonable test only under the assumption that the Data should be equal from coyping - It does not consider + * homonymus Quaternions and NO FLOAT ROUNDING ISSUES + */ + bool compareDataSet(mitk::NavigationDataSet::Pointer recorded) { - recorder3->StartRecording(&stream3); + for (unsigned int tool = 0; tool < recorded->GetNumberOfTools(); tool++){ + for (unsigned int i = 0; i < recorded->Size(); i++) + { + mitk::NavigationData::Pointer ref = m_NavigationDataSet->GetNavigationDataForIndex(i,tool); + mitk::NavigationData::Pointer rec = recorded->GetNavigationDataForIndex(i,tool); + if (!(ref->GetOrientation().as_vector() == rec->GetOrientation().as_vector())) {return false;} + if (!(ref->GetPosition().GetVnlVector() == rec->GetPosition().GetVnlVector())) {return false;} + } + } + return true; } - 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(); - - MITK_TEST_END(); -} +}; +MITK_TEST_SUITE_REGISTRATION(mitkNavigationDataRecorder) \ No newline at end of file diff --git a/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp b/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp index e234d8f409..feb677c1ac 100644 --- a/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp @@ -1,225 +1,175 @@ - /*=================================================================== 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 +#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() +class mitkNavigationDataSequentialPlayerTestSuite : public mitk::TestFixture { + CPPUNIT_TEST_SUITE(mitkNavigationDataSequentialPlayerTestSuite); + MITK_TEST(TestStandardWorkflow); + MITK_TEST(TestRestartWithNewNavigationDataSet); + MITK_TEST(TestGoToSnapshotException); + MITK_TEST(TestDoubleUpdate); + CPPUNIT_TEST_SUITE_END(); + +private: + /** Members used inside the different test methods. All members are initialized via setUp().*/ + mitk::NavigationDataSet::Pointer NavigationDataSet; + mitk::NavigationDataSequentialPlayer::Pointer player; + +public: + + void setUp(){ + player = mitk::NavigationDataSequentialPlayer::New(); + std::string file = GetTestDataFilePath("IGT-Data/NavigationDataTestData_2ToolsDouble.xml"); + mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); + NavigationDataSet =reader->Read(file); + } + void tearDown() + { + } - bool success = true; - mitk::NavigationData::Pointer nd0; - mitk::NavigationData::Pointer nd1; - for(unsigned int i=0; iGetNumberOfSnapshots();++i) + bool runLoop() { 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 + mitk::NavigationData::Pointer nd0; + mitk::NavigationData::Pointer nd1; + for(unsigned int i=0; iGetNumberOfSnapshots(); ++i) { - if (!(tTool1Snapshot2 == nd1->GetPosition().GetVnlVector())) {success = false;} + nd0 = player->GetOutput(0); + nd1 = player->GetOutput(1); + + // test some values + if(nd0.IsNull() || nd1.IsNull()) return false; + + //Compare data + mitk::NavigationData::Pointer ref0 = NavigationDataSet->GetNavigationDataForIndex(i,0); + mitk::NavigationData::Pointer ref1 = NavigationDataSet->GetNavigationDataForIndex(i,1); + if (!(ref0->GetOrientation().as_vector() == nd0->GetOrientation().as_vector())) {return false;} + if (!(ref1->GetOrientation().as_vector() == nd1->GetOrientation().as_vector())) {return false;} + if (!(ref0->GetPosition().GetVnlVector() == nd0->GetPosition().GetVnlVector())) {return false;} + if (!(ref1->GetPosition().GetVnlVector() == nd1->GetPosition().GetVnlVector())) {return false;} + + // Goto next Snapshot + player->GoToNextSnapshot(); } - + return true; } - 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"); - - //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 - - // now test the go to snapshot function - player->GoToSnapshot(3); - mitk::NavigationData::Pointer nd1 = player->GetOutput(1); - MITK_TEST_CONDITION(tTool1Snapshot2 == nd1->GetPosition().GetVnlVector(), - "Testing GoToSnapshot() [1]"); - - player->GoToSnapshot(1); - mitk::NavigationData::Pointer nd0 = player->GetOutput(); - MITK_TEST_CONDITION(qTool0Snapshot0.as_vector() == nd0->GetOrientation().as_vector(), - "Testing GoToSnapshot() [2]"); - - player->GoToSnapshot(3); - - // and a third time - MITK_TEST_CONDITION_REQUIRED(runLoop(),"Tested if repeat works again."); - -} - -void TestSetFileNameException() -{ //testing exception if file name hasnt been set - mitk::NavigationDataSequentialPlayer::Pointer myTestPlayer = mitk::NavigationDataSequentialPlayer::New(); - bool exceptionThrown=false; - try - { - myTestPlayer->SetFileName(""); - } - catch(mitk::IGTIOException) + void TestStandardWorkflow() { - 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."); + // Set NavigationDatas for player + player->SetNavigationDataSet(NavigationDataSet); - //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); - } - 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(player->GetNumberOfSnapshots() == 3,"Testing if player reports correct number of Snapshots"); + MITK_TEST_CONDITION(player->GetNumberOfIndexedOutputs() == 2,"Testing number of outputs"); -} + //rest repeat + player->SetRepeat(true); -void TestGoToSnapshotException() -{ - //testing GoToSnapShot for exception - mitk::NavigationDataSequentialPlayer::Pointer myTestPlayer2 = mitk::NavigationDataSequentialPlayer::New(); - myTestPlayer2->SetXMLString(XML_STRING); + MITK_TEST_CONDITION(runLoop(),"Testing first run."); + MITK_TEST_CONDITION(runLoop(),"Testing second run."); //repeat is on should work a second time - bool exceptionThrown2=false; - try - { - unsigned int invalidSnapshot = 1000; - myTestPlayer2->GoToSnapshot(invalidSnapshot); + // now test the go to snapshot function + player->GoToSnapshot(2); + mitk::NavigationData::Pointer nd1 = player->GetOutput(1); + mitk::NavigationData::Pointer ref1 = NavigationDataSet->GetNavigationDataForIndex(2,1); + MITK_TEST_CONDITION(ref1->GetPosition().GetVnlVector() == nd1->GetPosition().GetVnlVector(), + "Testing GoToSnapshot() [1]"); + + //MITK_TEST_OUTPUT( << "Reference:" << ref1->GetPosition().GetVnlVector() << "\tObserved: " << nd1->GetPosition().GetVnlVector()); + + player->GoToSnapshot(0); + mitk::NavigationData::Pointer nd0 = player->GetOutput(); + mitk::NavigationData::Pointer ref0 = NavigationDataSet->GetNavigationDataForIndex(0,0); + MITK_TEST_CONDITION(ref0->GetOrientation().as_vector() == nd0->GetOrientation().as_vector(), + "Testing GoToSnapshot() [2]"); + + //MITK_TEST_OUTPUT( << "Reference" << ref0->GetPosition().GetVnlVector() << "\tObserved:" <GetOrientation().as_vector() ); } - catch(mitk::IGTException) + + void TestRestartWithNewNavigationDataSet() { - exceptionThrown2=true; - } - MITK_TEST_CONDITION_REQUIRED(exceptionThrown2, "Testing if exception is thrown when GoToSnapShot method is called with an index that doesn't exist."); -} + player->SetNavigationDataSet(NavigationDataSet); + mitk::NavigationData::PositionType nd1 = player->GetOutput(0)->GetPosition(); + player->SetNavigationDataSet(NavigationDataSet); + mitk::NavigationData::PositionType nd2 = player->GetOutput(0)->GetPosition(); -void TestSetXMLStringException() -{ - mitk::NavigationDataSequentialPlayer::Pointer myTestPlayer3 = mitk::NavigationDataSequentialPlayer::New(); + MITK_TEST_CONDITION(nd1 == nd2, "First output must be the same after setting same navigation data again."); - bool exceptionThrown3=false; + // setting new NavigationDataSet with different tool count should result in an exception + std::string file = GetTestDataFilePath("IGT-Data/NavigationDataTestData.xml"); + mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); + MITK_TEST_FOR_EXCEPTION(mitk::IGTException, player->SetNavigationDataSet(reader->Read(file))); + } - //The string above XML_INVALID_TESTSTRING is a wrong string, some element were deleted in above - try + void TestGoToSnapshotException() { - myTestPlayer3->SetXMLString(XML_INVALID_TESTSTRING); + //testing GoToSnapShot for exception + mitk::NavigationDataSequentialPlayer::Pointer myTestPlayer2 = mitk::NavigationDataSequentialPlayer::New(); + std::string file = GetTestDataFilePath("IGT-Data/NavigationDataTestData_2Tools.xml"); + mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); + myTestPlayer2->SetNavigationDataSet(reader->Read(file)); + + bool exceptionThrown2=false; + try + { + unsigned int invalidSnapshot = 1000; + myTestPlayer2->GoToSnapshot(invalidSnapshot); + } + catch(mitk::IGTException) + { + exceptionThrown2=true; + } + MITK_TEST_CONDITION(exceptionThrown2, "Testing if exception is thrown when GoToSnapShot method is called with an index that doesn't exist."); } - catch(mitk::IGTException) + + void TestDoubleUpdate() { - exceptionThrown3=true; - } - MITK_TEST_CONDITION_REQUIRED(exceptionThrown3, "Testing SetXMLString method with an invalid XML string."); -} + //std::string file = GetTestDataFilePath("IGT-Data/NavigationDataTestData_2Tools.xml"); + //mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); + //player->SetNavigationDataSet(reader->Read(file)); + player->SetNavigationDataSet(NavigationDataSet); + player->Update(); + mitk::Quaternion nd1Orientation = player->GetOutput()->GetOrientation(); + player->Update(); + mitk::Quaternion nd2Orientation = player->GetOutput()->GetOrientation(); -/**Documentation - * test for the class "NavigationDataRecorder". - */ -int mitkNavigationDataSequentialPlayerTest(int /* argc */, char* /*argv*/[]) -{ - MITK_TEST_BEGIN("NavigationDataSequentialPlayer"); + MITK_TEST_CONDITION(nd1Orientation.as_vector() == nd2Orientation.as_vector(), "Output must be the same no matter if Update() was called between."); - TestStandardWorkflow(); - TestSetFileNameException(); - TestSetXMLStringException(); - TestGoToSnapshotException(); + MITK_TEST_CONDITION(player->GoToNextSnapshot(), "There must be a next snapshot available."); + player->Update(); + mitk::Quaternion nd3Orientation = player->GetOutput()->GetOrientation(); - MITK_TEST_END(); -} + MITK_TEST_CONDITION(nd1Orientation.as_vector() != nd3Orientation.as_vector(), "Output must be different if GoToNextSnapshot() was called between."); + } +}; +MITK_TEST_SUITE_REGISTRATION(mitkNavigationDataSequentialPlayer) \ No newline at end of file diff --git a/Modules/IGT/Testing/mitkNavigationDataSetReaderWriterTest.cpp b/Modules/IGT/Testing/mitkNavigationDataSetReaderWriterTest.cpp new file mode 100644 index 0000000000..828e75bcfc --- /dev/null +++ b/Modules/IGT/Testing/mitkNavigationDataSetReaderWriterTest.cpp @@ -0,0 +1,140 @@ +/*=================================================================== + +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. + +===================================================================*/ + +//testing headers +//#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +//for exceptions +#include "mitkIGTException.h" +#include "mitkIGTIOException.h" + +class mitkNavigationDataSetReaderWriterTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(mitkNavigationDataSetReaderWriterTestSuite); + MITK_TEST(TestCompareFunction); + MITK_TEST(TestReadWrite); + MITK_TEST(TestSetXMLStringException); + CPPUNIT_TEST_SUITE_END(); + +private: + + std::string pathRead; + std::string pathWrite; + std::string pathWrong; + mitk::NavigationDataSetWriterXML writer; + mitk::NavigationDataReaderXML::Pointer reader; + mitk::NavigationDataSet::Pointer set; + +public: + + void setUp() + { + pathRead = GetTestDataFilePath("IGT-Data/RecordedNavigationData.xml"); + + pathWrite = pathRead; + pathWrite.insert(pathWrite.end()-4,'2');;//Insert 2: IGT-Data/NavigationDataSet2.xml + std::ifstream FileTest(pathWrite.c_str()); + if(FileTest){ + //remove file if it already exists. TODO: Löschen funktioniert nicht!!!! xxxxxxxxxxxxxxxx + FileTest.close(); + std::remove(pathWrite.c_str()); + } + + pathWrong = GetTestDataFilePath("IGT-Data/NavigationDataTestData.xml"); + + reader = mitk::NavigationDataReaderXML::New(); + } + + void tearDown() + { + } + + void TestReadWrite() + { + // Aim is to read an xml into a pointset, write that xml again, and compare the output + + set = reader->Read(pathRead); + writer.Write(pathWrite, set); + + CPPUNIT_ASSERT_MESSAGE( "Testing if read/write cycle creates identical files", CompareFiles(pathRead, pathWrite)); + remove(pathWrite.c_str()); + } + + 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)) { + fclose(f1); + fclose(f2); + return false; // Files are not equal + } + } while (!feof(f1) && !feof(f2)); + bool returnValue = feof(f1) && feof(f2); + fclose(f1); + fclose(f2); + return returnValue; + } + + void TestSetXMLStringException() + { + bool exceptionThrown3=false; + try + { + std::string file = GetTestDataFilePath("IGT-Data/InvalidVersionNavigationDataTestData.xml"); + mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); + reader->Read(file); + } + catch(mitk::IGTIOException) + { + exceptionThrown3=true; + } + MITK_TEST_CONDITION(exceptionThrown3, "Reading an invalid XML string and expecting a exception"); + } + + void TestCompareFunction() + { + CPPUNIT_ASSERT_MESSAGE("Asserting that compare function for files works correctly - Positive Test", CompareFiles(pathRead, + pathRead)); + CPPUNIT_ASSERT_MESSAGE("Asserting that compare function for files works correctly - Negative Test", ! CompareFiles(pathRead, + pathWrong) ); + } +}; +MITK_TEST_SUITE_REGISTRATION(mitkNavigationDataSetReaderWriter) \ No newline at end of file diff --git a/Modules/IGT/Testing/mitkNavigationDataSetTest.cpp b/Modules/IGT/Testing/mitkNavigationDataSetTest.cpp new file mode 100644 index 0000000000..165730175e --- /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) == nd21, + "Second NavigationData object for tool 0 should be the same as added previously."); + MITK_TEST_CONDITION_REQUIRED(navigationDataSet->GetNavigationDataForIndex(1, 0) == nd12, + "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(); +} \ No newline at end of file diff --git a/Modules/IGT/Testing/mitkNavigationDataToPointSetFilterTest.cpp b/Modules/IGT/Testing/mitkNavigationDataToPointSetFilterTest.cpp index 396d9a8b35..8bb4d8d7a8 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(); +// TestMode3DMean(); //infinite loop in debug mode, see bug 17763 MITK_TEST_END(); } diff --git a/Modules/IGT/TrackingDevices/mitkVirtualTrackingTool.h b/Modules/IGT/TrackingDevices/mitkVirtualTrackingTool.h index 25b36ad42a..9c5fb8dd69 100644 --- a/Modules/IGT/TrackingDevices/mitkVirtualTrackingTool.h +++ b/Modules/IGT/TrackingDevices/mitkVirtualTrackingTool.h @@ -1,67 +1,67 @@ /*=================================================================== 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 MITKVirtualTrackingTool_H_HEADER_INCLUDED_ #define MITKVirtualTrackingTool_H_HEADER_INCLUDED_ #include #include #include #include #include namespace mitk { /**Documentation * \brief implements TrackingTool interface * * This class is a complete TrackingTool implementation. It can either be used directly by * TrackingDevices, or be subclassed for more specific implementations. * mitk::MicroBirdTrackingDevice uses this class to manage its tools. Other tracking devices * uses specialized versions of this class (e.g. mitk::NDITrackingTool) * * \ingroup IGT */ class MitkIGT_EXPORT VirtualTrackingTool : public InternalTrackingTool { public: mitkClassMacro(VirtualTrackingTool, InternalTrackingTool); friend class VirtualTrackingDevice; + itkFactorylessNewMacro(Self) typedef itk::NonUniformBSpline<3> SplineType; ///< spline type used for tool path interpolation itkGetMacro(SplineLength, mitk::ScalarType); itkSetMacro(SplineLength, mitk::ScalarType); itkGetMacro(Velocity, mitk::ScalarType); itkSetMacro(Velocity, mitk::ScalarType); itkGetObjectMacro(Spline, SplineType); protected: - itkFactorylessNewMacro(Self) itkCloneMacro(Self) VirtualTrackingTool(); virtual ~VirtualTrackingTool(); SplineType::Pointer m_Spline; mitk::ScalarType m_SplineLength; mitk::ScalarType m_Velocity; }; } // namespace mitk #endif /* MITKVirtualTrackingTool_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/Tutorial/mitkIGTTutorialStep1.cpp b/Modules/IGT/Tutorial/mitkIGTTutorialStep1.cpp index 6733e661d4..4a6cd200d3 100644 --- a/Modules/IGT/Tutorial/mitkIGTTutorialStep1.cpp +++ b/Modules/IGT/Tutorial/mitkIGTTutorialStep1.cpp @@ -1,198 +1,196 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include "mitkNavigationDataDisplacementFilter.h" #include #include +#include +#include #include //##Documentation //## \brief A small console tutorial about MITK-IGT int main(int /*argc*/, char* /*argv*/[]) { - - //************************************************************************* // What we will do... //************************************************************************* //In this tutorial we build up a small navigation pipeline with a virtual tracking device //which produce random positions and orientation so no additional hardware is required. //The source of the pipeline is a TrackingDeviceSource object. This we connect to a simple //filter which just displaces the positions with an offset. After that we use a recorder //to store this new positions and other information to disc in a XML file. After that we use //another source (NavigationDataPlayer) to replay the recorded data. - //************************************************************************* // Part I: Basic initialization of the source and tracking device //************************************************************************* //First of all create a tracking device object and two tools for this "device". //Here we take the VirtualTrackingDevice. This is not a real tracking device it just delivers random //positions and orientations. You can use other/real tracking devices if you replace the following //code with different tracking devices, e.g. mitk::NDITrackingDevice. The tools represent the //sensors of the tracking device. The TrackingDevice fills the tools with data. std::cout << "Generating TrackingDevice ..." << std::endl; mitk::VirtualTrackingDevice::Pointer tracker = mitk::VirtualTrackingDevice::New(); tracker->AddTool("tool1"); tracker->AddTool("tool2"); //The tracking device object is used for the physical connection to the device. To use the //data inside of our tracking pipeline we need a source. This source encapsulate the tracking device //and provides objects of the type mitk::NavigationData as output. The NavigationData objects stores //position, orientation, if the data is valid or not and special error informations in a covariance //matrix. // //Typically the start of our pipeline is a TrackingDeviceSource. To work correct we have to set a //TrackingDevice object. Attention you have to set the tools before you set the whole TrackingDevice //object to the TrackingDeviceSource because the source need to know how many outputs should be //generated. std::cout << "Generating Source ..." << std::endl; mitk::TrackingDeviceSource::Pointer source = mitk::TrackingDeviceSource::New(); source->SetTrackingDevice(tracker); //here we set the device for the pipeline source source->Connect(); //here we connect to the tracking system - //Note we do not call this on the TrackingDevice object + //Note we do not call this on the TrackingDevice object source->StartTracking(); //start the tracking - //Now the source generates outputs. - + //Now the source generates outputs. //************************************************************************* // Part II: Create a NavigationDataToNavigationDataFilter //************************************************************************* //The next thing we do is using a NavigationDataToNavigationDataFilter. One of these filter is the //very simple NavigationDataDisplacementFilter. This filter just changes the positions of the input //NavigationData objects with an offset for each direction (X,Y,Z). The input of this filter is the //source and the output of this filter is the "displaced" input. std::cout << "Generating DisplacementFilter ..." << std::endl; mitk::NavigationDataDisplacementFilter::Pointer displacer = mitk::NavigationDataDisplacementFilter::New(); mitk::Vector3D offset; mitk::FillVector3D(offset, 10.0, 100.0, 1.0); //initialize the offset displacer->SetOffset(offset); //now set the offset in the NavigationDataDisplacementFilter object //Connect the two filters. You can use the ConnectTo method to automatically connect all outputs from one filter // to inputs from another filter. displacer->ConnectTo(source.GetPointer()); // Alternatively, you can manually connect inputs and outputs. // The code below shows what the ConnectTo Methods does internally: // //for (unsigned int i = 0; i < source->GetNumberOfOutputs(); i++) //{ // displacer->SetInput(i, source->GetOutput(i)); //here we connect to the displacement filter //} - //************************************************************************* // Part III: Record the data with the NavigationDataRecorder //************************************************************************* - //The next part of our pipeline is the recorder. The recorder needs a filename. Otherwise the output - //is redirected to the console. The input of the recorder is the output of the displacement filter - //and the output is a XML file with the name "Test Output-0.xml". + //The next part of our pipeline is the recorder. The input of the recorder is the output of the displacement filter + //and the output is a XML file with the name "Test Output-0.xml", which is written with a NavigationDataSetWriter. std::cout << "Start Recording ..." << std::endl; //we need the stringstream for building up our filename std::stringstream filename; //the .xml extension and an counter is added automatically filename << itksys::SystemTools::GetCurrentWorkingDirectory() << "/Test Output"; std::cout << "Record to file: " << filename.str() << "-0.xml ..." << std::endl; mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New(); - recorder->SetFileName(filename.str()); - //now every output of the displacer object is connected to the recorder object - for (unsigned int i = 0; i < displacer->GetNumberOfOutputs(); i++) - { - recorder->AddNavigationData(displacer->GetOutput(i)); // here we connect to the recorder - } + //now the output of the displacer object is connected to the recorder object + recorder->ConnectTo(displacer); recorder->StartRecording(); //after finishing the settings you can start the recording mechanism - //now every update of the recorder stores one line into the file for - //each added NavigationData - + //now every update of the recorder stores one line into the file for + //each added NavigationData for (unsigned int x = 0; x < 100; x++) //write 100 datasets { recorder->Update(); //the update causes one line in the XML file for every tool - //in this case two lines + //in this case two lines itksys::SystemTools::Delay(100); //sleep a little } recorder->StopRecording(); //to get proper XML files you should stop recording - //if your application crashes during recording no data - //will be lost it is all stored to disc + //if your application crashes during recording no data + //will be lost it is all stored to disc + //The writer needs a filename. Otherwise the output + //is redirected to the console. + mitk::NavigationDataSetWriterXML writer; + writer.Write(filename.str(),recorder->GetNavigationDataSet()); //************************************************************************* // Part IV: Play the data with the NavigationDataPlayer //************************************************************************* //The recording is finished now so now we can play the data. The NavigationDataPlayer is similar //to the TrackingDevice source. It also derives from NavigationDataSource. So you can use a player - //instead of a TrackingDeviceSource. The input of this player is the filename and the output are - //NavigationData object. + //instead of a TrackingDeviceSource. The input of this player is a NavigationDataSet, which we + //read with a NavigationDataReader. filename << "-0.xml"; std::cout << "Start playing from file: " << filename.str() << " ..." << std::endl; - mitk::NavigationDataPlayer::Pointer player = mitk::NavigationDataPlayer::New(); + + mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); //this is first part of the file name the .xml extension and an counter is added automatically - player->SetFileName(filename.str()); + mitk::NavigationDataSet::Pointer naviDataSet = reader->Read(filename.str()); + player->SetNavigationDataSet(naviDataSet); + player->StartPlaying(); //this starts the player - //From now on the player provides NavigationDatas in the order and - //correct time as they were recorded + //From now on the player provides NavigationDatas in the order and + //correct time as they were recorded //this connects the outputs of the player to the NavigationData objects mitk::NavigationData::Pointer nd = player->GetOutput(); mitk::NavigationData::Pointer nd2 = player->GetOutput(1); for (unsigned int x=0; x<100; x++) { if (nd.IsNotNull()) //check if the output is not null { //With this update the NavigationData object propagates through the pipeline to get a new value. //In this case we only have a source (NavigationDataPlayer). nd->Update(); std::cout << x << ": 1:" << nd->GetPosition() << std::endl; std::cout << x << ": 2:" << nd2->GetPosition() << std::endl; std::cout << x << ": 1:" << nd->GetOrientation() << std::endl; std::cout << x << ": 2:" << nd2->GetOrientation() << std::endl; itksys::SystemTools::Delay(100); //sleep a little like in the recorder part } } player->StopPlaying(); //This stops the player - //With another call of StartPlaying the player will start again at the beginning of the file + //With another call of StartPlaying the player will start again at the beginning of the file itksys::SystemTools::Delay(2000); std::cout << "finished" << std::endl; } diff --git a/Modules/IGT/files.cmake b/Modules/IGT/files.cmake index d9c8cb2c35..2b3112756e 100644 --- a/Modules/IGT/files.cmake +++ b/Modules/IGT/files.cmake @@ -1,83 +1,89 @@ set(CPP_FILES TestingHelper/mitkNavigationToolStorageTestHelper.cpp Algorithms/mitkNavigationDataDelayFilter.cpp Algorithms/mitkNavigationDataDisplacementFilter.cpp Algorithms/mitkNavigationDataEvaluationFilter.cpp Algorithms/mitkNavigationDataLandmarkTransformFilter.cpp Algorithms/mitkNavigationDataReferenceTransformFilter.cpp Algorithms/mitkNavigationDataSmoothingFilter.cpp Algorithms/mitkNavigationDataToMessageFilter.cpp Algorithms/mitkNavigationDataToNavigationDataFilter.cpp Algorithms/mitkNavigationDataToPointSetFilter.cpp Algorithms/mitkNavigationDataTransformFilter.cpp Common/mitkIGTTimeStamp.cpp Common/mitkSerialCommunication.cpp Common/mitkTrackingTypes.cpp DataManagement/mitkNavigationData.cpp + DataManagement/mitkNavigationDataSet.cpp DataManagement/mitkNavigationDataSource.cpp DataManagement/mitkNavigationTool.cpp DataManagement/mitkNavigationToolStorage.cpp DataManagement/mitkTrackingDeviceSourceConfigurator.cpp DataManagement/mitkTrackingDeviceSource.cpp ExceptionHandling/mitkIGTException.cpp ExceptionHandling/mitkIGTHardwareException.cpp ExceptionHandling/mitkIGTIOException.cpp IO/mitkNavigationDataPlayer.cpp IO/mitkNavigationDataPlayerBase.cpp IO/mitkNavigationDataRecorder.cpp IO/mitkNavigationDataSequentialPlayer.cpp IO/mitkNavigationToolReader.cpp IO/mitkNavigationToolStorageSerializer.cpp IO/mitkNavigationToolStorageDeserializer.cpp IO/mitkNavigationToolWriter.cpp + IO/mitkNavigationDataReaderInterface.cpp + IO/mitkNavigationDataReaderXML.cpp + IO/mitkNavigationDataReaderCSV.cpp + IO/mitkNavigationDataSetWriterXML.cpp + IO/mitkNavigationDataSetWriterCSV.cpp Rendering/mitkCameraVisualization.cpp Rendering/mitkNavigationDataObjectVisualizationFilter.cpp TrackingDevices/mitkClaronTool.cpp TrackingDevices/mitkClaronTrackingDevice.cpp TrackingDevices/mitkInternalTrackingTool.cpp TrackingDevices/mitkNDIPassiveTool.cpp TrackingDevices/mitkNDIProtocol.cpp TrackingDevices/mitkNDITrackingDevice.cpp TrackingDevices/mitkTrackingDevice.cpp TrackingDevices/mitkTrackingTool.cpp TrackingDevices/mitkTrackingVolumeGenerator.cpp TrackingDevices/mitkVirtualTrackingDevice.cpp TrackingDevices/mitkVirtualTrackingTool.cpp TrackingDevices/mitkOptitrackErrorMessages.cpp TrackingDevices/mitkOptitrackTrackingDevice.cpp TrackingDevices/mitkOptitrackTrackingTool.cpp ) set(RESOURCE_FILES ClaronMicron.stl IntuitiveDaVinci.stl NDIAurora.stl NDIAurora_Dome.stl NDIAuroraCompactFG_Dome.stl NDIAuroraPlanarFG_Dome.stl NDIAuroraTabletopFG_Dome.stl NDIAuroraTabletopFG_Prototype_Dome.stl NDIPolarisOldModel.stl NDIPolarisSpectra.stl NDIPolarisSpectraExtendedPyramid.stl NDIPolarisVicra.stl ) if(MITK_USE_MICRON_TRACKER) set(CPP_FILES ${CPP_FILES} TrackingDevices/mitkClaronInterface.cpp) else() set(CPP_FILES ${CPP_FILES} TrackingDevices/mitkClaronInterfaceStub.cpp) endif(MITK_USE_MICRON_TRACKER) if(MITK_USE_MICROBIRD_TRACKER) set(CPP_FILES ${CPP_FILES} TrackingDevices/mitkMicroBirdTrackingDevice.cpp) endif(MITK_USE_MICROBIRD_TRACKER) diff --git a/Modules/IGTUI/Qmitk/QmitkIGTLoggerWidget.cpp b/Modules/IGTUI/Qmitk/QmitkIGTLoggerWidget.cpp index f89c481069..59fcdfb14b 100644 --- a/Modules/IGTUI/Qmitk/QmitkIGTLoggerWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkIGTLoggerWidget.cpp @@ -1,297 +1,310 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkIGTLoggerWidget.h" //mitk headers #include "mitkTrackingTypes.h" #include #include #include #include #include #include #include #include +#include //itk headers #include //qt headers #include #include #include QmitkIGTLoggerWidget::QmitkIGTLoggerWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f), m_Recorder(NULL), m_RecordingActivated(false) { m_Controls = NULL; CreateQtPartControl(this); CreateConnections(); //set output file this->SetOutputFileName(); //update milliseconds and samples this->SetDefaultRecordingSettings(); } QmitkIGTLoggerWidget::~QmitkIGTLoggerWidget() { m_RecordingTimer->stop(); m_Recorder = NULL; m_RecordingTimer = NULL; } void QmitkIGTLoggerWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkIGTLoggerWidgetControls; m_Controls->setupUi(parent); m_RecordingTimer = new QTimer(this); } } void QmitkIGTLoggerWidget::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_pbLoadDir), SIGNAL(clicked()), this, SLOT(OnChangePressed()) ); connect( (QObject*)(m_Controls->m_pbStartRecording), SIGNAL(clicked(bool)), this, SLOT(OnStartRecording(bool)) ); connect( m_RecordingTimer, SIGNAL(timeout()), this, SLOT(OnRecording()) ); connect( (QObject*)(m_Controls->m_leRecordingValue), SIGNAL(editingFinished()), this, SLOT(UpdateRecordingTime()) ); connect( (QObject*)(m_Controls->m_cbRecordingType), SIGNAL(activated(int)), this, SLOT(UpdateRecordingTime()) ); connect( (QObject*)(m_Controls->m_leOutputFile), SIGNAL(editingFinished()), this, SLOT(UpdateOutputFileName()) ); } } void QmitkIGTLoggerWidget::SetDataStorage(mitk::DataStorage* dataStorage) { m_DataStorage = dataStorage; } void QmitkIGTLoggerWidget::OnStartRecording(bool recording) { if (m_Recorder.IsNull()) { QMessageBox::warning(NULL, "Warning", QString("Please start tracking before recording!")); return; } if (m_CmpFilename.isEmpty()) { QMessageBox::warning(NULL, "Warning", QString("Please specify filename!")); return; } if(recording) { if (!m_RecordingActivated) { - m_Recorder->SetFileName(m_CmpFilename.toStdString()); + //m_Recorder->SetFileName(m_CmpFilename.toStdString()); try { /*start the recording mechanism */ m_Recorder->StartRecording(); m_RecordingTimer->start(50); //now every update of the recorder stores one line into the file for each added NavigationData mitk::StatusBar::GetInstance()->DisplayText("Recording tracking data now"); // Display recording message for 75ms in status bar emit SignalRecordingStarted(); } catch (std::exception& e) { QMessageBox::warning(NULL, "IGT-Tracking Logger: Error", QString("Error while recording tracking data: %1").arg(e.what())); mitk::StatusBar::GetInstance()->DisplayText(""); // Display recording message for 75ms in status bar } m_Controls->m_pbStartRecording->setText("Stop recording"); m_Controls->m_leRecordingValue->setEnabled(false); m_Controls->m_cbRecordingType->setEnabled(false); m_RecordingActivated = true; if(m_Controls->m_cbRecordingType->currentIndex()==0) { bool success = false; QString str_ms = m_Controls->m_leRecordingValue->text(); int int_ms = str_ms.toInt(&success); if (success) QTimer::singleShot(int_ms, this, SLOT(StopRecording())); } } else { this->StopRecording(); } } else { this->StopRecording(); m_Controls->m_pbStartRecording->setChecked(false); } } void QmitkIGTLoggerWidget::StopRecording() { m_RecordingTimer->stop(); m_Recorder->StopRecording(); mitk::StatusBar::GetInstance()->DisplayText("Recording STOPPED", 2000); // Display message for 2s in status bar m_Controls->m_pbStartRecording->setText("Start recording"); m_Controls->m_pbStartRecording->setChecked(false); m_Controls->m_leRecordingValue->setEnabled(true); m_Controls->m_cbRecordingType->setEnabled(true); m_RecordingActivated = false; + try + { + // write NavigationDataSet on StopRecording + mitk::NavigationDataSetWriterXML().Write(m_CmpFilename.toStdString(), m_Recorder->GetNavigationDataSet()); + } + catch(const std::exception &e) + { + // TODO: catch must be adapted when new file writer are merged to master + QMessageBox::warning(NULL, "IGT-Tracking Logger: Error", QString("Error while writing tracking data: %1").arg(e.what())); + MITK_WARN << "File could not be written."; + } + emit SignalRecordingStopped(); } void QmitkIGTLoggerWidget::OnRecording() { static unsigned int sampleCounter = 0; unsigned int int_samples = m_Samples.toInt(); if(sampleCounter >= int_samples) { this->StopRecording(); sampleCounter=0; return; } m_Recorder->Update(); if (m_Controls->m_cbRecordingType->currentIndex()==1) sampleCounter++; } void QmitkIGTLoggerWidget::OnChangePressed() { QString oldName = m_CmpFilename; m_CmpFilename.clear(); m_CmpFilename = QFileDialog::getSaveFileName( QApplication::activeWindow() , "Save tracking data", "IGT_Tracking_Data.xml", "XML files (*.xml)" ); if (m_CmpFilename.isEmpty())//if something went wrong or user pressed cancel in the save dialog { m_CmpFilename=oldName; } m_Controls->m_leOutputFile->setText(m_CmpFilename); } void QmitkIGTLoggerWidget::UpdateOutputFileName() { QString oldName = m_CmpFilename; m_CmpFilename.clear(); m_CmpFilename = m_Controls->m_leOutputFile->text(); if (m_CmpFilename.isEmpty()) { QMessageBox::warning(NULL, "Warning", QString("Please enter valid path! Using previous path again.")); m_CmpFilename=oldName; m_Controls->m_leOutputFile->setText(m_CmpFilename); } } void QmitkIGTLoggerWidget::SetRecorder( mitk::NavigationDataRecorder::Pointer recorder ) { m_Recorder = recorder; } void QmitkIGTLoggerWidget::UpdateRecordingTime() { // milliseconds selected in the combobox if (m_Controls->m_cbRecordingType->currentIndex()==0) { m_MilliSeconds = m_Controls->m_leRecordingValue->text(); if(m_MilliSeconds.compare("infinite")==0) { this->SetDefaultRecordingSettings(); } bool success = false; m_MilliSeconds.toInt(&success); if (!success) { QMessageBox::warning(NULL, "Warning", QString("Please enter a number!")); this->SetDefaultRecordingSettings(); return; } } else if(m_Controls->m_cbRecordingType->currentIndex()==1) // #samples selected in the combobox { m_Samples = m_Controls->m_leRecordingValue->text(); if(m_Samples.compare("infinite")==0) { this->SetDefaultRecordingSettings(); } bool success = false; m_Samples.toInt(&success); if (!success) { QMessageBox::warning(NULL, "Warning", QString("Please enter a number!")); this->SetDefaultRecordingSettings(); return; } } else if (m_Controls->m_cbRecordingType->currentIndex()==2)// infinite selected in the combobox { // U+221E unicode symbole for infinite QString infinite("infinite"); m_Controls->m_leRecordingValue->setText(infinite); } // m_Controls->m_leSamples->setText(QString::number(samples)); } void QmitkIGTLoggerWidget::SetDefaultRecordingSettings() { m_Controls->m_leRecordingValue->setText("2000"); m_Controls->m_cbRecordingType->setCurrentIndex(0); m_Samples="100"; m_MilliSeconds="2000"; } void QmitkIGTLoggerWidget::SetOutputFileName() { std::string tmpDir = itksys::SystemTools::GetCurrentWorkingDirectory(); QString dir = QString(tmpDir.c_str()); QString filename = "IGT_Tracking_Data.xml"; m_CmpFilename.append(dir); if(dir.isEmpty()) { QMessageBox::warning(NULL, "Warning", QString("Could not load current working directory")); return; } if(dir.endsWith("/")||dir.endsWith("\\")) { m_CmpFilename.append(filename); } else { m_CmpFilename.append("/"); m_CmpFilename.append(filename); } m_Controls->m_leOutputFile->setText(m_CmpFilename); } diff --git a/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.cpp b/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.cpp index fcb9fe20a6..63361eacd4 100644 --- a/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.cpp @@ -1,574 +1,576 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkIGTPlayerWidget.h" //mitk headers #include "mitkTrackingTypes.h" #include #include #include #include #include #include #include #include - +#include "mitkNavigationDataReaderXML.h" //qt headers #include #include #include - QmitkIGTPlayerWidget::QmitkIGTPlayerWidget(QWidget* parent, Qt::WindowFlags f) -: QWidget(parent, f) -,m_RealTimePlayer(NULL) -,m_SequentialPlayer(NULL) -,m_StartTime(-1.0) -,m_CurrentSequentialPointNumber(0) + : QWidget(parent, f), + m_RealTimePlayer(mitk::NavigationDataPlayer::New()), + m_SequentialPlayer(mitk::NavigationDataSequentialPlayer::New()), + m_StartTime(-1.0), + m_CurrentSequentialPointNumber(0), + m_Controls(new Ui::QmitkIGTPlayerWidgetControls) { - m_Controls = NULL; - CreateQtPartControl(this); + m_Controls->setupUi(this); + m_PlayingTimer = new QTimer(this); // initialize update timer + CreateConnections(); m_Controls->samplePositionHorizontalSlider->setVisible(false); this->ResetLCDNumbers(); // reset lcd numbers at start } - QmitkIGTPlayerWidget::~QmitkIGTPlayerWidget() { m_PlayingTimer->stop(); - m_RealTimePlayer = NULL; - m_PlayingTimer = NULL; -} - -void QmitkIGTPlayerWidget::CreateQtPartControl(QWidget *parent) -{ - if (!m_Controls) - { - // create GUI widgets - m_Controls = new Ui::QmitkIGTPlayerWidgetControls; - m_Controls->setupUi(parent); - - m_PlayingTimer = new QTimer(this); // initialize update timer - } + delete m_Controls; } void QmitkIGTPlayerWidget::CreateConnections() { - if ( m_Controls ) - { - connect( (QObject*)(m_Controls->selectPushButton), SIGNAL(clicked()), this, SLOT(OnSelectPressed()) ); // open file dialog - connect( (QObject*)(m_Controls->playPushButton), SIGNAL(clicked(bool)), this, SLOT(OnPlayButtonClicked(bool)) ); // play button - connect( (QObject*)(m_PlayingTimer), SIGNAL(timeout()), this, SLOT(OnPlaying()) ); // update timer - connect( (QObject*) (m_Controls->beginPushButton), SIGNAL(clicked()), this, SLOT(OnGoToBegin()) ); // reset player and go to begin - connect( (QObject*) (m_Controls->stopPushButton), SIGNAL(clicked()), this, SLOT(OnGoToEnd()) ); // reset player - // pass this widgets protected combobox signal to public signal - connect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) ); - // pass this widgets protected checkbox signal to public signal - connect( m_Controls->splineModeCheckBox, SIGNAL(toggled(bool)), this, SIGNAL(SignalSplineModeToggled(bool)) ); - connect( m_Controls->sequencialModeCheckBox, SIGNAL(toggled(bool)), this, SLOT(OnSequencialModeToggled(bool)) ); - - connect( m_Controls->samplePositionHorizontalSlider, SIGNAL(sliderPressed()), this, SLOT(OnSliderPressed()) ); - connect( m_Controls->samplePositionHorizontalSlider, SIGNAL(sliderReleased()), this, SLOT(OnSliderReleased()) ); + connect( (QObject*)(m_Controls->playPushButton), SIGNAL(clicked(bool)), this, SLOT(OnPlayButtonClicked(bool)) ); // play button + connect( (QObject*)(m_PlayingTimer), SIGNAL(timeout()), this, SLOT(OnPlaying()) ); // update timer + connect( (QObject*) (m_Controls->beginPushButton), SIGNAL(clicked()), this, SLOT(OnGoToBegin()) ); // reset player and go to begin + connect( (QObject*) (m_Controls->stopPushButton), SIGNAL(clicked()), this, SLOT(OnGoToEnd()) ); // reset player + // pass this widgets protected combobox signal to public signal + connect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) ); + // pass this widgets protected checkbox signal to public signal + connect( m_Controls->splineModeCheckBox, SIGNAL(toggled(bool)), this, SIGNAL(SignalSplineModeToggled(bool)) ); + //connect( m_Controls->sequencialModeCheckBox, SIGNAL(toggled(bool)), this, SLOT(OnSequencialModeToggled(bool)) ); - } -} + connect( m_Controls->samplePositionHorizontalSlider, SIGNAL(sliderPressed()), this, SLOT(OnSliderPressed()) ); + connect( m_Controls->samplePositionHorizontalSlider, SIGNAL(sliderReleased()), this, SLOT(OnSliderReleased()) ); + connect( m_Controls->m_OpenFileButton, SIGNAL(clicked()), this, SLOT(OnOpenFileButtonPressed()) ); +} bool QmitkIGTPlayerWidget::IsTrajectoryInSplineMode() { return m_Controls->splineModeCheckBox->isChecked(); } - bool QmitkIGTPlayerWidget::CheckInputFileValid() { QFile file(m_CmpFilename); // check if file exists if(!file.exists()) { QMessageBox::warning(NULL, "IGTPlayer: Error", "No valid input file was loaded. Please load input file first!"); return false; } return true; } - unsigned int QmitkIGTPlayerWidget::GetNumberOfTools() { unsigned int result = 0; if(this->GetCurrentPlaybackMode() == RealTimeMode) { if(m_RealTimePlayer.IsNotNull()) result = m_RealTimePlayer->GetNumberOfOutputs(); } else if(this->GetCurrentPlaybackMode() == SequentialMode) { if(m_SequentialPlayer.IsNotNull()) result = m_SequentialPlayer->GetNumberOfOutputs(); } // at the moment this works only if player is initialized return result; } - void QmitkIGTPlayerWidget::SetUpdateRate(unsigned int msecs) { m_PlayingTimer->setInterval((int) msecs); // set update timer update rate } void QmitkIGTPlayerWidget::OnPlayButtonClicked(bool checked) { - + if ( ! checked ) + { + if ( this->GetCurrentPlaybackMode() == RealTimeMode ) + { + m_RealTimePlayer->StopPlaying(); + } + else if ( this->GetCurrentPlaybackMode() == SequentialMode ) + { + // m_SequentialPlayer-> + } + } if(CheckInputFileValid()) // no playing possible without valid input file { + switch ( this->GetCurrentPlaybackMode() ) + { + case RealTimeMode: + { + break; + } + case SequentialMode: + { + break; + } + } + PlaybackMode currentMode = this->GetCurrentPlaybackMode(); bool isRealTimeMode = currentMode == RealTimeMode; bool isSequentialMode = currentMode == SequentialMode; if(checked) // play { if( (isRealTimeMode && m_RealTimePlayer.IsNull()) || (isSequentialMode && m_SequentialPlayer.IsNull())) // start play { + mitk::NavigationDataSet::Pointer navigationDataSet; + try + { + mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); + navigationDataSet = reader->Read(m_CmpFilename.toStdString()); + } + catch(mitk::IGTException) + { + std::string errormessage = "Error during start playing. Invalid or wrong file?"; + QMessageBox::warning(NULL, "IGTPlayer: Error", errormessage.c_str()); + m_Controls->playPushButton->setChecked(false); + m_RealTimePlayer = NULL; + return; + } + if(isRealTimeMode) { m_RealTimePlayer = mitk::NavigationDataPlayer::New(); - m_RealTimePlayer->SetFileName(m_CmpFilename.toStdString()); + m_RealTimePlayer->SetNavigationDataSet(navigationDataSet); try - { + { m_RealTimePlayer->StartPlaying(); - } + } catch(mitk::IGTException) - { + { std::string errormessage = "Error during start playing. Invalid or wrong file?"; QMessageBox::warning(NULL, "IGTPlayer: Error", errormessage.c_str()); m_Controls->playPushButton->setChecked(false); m_RealTimePlayer = NULL; return; - } + } } else if(isSequentialMode) { m_SequentialPlayer = mitk::NavigationDataSequentialPlayer::New(); try { - m_SequentialPlayer->SetFileName(m_CmpFilename.toStdString()); + m_SequentialPlayer->SetNavigationDataSet(navigationDataSet); } catch(mitk::IGTException) { - std::string errormessage = "Error during start playing. Invalid or wrong file type?"; - QMessageBox::warning(NULL, "IGTPlayer: Error", errormessage.c_str()); - m_Controls->playPushButton->setChecked(false); - m_RealTimePlayer = NULL; - return; + std::string errormessage = "Error during start playing. Invalid or wrong file type?"; + QMessageBox::warning(NULL, "IGTPlayer: Error", errormessage.c_str()); + m_Controls->playPushButton->setChecked(false); + m_RealTimePlayer = NULL; + return; } m_Controls->samplePositionHorizontalSlider->setMinimum(0); m_Controls->samplePositionHorizontalSlider->setMaximum(m_SequentialPlayer->GetNumberOfSnapshots()); m_Controls->samplePositionHorizontalSlider->setEnabled(true); } m_PlayingTimer->start(100); emit SignalPlayingStarted(); } else // resume play { if(isRealTimeMode) m_RealTimePlayer->Resume(); m_PlayingTimer->start(100); emit SignalPlayingResumed(); } } else // pause { if(isRealTimeMode) m_RealTimePlayer->Pause(); m_PlayingTimer->stop(); emit SignalPlayingPaused(); } } else + { m_Controls->playPushButton->setChecked(false); // uncheck play button if file unvalid + } } - QmitkIGTPlayerWidget::PlaybackMode QmitkIGTPlayerWidget::GetCurrentPlaybackMode() { - if(m_Controls->sequencialModeCheckBox->isChecked()) - return SequentialMode; - else - return RealTimeMode; + /*if(m_Controls->sequencialModeCheckBox->isChecked()) + return SequentialMode; + else*/ + return RealTimeMode; } QTimer* QmitkIGTPlayerWidget::GetPlayingTimer() { return m_PlayingTimer; } void QmitkIGTPlayerWidget::OnStopPlaying() { this->StopPlaying(); } - void QmitkIGTPlayerWidget::StopPlaying() { m_PlayingTimer->stop(); emit SignalPlayingStopped(); if(m_RealTimePlayer.IsNotNull()) m_RealTimePlayer->StopPlaying(); - m_RealTimePlayer = NULL; - m_SequentialPlayer = NULL; - m_StartTime = -1; // set starttime back m_CurrentSequentialPointNumber = 0; m_Controls->samplePositionHorizontalSlider->setSliderPosition(m_CurrentSequentialPointNumber); m_Controls->sampleLCDNumber->display(static_cast(m_CurrentSequentialPointNumber)); this->ResetLCDNumbers(); m_Controls->playPushButton->setChecked(false); // set play button unchecked - } void QmitkIGTPlayerWidget::OnPlaying() { - PlaybackMode currentMode = this->GetCurrentPlaybackMode(); - bool isRealTimeMode = currentMode == RealTimeMode; - bool isSequentialMode = currentMode == SequentialMode; - - if(isRealTimeMode && m_RealTimePlayer.IsNull()) - return; - - else if(isSequentialMode && m_SequentialPlayer.IsNull()) - return; + switch ( this->GetCurrentPlaybackMode() ) + { + case RealTimeMode: + { + if ( m_RealTimePlayer.IsNull() ) { return; } - if(isRealTimeMode && m_StartTime < 0) - m_StartTime = m_RealTimePlayer->GetOutput()->GetTimeStamp(); // get playback start time + if ( m_StartTime < 0 ) + { + // get playback start time + m_StartTime = m_RealTimePlayer->GetOutput()->GetTimeStamp(); + } + if( ! m_RealTimePlayer->IsAtEnd() ) + { + m_RealTimePlayer->Update(); // update player + int msc = (int) (m_RealTimePlayer->GetOutput()->GetTimeStamp() - m_StartTime); - if(isRealTimeMode && !m_RealTimePlayer->IsAtEnd()) - { - m_RealTimePlayer->Update(); // update player + // calculation for playing time display + int ms = msc % 1000; + msc = (msc - ms) / 1000; + int s = msc % 60; + int min = (msc-s) / 60; - int msc = (int) (m_RealTimePlayer->GetOutput()->GetTimeStamp() - m_StartTime); + // set lcd numbers + m_Controls->msecLCDNumber->display(ms); + m_Controls->secLCDNumber->display(s); + m_Controls->minLCDNumber->display(min); - // calculation for playing time display - int ms = msc % 1000; - msc = (msc - ms) / 1000; - int s = msc % 60; - int min = (msc-s) / 60; + emit SignalPlayerUpdated(); // player successfully updated + } + else + { + this->StopPlaying(); // if player is at EOF + } - // set lcd numbers - m_Controls->msecLCDNumber->display(ms); - m_Controls->secLCDNumber->display(s); - m_Controls->minLCDNumber->display(min); + break; + } + case SequentialMode: + { + if ( m_SequentialPlayer.IsNull() ) { return; } - emit SignalPlayerUpdated(); // player successfully updated - } - else if(isSequentialMode && (m_CurrentSequentialPointNumber < m_SequentialPlayer->GetNumberOfSnapshots())) - { - m_SequentialPlayer->Update(); // update sequential player + if ( m_CurrentSequentialPointNumber < m_SequentialPlayer->GetNumberOfSnapshots() ) + { + m_SequentialPlayer->Update(); // update sequential player - m_Controls->samplePositionHorizontalSlider->setSliderPosition(m_CurrentSequentialPointNumber++); // refresh slider position - m_Controls->sampleLCDNumber->display(static_cast(m_CurrentSequentialPointNumber)); + m_Controls->samplePositionHorizontalSlider->setSliderPosition(m_CurrentSequentialPointNumber++); // refresh slider position + m_Controls->sampleLCDNumber->display(static_cast(m_CurrentSequentialPointNumber)); - //for debugging purposes - //std::cout << "Sample: " << m_CurrentSequentialPointNumber << " X: " << m_SequentialPlayer->GetOutput()->GetPosition()[0] << " Y: " << m_SequentialPlayer->GetOutput()->GetPosition()[1] << " Y: " << m_SequentialPlayer->GetOutput()->GetPosition()[2] << std::endl; + //for debugging purposes + //std::cout << "Sample: " << m_CurrentSequentialPointNumber << " X: " << m_SequentialPlayer->GetOutput()->GetPosition()[0] << " Y: " << m_SequentialPlayer->GetOutput()->GetPosition()[1] << " Y: " << m_SequentialPlayer->GetOutput()->GetPosition()[2] << std::endl; - emit SignalPlayerUpdated(); // player successfully updated + emit SignalPlayerUpdated(); // player successfully updated + } + else + { + this->StopPlaying(); // if player is at EOF + } + break; + } } - else - this->StopPlaying(); // if player is at EOF - } const std::vector QmitkIGTPlayerWidget::GetNavigationDatas() { std::vector navDatas; if(this->GetCurrentPlaybackMode() == RealTimeMode && m_RealTimePlayer.IsNotNull()) { for(unsigned int i=0; i < m_RealTimePlayer->GetNumberOfOutputs(); ++i) { navDatas.push_back(m_RealTimePlayer->GetOutput(i)); // push back current navigation data for each tool } } else if(this->GetCurrentPlaybackMode() == SequentialMode && m_SequentialPlayer.IsNotNull()) { for(unsigned int i=0; i < m_SequentialPlayer->GetNumberOfOutputs(); ++i) { navDatas.push_back(m_SequentialPlayer->GetOutput(i)); // push back current navigation data for each tool } } return navDatas; } const mitk::PointSet::Pointer QmitkIGTPlayerWidget::GetNavigationDatasPointSet() { mitk::PointSet::Pointer result = mitk::PointSet::New(); mitk::PointSet::PointType pointType; PlaybackMode currentMode = this->GetCurrentPlaybackMode(); bool isRealTimeMode = currentMode == RealTimeMode; bool isSequentialMode = currentMode == SequentialMode; - if( (isRealTimeMode && m_RealTimePlayer.IsNotNull()) || (isSequentialMode && m_SequentialPlayer.IsNotNull())) { int numberOfOutputs = 0; if(isRealTimeMode) numberOfOutputs = m_RealTimePlayer->GetNumberOfOutputs(); else if(isSequentialMode) numberOfOutputs = m_SequentialPlayer->GetNumberOfOutputs(); for(unsigned int i=0; i < m_RealTimePlayer->GetNumberOfOutputs(); ++i) { mitk::NavigationData::PositionType position; if(isRealTimeMode) position = m_RealTimePlayer->GetOutput(i)->GetPosition(); else if(isSequentialMode) position = m_SequentialPlayer->GetOutput(i)->GetPosition(); pointType[0] = position[0]; pointType[1] = position[1]; pointType[2] = position[2]; result->InsertPoint(i,pointType); // insert current ND as Pointtype in PointSet for return } } return result; } const mitk::PointSet::PointType QmitkIGTPlayerWidget::GetNavigationDataPoint(unsigned int index) { if( index > this->GetNumberOfTools() || index < 0 ) throw std::out_of_range("Tool Index out of range!"); PlaybackMode currentMode = this->GetCurrentPlaybackMode(); bool isRealTimeMode = currentMode == RealTimeMode; bool isSequentialMode = currentMode == SequentialMode; // create return PointType from current ND for tool index mitk::PointSet::PointType result; if( (isRealTimeMode && m_RealTimePlayer.IsNotNull()) || (isSequentialMode && m_SequentialPlayer.IsNotNull())) { mitk::NavigationData::PositionType position; - if(isRealTimeMode) - position = m_RealTimePlayer->GetOutput(index)->GetPosition(); - else if(isSequentialMode) - position = m_SequentialPlayer->GetOutput(index)->GetPosition(); + if(isRealTimeMode) + position = m_RealTimePlayer->GetOutput(index)->GetPosition(); + else if(isSequentialMode) + position = m_SequentialPlayer->GetOutput(index)->GetPosition(); result[0] = position[0]; result[1] = position[1]; result[2] = position[2]; } return result; } - -void QmitkIGTPlayerWidget::SetInputFileName(const QString& inputFileName) +/*void QmitkIGTPlayerWidget::SetRealTimePlayer( mitk::NavigationDataPlayer::Pointer player ) { - this->OnGoToEnd(); /// stops playing and resets lcd numbers - - QString oldName = m_CmpFilename; - m_CmpFilename.clear(); - - m_CmpFilename = inputFileName; - - QFile file(m_CmpFilename); - if(m_CmpFilename.isEmpty() || !file.exists()) - { - QMessageBox::warning(NULL, "Warning", QString("Please enter valid path! Using previous path again.")); - m_CmpFilename=oldName; - m_Controls->inputFileLineEdit->setText(m_CmpFilename); - } +if(player.IsNotNull()) +m_RealTimePlayer = player; } -void QmitkIGTPlayerWidget::SetRealTimePlayer( mitk::NavigationDataPlayer::Pointer player ) +void QmitkIGTPlayerWidget::SetSequentialPlayer( mitk::NavigationDataSequentialPlayer::Pointer player ) { - if(player.IsNotNull()) - m_RealTimePlayer = player; -} +if(player.IsNotNull()) +m_SequentialPlayer = player; +}*/ -void QmitkIGTPlayerWidget::SetSequentialPlayer( mitk::NavigationDataSequentialPlayer::Pointer player ) +void QmitkIGTPlayerWidget::OnOpenFileButtonPressed() { - if(player.IsNotNull()) - m_SequentialPlayer = player; -} + QString filename = QFileDialog::getOpenFileName(this, "Load tracking data", QDir::currentPath(),"XML files (*.xml)"); + QFile file(filename); + // if something went wrong or user pressed cancel in the save dialog + if ( filename.isEmpty() || ! file.exists() ) + { + QMessageBox::warning(NULL, "Warning", QString("Please enter valid path. Using previous path again.")); + return; + } + m_CmpFilename = filename; -void QmitkIGTPlayerWidget::OnSelectPressed() -{ + this->OnGoToEnd(); /// stops playing and resets lcd numbers - QString oldName = m_CmpFilename; - m_CmpFilename.clear(); - m_CmpFilename = QFileDialog::getOpenFileName(this, "Load tracking data", QDir::currentPath(),"XML files (*.xml)"); + m_Controls->m_ActiveFileLabel->setText(m_CmpFilename); - if (m_CmpFilename.isEmpty())//if something went wrong or user pressed cancel in the save dialog - m_CmpFilename=oldName; - else - { - this->OnGoToEnd(); /// stops playing and resets lcd numbers - emit SignalInputFileChanged(); - } + emit SignalInputFileChanged(); - m_Controls->inputFileLineEdit->setText(m_CmpFilename); -} + mitk::NavigationDataReaderInterface::Pointer navigationDataReader = mitk::NavigationDataReaderXML::New().GetPointer(); + mitk::NavigationDataSet::Pointer navigationDataSet = navigationDataReader->Read(m_CmpFilename.toStdString()); + m_RealTimePlayer->SetNavigationDataSet(navigationDataSet); + m_SequentialPlayer->SetNavigationDataSet(navigationDataSet); + m_Controls->m_PlayerControlsGroupBox->setEnabled(true); +} void QmitkIGTPlayerWidget::OnGoToEnd() { this->StopPlaying(); // reset lcd numbers this->ResetLCDNumbers(); - - } - void QmitkIGTPlayerWidget::OnGoToBegin() { // stop player manual so no PlayingStopped() m_PlayingTimer->stop(); if(this->GetCurrentPlaybackMode() == RealTimeMode && m_RealTimePlayer.IsNotNull()) { m_RealTimePlayer->StopPlaying(); m_RealTimePlayer = NULL; // set player to NULL so it can be initialized again if playback is called afterwards } m_StartTime = -1; // set starttime back //reset view elements m_Controls->playPushButton->setChecked(false); this->ResetLCDNumbers(); } void QmitkIGTPlayerWidget::ResetLCDNumbers() { - m_Controls->minLCDNumber->display(QString("00")); - m_Controls->secLCDNumber->display(QString("00")); - m_Controls->msecLCDNumber->display(QString("000")); + m_Controls->minLCDNumber->display(QString("00")); + m_Controls->secLCDNumber->display(QString("00")); + m_Controls->msecLCDNumber->display(QString("000")); } - - void QmitkIGTPlayerWidget::SetTrajectoryNames(const QStringList toolNames) { QComboBox* cBox = m_Controls->trajectorySelectComboBox; if(cBox->count() > 0) this->ClearTrajectorySelectCombobox(); // before making changed to QComboBox it is recommended to disconnet it's SIGNALS and SLOTS disconnect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) ); if(!toolNames.isEmpty()) m_Controls->trajectorySelectComboBox->insertItems(0, toolNames); // adding current tool names to combobox // reconnect after performed changes connect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) ); } - int QmitkIGTPlayerWidget::GetResolution() { - return m_Controls->resolutionSpinBox->value(); // return currently selected trajectory resolution + return m_Controls->resolutionSpinBox->value(); // return currently selected trajectory resolution } void QmitkIGTPlayerWidget::ClearTrajectorySelectCombobox() { // before making changed to QComboBox it is recommended to disconnet it's SIGNALS and SLOTS disconnect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) ); m_Controls->trajectorySelectComboBox->clear(); // reconnect after performed changes connect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) ); } - - void QmitkIGTPlayerWidget::OnSequencialModeToggled(bool toggled) { - this->StopPlaying(); // stop playing when mode is changed - - if(toggled) - { - m_Controls->samplePositionHorizontalSlider->setEnabled(true); // enable slider if sequential mode - } - else if(!toggled) - { - m_Controls->samplePositionHorizontalSlider->setSliderPosition(0); // set back and disable slider - m_Controls->samplePositionHorizontalSlider->setDisabled(true); - } - + this->StopPlaying(); // stop playing when mode is changed + if(toggled) + { + m_Controls->samplePositionHorizontalSlider->setEnabled(true); // enable slider if sequential mode + } + else if(!toggled) + { + m_Controls->samplePositionHorizontalSlider->setSliderPosition(0); // set back and disable slider + m_Controls->samplePositionHorizontalSlider->setDisabled(true); + } } void QmitkIGTPlayerWidget::OnSliderReleased() { int currentSliderValue = m_Controls->samplePositionHorizontalSlider->value(); // current slider value selected through user movement if(currentSliderValue > m_CurrentSequentialPointNumber) // at the moment only forward scrolling is possible { unsigned int snapshotNumber = currentSliderValue; m_SequentialPlayer->GoToSnapshot(snapshotNumber); // move player to selected snapshot m_CurrentSequentialPointNumber = currentSliderValue; m_Controls->sampleLCDNumber->display(currentSliderValue); // update lcdnumber in widget } else m_Controls->samplePositionHorizontalSlider->setValue(m_CurrentSequentialPointNumber); } void QmitkIGTPlayerWidget::OnSliderPressed() { if(m_Controls->playPushButton->isChecked()) // check if widget is playing m_Controls->playPushButton->click(); // perform click to pause the play } \ No newline at end of file diff --git a/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.h b/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.h index dbef727ab9..0af371b00e 100644 --- a/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.h +++ b/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.h @@ -1,259 +1,252 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkIGTPlayerWidget_H #define QmitkIGTPlayerWidget_H //QT headers #include //mitk headers #include "MitkIGTUIExports.h" #include #include #include #include //ui header #include "ui_QmitkIGTPlayerWidgetControls.h" /** Documentation: * \brief GUI to access the IGT Player. * User must specify the file name where the input xml-file is located. The NavigationDatas from the xml-file can be * played in normal mode or in PointSet mode. * * In normal mode the player updates the NavigationDatas every 100ms (can be changed in SetUpdateRate()) and returns * them when GetNavigationDatas() is called. * In PointSet mode the player generates a PointSet with all NavigationDatas from the xml-file. So the playback is * performed on this ND PointSet. * * \ingroup IGTUI */ class MitkIGTUI_EXPORT QmitkIGTPlayerWidget : public QWidget { Q_OBJECT public: static const std::string VIEW_ID; /*! \brief default constructor */ QmitkIGTPlayerWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); /*! \brief default deconstructor */ ~QmitkIGTPlayerWidget(); /*! \brief Sets the real time player for this player widget */ - void SetRealTimePlayer(mitk::NavigationDataPlayer::Pointer player); + //void SetRealTimePlayer(mitk::NavigationDataPlayer::Pointer player); /*! \brief Sets the sequential player for this player widget */ - void SetSequentialPlayer(mitk::NavigationDataSequentialPlayer::Pointer player); + //void SetSequentialPlayer(mitk::NavigationDataSequentialPlayer::Pointer player); /*! \brief Returns the playing timer of this widget */ QTimer* GetPlayingTimer(); /*! \brief Returns the current playback NavigationDatas from the xml-file */ const std::vector GetNavigationDatas(); /*! \brief Returns a PointSet of the current NavigationDatas for all recorded tools. */ const mitk::PointSet::Pointer GetNavigationDatasPointSet(); /*! \brief Returns a PointType of the current NavigationData for a specific tool with the given index. */ const mitk::PointSet::PointType GetNavigationDataPoint(unsigned int index); /*! \brief Sets the update rate of this widget's playing timer */ void SetUpdateRate(unsigned int msecs); /*! \brief Returns the number of different tools from the current playing stream. * * Retuns 0 if playback file is invalid. */ unsigned int GetNumberOfTools(); /*! \brief Stops the playback */ void StopPlaying(); /*! \brief Sets the given tool names list to the trajectory select combobox. */ void SetTrajectoryNames(const QStringList toolNames); /*! \brief Returns the current resolution value from the resolution spinbox. */ int GetResolution(); /*! \brief Clears all items in the trajectory selection combobox. */ void ClearTrajectorySelectCombobox(); /*! \brief Returns whether spline mode checkbox is selected. */ bool IsTrajectoryInSplineMode(); enum PlaybackMode { ///< playback mode enum RealTimeMode = 1, SequentialMode = 2 }; PlaybackMode GetCurrentPlaybackMode(); signals: /*! \brief This signal is emitted when the player starts the playback. */ void SignalPlayingStarted(); /*! \brief This signal is emitted when the player resumes after a pause. */ void SignalPlayingResumed(); /*! \brief This signal is emitted when the player stops. */ void SignalPlayingStopped(); /*! \brief This signal is emitted when the player is paused. */ void SignalPlayingPaused(); /*! \brief This signal is emitted when the player reaches the end of the playback. */ void SignalPlayingEnded(); /*! \brief This signal is emitted every time the player updated the NavigationDatas. */ void SignalPlayerUpdated(); /*! \brief This signal is emitted if the input file for the replay was changed. */ void SignalInputFileChanged(); /*! \brief This signal is emitted if the index of the current selected trajectory select combobox item changes. */ void SignalCurrentTrajectoryChanged(int index); /*! \brief This signal is emitted if the spline mode checkbox is toggled or untoggled. */ void SignalSplineModeToggled(bool toggled); protected slots: /*! \brief Starts or pauses the playback */ void OnPlayButtonClicked(bool toggled); /*! \brief Updates the playback data */ void OnPlaying(); /*! \brief Stops the playback */ void OnStopPlaying(); /*! - \brief Updates the input filename - */ - void SetInputFileName(const QString& inputFileName); - /*! \brief Opens file open dialog for searching the input file */ - void OnSelectPressed(); + void OnOpenFileButtonPressed(); /*! \brief Stops the playback */ void OnGoToEnd(); /*! \brief Stops the playback and resets the player to the beginning */ void OnGoToBegin(); /*! \brief Switches widget between realtime and sequential mode */ void OnSequencialModeToggled(bool toggled); /*! \brief Pauses playback when slider is pressed by user */ void OnSliderPressed(); /*! \brief Moves player position to the position selected with the slider */ void OnSliderReleased(); protected: /// \brief Creation of the connections virtual void CreateConnections(); - /// \brief Creation of the Qt control - virtual void CreateQtPartControl(QWidget *parent); - /*! \brief Checks if an imput file with the set filename exists */ bool CheckInputFileValid(); /*! \brief Sets all LCD numbers to 0 */ void ResetLCDNumbers(); Ui::QmitkIGTPlayerWidgetControls* m_Controls; mitk::NavigationDataPlayer::Pointer m_RealTimePlayer; ///< plays NDs from a XML file mitk::NavigationDataSequentialPlayer::Pointer m_SequentialPlayer; QString m_CmpFilename; ///< filename of the input file QTimer* m_PlayingTimer; ///< update timer mitk::NavigationData::TimeStampType m_StartTime; ///< start time of playback needed for time display unsigned int m_CurrentSequentialPointNumber; ///< current point number }; #endif diff --git a/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidgetControls.ui b/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidgetControls.ui index 2a4a998dec..f7c9180bd1 100644 --- a/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidgetControls.ui +++ b/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidgetControls.ui @@ -1,427 +1,476 @@ QmitkIGTPlayerWidgetControls 0 0 - 416 + 424 689 + + + 0 + 0 + + Form - + - Settings + File Management - - true - - - false - - + + + + + Open Navigation Data File + + + - - - + + + - + 0 0 - - Input File - - - - - - - - 2 - 0 - - - - - 150 - 0 - - - - true - - - - - - - - 0 - 0 - + + + 8 + 75 + true + - Trajectory - - - - - - - - 4 - 0 - - - - - - - - - 0 - 0 - - - - 1 - - - 25 + Active File: - - - - - 0 - 0 - + + + + + 8 + - Res.: 1: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + No navigation data file loaded. - - + + + + + + + + + Tool Colors + + + + + + - + 0 0 - - Qt::LeftToRight - - Splines + 1) - - + + + + + + + + + - + 0 0 - - - 90 - 16777215 - - - - - 50 - false - - - Select - - - false + 2) + + + - + + + true + + + + 0 + 0 + + - Player + Settings - - true + + + QFormLayout::AllNonFixedFieldsGrow + + + + + Player Type + + + + + + + + Time Based Player + + + + + Sequential Player + + + + + + + + + 0 + 0 + + + + Trajectory + + + + + + + + 4 + 0 + + + + + + + + + 0 + 0 + + + + Qt::LeftToRight + + + Splines + + + + + + + + 0 + 0 + + + + Res.: 1: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + 1 + + + 25 + + + + + + + + + + false - + + Player Controls + + background-color: rgb(60, 60, 60); color: rgb(250, 250, 250); QFrame::Raised 3 QLCDNumber::Flat 0 min background-color: rgb(60, 60, 60); color: rgb(250, 250, 250); 2 QLCDNumber::Flat 0 sec background-color: rgb(60, 60, 60); color: rgb(250, 250, 250); 3 QLCDNumber::Flat 0 msec Qt::Horizontal 40 20 Sample 0 0 false background-color: rgb(60,60,60) 10 QLCDNumber::Outline - - - - - false - - - Qt::Horizontal - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::LeftToRight - - - Sequential Mode - - - - + + + false + + + Qt::Horizontal + + - + 1 0 + + Restart from beginning + - + Restart :/IGTUI/firstframe.png:/IGTUI/firstframe.png - 4 + 1 0 Play at normal speed - + Play :/IGTUI/play.png :/IGTUI/pause.png:/IGTUI/play.png 16 16 true false 1 0 + + Stop playing + - + Stop :/IGTUI/stop.png:/IGTUI/stop.png Qt::Vertical 20 40 diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationDataPlayerControlWidget.cpp b/Modules/IGTUI/Qmitk/QmitkNavigationDataPlayerControlWidget.cpp new file mode 100644 index 0000000000..24cd111439 --- /dev/null +++ b/Modules/IGTUI/Qmitk/QmitkNavigationDataPlayerControlWidget.cpp @@ -0,0 +1,122 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "QmitkNavigationDataPlayerControlWidget.h" +#include "ui_QmitkNavigationDataPlayerControlWidget.h" + +#include + +QmitkNavigationDataPlayerControlWidget::QmitkNavigationDataPlayerControlWidget(QWidget *parent) : + QWidget(parent), + m_UpdateTimer(new QTimer(this)), + ui(new Ui::QmitkNavigationDataPlayerControlWidget) +{ + ui->setupUi(this); + + connect(m_UpdateTimer, SIGNAL(timeout()), this, SLOT(OnUpdate())); +} + +QmitkNavigationDataPlayerControlWidget::~QmitkNavigationDataPlayerControlWidget() +{ + delete ui; +} + +void QmitkNavigationDataPlayerControlWidget::SetPlayer(mitk::NavigationDataPlayer::Pointer player) +{ + m_Player = player; + + ui->samplePositionHorizontalSlider->setMaximum(player->GetNumberOfSnapshots()-1); +} + +void QmitkNavigationDataPlayerControlWidget::OnStop() +{ + m_UpdateTimer->stop(); + m_Player->StopPlaying(); + + ui->playPushButton->setChecked(false); + + this->ResetPlayerDisplay(); +} + +void QmitkNavigationDataPlayerControlWidget::OnPlayPause() +{ + switch ( m_Player->GetCurrentPlayerState() ) + { + case mitk::NavigationDataPlayer::PlayerStopped: + { + m_Player->StartPlaying(); + if ( ! m_UpdateTimer->isActive() ) { m_UpdateTimer->start(10); } + if ( ! ui->playPushButton->isChecked() ) { ui->playPushButton->setChecked(true); } + break; + } + case mitk::NavigationDataPlayer::PlayerPaused: + { + m_Player->Resume(); + break; + } + case mitk::NavigationDataPlayer::PlayerRunning: + { + m_Player->Pause(); + break; + } + } +} + +void QmitkNavigationDataPlayerControlWidget::OnRestart() +{ + this->OnStop(); + this->OnPlayPause(); +} + +void QmitkNavigationDataPlayerControlWidget::OnUpdate() +{ + m_Player->Update(); + + int msc = static_cast(m_Player->GetTimeStampSinceStart()); + + // calculation for playing time display + int ms = msc % 1000; + msc = (msc - ms) / 1000; + int s = msc % 60; + int min = (msc-s) / 60; + + // set lcd numbers + ui->msecLCDNumber->display(ms); + ui->secLCDNumber->display(s); + ui->minLCDNumber->display(min); + + ui->samplePositionHorizontalSlider->setValue(static_cast(m_Player->GetCurrentSnapshotNumber())); + + emit SignalUpdate(); + + if ( m_Player->GetCurrentPlayerState() == mitk::NavigationDataPlayer::PlayerStopped ) + { + m_UpdateTimer->stop(); + ui->playPushButton->setChecked(false); + + emit SignalEndReached(); + } +} + +void QmitkNavigationDataPlayerControlWidget::ResetPlayerDisplay() +{ + // set lcd numbers + ui->msecLCDNumber->display(0); + ui->secLCDNumber->display(0); + ui->minLCDNumber->display(0); + + ui->samplePositionHorizontalSlider->setValue(0); +} diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationDataPlayerControlWidget.h b/Modules/IGTUI/Qmitk/QmitkNavigationDataPlayerControlWidget.h new file mode 100644 index 0000000000..138e4a424f --- /dev/null +++ b/Modules/IGTUI/Qmitk/QmitkNavigationDataPlayerControlWidget.h @@ -0,0 +1,62 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QMITKNAVIGATIONDATAPLAYERCONTROLWIDGET_H +#define QMITKNAVIGATIONDATAPLAYERCONTROLWIDGET_H + +#include +#include "mitkNavigationDataPlayer.h" +#include "MitkIGTUIExports.h" + +class QTimer; + +namespace Ui { + class QmitkNavigationDataPlayerControlWidget; +} + +class MitkIGTUI_EXPORT QmitkNavigationDataPlayerControlWidget : public QWidget +{ + Q_OBJECT + +signals: + void SignalUpdate(); + void SignalEndReached(); + +public slots: + void OnStop(); + void OnPlayPause(); + void OnRestart(); + +protected slots: + void OnUpdate(); + +public: + explicit QmitkNavigationDataPlayerControlWidget(QWidget *parent = 0); + ~QmitkNavigationDataPlayerControlWidget(); + + void SetPlayer(mitk::NavigationDataPlayer::Pointer player); + +private: + void ResetPlayerDisplay(); + + mitk::NavigationDataPlayer::Pointer m_Player; + + QTimer* m_UpdateTimer; + + Ui::QmitkNavigationDataPlayerControlWidget *ui; +}; + +#endif // QMITKNAVIGATIONDATAPLAYERCONTROLWIDGET_H diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationDataPlayerControlWidget.ui b/Modules/IGTUI/Qmitk/QmitkNavigationDataPlayerControlWidget.ui new file mode 100644 index 0000000000..4fe63079b5 --- /dev/null +++ b/Modules/IGTUI/Qmitk/QmitkNavigationDataPlayerControlWidget.ui @@ -0,0 +1,267 @@ + + + QmitkNavigationDataPlayerControlWidget + + + + 0 + 0 + 364 + 95 + + + + Form + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + sec + + + + + + + msec + + + + + + + background-color: rgb(60, 60, 60); +color: rgb(250, 250, 250); + + + 2 + + + QLCDNumber::Flat + + + 0 + + + + + + + min + + + + + + + background-color: rgb(60, 60, 60); +color: rgb(250, 250, 250); + + + QFrame::Raised + + + 3 + + + QLCDNumber::Flat + + + 0 + + + + + + + background-color: rgb(60, 60, 60); +color: rgb(250, 250, 250); + + + 3 + + + QLCDNumber::Flat + + + 0 + + + + + + + + + false + + + Qt::Horizontal + + + + + + + + + + 1 + 0 + + + + Restart from beginning + + + Restart + + + + :/IGTUI/firstframe.png:/IGTUI/firstframe.png + + + + + + + + 1 + 0 + + + + Play at normal speed + + + Play + + + + :/IGTUI/play.png + :/IGTUI/pause.png:/IGTUI/play.png + + + + 16 + 16 + + + + true + + + false + + + + + + + + 1 + 0 + + + + Stop playing + + + Stop + + + + :/IGTUI/stop.png:/IGTUI/stop.png + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + playPushButton + clicked() + QmitkNavigationDataPlayerControlWidget + OnPlayPause() + + + 181 + 73 + + + 181 + 47 + + + + + restartPushButton + clicked() + QmitkNavigationDataPlayerControlWidget + OnRestart() + + + 62 + 73 + + + 181 + 47 + + + + + stopPushButton + clicked() + QmitkNavigationDataPlayerControlWidget + OnStop() + + + 301 + 73 + + + 181 + 47 + + + + + + OnStop() + OnRestart() + OnPlayPause() + + diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.cpp b/Modules/IGTUI/Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.cpp new file mode 100644 index 0000000000..6e34475370 --- /dev/null +++ b/Modules/IGTUI/Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.cpp @@ -0,0 +1,105 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "QmitkNavigationDataSequentialPlayerControlWidget.h" +#include "ui_QmitkNavigationDataSequentialPlayerControlWidget.h" + +#include + +QmitkNavigationDataSequentialPlayerControlWidget::QmitkNavigationDataSequentialPlayerControlWidget(QWidget *parent) : + QWidget(parent), + ui(new Ui::QmitkNavigationDataSequentialPlayerControlWidget) +{ + ui->setupUi(this); + m_UpdateTimer = new QTimer(); + connect( m_UpdateTimer, SIGNAL(timeout()), this, SLOT(OnUpdate()) ); +} + +QmitkNavigationDataSequentialPlayerControlWidget::~QmitkNavigationDataSequentialPlayerControlWidget() +{ + delete ui; +} + +void QmitkNavigationDataSequentialPlayerControlWidget::SetPlayer(mitk::NavigationDataSequentialPlayer::Pointer player) +{ + m_Player = player; + + ui->samplePositionHorizontalSlider->setMaximum(player->GetNumberOfSnapshots()); +} + +void QmitkNavigationDataSequentialPlayerControlWidget::OnStop() +{ + m_UpdateTimer->stop(); + m_Player->GoToSnapshot(0); + + this->UpdatePlayerDisplay(); + + // make sure that the play/pause button is not checked after stopping + ui->playPushButton->setChecked(false); +} + +void QmitkNavigationDataSequentialPlayerControlWidget::OnPlayPause() +{ + if ( m_UpdateTimer->isActive() ) + { + m_UpdateTimer->stop(); + } + else + { + if ( m_Player->IsAtEnd() ) { m_Player->GoToSnapshot(0); } + + m_UpdateTimer->start(ui->updateIntervalSpinBox->value()); + if ( ! ui->playPushButton->isChecked() ) { ui->playPushButton->setChecked(true); } + } +} + +void QmitkNavigationDataSequentialPlayerControlWidget::OnRestart() +{ + this->OnStop(); + this->OnPlayPause(); +} + +void QmitkNavigationDataSequentialPlayerControlWidget::OnUpdate() +{ + // if the last snapshot was reached + if ( ! m_Player->GoToNextSnapshot() ) + { + m_UpdateTimer->stop(); + ui->playPushButton->setChecked(false); + + emit SignalEndReached(); + } + + m_Player->Update(); + + this->UpdatePlayerDisplay(); + + emit SignalUpdate(); +} + +void QmitkNavigationDataSequentialPlayerControlWidget::OnUpdateIntervalChanged(int value) +{ + m_UpdateTimer->setInterval(value); +} + +void QmitkNavigationDataSequentialPlayerControlWidget::UpdatePlayerDisplay() +{ + int currentSnapshotNumber = static_cast(m_Player->GetCurrentSnapshotNumber()); + + ui->sampleLCDNumber->display(currentSnapshotNumber); + + ui->samplePositionHorizontalSlider->setValue(currentSnapshotNumber); +} diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.h b/Modules/IGTUI/Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.h new file mode 100644 index 0000000000..1252f468af --- /dev/null +++ b/Modules/IGTUI/Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.h @@ -0,0 +1,64 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QMITKNAVIGATIONDATASEQUENTIALPLAYERCONTROLWIDGET_H +#define QMITKNAVIGATIONDATASEQUENTIALPLAYERCONTROLWIDGET_H + +#include +#include "mitkNavigationDataSequentialPlayer.h" +#include "MitkIGTUIExports.h" + +class QTimer; + +namespace Ui { + class QmitkNavigationDataSequentialPlayerControlWidget; +} + +class MitkIGTUI_EXPORT QmitkNavigationDataSequentialPlayerControlWidget : public QWidget +{ + Q_OBJECT + +signals: + void SignalUpdate(); + void SignalEndReached(); + +public slots: + void OnStop(); + void OnPlayPause(); + void OnRestart(); + +protected slots: + void OnUpdate(); + void OnUpdateIntervalChanged(int); + +public: + explicit QmitkNavigationDataSequentialPlayerControlWidget(QWidget *parent = 0); + ~QmitkNavigationDataSequentialPlayerControlWidget(); + + void SetPlayer(mitk::NavigationDataSequentialPlayer::Pointer player); + +protected: + void UpdatePlayerDisplay(); + +private: + mitk::NavigationDataSequentialPlayer::Pointer m_Player; + + QTimer* m_UpdateTimer; + + Ui::QmitkNavigationDataSequentialPlayerControlWidget *ui; +}; + +#endif // QMITKNAVIGATIONDATASEQUENTIALPLAYERCONTROLWIDGET_H diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.ui b/Modules/IGTUI/Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.ui new file mode 100644 index 0000000000..5b8a04d4bb --- /dev/null +++ b/Modules/IGTUI/Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.ui @@ -0,0 +1,266 @@ + + + QmitkNavigationDataSequentialPlayerControlWidget + + + + 0 + 0 + 407 + 106 + + + + Form + + + + + + + + Sample + + + + + + + + 0 + 0 + + + + false + + + background-color: rgb(60,60,60) + + + 10 + + + QLCDNumber::Outline + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Update Inverval + + + + + + + ms + + + 1 + + + 10000 + + + 20 + + + 40 + + + + + + + + + false + + + Qt::Horizontal + + + + + + + + + + 1 + 0 + + + + Restart from beginning + + + Restart + + + + :/IGTUI/firstframe.png:/IGTUI/firstframe.png + + + + + + + + 1 + 0 + + + + Play at normal speed + + + Play + + + + :/IGTUI/play.png + :/IGTUI/pause.png:/IGTUI/play.png + + + + 16 + 16 + + + + true + + + false + + + + + + + + 1 + 0 + + + + Stop playing + + + Stop + + + + :/IGTUI/stop.png:/IGTUI/stop.png + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + updateIntervalSpinBox + valueChanged(int) + QmitkNavigationDataSequentialPlayerControlWidget + OnUpdateIntervalChanged(int) + + + 349 + 16 + + + 203 + 47 + + + + + restartPushButton + clicked() + QmitkNavigationDataSequentialPlayerControlWidget + OnRestart() + + + 69 + 73 + + + 203 + 47 + + + + + playPushButton + clicked() + QmitkNavigationDataSequentialPlayerControlWidget + OnPlayPause() + + + 203 + 73 + + + 203 + 47 + + + + + stopPushButton + clicked() + QmitkNavigationDataSequentialPlayerControlWidget + OnStop() + + + 336 + 73 + + + 203 + 47 + + + + + + OnUpdateIntervalChanged(int) + OnRestart() + OnPlayPause() + OnStop() + + diff --git a/Modules/IGTUI/files.cmake b/Modules/IGTUI/files.cmake index 6adfd68e09..49de91f954 100644 --- a/Modules/IGTUI/files.cmake +++ b/Modules/IGTUI/files.cmake @@ -1,69 +1,78 @@ set(CPP_FILES Qmitk/QmitkTrackingDeviceWidget.cpp Qmitk/QmitkTrackingDeviceConfigurationWidget.cpp Qmitk/QmitkNDIConfigurationWidget.cpp Qmitk/QmitkFiducialRegistrationWidget.cpp Qmitk/QmitkNDIToolDelegate.cpp Qmitk/QmitkNavigationToolManagementWidget.cpp Qmitk/QmitkIGTLoggerWidget.cpp Qmitk/QmitkUpdateTimerWidget.cpp Qmitk/QmitkToolDistanceWidget.cpp Qmitk/QmitkToolTrackingStatusWidget.cpp Qmitk/QmitkTrackingSourcesCheckBoxPanelWidget.cpp Qmitk/QmitkIGTPlayerWidget.cpp Qmitk/QmitkIGTConnectionWidget.cpp Qmitk/QmitkToolSelectionWidget.cpp Qmitk/QmitkNavigationToolCreationWidget.cpp Qmitk/QmitkNavigationToolCreationAdvancedWidget.cpp Qmitk/QmitkNavigationDataSourceSelectionWidget.cpp Qmitk/QmitkInteractiveTransformationWidget.cpp Qmitk/QmitkNavigationToolStorageSelectionWidget.cpp + + Qmitk/QmitkNavigationDataPlayerControlWidget.cpp + Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.cpp ) set(UI_FILES Qmitk/QmitkNavigationToolManagementWidgetControls.ui Qmitk/QmitkTrackingDeviceConfigurationWidgetControls.ui Qmitk/QmitkNDIConfigurationWidget.ui Qmitk/QmitkFiducialRegistrationWidget.ui Qmitk/QmitkIGTLoggerWidgetControls.ui Qmitk/QmitkUpdateTimerWidgetControls.ui Qmitk/QmitkToolDistanceWidgetControls.ui Qmitk/QmitkToolTrackingStatusWidgetControls.ui Qmitk/QmitkTrackingSourcesCheckBoxPanelWidgetControls.ui Qmitk/QmitkIGTPlayerWidgetControls.ui Qmitk/QmitkIGTConnectionWidgetControls.ui Qmitk/QmitkToolSelectionWidgetControls.ui Qmitk/QmitkNavigationToolCreationWidget.ui Qmitk/QmitkNavigationToolCreationAdvancedWidgetControls.ui Qmitk/QmitkNavigationDataSourceSelectionWidgetControls.ui Qmitk/QmitkInteractiveTransformationWidgetControls.ui Qmitk/QmitkNavigationToolStorageSelectionWidgetControls.ui + + Qmitk/QmitkNavigationDataPlayerControlWidget.ui + Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.ui ) set(MOC_H_FILES Qmitk/QmitkNavigationToolManagementWidget.h Qmitk/QmitkTrackingDeviceWidget.h Qmitk/QmitkTrackingDeviceConfigurationWidget.h Qmitk/QmitkNDIConfigurationWidget.h Qmitk/QmitkFiducialRegistrationWidget.h Qmitk/QmitkNDIToolDelegate.h Qmitk/QmitkIGTLoggerWidget.h Qmitk/QmitkUpdateTimerWidget.h Qmitk/QmitkToolDistanceWidget.h Qmitk/QmitkToolTrackingStatusWidget.h Qmitk/QmitkTrackingSourcesCheckBoxPanelWidget.h Qmitk/QmitkIGTPlayerWidget.h Qmitk/QmitkIGTConnectionWidget.h Qmitk/QmitkToolSelectionWidget.h Qmitk/QmitkNavigationToolCreationWidget.h Qmitk/QmitkNavigationToolCreationAdvancedWidget.h Qmitk/QmitkNavigationDataSourceSelectionWidget.h Qmitk/QmitkInteractiveTransformationWidget.h Qmitk/QmitkNavigationToolStorageSelectionWidget.h + + Qmitk/QmitkNavigationDataPlayerControlWidget.h + Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.h ) set(QRC_FILES resources/IGTUI.qrc ) diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp index 77f4d25a8b..4064fa8c07 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp @@ -1,1114 +1,1079 @@ /*=================================================================== 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 // 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 ) + : QmitkFunctionality() + , m_Controls( 0 ) + , m_MultiWidget( NULL ) { m_TrackingTimer = new QTimer(this); m_tracking = false; m_logging = false; m_loggedFrames = 0; //initialize worker thread m_WorkerThread = new QThread(); m_Worker = new QmitkMITKIGTTrackingToolboxViewWorker(); } QmitkMITKIGTTrackingToolboxView::~QmitkMITKIGTTrackingToolboxView() { -try + try { - //clean up worker thread - if(m_WorkerThread) {delete m_WorkerThread;} - if(m_Worker) {delete m_Worker;} - //remove the tracking volume - this->GetDataStorage()->Remove(m_TrackingVolumeNode); - //remove the tool storage - if(m_toolStorage) {m_toolStorage->UnRegisterMicroservice();} - if(m_TrackingDeviceSource) {m_TrackingDeviceSource->UnRegisterMicroservice();} + //clean up worker thread + if(m_WorkerThread) {delete m_WorkerThread;} + if(m_Worker) {delete m_Worker;} + //remove the tracking volume + this->GetDataStorage()->Remove(m_TrackingVolumeNode); + //remove the tool storage + if(m_toolStorage) {m_toolStorage->UnRegisterMicroservice();} + if(m_TrackingDeviceSource) {m_TrackingDeviceSource->UnRegisterMicroservice();} } -catch(std::exception& e) {MITK_WARN << "Unexpected exception during clean up of tracking toolbox view: " << e.what();} -catch(...) {MITK_WARN << "Unexpected unknown error during clean up of tracking toolbox view!";} + catch(std::exception& e) {MITK_WARN << "Unexpected exception during clean up of tracking toolbox view: " << e.what();} + catch(...) {MITK_WARN << "Unexpected unknown error during clean up of tracking toolbox view!";} } - 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_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())); connect( m_Controls->m_csvFormat, SIGNAL(clicked()), this, SLOT(OnToggleFileExtension())); connect( m_Controls->m_xmlFormat, SIGNAL(clicked()), this, SLOT(OnToggleFileExtension())); //connections for the tracking device configuration widget connect( m_Controls->m_configurationWidget, SIGNAL(TrackingDeviceSelectionChanged()), this, SLOT(OnTrackingDeviceChanged())); connect( m_Controls->m_configurationWidget, SIGNAL(ProgressStarted()), this, SLOT(DisableOptionsButtons())); connect( m_Controls->m_configurationWidget, SIGNAL(ProgressStarted()), this, SLOT(DisableTrackingConfigurationButtons())); connect( m_Controls->m_configurationWidget, SIGNAL(ProgressStarted()), this, SLOT(DisableTrackingControls())); connect( m_Controls->m_configurationWidget, SIGNAL(ProgressFinished()), this, SLOT(EnableOptionsButtons())); connect( m_Controls->m_configurationWidget, SIGNAL(ProgressFinished()), this, SLOT(EnableTrackingConfigurationButtons())); connect( m_Controls->m_configurationWidget, SIGNAL(ProgressFinished()), this, SLOT(EnableTrackingControls())); //connect worker thread connect(m_Worker, SIGNAL(AutoDetectToolsFinished(bool,QString)), this, SLOT(OnAutoDetectToolsFinished(bool,QString)) ); connect(m_Worker, SIGNAL(ConnectDeviceFinished(bool,QString)), this, SLOT(OnConnectFinished(bool,QString)) ); connect(m_Worker, SIGNAL(StartTrackingFinished(bool,QString)), this, SLOT(OnStartTrackingFinished(bool,QString)) ); connect(m_Worker, SIGNAL(StopTrackingFinished(bool,QString)), this, SLOT(OnStopTrackingFinished(bool,QString)) ); connect(m_Worker, SIGNAL(DisconnectDeviceFinished(bool,QString)), this, SLOT(OnDisconnectFinished(bool,QString)) ); connect(m_WorkerThread,SIGNAL(started()), m_Worker, SLOT(ThreadFunc()) ); //move the worker to the thread m_Worker->moveToThread(m_WorkerThread); //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; if ( (m_Controls == NULL) || //check all these stuff for NULL, latterly this causes crashes from time to time - (m_Controls->m_configurationWidget == NULL) || - (m_Controls->m_configurationWidget->GetTrackingDevice().IsNull())) - { + (m_Controls->m_configurationWidget == NULL) || + (m_Controls->m_configurationWidget->GetTrackingDevice().IsNull())) + { MITK_ERROR << "Couldn't get current tracking device or an object is NULL, something went wrong!"; return; - } + } else - { + { 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"); //set home directory as default path for logfile m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(QDir::homePath()) + QDir::separator() + "logfile.csv"); } } - 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; + 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() - { +{ MITK_INFO << "Connect Clicked"; //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; } //parse tracking device 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 } //initialize worker thread m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eConnectDevice); m_Worker->SetTrackingDevice(this->m_Controls->m_configurationWidget->GetTrackingDevice()); m_Worker->SetInverseMode(m_Controls->m_InverseMode->isChecked()); m_Worker->SetNavigationToolStorage(this->m_toolStorage); m_Worker->SetTrackingDeviceData(data); //start worker thread m_WorkerThread->start(); //disable buttons this->m_Controls->m_MainWidget->setEnabled(false); - } +} void QmitkMITKIGTTrackingToolboxView::OnConnectFinished(bool success, QString errorMessage) - { +{ m_WorkerThread->quit(); //enable buttons this->m_Controls->m_MainWidget->setEnabled(true); if (!success) - { + { MITK_WARN << errorMessage.toStdString(); MessageBox(errorMessage.toStdString()); return; - } + } //get data from worker thread m_TrackingDeviceSource = m_Worker->GetTrackingDeviceSource(); m_TrackingDeviceData = m_Worker->GetTrackingDeviceData(); m_ToolVisualizationFilter = m_Worker->GetToolVisualizationFilter(); //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() - { +{ m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eDisconnectDevice); m_WorkerThread->start(); m_Controls->m_MainWidget->setEnabled(false); - } +} void QmitkMITKIGTTrackingToolboxView::OnDisconnectFinished(bool success, QString errorMessage) - { +{ m_WorkerThread->quit(); m_Controls->m_MainWidget->setEnabled(true); if (!success) - { + { MITK_WARN << errorMessage.toStdString(); MessageBox(errorMessage.toStdString()); return; - } + } //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() { m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eStartTracking); m_WorkerThread->start(); this->m_Controls->m_MainWidget->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::OnStartTrackingFinished(bool success, QString errorMessage) { m_WorkerThread->quit(); this->m_Controls->m_MainWidget->setEnabled(true); if(!success) { MessageBox(errorMessage.toStdString()); MITK_WARN << errorMessage.toStdString(); 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_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eStopTracking); m_WorkerThread->start(); m_Controls->m_MainWidget->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::OnStopTrackingFinished(bool success, QString errorMessage) - { +{ m_WorkerThread->quit(); m_Controls->m_MainWidget->setEnabled(true); if(!success) - { - MessageBox(errorMessage.toStdString()); - MITK_WARN << errorMessage.toStdString(); - return; - } + { + MessageBox(errorMessage.toStdString()); + MITK_WARN << errorMessage.toStdString(); + return; + } 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; if (m_Controls->m_configurationWidget->GetTrackingDevice().IsNotNull()) - { - Type = m_Controls->m_configurationWidget->GetTrackingDevice()->GetType(); - //enable controls because device is valid - m_Controls->m_TrackingToolsGoupBox->setEnabled(true); - m_Controls->m_TrackingControlsGroupBox->setEnabled(true); - } + { + Type = m_Controls->m_configurationWidget->GetTrackingDevice()->GetType(); + //enable controls because device is valid + m_Controls->m_TrackingToolsGoupBox->setEnabled(true); + m_Controls->m_TrackingControlsGroupBox->setEnabled(true); + } else - { - Type = mitk::TrackingSystemNotSpecified; - MessageBox("Error: This tracking device is not included in this project. Please make sure that the device is installed and activated in your MITK build."); - m_Controls->m_TrackingToolsGoupBox->setEnabled(false); - m_Controls->m_TrackingControlsGroupBox->setEnabled(false); - return; - } - - + { + Type = mitk::TrackingSystemNotSpecified; + MessageBox("Error: This tracking device is not included in this project. Please make sure that the device is installed and activated in your MITK build."); + m_Controls->m_TrackingToolsGoupBox->setEnabled(false); + m_Controls->m_TrackingControlsGroupBox->setEnabled(false); + return; + } // 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); m_TrackingDeviceData = data; 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) - { + if (m_Controls->m_configurationWidget->GetTrackingDevice()->GetType() == mitk::NDIAurora) + { DisableTrackingConfigurationButtons(); m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eAutoDetectTools); m_Worker->SetTrackingDevice(m_Controls->m_configurationWidget->GetTrackingDevice().GetPointer()); m_Worker->SetDataStorage(this->GetDataStorage()); m_WorkerThread->start(); //disable controls until worker thread is finished this->m_Controls->m_MainWidget->setEnabled(false); - } + } } void QmitkMITKIGTTrackingToolboxView::OnAutoDetectToolsFinished(bool success, QString errorMessage) { - m_WorkerThread->quit(); + m_WorkerThread->quit(); - //enable controls again - this->m_Controls->m_MainWidget->setEnabled(true); + //enable controls again + this->m_Controls->m_MainWidget->setEnabled(true); - if(!success) - { - MITK_WARN << errorMessage.toStdString(); - MessageBox(errorMessage.toStdString()); - EnableTrackingConfigurationButtons(); - return; - } + if(!success) + { + MITK_WARN << errorMessage.toStdString(); + MessageBox(errorMessage.toStdString()); + EnableTrackingConfigurationButtons(); + return; + } - mitk::NavigationToolStorage::Pointer autoDetectedStorage = m_Worker->GetNavigationToolStorage(); + mitk::NavigationToolStorage::Pointer autoDetectedStorage = m_Worker->GetNavigationToolStorage(); - //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); + //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); + EnableTrackingConfigurationButtons(); - 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 (m_toolStorage->GetToolCount()>0) + 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 { - //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) - { + } + 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; - } - } - + 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(); } + m_Controls->m_TrackingToolsStatusWidget->Refresh(); +} void QmitkMITKIGTTrackingToolboxView::OnChooseFileClicked() - { +{ QDir currentPath = QFileInfo(m_Controls->m_LoggingFileName->text()).dir(); // if no path was selected (QDir would select current working dir then) or the // selected path does not exist -> use home directory if ( currentPath == QDir() || ! currentPath.exists() ) { currentPath = QDir(QDir::homePath()); } QString filename = QFileDialog::getSaveFileName(NULL,tr("Choose Logging File"), currentPath.absolutePath(), "*.*"); if (filename == "") return; this->m_Controls->m_LoggingFileName->setText(filename); this->OnToggleFileExtension(); - } +} // bug-16470: toggle file extension after clicking on radio button void QmitkMITKIGTTrackingToolboxView::OnToggleFileExtension() { - QString currentInputText = this->m_Controls->m_LoggingFileName->text(); QString currentFile = QFileInfo(currentInputText).baseName(); QDir currentPath = QFileInfo(currentInputText).dir(); if(currentFile.isEmpty()) { currentFile = "logfile"; } // Setting currentPath to default home path when currentPath is empty or it does not exist if(currentPath == QDir() || !currentPath.exists()) { currentPath = QDir::homePath(); } // check if csv radio button is clicked if(this->m_Controls->m_csvFormat->isChecked()) { // you needn't add a seperator to the input text when currentpath is the rootpath if(currentPath.isRoot()) { this->m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(currentPath.absolutePath()) + currentFile + ".csv"); } else { this->m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(currentPath.absolutePath()) + QDir::separator() + currentFile + ".csv"); } } // check if xml radio button is clicked else if(this->m_Controls->m_xmlFormat->isChecked()) { // you needn't add a seperator to the input text when currentpath is the rootpath if(currentPath.isRoot()) { this->m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(currentPath.absolutePath()) + currentFile + ".xml"); } else { this->m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(currentPath.absolutePath()) + QDir::separator() + currentFile + ".xml"); } - } - - - } void QmitkMITKIGTTrackingToolboxView::StartLogging() - { - +{ if (m_ToolVisualizationFilter.IsNull()) { MessageBox("Cannot activate logging without a connected device. Configure and connect a tracking device first."); return; } 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());} + m_loggingFilter->ConnectTo(m_ToolVisualizationFilter); - //connect filter - for(int i=0; iGetNumberOfOutputs(); i++){m_loggingFilter->AddNavigationData(m_ToolVisualizationFilter->GetOutput(i));} + if (m_Controls->m_LoggingLimit->isChecked()){m_loggingFilter->SetRecordCountLimit(m_Controls->m_LoggedFramesLimit->value());} //start filter with try-catch block for exceptions try { - m_loggingFilter->StartRecording(); + 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; + 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(); - } } +} 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 + // 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::TimeGeometry::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); + 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); + 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); + 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); + 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::EnableTrackingControls() { - m_Controls->m_TrackingControlsGroupBox->setEnabled(true); + m_Controls->m_TrackingControlsGroupBox->setEnabled(true); } void QmitkMITKIGTTrackingToolboxView::DisableTrackingControls() { - m_Controls->m_TrackingControlsGroupBox->setEnabled(false); + m_Controls->m_TrackingControlsGroupBox->setEnabled(false); } 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); + 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); + 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"); + //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"); } void QmitkMITKIGTTrackingToolboxViewWorker::SetWorkerMethod(WorkerMethod w) { m_WorkerMethod = w; } void QmitkMITKIGTTrackingToolboxViewWorker::SetTrackingDevice(mitk::TrackingDevice::Pointer t) { m_TrackingDevice = t; } void QmitkMITKIGTTrackingToolboxViewWorker::SetDataStorage(mitk::DataStorage::Pointer d) { m_DataStorage = d; } void QmitkMITKIGTTrackingToolboxViewWorker::SetInverseMode(bool mode) { m_InverseMode = mode; } void QmitkMITKIGTTrackingToolboxViewWorker::SetTrackingDeviceData(mitk::TrackingDeviceData d) { m_TrackingDeviceData = d; } void QmitkMITKIGTTrackingToolboxViewWorker::SetNavigationToolStorage(mitk::NavigationToolStorage::Pointer n) { m_NavigationToolStorage = n; } void QmitkMITKIGTTrackingToolboxViewWorker::ThreadFunc() { switch(m_WorkerMethod) { case eAutoDetectTools: this->AutoDetectTools(); break; case eConnectDevice: this->ConnectDevice(); break; case eStartTracking: this->StartTracking(); break; case eStopTracking: this->StopTracking(); break; case eDisconnectDevice: this->DisconnectDevice(); break; default: MITK_WARN << "Undefined worker method was set ... something went wrong!"; break; } } void QmitkMITKIGTTrackingToolboxViewWorker::AutoDetectTools() - { -mitk::ProgressBar::GetInstance()->AddStepsToDo(4); - mitk::NavigationToolStorage::Pointer autoDetectedStorage = mitk::NavigationToolStorage::New(m_DataStorage); - mitk::NDITrackingDevice::Pointer currentDevice = dynamic_cast(m_TrackingDevice.GetPointer()); -try - { - currentDevice->OpenConnection(); - mitk::ProgressBar::GetInstance()->Progress(); - currentDevice->StartTracking(); - } - catch(mitk::Exception& e) - { - QString message = QString("Warning, can not auto-detect tools! (") + QString(e.GetDescription()) + QString(")"); - //MessageBox(message.toStdString()); //TODO: give message to the user here! +{ + mitk::ProgressBar::GetInstance()->AddStepsToDo(4); + mitk::NavigationToolStorage::Pointer autoDetectedStorage = mitk::NavigationToolStorage::New(m_DataStorage); + mitk::NDITrackingDevice::Pointer currentDevice = dynamic_cast(m_TrackingDevice.GetPointer()); + try + { + currentDevice->OpenConnection(); + mitk::ProgressBar::GetInstance()->Progress(); + currentDevice->StartTracking(); + } + catch(mitk::Exception& e) + { + QString message = QString("Warning, can not auto-detect tools! (") + QString(e.GetDescription()) + QString(")"); + //MessageBox(message.toStdString()); //TODO: give message to the user here! - MITK_WARN << message.toStdString(); - mitk::ProgressBar::GetInstance()->Progress(4); - emit AutoDetectToolsFinished(false,message.toStdString().c_str()); - return; - } + MITK_WARN << message.toStdString(); + mitk::ProgressBar::GetInstance()->Progress(4); + emit AutoDetectToolsFinished(false,message.toStdString().c_str()); + return; + } 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); - } + } m_NavigationToolStorage = autoDetectedStorage; currentDevice->StopTracking(); mitk::ProgressBar::GetInstance()->Progress(); currentDevice->CloseConnection(); emit AutoDetectToolsFinished(true,""); mitk::ProgressBar::GetInstance()->Progress(4); - } +} void QmitkMITKIGTTrackingToolboxViewWorker::ConnectDevice() { std::string message = ""; mitk::ProgressBar::GetInstance()->AddStepsToDo(10); //build the IGT pipeline mitk::TrackingDevice::Pointer trackingDevice = m_TrackingDevice; trackingDevice->SetData(m_TrackingDeviceData); //set device to rotation mode transposed becaus we are working with VNL style quaternions if(m_InverseMode) - {trackingDevice->SetRotationMode(mitk::TrackingDevice::RotationTransposed);} + {trackingDevice->SetRotationMode(mitk::TrackingDevice::RotationTransposed);} //Get Tracking Volume Data mitk::TrackingDeviceData data = m_TrackingDeviceData; mitk::ProgressBar::GetInstance()->Progress(); //Create Navigation Data Source with the factory class mitk::TrackingDeviceSourceConfigurator::Pointer myTrackingDeviceSourceFactory = mitk::TrackingDeviceSourceConfigurator::New(m_NavigationToolStorage,trackingDevice); m_TrackingDeviceSource = myTrackingDeviceSourceFactory->CreateTrackingDeviceSource(m_ToolVisualizationFilter); mitk::ProgressBar::GetInstance()->Progress(); if ( m_TrackingDeviceSource.IsNull() ) { message = std::string("Cannot connect to device: ") + myTrackingDeviceSourceFactory->GetErrorMessage(); emit ConnectDeviceFinished(false,QString(message.c_str())); return; } //set filter to rotation mode transposed becaus we are working with VNL style quaternions if(m_InverseMode) m_ToolVisualizationFilter->SetRotationMode(mitk::NavigationDataObjectVisualizationFilter::RotationTransposed); //First check if the created object is valid if (m_TrackingDeviceSource.IsNull()) { message = myTrackingDeviceSourceFactory->GetErrorMessage(); emit ConnectDeviceFinished(false,QString(message.c_str())); return; } MITK_INFO << "Number of tools: " << m_TrackingDeviceSource->GetNumberOfOutputs(); mitk::ProgressBar::GetInstance()->Progress(); //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_NavigationToolStorage->DeleteAllTools(); for (int i=0; i < toolsInNewOrder->GetToolCount(); i++) {m_NavigationToolStorage->AddTool(toolsInNewOrder->GetTool(i));} - } + } mitk::ProgressBar::GetInstance()->Progress(); //connect to device try - { + { m_TrackingDeviceSource->Connect(); mitk::ProgressBar::GetInstance()->Progress(); //Microservice registration: m_TrackingDeviceSource->RegisterAsMicroservice(); m_NavigationToolStorage->UnRegisterMicroservice(); m_NavigationToolStorage->RegisterAsMicroservice(m_TrackingDeviceSource->GetMicroserviceID()); m_NavigationToolStorage->LockStorage(); - } + } catch (...) //todo: change to mitk::IGTException - { + { message = "Error on connecting the tracking device."; emit ConnectDeviceFinished(false,QString(message.c_str())); return; - } + } emit ConnectDeviceFinished(true,QString(message.c_str())); mitk::ProgressBar::GetInstance()->Progress(10); } void QmitkMITKIGTTrackingToolboxViewWorker::StartTracking() { QString errorMessage = ""; try - { + { m_TrackingDeviceSource->StartTracking(); - } + } catch (...) //todo: change to mitk::IGTException - { + { errorMessage += "Error while starting the tracking device!"; emit StartTrackingFinished(false,errorMessage); return; - } + } emit StartTrackingFinished(true,errorMessage); } void QmitkMITKIGTTrackingToolboxViewWorker::StopTracking() { try { - m_TrackingDeviceSource->StopTracking(); + m_TrackingDeviceSource->StopTracking(); } catch(mitk::Exception& e) { emit StopTrackingFinished(false, e.GetDescription()); } emit StopTrackingFinished(true, ""); - } void QmitkMITKIGTTrackingToolboxViewWorker::DisconnectDevice() { try - { + { if (m_TrackingDeviceSource->IsTracking()) {m_TrackingDeviceSource->StopTracking();} m_TrackingDeviceSource->Disconnect(); m_TrackingDeviceSource->UnRegisterMicroservice(); m_NavigationToolStorage->UnLockStorage(); - } + } catch(mitk::Exception& e) - { + { emit DisconnectDeviceFinished(false, e.GetDescription()); - } + } emit DisconnectDeviceFinished(true, ""); -} +} \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.cpp b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.cpp index 4badf81dc5..b39112e2bb 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,230 @@ /*=================================================================== 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 +// QT +#include #include -// vtk -#include +//mitk +#include +#include +#include +#include +#include +// VTK +#include const std::string QmitkNavigationDataPlayerView::VIEW_ID = "org.mitk.views.navigationdataplayer"; QmitkNavigationDataPlayerView::QmitkNavigationDataPlayerView() -: QmitkFunctionality() -, m_Controls( 0 ) -, m_MultiWidget( NULL ) -, m_Trajectory( NULL ) -, m_TrajectoryIndex( -1 ) -, m_ReloadData( true ) -, m_ShowTrajectory( false ) -, m_SplineMapper( NULL ) -, m_PointSetMapper( NULL ) + : m_Controls( 0 ) { - - 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 + // make deselected Player invisible + m_Controls->m_TimedWidget->setVisible(false); + } } -void QmitkNavigationDataPlayerView::OnCreatePlaybackVisualization() +void QmitkNavigationDataPlayerView::SetFocus() { - if(m_ReloadData) // only if input file changed + if ( m_Controls ) { - 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::TimeGeometry::Pointer bounds = this->GetDataStorage()->ComputeBoundingGeometry3D(rs, "visible"); - - // initialize the views to the bounding geometry - mitk::RenderingManager::GetInstance()->InitializeViews(bounds); - - /// global reinit end - - - + m_Controls->m_grpbxControls->setFocus(); } - -} - -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) +void QmitkNavigationDataPlayerView::CreateConnections() { - 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(); + connect( m_Controls->m_RdbSequential, SIGNAL(released()), this, SLOT(OnSelectPlayer()) ); + connect( m_Controls->m_RdbTimeBased, SIGNAL(released()), this, SLOT(OnSelectPlayer()) ); + connect( m_Controls->m_BtnOpenFile, SIGNAL(released()), this, SLOT(OnOpenFile()) ); + connect( m_Controls->m_ChkDisplay, SIGNAL(released()), this, SLOT(OnSetDisplay()) ); + connect( m_Controls->m_chkRepeat, SIGNAL(stateChanged(int)), this, SLOT(OnSetRepeat(int)) ); + connect( m_Controls->m_ChkMicroservice, SIGNAL(released()), this, SLOT(OnSetMicroservice()) ); - cone->SetVtkPolyData(vtkData->GetOutput()); + connect( m_Controls->m_SequentialWidget, SIGNAL(SignalUpdate()), this, SLOT(OnUpdate()) ); + connect( m_Controls->m_TimedWidget, SIGNAL(SignalUpdate()), this, SLOT(OnUpdate()) ); - 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; + this->SetInteractionComponentsEnabledState(false); } +void QmitkNavigationDataPlayerView::OnOpenFile(){ + mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); -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 - + // FIXME Filter for correct Files and use correct Reader + QString fileName = QFileDialog::getOpenFileName(NULL, "Open Navigation Data Set", "", "XML files (*.xml)"); //"XML files (*.xml);; Csv files (*.csv)" for additional csv files. Not supported yet. + if ( fileName.isNull() ) { return; } // user pressed cancel - // 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"; + m_Data = reader->Read(fileName.toStdString()); } - catch (...) + catch ( const mitk::Exception &e ) { - std::cout << "RenderAll unknown exception\n"; + MITK_WARN("NavigationDataPlayerView") << "could not open file " << fileName.toStdString(); + QMessageBox::critical(0, "Error Reading File", "The file '" + fileName + +"' could not be read.\n" + e.GetDescription() ); + return; } -} - -void QmitkNavigationDataPlayerView::OnReinit() -{ - std::vector::iterator it; + // Update Labels + m_Controls->m_LblFilePath->setText(fileName); + m_Controls->m_LblFrames->setText(QString::number(m_Data->Size())); + m_Controls->m_LblTools->setText(QString::number(m_Data->GetNumberOfTools())); - mitk::DataStorage* ds = this->GetDefaultDataStorage(); + // Initialize Widgets and create Player + this->OnSelectPlayer(); + this->SetInteractionComponentsEnabledState(true); +} - // clear tool representation objects from DataStorage - for ( it = m_RepresentationObjects.begin() ; it != m_RepresentationObjects.end(); it++ ) +void QmitkNavigationDataPlayerView::OnSelectPlayer() +{ + if (m_Controls->m_RdbSequential->isChecked()) { - //ds->Remove(*it); - mitk::DataNode::Pointer dn = ds->GetNamedNode((*it)->GetName()); - if(dn.IsNotNull()) - ds->Remove(dn); + m_Controls->m_SequentialWidget->setVisible(true); + m_Controls->m_TimedWidget->setVisible(false); + mitk::NavigationDataSequentialPlayer::Pointer seqPlayer = mitk::NavigationDataSequentialPlayer::New(); + seqPlayer->SetNavigationDataSet(m_Data); + m_Controls->m_SequentialWidget->SetPlayer(seqPlayer); + m_Player = seqPlayer; + } else { + m_Controls->m_SequentialWidget->setVisible(false); + m_Controls->m_TimedWidget->setVisible(true); + mitk::NavigationDataPlayer::Pointer timedPlayer = mitk::NavigationDataPlayer::New(); + timedPlayer->SetNavigationDataSet(m_Data); + m_Controls->m_TimedWidget->SetPlayer(timedPlayer); + m_Player = timedPlayer; } - 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 + this->ConfigurePlayer(); + // SetupRenderingPipeline + this->OnSetDisplay(); } -void QmitkNavigationDataPlayerView::AddTrajectory(mitk::DataStorage* ds, mitk::DataNode::Pointer trajectoryNode) +void QmitkNavigationDataPlayerView::ConfigurePlayer() { - 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); - } + // set repeat mode according to the checkbox + m_Player->SetRepeat( m_Controls->m_chkRepeat->isChecked() ); } -void QmitkNavigationDataPlayerView::AddRepresentationObject(mitk::DataStorage* ds, mitk::DataNode::Pointer reprObject) +void QmitkNavigationDataPlayerView::OnSetRepeat(int checkState) { - m_RepresentationObjects.push_back(reprObject); - ds->Add(reprObject); + m_Player->SetRepeat(checkState != 0); } -void QmitkNavigationDataPlayerView::RemoveRepresentationObject(mitk::DataStorage* ds, mitk::DataNode::Pointer reprObject) -{ - std::vector::iterator it; - - for ( it = m_RepresentationObjects.begin() ; it != m_RepresentationObjects.end(); it++ ) +void QmitkNavigationDataPlayerView::OnSetMicroservice(){ + if(m_Controls->m_ChkMicroservice->isChecked()) { - if(*it == reprObject) + m_ToolStorage = mitk::NavigationToolStorage::New(); + for (itk::ProcessObject::DataObjectPointerArraySizeType i = 0; + i < m_Player->GetNumberOfIndexedOutputs(); i++) { - m_RepresentationObjects.erase(it); - ds->Remove(reprObject); + mitk::NavigationTool::Pointer currentDummyTool = mitk::NavigationTool::New(); + mitk::VirtualTrackingTool::Pointer dummyTool = mitk::VirtualTrackingTool::New(); + std::stringstream name; + name << "Virtual Tool " << i; + dummyTool->SetToolName(name.str()); + currentDummyTool->SetTrackingTool(dummyTool.GetPointer()); + currentDummyTool->SetDataNode(m_RenderingNodes.at(i)); + currentDummyTool->SetIdentifier(name.str()); + m_ToolStorage->AddTool(currentDummyTool); } + m_Player->RegisterAsMicroservice(); + m_ToolStorage->SetName("NavigationDataPlayer Tool Storage"); + m_ToolStorage->RegisterAsMicroservice(m_Player->GetMicroserviceID()); + } else { + if (m_ToolStorage.IsNotNull()) m_ToolStorage->UnRegisterMicroservice(); + m_ToolStorage = NULL; + m_Player->UnRegisterMicroservice(); } } -void QmitkNavigationDataPlayerView::OnShowTrajectory(int index) -{ - - mitk::DataStorage* ds = this->GetDefaultDataStorage(); - - - // no trajectory selected - if(index == 0) +void QmitkNavigationDataPlayerView::OnUpdate(){ + if (m_VisFilter.IsNotNull()) { - 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); + m_VisFilter->Update(); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } - -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) +void QmitkNavigationDataPlayerView::OnSetDisplay(){ + DestroyPipeline(); + if ( (m_Controls->m_ChkDisplay->isChecked()) && ( m_Player.IsNotNull() )) { - result = colorCycle.GetNextColor(); + CreatePipeline(); } - - return result; } - -mitk::PointSetVtkMapper3D::Pointer QmitkNavigationDataPlayerView::GetTrajectoryMapper(TrajectoryStyle style) -{ - if(style == Points) - { - if(m_PointSetMapper.IsNull()) - m_PointSetMapper = mitk::PointSetVtkMapper3D::New(); - - return m_PointSetMapper; +void QmitkNavigationDataPlayerView::CreatePipeline(){ + m_VisFilter = mitk::NavigationDataObjectVisualizationFilter::New(); + m_VisFilter->ConnectTo(m_Player); + + for (unsigned int i = 0 ; i < m_Player->GetNumberOfIndexedOutputs(); i++ ) { + mitk::DataNode::Pointer node = mitk::DataNode::New(); + QString name = "Recorded Tool " + QString::number(i + 1); + node->SetName(name.toStdString()); + + //create small sphere and use it as surface + mitk::Surface::Pointer mySphere = mitk::Surface::New(); + vtkSphereSource *vtkData = vtkSphereSource::New(); + vtkData->SetRadius(5.0f); + vtkData->SetCenter(0.0, 0.0, 0.0); + vtkData->Update(); + mySphere->SetVtkPolyData(vtkData->GetOutput()); + vtkData->Delete(); + node->SetData(mySphere); + m_VisFilter->SetRepresentationObject(i, mySphere); + + // Add Node to DataStorageand to local list of Nodes + GetDataStorage()->Add(node); + m_RenderingNodes.push_back(node); } + m_VisFilter->Update(); +} - else if(style == Splines) - { - if(m_SplineMapper.IsNull()) - m_SplineMapper = mitk::SplineVtkMapper3D::New(); - - return m_SplineMapper.GetPointer(); +void QmitkNavigationDataPlayerView::DestroyPipeline(){ + m_VisFilter = NULL; + for (unsigned int i = 0; i < m_RenderingNodes.size(); i++){ + this->GetDataStorage()->Remove(m_RenderingNodes[i]); } - else - return NULL; + m_RenderingNodes.clear(); } - - - +void QmitkNavigationDataPlayerView::SetInteractionComponentsEnabledState(bool isActive){ + m_Controls->m_grpbxSettings->setEnabled(isActive); + m_Controls->m_grpbxControls->setEnabled(isActive); +} diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.h b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.h index ce3af69378..9c432a85c5 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.h +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.h @@ -1,177 +1,124 @@ /*=================================================================== 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 - - - - +#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 +class QmitkNavigationDataPlayerView : public QmitkAbstractView { // 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); + void SetFocus(); /** \brief This method creates this bundle's SIGNAL and SLOT connections */ - virtual void CreateConnections(); + void CreateConnections(); - - virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget); - virtual void StdMultiWidgetNotAvailable(); - - - protected slots: +protected slots: /*! - \brief Creates DataNodes for all available playback objects + \brief loads a file and triggers creation of players and the pipeline */ - void OnCreatePlaybackVisualization(); + void OnOpenFile(); + /*! - \brief Assigns position changings from the player widget to the visualization objects + \brief Creates the correct player and displays the according widget */ - void OnPerformPlaybackVisualization(); + void OnSelectPlayer(); + /*! - \brief Reinits this player. Cleans all timers and trajectory data + \brief Changes the repeat mode of the selected player */ - void OnReinit(); + void OnSetRepeat(int); + /*! - \brief Shows trajectory of tool with index + \brief Registers or unregisters a virtual tracking device for the player. */ - void OnShowTrajectory(int index); + void OnSetMicroservice(); + /*! - \brief Cleans trajectory data before playing is started + \brief Triggers the creation and destruction of the rendering pipeline */ - void OnPlayingStarted(); + void OnSetDisplay(); + /*! - \brief Enables or disables trajectory visualization with splines + \brief Updates the visualization */ - void OnEnableSplineTrajectoryMapper(bool enable); - + void OnUpdate(); protected: - enum TrajectoryStyle { - Points = 1, - Splines = 2 - }; - - void CreateBundleWidgets(QWidget* parent); - - /** - \brief Refreshes the visualization of the playback object DataNodes. - */ - void RenderScene(); - - /** - \brief Creates representation DataNode with given name and color - */ - mitk::DataNode::Pointer CreateRepresentationObject( const std::string& name , const mitk::Color color ); /** - \brief Adds representation DataNode to the DataStorage + * \brief configures the player according to the checkboxes set in the GUI */ - void AddRepresentationObject(mitk::DataStorage* ds, mitk::DataNode::Pointer reprObject); + void ConfigurePlayer(); + /** - \brief Removes representation DataNode from the DataStorage + * \brief Creates the Rendering Pipeline necessary to Render the images */ - void RemoveRepresentationObject(mitk::DataStorage* ds, mitk::DataNode::Pointer reprObject); + void CreatePipeline(); /** - \brief Adds trajectory DataNode to the DataStorage + * \brief Destroys the Rendering Pipeline (but not the player) */ - void AddTrajectory(mitk::DataStorage* ds, mitk::DataNode::Pointer trajectoryNode); + void DestroyPipeline(); /** - \brief Creates a trajectory DataNode from given PointSet with given name and color + * \brief Makes player component active or inactive. + * + * Used to activate all components once data is loaded */ - mitk::DataNode::Pointer CreateTrajectory( mitk::PointSet::Pointer points, const std::string& name, const mitk::Color color ); - - - + void SetInteractionComponentsEnabledState(bool isActive); 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 - - - + mitk::NavigationDataObjectVisualizationFilter::Pointer m_VisFilter; + std::vector m_RenderingNodes; + mitk::NavigationDataPlayerBase::Pointer m_Player; + mitk::NavigationDataSet::Pointer m_Data; + mitk::NavigationToolStorage::Pointer m_ToolStorage; private: - /** - \brief Returns color from colorcycle with given index - */ - mitk::Color GetColorCircleColor(int index); - /** - \brief Returns the trajectory mapper for the given style if stıle is not Points or Splines NULL will be returned. - */ - mitk::PointSetVtkMapper3D::Pointer GetTrajectoryMapper(TrajectoryStyle style); - }; - - #endif // _QMITKNAVIGATIONDATAPLAYERVIEW_H_INCLUDED - diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerViewControls.ui b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerViewControls.ui index f136cc7545..01b0369fbc 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerViewControls.ui +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerViewControls.ui @@ -1,44 +1,188 @@ QmitkNavigationDataPlayerViewControls 0 0 - 222 - 161 + 415 + 762 0 0 QmitkTemplate - + + + File Management + + + + + + + + Open File + + + + + + + No navigation data set loaded... + + + + + + + Frames: + + + + + + + Tools: + + + + + + + N/A + + + + + + + N/A + + + + + + + + + + + + true + + + Settings + + + + + + + + Sequential Player + + + true + + + + + + + Time-based Player + + + + + + + + + Repeat + + + true + + + + + + + Register as Microservice + + + false + + + + + + + Display + + + true + + + + + + + + + + Player Controls + + + + + + + + + + + + + Qt::Vertical - - QSizePolicy::Expanding - 20 - 220 + 40 + + + QmitkNavigationDataSequentialPlayerControlWidget + QWidget +
QmitkNavigationDataSequentialPlayerControlWidget.h
+ 1 +
+ + QmitkNavigationDataPlayerControlWidget + QWidget +
QmitkNavigationDataPlayerControlWidget.h
+ 1 +
+