diff --git a/Modules/CameraCalibration/mitkEndoDebug.cpp b/Modules/CameraCalibration/mitkEndoDebug.cpp index 2b5654ced5..5941f03309 100644 --- a/Modules/CameraCalibration/mitkEndoDebug.cpp +++ b/Modules/CameraCalibration/mitkEndoDebug.cpp @@ -1,173 +1,207 @@ #include "mitkEndoDebug.h" #include #include #include +#include +#include +#include namespace mitk { struct EndoDebugData { EndoDebugData() : m_DebugEnabled(false) , m_ShowImagesInDebug(false) , m_ShowImagesTimeOut(false) , m_Mutex(itk::FastMutexLock::New()) { } std::set m_FilesToDebug; std::set m_SymbolsToDebug; bool m_DebugEnabled; bool m_ShowImagesInDebug; size_t m_ShowImagesTimeOut; + std::ofstream m_Stream; itk::FastMutexLock::Pointer m_Mutex; }; EndoDebug::EndoDebug() : d ( new EndoDebugData ) { } EndoDebug::~EndoDebug() { + if(d->m_Stream.is_open()) + d->m_Stream.close(); delete d; } EndoDebug& EndoDebug::GetInstance() { static EndoDebug instance; return instance; } std::string EndoDebug::GetFilenameWithoutExtension(const std::string& s) { return itksys::SystemTools::GetFilenameWithoutExtension( s ); } void EndoDebug::AddFileToDebug(const std::string& s) { { itk::MutexLockHolder lock(*d->m_Mutex); d->m_FilesToDebug.insert( s ); } } void EndoDebug::AddSymbolToDebug(const std::string& symbolToDebug) { { itk::MutexLockHolder lock(*d->m_Mutex); d->m_SymbolsToDebug.insert( symbolToDebug ); } } bool EndoDebug::DebugSymbol(const std::string& s) { { itk::MutexLockHolder lock(*d->m_Mutex); return d->m_SymbolsToDebug.find(s) != d->m_SymbolsToDebug.end(); } } bool EndoDebug::DebugFile(const std::string& s) { std::string filename = GetFilenameWithoutExtension(s); { itk::MutexLockHolder lock(*d->m_Mutex); return d->m_FilesToDebug.find(filename) != d->m_FilesToDebug.end(); } } bool EndoDebug::Debug( const std::string& fileToDebug, const std::string& symbol ) { bool debug = false; { bool debugEnabled = false; size_t filesSize = 0; size_t symbolsSize = 0; bool symbolFound = false; { itk::MutexLockHolder lock(*d->m_Mutex); debugEnabled = d->m_DebugEnabled; filesSize = d->m_FilesToDebug.size(); symbolsSize = d->m_SymbolsToDebug.size(); symbolFound = d->m_SymbolsToDebug.find(symbol) != d->m_SymbolsToDebug.end(); } if( debugEnabled ) { if( filesSize == 0 ) debug = true; else debug = DebugFile(fileToDebug); // ok debug is determined so far, now check if symbol set if( symbolsSize > 0 ) { debug = symbolFound; } else { // do not show symbol debug output if no symbols are set at all if( !symbol.empty() ) debug = false; } } } return debug; } void EndoDebug::SetDebugEnabled(bool _DebugEnabled) { { itk::MutexLockHolder lock(*d->m_Mutex); d->m_DebugEnabled = _DebugEnabled; } } bool EndoDebug::GetDebugEnabled() { { itk::MutexLockHolder lock(*d->m_Mutex); return d->m_DebugEnabled; } } void EndoDebug::SetShowImagesInDebug(bool _ShowImagesInDebug) { { itk::MutexLockHolder lock(*d->m_Mutex); d->m_ShowImagesInDebug = _ShowImagesInDebug; } } bool EndoDebug::GetShowImagesInDebug() { { itk::MutexLockHolder lock(*d->m_Mutex); return d->m_ShowImagesInDebug; } } void EndoDebug::SetShowImagesTimeOut(size_t _ShowImagesTimeOut) { { itk::MutexLockHolder lock(*d->m_Mutex); d->m_ShowImagesTimeOut = _ShowImagesTimeOut; } } bool EndoDebug::GetShowImagesTimeOut() { { itk::MutexLockHolder lock(*d->m_Mutex); return d->m_ShowImagesTimeOut; } } + + void EndoDebug::SetLogFile( const std::string& file ) + { + { + itk::MutexLockHolder lock(*d->m_Mutex); + d->m_Stream.open ( file.c_str(), std::ios::out | std::ios::app); + } + } + + void EndoDebug::ShowMessage( const std::string& message ) + { + { + itk::MutexLockHolder lock(*d->m_Mutex); + if(d->m_Stream.is_open()) + { + char *timestr; + struct tm *newtime; + time_t aclock; + time(&aclock); + newtime = localtime(&aclock); + timestr = asctime(newtime); + + d->m_Stream << timestr << ", " << message; + } + else + std::cout << message << std::flush; + } + } } diff --git a/Modules/CameraCalibration/mitkEndoDebug.h b/Modules/CameraCalibration/mitkEndoDebug.h index 801658632e..c6b2d042d8 100644 --- a/Modules/CameraCalibration/mitkEndoDebug.h +++ b/Modules/CameraCalibration/mitkEndoDebug.h @@ -1,179 +1,209 @@ #ifndef mitkEndoDebug_h #define mitkEndoDebug_h #include #include #include +#include #include namespace mitk { /// /// again d pointer impl /// struct EndoDebugData; /// /// class responsible for handling debug matters /// in endotracking /// struct mitkCameraCalibration_EXPORT EndoDebug { /// /// singleton class /// static EndoDebug& GetInstance(); /// /// set if debug is enabled at all /// void SetDebugEnabled(bool _DebugEnabled); /// /// \return true if debug should be enabled /// bool GetDebugEnabled(); /// /// set if debug is enabled at all /// void SetShowImagesInDebug(bool _ShowImagesInDebug); /// /// \return true if debug should be enabled /// bool GetShowImagesInDebug(); /// /// set if debug is enabled at all /// void SetShowImagesTimeOut(size_t _ShowImagesTimeOut); /// /// \return true if debug should be enabled /// bool GetShowImagesTimeOut(); /// /// \return the basename of a file without path /// std::string GetFilenameWithoutExtension(const std::string& s); /// /// add a file to debug ( if one or more files are set ) /// only those files will be debugged when using the macros /// below. e.g. call AddFileToDebug("MyClass.cpp"), then /// statements like endodebug(...) will be evaluated in /// MyClass.cpp and nowhere else /// void AddFileToDebug(const std::string& fileToDebug); /// /// same as files to debug, but the user can provide /// any symbol string. if one or more symbols /// are set only for these symbols Debug() will return true /// void AddSymbolToDebug(const std::string& symbolToDebug); /// /// \return true if file should be debugged /// bool DebugFile( const std::string& fileToDebug ); /// /// \return true if symbol should be debugged /// bool DebugSymbol( const std::string& symbolToDebug ); - /// /// \return the all in all status if debug output /// should be generated /// bool Debug( const std::string& fileToDebug, const std::string& symbol="" ); /// + /// set a log file. if a log file is set and debug is activated all messages will be appended to that file + /// + void SetLogFile( const std::string& file ); + /// + /// shows a message or writes it to a log file if a file is set (and is valid for writing) + /// + void ShowMessage( const std::string& message ); + /// /// init defaults /// EndoDebug(); /// /// delete d pointer /// virtual ~EndoDebug(); private: /// /// d pointer /// EndoDebugData* d; }; } -/// -/// macro for debugging purposes -/// -#define endodebugmarker\ - if( mitk::EndoDebug::GetInstance().Debug(__FILE__) ) \ - { \ - std::cout << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " << __LINE__\ - << ": " << __FUNCTION__ << std::endl;\ - } - -/// -/// macro for debugging purposes -/// -#define endodebug(msg)\ - if( mitk::EndoDebug::GetInstance().Debug(__FILE__) ) \ - { \ - std::cout << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " << __LINE__\ - << ": " << msg << std::endl;\ - } - -/// -/// macro for debugging variables -/// -#define endodebugvar(var)\ - if( mitk::EndoDebug::GetInstance().Debug(__FILE__) ) \ - { \ - std::cout << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " << __LINE__\ - << ": " #var " = " << var << std::endl;\ - } - -/// -/// macro for debugging a variable as symbol -/// -#define endodebugsymbol(var, mSymbol)\ - if( mitk::EndoDebug::GetInstance().Debug(__FILE__, mSymbol) ) \ - { \ - std::cout << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " << __LINE__\ - << ": " #var " = " << var << std::endl;\ - } - -/// -/// macro for showing cv image if in debug mode -/// highgui.h must be included before -/// -#define endodebugimg(imgVariableName)\ - if( mitk::EndoDebug::GetInstance().Debug(__FILE__) \ - && mitk::EndoDebug::GetInstance().GetShowImagesInDebug()) \ - { \ - std::cout << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " << __LINE__\ - << ": Showing " #imgVariableName << std::endl; \ - cv::imshow( "Debug", imgVariableName ); \ - cv::waitKey( mitk::EndoDebug::GetInstance().GetShowImagesTimeOut() ); \ - } - -/// -/// macro for a section that should only be executed if debugging is enabled -/// -#define endodebugbegin \ - if( mitk::EndoDebug::GetInstance().Debug(__FILE__) ) \ - { \ - -/// -/// macro for a section that should only be executed if debugging is enabled -/// -#define endodebugend \ - } +// DISABLE DEBUGGING FOR RELEASE MODE ON WINDOWS +#if defined(WIN32) && !defined(_DEBUG) + #define endodebugmarker + #define endodebug(msg) + #define endodebugvar(var) + #define endodebugsymbol(var, mSymbol) + #define endodebugimg(imgVariableName) + #define endodebugbegin if( false ) { + #define endodebugend } +#else + /// + /// macro for debugging purposes + /// + #define endodebugmarker\ + if( mitk::EndoDebug::GetInstance().Debug(__FILE__) ) \ + { \ + std::ostringstream ___ostringstream; \ + ___ostringstream << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " << __LINE__\ + << ": " << __FUNCTION__ << std::endl;\ + mitk::EndoDebug::GetInstance().ShowMessage( ___ostringstream.str() ); \ + } + + /// + /// macro for debugging purposes + /// + #define endodebug(msg)\ + if( mitk::EndoDebug::GetInstance().Debug(__FILE__) ) \ + { \ + std::ostringstream ___ostringstream; \ + ___ostringstream << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " << __LINE__\ + << ": " << msg << std::endl;\ + mitk::EndoDebug::GetInstance().ShowMessage( ___ostringstream.str() ); \ + } + + /// + /// macro for debugging variables + /// + #define endodebugvar(var)\ + if( mitk::EndoDebug::GetInstance().Debug(__FILE__) ) \ + { \ + std::ostringstream ___ostringstream; \ + ___ostringstream << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " << __LINE__\ + << ": " #var " = " << var << std::endl;\ + mitk::EndoDebug::GetInstance().ShowMessage( ___ostringstream.str() ); \ + } + + /// + /// macro for debugging a variable as symbol + /// + #define endodebugsymbol(var, mSymbol)\ + if( mitk::EndoDebug::GetInstance().Debug(__FILE__, mSymbol) ) \ + { \ + std::ostringstream ___ostringstream; \ + ___ostringstream << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " << __LINE__\ + << ": " #var " = " << var << std::endl;\ + mitk::EndoDebug::GetInstance().ShowMessage( ___ostringstream.str() ); \ + } + + /// + /// macro for showing cv image if in debug mode + /// highgui.h must be included before + /// + #define endodebugimg(imgVariableName)\ + if( mitk::EndoDebug::GetInstance().Debug(__FILE__) \ + && mitk::EndoDebug::GetInstance().GetShowImagesInDebug()) \ + { \ + std::ostringstream ___ostringstream; \ + ___ostringstream << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " << __LINE__\ + << ": Showing " #imgVariableName << std::endl; \ + mitk::EndoDebug::GetInstance().ShowMessage( ___ostringstream.str() ); \ + cv::imshow( "Debug", imgVariableName ); \ + cv::waitKey( mitk::EndoDebug::GetInstance().GetShowImagesTimeOut() ); \ + } + + /// + /// macro for a section that should only be executed if debugging is enabled + /// + #define endodebugbegin \ + if( mitk::EndoDebug::GetInstance().Debug(__FILE__) ) \ + { + + /// + /// macro for a section that should only be executed if debugging is enabled + /// + #define endodebugend \ + } + +#endif #endif // mitkEndoDebug_h diff --git a/Modules/CameraCalibration/mitkTransform.cpp b/Modules/CameraCalibration/mitkTransform.cpp index 17783e6838..97c6a9c6e2 100644 --- a/Modules/CameraCalibration/mitkTransform.cpp +++ b/Modules/CameraCalibration/mitkTransform.cpp @@ -1,700 +1,717 @@ #include "mitkTransform.h" #include #include #include #include #include #include namespace mitk { // DO NOT CHANGE THE VALUES OF THESE CONSTANTS!! const std::string Transform::UNKNOWN_TYPE = "Unknown type"; const std::string Transform::ENDOSCOPE_SCOPE_TOOL = "Endoscope scope tool"; const std::string Transform::ENDOSCOPE_CAM_TOOL = "Endoscope camera tool"; const std::string Transform::CHESSBOARD_TOOL = "Chessboard tool"; const std::string Transform::POINTER_TOOL = "Pointer tool"; + const std::string Transform::POINTER_TO_CHESSBOARD_ORIGIN = "Pointer to chessboard origin"; + const std::string Transform::POINTER_TO_CHESSBOARD_X_SUPPORT_POINT = "Pointer to chessboard X support origin"; + const std::string Transform::POINTER_TO_CHESSBOARD_Y_SUPPORT_POINT = "Pointer to chessboard Y support origin"; const std::string Transform::BOARD_TO_BOARD_TOOL = "Board to board tool"; + const std::string Transform::REFERENCE_CAMERA_TRANSFORM = "Reference camera transform"; + const std::string Transform::REFERENCE_SCOPE_TRANSFORM = "Reference scope transform"; + const std::string Transform::EYE_TO_HAND_TRANSFORM = "Eye to hand transform"; + const std::string Transform::CAMERA_EXTRINSICS = "Camera extrinsics"; Transform::Transform() : m_NavData(mitk::NavigationData::New()), m_Type( UNKNOWN_TYPE ) { vnl_matrix_fixed rot; rot.set_identity(); this->SetRotation( rot ); } Transform::Transform(const mitk::NavigationData* nd) : m_NavData(mitk::NavigationData::New()), m_Type( UNKNOWN_TYPE ) { m_NavData->Graft(nd); } + Transform::Transform(const std::string& s) + : m_NavData(mitk::NavigationData::New()), m_Type( s ) + { + vnl_matrix_fixed rot; + rot.set_identity(); + this->SetRotation( rot ); + } + void Transform::Copy(const mitk::NavigationData* nd) { (const_cast(m_NavData.GetPointer()))->Graft(nd); } void Transform::Concatenate( mitk::Transform* transform ) { vnl_matrix_fixed mat = transform->GetMatrix(); mat = mat * this->GetMatrix(); // this->SetMatrix( mat ); + } void Transform::Concatenate( const vnl_matrix_fixed& transform ) { Transform::Pointer t = Transform::New(); t->SetMatrix( transform ); this->Concatenate( t ); } void Transform::Concatenate( const vtkMatrix4x4* transform ) { Transform::Pointer t = Transform::New(); t->SetMatrix( transform ); this->Concatenate( t ); } void Transform::SetOrientation( const vnl_quaternion& orientation) { m_NavData->SetOrientation(orientation); this->Modified(); } void Transform::SetTranslation( const vnl_vector_fixed& transl) { mitk::Point3D p; for(unsigned int i=0; i<3; ++i) p[i] = transl[i]; m_NavData->SetPosition(p); this->Modified(); } void Transform::SetTranslation( float* array ) { vnl_vector_fixed vec; for(unsigned int i=0; iSetTranslation( vec ); } void Transform::SetRotation( float* array ) { vnl_matrix_fixed mat; unsigned int row = 0; unsigned int col = 0; for(unsigned int i=0; i 0 && i % 3 == 0 ) { ++row; col = 0; } mat(row,col) = array[i]; ++col; } this->SetRotation( mat ); } void Transform::SetOrientation( const vnl_quaternion& orientation) { vnl_vector_fixed qvec; VnlVectorFixedCaster caster( &orientation, &qvec ); caster.Update(); mitk::Quaternion p( qvec ); this->SetOrientation( p ); } vnl_vector_fixed Transform::GetVnlDoubleTranslation() const { vnl_vector_fixed vecFloat = this->GetVnlTranslation(); vnl_vector_fixed vecDouble; VnlVectorFixedCaster caster( &vecFloat, &vecDouble ); caster.Update(); return vecDouble; } void Transform::SetTranslation( const vnl_vector& transl) { vnl_vector_fixed dTransl(transl); vnl_vector_fixed fTransl; VnlVectorFixedCaster caster( &dTransl, &fTransl ); caster.Update(); this->SetTranslation( fTransl ); } vnl_quaternion Transform::GetVnlDoubleQuaternion() const { mitk::Quaternion fOrientation = this->GetOrientation(); vnl_quaternion dOrientation; VnlVectorFixedCaster caster( &fOrientation, &dOrientation ); caster.Update(); return dOrientation; } void Transform::FromCSVFile(const std::string& file) { std::ifstream csvFile (file.c_str()); endoAssert ( csvFile.fail() == false ); mitk::Transform::Pointer transform = mitk::Transform::New(); vnl_matrix_fixed mat; std::string line; mitk::ScalarType d = 0.0f; int row=0,column = 0; while (std::getline (csvFile, line)) { std::istringstream linestream(line); std::string item; column = 0; while (std::getline (linestream, item, ',')) { std::istringstream number; number.str(item); number >> d; mat(row, column) = d; ++column; } ++row; } endoAssert( row == 4 && column == 4 ); transform->SetMatrix( mat ); this->SetNavigationData( transform->GetNavigationData() ); // modified is called in SetNavigationData } std::string Transform::ToCSVString() const { std::ostringstream s; s.precision(12); vnl_matrix_fixed mat = this->GetMatrix(); for( unsigned int j=0; j mat = this->GetMatrix(); s << varname << " = ["; for( unsigned int j=0; jGraft(transform->GetNavigationData()); + m_Type = transform->GetType(); } mitk::Transform::Pointer Transform::Clone() const { Transform::Pointer copy = Transform::New(); copy->Copy( this ); return copy; } void Transform::SetMatrix( const vtkMatrix4x4* mat) { vnl_matrix_fixed vnlMat; for(unsigned int i=0; i<4; ++i) for(unsigned int j=0; j<4; ++j) vnlMat(i,j) = mat->GetElement(i, j); this->SetMatrix( vnlMat ); } void Transform::ToCSVFile(const std::string& file) const { std::ofstream csvFile; csvFile.open(file.c_str()); endoAssert ( csvFile.fail() == false ); csvFile << this->ToCSVString(); csvFile.close(); } void Transform::ToMatlabFile(const std::string& file , const std::string& varname) const { std::ofstream csvFile; csvFile.open(file.c_str()); endoAssert ( csvFile.fail() == false ); csvFile << this->ToMatlabString(varname); csvFile.close(); } void Transform::SetNavigationData( const mitk::NavigationData* naviData ) { endoAssert( naviData != 0 ); m_NavData->Graft( naviData ); this->Modified(); } void Transform::SetRotation( vnl_matrix_fixed& mat) { this->m_NavData->SetOrientation( mitk::Quaternion(mat) ); this->Modified(); } void Transform::SetRotation( vnl_matrix& mat) { vnl_matrix_fixed tmp(mat); this->SetRotation( tmp ); } void Transform::SetPosition( const mitk::Point3D& transl) { this->SetTranslation( transl.GetVnlVector() ); } void Transform::SetTranslation( double array[3] ) { mitk::Point3D p; for(unsigned int i = 0; i < 3; ++i) p.SetElement(i, array[i]); this->SetTranslation( p.GetVnlVector() ); } void Transform::SetRotation( double array[3][3] ) { vnl_matrix_fixed mat; for(unsigned int i = 0; i < 3; ++i) for(unsigned int j = 0; j < 3; ++j) mat(i, j) = array[i][j]; this->SetRotation( mat ); } void Transform::Invert() { vnl_matrix_fixed tmp(this->GetMatrix()); this->SetMatrix( vnl_inverse( tmp ) ); } void Transform::SetMatrix( const vnl_matrix_fixed& mat) { // set translation first vnl_vector transl = mat.get_column(3); mitk::Point3D p; for(unsigned int i=0; i<3; ++i) p[i] = transl[i]; m_NavData->SetPosition(p); // set rotation vnl_matrix_fixed rotMatFixed( mat.extract(3,3)); this->SetRotation(rotMatFixed); } bool Transform::IsValid() const { return m_NavData->IsDataValid(); } void Transform::SetTranslation( const cv::Mat& transl) { vnl_vector vec(3); VnlVectorFromCvMat _VnlVectorFromCvMat( &transl, &vec ); _VnlVectorFromCvMat.Update(); this->SetTranslation( vnl_vector_fixed( vec ) ); } void Transform::SetRotation( const cv::Mat& mat ) { vnl_matrix vnlMat(3, 3); VnlMatrixFromCvMat _VnlMatrixFromCvMat( &mat, &vnlMat ); _VnlMatrixFromCvMat.Update(); vnl_matrix_fixed vnlMatFixed(vnlMat); this->SetRotation(vnlMatFixed); } void Transform::SetRotationVector( const cv::Mat& rotVec ) { cv::Mat rotMat; cv::Rodrigues( rotVec, rotMat ); vnl_matrix vnlMat(3, 3); VnlMatrixFromCvMat _VnlMatrixFromCvMat( &rotMat, &vnlMat ); _VnlMatrixFromCvMat.Update(); vnl_matrix_fixed vnlMatFixed(vnlMat); this->SetRotation( vnlMatFixed ); } //# getter mitk::NavigationData::Pointer Transform::GetNavigationData() const { return m_NavData; } mitk::Point3D Transform::GetTranslation() const { return m_NavData->GetPosition(); } mitk::Point3D Transform::GetPosition() const { return m_NavData->GetPosition(); } mitk::Quaternion Transform::GetOrientation() const { return m_NavData->GetOrientation(); } void Transform::GetMatrix(vtkMatrix4x4* matrix) const { vnl_matrix_fixed vnlMat = this->GetMatrix(); for(unsigned int i=0; iSetElement(i,j, vnlMat(i,j)); } void Transform::GetVtkOpenGlMatrix(vtkMatrix4x4* matrix) const { vnl_matrix vnlRotation = this->GetVnlRotationMatrix().as_matrix(); // normalize rows of rotation matrix vnlRotation.normalize_rows(); vnl_matrix vnlInverseRotation(3,3); // invert rotation vnlInverseRotation = vnl_matrix_inverse(vnlRotation); vnl_vector vnlTranslation = this->GetPosition().GetVnlVector(); // rotate translation vector by inverse rotation P = P' vnlTranslation = vnlInverseRotation * vnlTranslation; vnlTranslation *= -1; // save -P' // set position mitk::Transform::Pointer tmp = mitk::Transform::New(); tmp->SetTranslation( vnlTranslation ); tmp->SetRotation( vnlRotation ); tmp->GetMatrix(matrix); } //# cv getter cv::Mat Transform::GetCvTranslation() const { cv::Mat mat; vnl_vector vec = this->GetVnlTranslation().as_vector(); endodebugvar( vec ) CvMatFromVnlVector _CvMatFromVnlVector(&vec, &mat); _CvMatFromVnlVector.Update(); return mat; } cv::Mat Transform::GetCvRotationMatrix() const { cv::Mat mat; vnl_matrix vec = this->GetVnlRotationMatrix().as_matrix(); endodebugvar( vec ) CvMatFromVnlMatrix _CvMatFromVnlMatrix(&vec, &mat); _CvMatFromVnlMatrix.Update(); return mat; } cv::Mat Transform::GetCvMatrix() const { cv::Mat mat; vnl_matrix vec = this->GetMatrix().as_matrix(); CvMatFromVnlMatrix _CvMatFromVnlMatrix(&vec, &mat); _CvMatFromVnlMatrix.Update(); return mat; } cv::Mat Transform::GetCvRotationVector() const { cv::Mat rotVec(3,1,cv::DataType::type); cv::Rodrigues( this->GetCvRotationMatrix(), rotVec ); return rotVec; } //# vnl getter vnl_vector_fixed Transform::GetVnlTranslation() const { vnl_vector_fixed vec(m_NavData->GetPosition() .GetVnlVector()); return vec; } vnl_matrix_fixed Transform::GetVnlRotationMatrix() const { return m_NavData->GetOrientation().rotation_matrix_transpose(); } vnl_matrix_fixed Transform::GetVnlDoubleMatrix() const { vnl_matrix_fixed mat = this->GetMatrix(); vnl_matrix_fixed doubleMat; for(unsigned int i=0; i( mat(i,j) ); return doubleMat; } vnl_matrix_fixed Transform::GetMatrix() const { vnl_vector_fixed transl = this->GetVnlTranslation(); vnl_matrix_fixed rot = this->GetVnlRotationMatrix(); vnl_matrix_fixed homMat; homMat.set_identity(); //std::cout << homMat << std::endl; for(unsigned int i=0; i rotMat = this->GetVnlRotationMatrix().transpose(); this->SetRotation( rotMat ); } void Transform::SetValid( bool valid ) { if( m_NavData->IsDataValid() == valid ) return; m_NavData->SetDataValid( valid ); this->Modified(); } std::string mitk::Transform::ToString() const { std::ostringstream s; s.precision(12); mitk::NavigationData::PositionType position; position.Fill(0.0); position = m_NavData->GetPosition(); mitk::NavigationData::OrientationType orientation(0.0, 0.0, 0.0, 0.0); orientation = m_NavData->GetOrientation(); s << "Translation: [" << position[0] << ", " << position[1] << ", " << position[2] << "]"; s << ", orientation: [" << orientation[0] << ", " << orientation[1] << ", " << orientation[2] << ", " << orientation[3] << "]"; s << ", valid: [" << (this->IsValid()? "true": "false") << "]"; return s.str(); } void mitk::Transform::ToXML(TiXmlElement* elem) const { std::string value = elem->ValueStr(); if(value.empty()) elem->SetValue(this->GetNameOfClass()); mitk::NavigationData::PositionType position; position.Fill(0.0); position = m_NavData->GetPosition(); mitk::NavigationData::OrientationType orientation(0.0, 0.0, 0.0, 0.0); orientation = m_NavData->GetOrientation(); mitk::NavigationData::CovarianceMatrixType matrix; matrix.SetIdentity(); matrix = m_NavData->GetCovErrorMatrix(); bool hasPosition = true; hasPosition = m_NavData->GetHasPosition(); bool hasOrientation = true; hasOrientation = m_NavData->GetHasOrientation(); bool dataValid = false; dataValid = m_NavData->IsDataValid(); mitk::NavigationData::TimeStampType timestamp=0.0; elem->SetAttribute("Type", m_Type); elem->SetDoubleAttribute("Time", timestamp); 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); } void mitk::Transform::FromXML(TiXmlElement* elem) { assert(elem); 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(); std::string type = Transform::UNKNOWN_TYPE; elem->QueryStringAttribute("Type", &type); elem->QueryDoubleAttribute("Time",×tamp); // position and orientation is mandatory! if(elem->QueryFloatAttribute("X", &position[0]) != TIXML_SUCCESS) throw std::invalid_argument("No X position found in xml"); if(elem->QueryFloatAttribute("Y", &position[1]) != TIXML_SUCCESS) throw std::invalid_argument("No Y position found in xml"); if(elem->QueryFloatAttribute("Z", &position[2]) != TIXML_SUCCESS) throw std::invalid_argument("No Z position found in xml"); if(elem->QueryFloatAttribute("QX", &orientation[0]) != TIXML_SUCCESS) throw std::invalid_argument("No QX orientation found in xml"); if(elem->QueryFloatAttribute("QY", &orientation[1]) != TIXML_SUCCESS) throw std::invalid_argument("No QY orientation found in xml"); if(elem->QueryFloatAttribute("QZ", &orientation[2]) != TIXML_SUCCESS) throw std::invalid_argument("No QZ orientation found in xml"); if(elem->QueryFloatAttribute("QR", &orientation[3]) != TIXML_SUCCESS) throw std::invalid_argument("No QR orientation found in xml"); elem->QueryFloatAttribute("C00", &matrix[0][0]); elem->QueryFloatAttribute("C01", &matrix[0][1]); elem->QueryFloatAttribute("C02", &matrix[0][2]); elem->QueryFloatAttribute("C03", &matrix[0][3]); elem->QueryFloatAttribute("C04", &matrix[0][4]); elem->QueryFloatAttribute("C05", &matrix[0][5]); elem->QueryFloatAttribute("C10", &matrix[1][0]); elem->QueryFloatAttribute("C11", &matrix[1][1]); elem->QueryFloatAttribute("C12", &matrix[1][2]); elem->QueryFloatAttribute("C13", &matrix[1][3]); elem->QueryFloatAttribute("C14", &matrix[1][4]); elem->QueryFloatAttribute("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->SetTimeStamp(timestamp); nd->SetPosition(position); nd->SetOrientation(orientation); nd->SetCovErrorMatrix(matrix); nd->SetDataValid(dataValid); nd->SetHasOrientation(hasOrientation); nd->SetHasPosition(hasPosition); m_NavData = nd; m_Type = type; this->Modified(); } } // namespace mitk std::ostream& operator<< (std::ostream& os, mitk::Transform::Pointer p) { os << p->ToString(); return os; } diff --git a/Modules/CameraCalibration/mitkTransform.h b/Modules/CameraCalibration/mitkTransform.h index c2d2abbe6f..506424b845 100644 --- a/Modules/CameraCalibration/mitkTransform.h +++ b/Modules/CameraCalibration/mitkTransform.h @@ -1,276 +1,284 @@ #ifndef MITKTRANSFORM_H #define MITKTRANSFORM_H #include #include #include #include #include #include #include #include #include #include namespace mitk { /// /// \brief class representing a transfrom in 3D /// /// internally it stores a mitk navigation data. this is more /// or less a wrapper for navigation data for easy casting /// between opencv/vnl/mitk/xml representations of transform /// data /// class mitkCameraCalibration_EXPORT Transform: public itk::Object, public XMLSerializable { public: mitkClassMacro(Transform, itk::Object); itkFactorylessNewMacro(Transform); mitkNewMacro1Param(Transform, const mitk::NavigationData*); + mitkNewMacro1Param(Transform, const std::string&); /// /// constants describing the type of transform /// represented here /// static const std::string UNKNOWN_TYPE; static const std::string ENDOSCOPE_SCOPE_TOOL; static const std::string ENDOSCOPE_CAM_TOOL; static const std::string CHESSBOARD_TOOL; static const std::string POINTER_TOOL; + static const std::string POINTER_TO_CHESSBOARD_ORIGIN; + static const std::string POINTER_TO_CHESSBOARD_X_SUPPORT_POINT; + static const std::string POINTER_TO_CHESSBOARD_Y_SUPPORT_POINT; static const std::string BOARD_TO_BOARD_TOOL; - + static const std::string REFERENCE_CAMERA_TRANSFORM; + static const std::string REFERENCE_SCOPE_TRANSFORM; + static const std::string EYE_TO_HAND_TRANSFORM; + static const std::string CAMERA_EXTRINSICS; itkGetConstMacro(Type, std::string); itkSetMacro(Type, std::string&); /// /// Copies the content of transform to this /// instance /// void Copy( const mitk::Transform* transform ); /// /// Copies the content of transform to this /// instance /// void Copy( const mitk::NavigationData* transform ); /// /// Inverts the rotation of this transform /// (Polaris navigation Data have inverted rotation /// so you may want to call this function when using /// polaris data) /// void TransposeRotation(); /// /// get a copy of this transform /// mitk::Transform::Pointer Clone() const; /// /// concatenate this transform with the given one, /// i.e. this transform is done first, then transform /// ( if x is this transform, y is transform, then this will be y*x) /// post multiply semantics! /// \see vtkTransform /// void Concatenate( mitk::Transform* transform ); /// /// same as above with vnl mat argument /// void Concatenate( const vnl_matrix_fixed& transform ); /// /// same as above with vtk mat argument /// void Concatenate( const vtkMatrix4x4* transform ); /// /// invert this transform /// void Invert(); /// /// read from xml /// void FromXML(TiXmlElement* elem); /// /// read csv file /// void FromCSVFile(const std::string& file); /// /// grafts the data from naviData to this transform /// void SetNavigationData( const mitk::NavigationData* naviData ); /// /// method to set orientation quat /// void SetOrientation( const vnl_quaternion& orientation); /// /// method to set double valued orientation quat /// void SetOrientation( const vnl_quaternion& orientation); /// /// method to set translation /// void SetTranslation( const vnl_vector_fixed& transl); /// /// method to set a vector of doubles as translation /// void SetTranslation( const vnl_vector& transl); /// /// method to set a mitk::Point3D as position /// void SetPosition( const mitk::Point3D& transl); /// /// sets rotation with a rotation matrix /// void SetRotation( vnl_matrix_fixed& mat); /// /// sets rotation with a non fixed rotation matrix /// void SetRotation( vnl_matrix& mat); /// /// sets rotation and translation with a transformation matrix /// void SetMatrix( const vnl_matrix_fixed& mat); /// /// sets rotation and translation with a vtk transformation matrix /// void SetMatrix( const vtkMatrix4x4* mat); /// /// sets translation from a POD vector /// void SetTranslation( float* array ); /// /// sets translation from a POD vector. this must be a /// 3x3=9 sized vector in row major format (first row = first /// three elements) /// void SetRotation( float* array ); /// /// sets translation from a POD vector /// void SetTranslation( double array[3] ); /// /// sets translation from a POD vector /// void SetRotation( double array[3][3] ); /// /// method to set translation by cv vector /// void SetTranslation( const cv::Mat& transl); /// /// sets rotation with a rotation matrix /// void SetRotation( const cv::Mat& mat ); /// /// sets rotation with a rodrigues rotation vector /// void SetRotationVector( const cv::Mat& rotVec); /// /// \return the navigation data that stores all information /// mitk::NavigationData::Pointer GetNavigationData() const; /// /// calls navigationdata::GetPosition() /// mitk::Point3D GetPosition() const; /// /// same as GetPosition /// mitk::Point3D GetTranslation() const; /// /// calls navigationdata::IsValid() /// bool IsValid() const; /// /// calls navigationdata::SetValid() /// void SetValid(bool valid); /// /// calls navigationdata::GetOrientation() /// mitk::Quaternion GetOrientation() const; /// /// \return the homogeneous matrix representing this transform /// vnl_matrix_fixed GetMatrix() const; /// /// \return the homogeneous vtk matrix representing this transform /// void GetMatrix(vtkMatrix4x4* matrix) const; /// /// \return the homogeneous vtk matrix representing this transform /// in !OpenGL! left handed coordinate system /// void GetVtkOpenGlMatrix(vtkMatrix4x4* matrix) const; /// /// create xml representation /// void ToXML(TiXmlElement* elem) const; /// /// create string representation /// std::string ToString() const; /// /// create string csv representation (only the transformation values!!!!) /// std::string ToCSVString() const; /// /// create matlab representation /// std::string ToMatlabString(const std::string& varname="transform", bool printLastRow=true) const; /// /// write csv representation to file (only the transformation values!!!!) /// void ToCSVFile(const std::string& file) const; /// /// write matlab representation to file /// void ToMatlabFile(const std::string& file , const std::string& varname="transform") const; /// /// conversion to cv types /// cv::Mat GetCvTranslation() const; cv::Mat GetCvRotationVector() const; cv::Mat GetCvRotationMatrix() const; cv::Mat GetCvMatrix() const; /// /// conversion to vnl types /// vnl_vector_fixed GetVnlTranslation() const; vnl_vector_fixed GetVnlDoubleTranslation() const; vnl_quaternion GetVnlDoubleQuaternion() const; vnl_matrix_fixed GetVnlRotationMatrix() const; vnl_matrix_fixed GetVnlDoubleMatrix() const; protected: Transform(); Transform(const mitk::NavigationData* nd); + Transform(const std::string& s); // everything is stored here mitk::NavigationData::Pointer m_NavData; /// /// saves the type of the transform (Default is UNKNOWN_TYPE) /// std::string m_Type; }; } // namespace mitk mitkCameraCalibration_EXPORT std::ostream& operator<< (std::ostream& os, mitk::Transform::Pointer p); #endif // MITKTRANSFORM_H diff --git a/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.cpp b/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.cpp index 816471362e..9b18685651 100644 --- a/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.cpp +++ b/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.cpp @@ -1,325 +1,357 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2007-12-11 14:46:19 +0100 (Di, 11 Dez 2007) $ Version: $Revision: 13129 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkNavigationDataRecorder.h" #include #include #include #include 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_RecordCountLimit = -1; m_DoNotOverwriteFiles = false; //To get a start time mitk::TimeStamp::GetInstance()->Start(this); } mitk::NavigationDataRecorder::~NavigationDataRecorder() { } void mitk::NavigationDataRecorder::GenerateData() { } 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->Modified(); } void mitk::NavigationDataRecorder::SetRecordingMode( RecordingMode mode ) { m_RecordingMode = mode; this->Modified(); } void mitk::NavigationDataRecorder::Update() { if (m_Recording) { DataObjectPointerArray inputs = this->GetInputs(); //get all inputs mitk::NavigationData::TimeStampType timestamp=0.0; // timestamp for mitk time timestamp = mitk::TimeStamp::GetInstance()->GetElapsed(); mitk::NavigationData::TimeStampType sysTimestamp = 0.0; // timestamp for system time sysTimestamp = m_SystemTimeClock->GetCurrentStamp(); // 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(); //if csv-mode: write csv header and timpstamp 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++) { 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->GetTimeStamp(); //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"; } } 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; + } + +} + +void mitk::NavigationDataRecorder::RemoveAdditionalAttribute( const NavigationData* nd ) +{ + std::map >::iterator + it = m_AdditionalAttributes.find( nd ); + if( it != m_AdditionalAttributes.end() ) + m_AdditionalAttributes.erase(it); +} + void mitk::NavigationDataRecorder::StartRecording() { if (m_Recording) { std::cout << "Already recording please stop before start new recording session" << std::endl; return; } 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: //Check if there is a file name and path if (m_FileName == "") { stream = &std::cout; std::cout << "No file name or file path set the output is redirected to the console"; } else { stream = new std::ofstream(ss.str().c_str()); } break; case ZipFile: stream = &std::cout; std::cout << "Sorry no ZipFile support yet"; break; default: stream = &std::cout; break; } m_firstLine = true; m_RecordCounter = 0; StartRecording(stream); } } void mitk::NavigationDataRecorder::StartRecording(std::ostream* stream) { if (m_Recording) { std::cout << "Already recording please stop before start new recording session" << std::endl; return; } m_Stream = stream; m_Stream->precision(10); //TODO store date and GMT time if (m_Stream) { 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; } } void mitk::NavigationDataRecorder::StopRecording() { if (!m_Recording) { std::cout << "You have to start a recording first" << std::endl; return; } if ((m_Stream) && (m_OutputFormat == mitk::NavigationDataRecorder::xml)) { *m_Stream << "" << std::endl; } m_NumberOfRecordedFiles++; m_Recording = false; m_Stream->flush(); m_Stream = NULL; -} \ No newline at end of file +} diff --git a/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.h b/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.h index f0f22a4ff7..8c45e09864 100644 --- a/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.h +++ b/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.h @@ -1,193 +1,204 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2008-02-08 13:23:19 +0100 (Fr, 08 Feb 2008) $ Version: $Revision: 13561 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef _MITK_NavigationDataRecorder_H #define _MITK_NavigationDataRecorder_H #include #include "mitkNavigationData.h" #include #include 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 ); itkNewMacro( Self ); /** * \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 */ itkSetStringMacro(FileName); /** * \brief Returns the file name of the recording file (in OutputMode NormalFile and ZipFile) */ itkGetStringMacro(FileName); /** * \brief If true the recorder will never overwrite a file */ itkSetMacro(DoNotOverwriteFiles,bool); /** * \brief Returns whether the NavigationDataRecorder is recording or not */ itkGetMacro(Recording,bool); /** * \brief Returns the number of data sets / frames which were recorded by the NavigationDataRecorder since start */ itkGetMacro(RecordCounter,int); /** * \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. */ itkSetMacro(RecordCountLimit,int); /** * \brief Adds the input NavigationDatas */ 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 ); + /**Documentation * \brief Starts the recording with the presetted OutputMode * this method calls StartRecording(std::ostream*) */ void StartRecording(); /**Documentation * \brief Starts the recording with an own preinitialized stream */ 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 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 }; /**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. */ itkSetMacro(OutputFormat,mitk::NavigationDataRecorder::OutputFormatEnum); 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 RecordingMode m_RecordingMode; ///< stores the mode see enum RecordingMode OutputFormatEnum m_OutputFormat; ///< stores the output format; see enum OutputFormat 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 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; + }; } #endif // #define _MITK_POINT_SET_SOURCE_H