diff --git a/Modules/IGT/Rendering/mitkNavigationDataObjectVisualizationFilter.cpp b/Modules/IGT/Rendering/mitkNavigationDataObjectVisualizationFilter.cpp index 413a67888f..930c473485 100644 --- a/Modules/IGT/Rendering/mitkNavigationDataObjectVisualizationFilter.cpp +++ b/Modules/IGT/Rendering/mitkNavigationDataObjectVisualizationFilter.cpp @@ -1,243 +1,256 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkNavigationDataObjectVisualizationFilter.h" #include "mitkDataStorage.h" - +#include mitk::NavigationDataObjectVisualizationFilter::NavigationDataObjectVisualizationFilter() -: NavigationDataToNavigationDataFilter(), -m_RepresentationList(), m_TransformPosition(), m_TransformOrientation(), m_RotationMode(RotationStandard) + : NavigationDataToNavigationDataFilter(), + m_RepresentationVectorMap(), + m_TransformPosition(), + m_TransformOrientation(), + m_RotationMode(RotationStandard) { - } - mitk::NavigationDataObjectVisualizationFilter::~NavigationDataObjectVisualizationFilter() { - m_RepresentationList.clear(); + m_RepresentationVectorMap.clear(); m_OffsetList.clear(); } +mitk::BaseData::Pointer mitk::NavigationDataObjectVisualizationFilter::GetRepresentationObject(unsigned int idx) const +{ + auto iter = m_RepresentationVectorMap.find(idx); + if (iter != m_RepresentationVectorMap.end()) + return iter->second.at(0); + + return nullptr; +} -const mitk::BaseData* mitk::NavigationDataObjectVisualizationFilter::GetRepresentationObject(unsigned int idx) +std::vector mitk::NavigationDataObjectVisualizationFilter::GetAllRepresentationObjects(unsigned int idx) const { - RepresentationPointerMap::const_iterator iter = m_RepresentationList.find(idx); - if (iter != m_RepresentationList.end()) + RepresentationVectorPointerMap::const_iterator iter = m_RepresentationVectorMap.find(idx); + if (iter != m_RepresentationVectorMap.end()) return iter->second; - return nullptr; + std::vector empty; + return empty; } mitk::AffineTransform3D::Pointer mitk::NavigationDataObjectVisualizationFilter::GetOffset(int index) { OffsetPointerMap::const_iterator iter = m_OffsetList.find(index); if (iter != m_OffsetList.end()) return iter->second; return nullptr; } +void mitk::NavigationDataObjectVisualizationFilter::SetRepresentationObject(unsigned int idx, BaseData::Pointer data) +{ + std::vector dataVector; + dataVector.push_back(data); + SetRepresentationObjects(idx, dataVector); +} -void mitk::NavigationDataObjectVisualizationFilter::SetRepresentationObject(unsigned int idx, BaseData* data) +void mitk::NavigationDataObjectVisualizationFilter::SetRepresentationObjects(unsigned int idx, const std::vector &data) { - m_RepresentationList[idx] = RepresentationPointer(data); + m_RepresentationVectorMap[idx] = data; } void mitk::NavigationDataObjectVisualizationFilter::SetOffset(int index, mitk::AffineTransform3D::Pointer offset) { -m_OffsetList[index] = offset; + m_OffsetList[index] = offset; } - void mitk::NavigationDataObjectVisualizationFilter::SetRotationMode(RotationMode r) { m_RotationMode = r; } - void mitk::NavigationDataObjectVisualizationFilter::GenerateData() { /*get each input, lookup the associated BaseData and transfer the data*/ - DataObjectPointerArray inputs = this->GetInputs(); //get all inputs - for (unsigned int index=0; index < inputs.size(); index++) + DataObjectPointerArray inputs = this->GetInputs(); // get all inputs + for (unsigned int index = 0; index < inputs.size(); index++) { - //get the needed variables - const mitk::NavigationData* nd = this->GetInput(index); + // get the needed variables + const mitk::NavigationData *nd = this->GetInput(index); assert(nd); - mitk::NavigationData* output = this->GetOutput(index); + mitk::NavigationData *output = this->GetOutput(index); assert(output); - //check if the data is valid + // check if the data is valid if (!nd->IsDataValid()) { output->SetDataValid(false); continue; } output->Graft(nd); // copy all information from input to output - const mitk::BaseData* data = this->GetRepresentationObject(index); - if (data == nullptr) - { - MITK_WARN << "No BaseData associated with input " << index; - continue; - } - //get the transform from data - mitk::AffineTransform3D::Pointer affineTransform = data->GetGeometry()->GetIndexToWorldTransform(); - if (affineTransform.IsNull()) + const std::vector data = + this->GetAllRepresentationObjects(index); + + for (unsigned int dataIdx = 0; dataIdx < data.size(); dataIdx++) { - MITK_WARN << "AffineTransform IndexToWorldTransform not initialized!"; - continue; - } + if (data.at(dataIdx) == nullptr) + { + MITK_WARN << "No BaseData associated with input " << index; + continue; + } + + // get the transform from data + mitk::AffineTransform3D::Pointer affineTransform = data.at(dataIdx)->GetGeometry()->GetIndexToWorldTransform(); + if (affineTransform.IsNull()) + { + MITK_WARN << "AffineTransform IndexToWorldTransform not initialized!"; + continue; + } - //check for offset - mitk::AffineTransform3D::Pointer offset = this->GetOffset(index); + // check for offset + mitk::AffineTransform3D::Pointer offset = this->GetOffset(index); - //store the current scaling to set it after transformation - mitk::Vector3D spacing = data->GetGeometry()->GetSpacing(); - //clear spacing of data to be able to set it again afterwards - ScalarType scale[] = {1.0, 1.0, 1.0}; - data->GetGeometry()->SetSpacing(scale); + // store the current scaling to set it after transformation + mitk::Vector3D spacing = data.at(dataIdx)->GetGeometry()->GetSpacing(); + // clear spacing of data to be able to set it again afterwards + ScalarType scale[] = {1.0, 1.0, 1.0}; + data.at(dataIdx)->GetGeometry()->SetSpacing(scale); - /*now bring quaternion to affineTransform by using vnl_Quaternion*/ - affineTransform->SetIdentity(); + /*now bring quaternion to affineTransform by using vnl_Quaternion*/ + affineTransform->SetIdentity(); - if (this->GetTransformOrientation(index) == true) - { - mitk::NavigationData::OrientationType orientation = nd->GetOrientation(); + if (this->GetTransformOrientation(index) == true) + { + mitk::NavigationData::OrientationType orientation = nd->GetOrientation(); - /* because of an itk bug, the transform can not be calculated with float data type. - To use it in the mitk geometry classes, it has to be transfered to mitk::ScalarType which is float */ - static AffineTransform3D::MatrixType m; + /* because of an itk bug, the transform can not be calculated with float data type. + To use it in the mitk geometry classes, it has to be transfered to mitk::ScalarType which is float */ + static AffineTransform3D::MatrixType m; - //convert quaternion to rotation matrix depending on the rotation mode - if(m_RotationMode == RotationStandard) + // convert quaternion to rotation matrix depending on the rotation mode + if (m_RotationMode == RotationStandard) { - //calculate the transform from the quaternions - static itk::QuaternionRigidTransform::Pointer quatTransform = itk::QuaternionRigidTransform::New(); - // convert mitk::ScalarType quaternion to double quaternion because of itk bug - vnl_quaternion doubleQuaternion(orientation.x(), orientation.y(), orientation.z(), orientation.r()); - quatTransform->SetIdentity(); - quatTransform->SetRotation(doubleQuaternion); - quatTransform->Modified(); - mitk::TransferMatrix(quatTransform->GetMatrix(), m); + // calculate the transform from the quaternions + static itk::QuaternionRigidTransform::Pointer quatTransform = + itk::QuaternionRigidTransform::New(); + // convert mitk::ScalarType quaternion to double quaternion because of itk bug + vnl_quaternion doubleQuaternion(orientation.x(), orientation.y(), orientation.z(), orientation.r()); + quatTransform->SetIdentity(); + quatTransform->SetRotation(doubleQuaternion); + quatTransform->Modified(); + mitk::TransferMatrix(quatTransform->GetMatrix(), m); } - else if(m_RotationMode == RotationTransposed) + else if (m_RotationMode == RotationTransposed) { - vnl_matrix_fixed rot = orientation.rotation_matrix_transpose(); - for(int i=0; i<3; i++) for (int j=0; j<3; j++) m[i][j] = rot[i][j]; + vnl_matrix_fixed rot = orientation.rotation_matrix_transpose(); + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + m[i][j] = rot[i][j]; } - affineTransform->SetMatrix(m); - - } - if (this->GetTransformPosition(index) == true) - { - ///*set the offset by convert from itkPoint to itkVector and setting offset of transform*/ - mitk::Vector3D pos; - pos.SetVnlVector(nd->GetPosition().GetVnlVector()); - affineTransform->SetOffset(pos); - } - affineTransform->Modified(); - + affineTransform->SetMatrix(m); + } + if (this->GetTransformPosition(index) == true) + { + ///*set the offset by convert from itkPoint to itkVector and setting offset of transform*/ + mitk::Vector3D pos; + pos.SetVnlVector(nd->GetPosition().GetVnlVector()); + affineTransform->SetOffset(pos); + } + affineTransform->Modified(); - //set the transform to data - if(offset.IsNotNull()) //first use offset if there is one. + // set the transform to data + if (offset.IsNotNull()) // first use offset if there is one. { - mitk::AffineTransform3D::Pointer overallTransform = mitk::AffineTransform3D::New(); - overallTransform->SetIdentity(); - overallTransform->Compose(offset); - overallTransform->Compose(affineTransform); - data->GetGeometry()->SetIndexToWorldTransform(overallTransform); + mitk::AffineTransform3D::Pointer overallTransform = mitk::AffineTransform3D::New(); + overallTransform->SetIdentity(); + overallTransform->Compose(offset); + overallTransform->Compose(affineTransform); + data.at(dataIdx)->GetGeometry()->SetIndexToWorldTransform(overallTransform); } - else + else { - data->GetGeometry()->SetIndexToWorldTransform(affineTransform); + data.at(dataIdx)->GetGeometry()->SetIndexToWorldTransform(affineTransform); } - //set the original spacing to keep scaling of the geometrical object - data->GetGeometry()->SetSpacing(spacing); - data->GetGeometry()->Modified(); - data->Modified(); - output->SetDataValid(true); // operation was successful, therefore data of output is valid. + // set the original spacing to keep scaling of the geometrical object + data.at(dataIdx)->GetGeometry()->SetSpacing(spacing); + data.at(dataIdx)->GetGeometry()->Modified(); + data.at(dataIdx)->Modified(); + output->SetDataValid(true); // operation was successful, therefore data of output is valid. + } } } - -void mitk::NavigationDataObjectVisualizationFilter::SetTransformPosition( unsigned int index, bool applyTransform ) +void mitk::NavigationDataObjectVisualizationFilter::SetTransformPosition(unsigned int index, bool applyTransform) { itkDebugMacro("setting TransformPosition for index " << index << " to " << applyTransform); BooleanInputMap::const_iterator it = this->m_TransformPosition.find(index); if ((it != this->m_TransformPosition.end()) && (it->second == applyTransform)) return; this->m_TransformPosition[index] = applyTransform; this->Modified(); } - -bool mitk::NavigationDataObjectVisualizationFilter::GetTransformPosition( unsigned int index ) const +bool mitk::NavigationDataObjectVisualizationFilter::GetTransformPosition(unsigned int index) const { itkDebugMacro("returning TransformPosition for index " << index); BooleanInputMap::const_iterator it = this->m_TransformPosition.find(index); if (it != this->m_TransformPosition.end()) return it->second; else return true; // default to true } - -void mitk::NavigationDataObjectVisualizationFilter::TransformPositionOn( unsigned int index ) +void mitk::NavigationDataObjectVisualizationFilter::TransformPositionOn(unsigned int index) { this->SetTransformPosition(index, true); } - -void mitk::NavigationDataObjectVisualizationFilter::TransformPositionOff( unsigned int index ) +void mitk::NavigationDataObjectVisualizationFilter::TransformPositionOff(unsigned int index) { this->SetTransformPosition(index, false); } - -void mitk::NavigationDataObjectVisualizationFilter::SetTransformOrientation( unsigned int index, bool applyTransform ) +void mitk::NavigationDataObjectVisualizationFilter::SetTransformOrientation(unsigned int index, bool applyTransform) { itkDebugMacro("setting TransformOrientation for index " << index << " to " << applyTransform); BooleanInputMap::const_iterator it = this->m_TransformOrientation.find(index); if ((it != this->m_TransformOrientation.end()) && (it->second == applyTransform)) return; this->m_TransformOrientation[index] = applyTransform; - this->Modified(); \ + this->Modified(); } - -bool mitk::NavigationDataObjectVisualizationFilter::GetTransformOrientation( unsigned int index ) const +bool mitk::NavigationDataObjectVisualizationFilter::GetTransformOrientation(unsigned int index) const { itkDebugMacro("returning TransformOrientation for index " << index); BooleanInputMap::const_iterator it = this->m_TransformOrientation.find(index); if (it != this->m_TransformOrientation.end()) return it->second; else return true; // default to true } - -void mitk::NavigationDataObjectVisualizationFilter::TransformOrientationOn( unsigned int index ) +void mitk::NavigationDataObjectVisualizationFilter::TransformOrientationOn(unsigned int index) { this->SetTransformOrientation(index, true); } - -void mitk::NavigationDataObjectVisualizationFilter::TransformOrientationOff( unsigned int index ) +void mitk::NavigationDataObjectVisualizationFilter::TransformOrientationOff(unsigned int index) { this->SetTransformOrientation(index, false); } diff --git a/Modules/IGT/Rendering/mitkNavigationDataObjectVisualizationFilter.h b/Modules/IGT/Rendering/mitkNavigationDataObjectVisualizationFilter.h index bbfd2df5ba..42871e0337 100644 --- a/Modules/IGT/Rendering/mitkNavigationDataObjectVisualizationFilter.h +++ b/Modules/IGT/Rendering/mitkNavigationDataObjectVisualizationFilter.h @@ -1,153 +1,176 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef MITKNAVIGATIONDATAOBJECTVISUALIZATIONFILTER_H_HEADER_INCLUDED_ #define MITKNAVIGATIONDATAOBJECTVISUALIZATIONFILTER_H_HEADER_INCLUDED_ #include "mitkNavigationDataToNavigationDataFilter.h" #include "mitkNavigationData.h" #include "mitkBaseData.h" namespace mitk { /** * \brief Class that reads NavigationData from input and transfers the information to the geometry of the associated BaseData * * Derived from NavigationDataToNavigationDataFilter * * \ingroup IGT */ class MITKIGT_EXPORT NavigationDataObjectVisualizationFilter : public NavigationDataToNavigationDataFilter { public: mitkClassMacro(NavigationDataObjectVisualizationFilter, NavigationDataToNavigationDataFilter); itkFactorylessNewMacro(Self); itkCloneMacro(Self); /** Defines the rotation modes of this tracking device which results in different representations * of quaternions. * * - Standard: normal representation, rawdata from the device is not changed (DEFAULT) * * - Transposed: the rotation is stored transposed, which is (by mistake!) expected by some older MITK classes due * to an ambigious method naming in VNL. * * CAUTION: The rotation mode can only be changed for backward compatibility of old WRONG code. * PLEASE DO NOT CHANGE THE ROTATION MODE UNLESS YOU ARE KNOWING EXACTLY WHAT YOU ARE DOING! * * use SetRotationMode to change the mode. */ enum RotationMode {RotationStandard, RotationTransposed}; /** * \brief Smart Pointer type to a BaseData. */ - typedef BaseData::ConstPointer RepresentationPointer; + typedef BaseData::Pointer RepresentationPointer; /** - * \brief STL map of index to BaseData . Using map to be able to set non continuous indices - */ + * \brief STL map of index to BaseData . Using map to be able to set non continuous indices + */ typedef std::map RepresentationPointerMap; /** - * \brief Size type of an std::vector + * \brief STL vector map of index to BaseData . Using map to be able to set non continuous indices */ - typedef RepresentationPointerMap::size_type RepresentationPointerMapSizeType; + typedef std::map> RepresentationVectorPointerMap; + + /** + * \brief Size type of an std::vector + */ + typedef RepresentationVectorPointerMap::size_type RepresentationPointerMapSizeType; /** * \brief Set the representation object of the input * * \param data The BaseData to be associated to the index * \param index the index with which data will be associated */ - void SetRepresentationObject(unsigned int index, BaseData* data); + void SetRepresentationObject(unsigned int index, BaseData::Pointer data); + /** + * \brief Set the representation objects vector of the input + * + * \param data The BaseData vector to be associated to the index + * \param index the index with which data will be associated + */ + void SetRepresentationObjects(unsigned int index, const std::vector &data); + /** * \brief Get the representation object associated with the index idx * * \param idx the corresponding input number with which the BaseData is associated * \return Returns the desired BaseData if it exists for the given input; Returns nullptr * if no BaseData was found. */ - const BaseData* GetRepresentationObject(unsigned int idx); + BaseData::Pointer GetRepresentationObject(unsigned int idx) const; + + /** + * \brief Get all the representation objects associated with the index idx + * + * \param idx the corresponding input number with which the BaseData is associated + * \return Returns the desired BaseData if it exists for the given input; Returns nullptr + * if no BaseData was found. + */ + std::vector GetAllRepresentationObjects(unsigned int idx) const; virtual void SetTransformPosition(unsigned int index, bool applyTransform); ///< if set to true, the filter will use the position part of the input navigation data at the given index to transform the representation object. If set to false, it will not. If no value is set, it defaults to true. virtual bool GetTransformPosition(unsigned int index) const; ///< returns whether position part of the input navigation data at the given index is used for the transformation of the representation object. virtual void TransformPositionOn(unsigned int index); ///< sets the TransformPosition flag to true for the given index virtual void TransformPositionOff(unsigned int index); ///< sets the TransformPosition flag to false for the given index virtual void SetTransformOrientation(unsigned int index, bool applyTransform); ///< if set to true, the filter will use the orientation part of the input navigation data at the given index to transform the representation object. If set to false, it will not. If no value is set, it defaults to true. virtual bool GetTransformOrientation(unsigned int index) const; ///< returns whether orientation part of the input navigation data at the given index is used for the transformation of the representation object. virtual void TransformOrientationOn(unsigned int index); ///< sets the TransformOrientation flag to true for the given index virtual void TransformOrientationOff(unsigned int index); ///< sets the TransformOrientation flag to false for the given index /** @brief Defines an offset for a representation object. This offset is applied before the object is visualized. * If no offset is given, no offset will be used. To deactivate the offset just set it to nullptr. The offset is deactivated by default. * @param offset The new offset which will be set. Set to nullptr to deactivate the offset. */ void SetOffset(int index, mitk::AffineTransform3D::Pointer offset); /** Sets the rotation mode of this class. See documentation of enum RotationMode for details * on the different modes. * CAUTION: The rotation mode can only be changed for backward compatibility of old WRONG code. * PLEASE DO NOT CHANGE THE ROTATION MODE UNLESS YOU ARE KNOWING EXACTLY WHAT YOU ARE DOING! */ virtual void SetRotationMode(RotationMode r); /** @return Returns the offset of a represenation object. Returns nullptr if there is no offset. */ mitk::AffineTransform3D::Pointer GetOffset(int index); /** *\brief Get the number of added BaseData associated to NavigationData * \return Returns the size of the internal map */ RepresentationPointerMapSizeType GetNumberOfToolRepresentations() const { - return m_RepresentationList.size(); + return m_RepresentationVectorMap.size(); } /* * \brief Transfer the information from the input to the associated BaseData */ void GenerateData() override; protected: typedef std::map BooleanInputMap; typedef std::map OffsetPointerMap; /** * \brief Constructor **/ NavigationDataObjectVisualizationFilter(); /** * \brief Destructor **/ ~NavigationDataObjectVisualizationFilter() override; /** * \brief An array of the BaseData which represent the tools. */ - RepresentationPointerMap m_RepresentationList; + + RepresentationVectorPointerMap m_RepresentationVectorMap; BooleanInputMap m_TransformPosition; ///< if set to true, the filter will use the position part of the input navigation data at the given index for the calculation of the transform. If no entry for the index exists, it defaults to true. BooleanInputMap m_TransformOrientation; ///< if set to true, the filter will use the orientation part of the input navigation data at the given index for the calculation of the transform. If no entry for the index exists, it defaults to true. OffsetPointerMap m_OffsetList; private: RotationMode m_RotationMode; ///< defines the rotation mode Standard or Transposed, Standard is default }; } // namespace mitk #endif /* MITKNAVIGATIONDATAOBJECTVISUALIZATIONFILTER_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/Testing/mitkNavigationDataObjectVisualizationFilterTest.cpp b/Modules/IGT/Testing/mitkNavigationDataObjectVisualizationFilterTest.cpp index ef5726e4bc..2163f6531a 100644 --- a/Modules/IGT/Testing/mitkNavigationDataObjectVisualizationFilterTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationDataObjectVisualizationFilterTest.cpp @@ -1,433 +1,458 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkNavigationDataObjectVisualizationFilter.h" #include "mitkNavigationData.h" #include "mitkTestingMacros.h" #include #include #include #include #include "mitkSurface.h" /**Documentation * test for the class "NavigationDataObjectVisualizationFilter". */ class mitkNavigationDataObjectVisualizationFilterTestSuite : public mitk::TestFixture { // List of Tests CPPUNIT_TEST_SUITE(mitkNavigationDataObjectVisualizationFilterTestSuite); //Constructor MITK_TEST(TestInitialize); MITK_TEST(TestInput); MITK_TEST(TestOutput); MITK_TEST(TestRepresentationObjects); MITK_TEST(TestTransforms); MITK_TEST(TestMessWithRepresentationObjects); MITK_TEST(TestThirdInput); MITK_TEST(TestSetTransformPosition); MITK_TEST(TestSetTransformOrientation); MITK_TEST(TestConvenienceSetTransformOrientation); MITK_TEST(TestUpdateOrientation); CPPUNIT_TEST_SUITE_END(); // Used Variables private: mitk::NavigationDataObjectVisualizationFilter::Pointer myFilter; mitk::NavigationData::PositionType initialPos1, initialPos2; mitk::NavigationData::OrientationType initialOri1; mitk::NavigationData::OrientationType initialOri2; mitk::ScalarType initialError1; mitk::ScalarType initialError2; bool initialValid1; bool initialValid2; mitk::NavigationData::Pointer nd1; mitk::NavigationData::Pointer nd2; // Test setting BaseData - mitk::Surface::Pointer mitkToolData1 ; - - mitk::Surface::Pointer mitkToolData2 ; + mitk::Surface::Pointer mitkToolData1; + std::vector mitkToolVectorData1; + mitk::Surface::Pointer mitkToolData2; + std::vector mitkToolVectorData2; //dummy for test; will not be set but used to test find - mitk::Surface::Pointer mitkToolDataDummy ; + mitk::Surface::Pointer mitkToolDataDummy; + std::vector mitkToolVectorDataDummy; //and the Dummy NavigationData for this mitk::NavigationData::OrientationType initialOriDummy; mitk::NavigationData::PositionType initialPosDummy; mitk::ScalarType initialErrorDummy; bool initialValidDummy; mitk::NavigationData::Pointer ndDummy ; mitk::NavigationData* output; mitk::AffineTransform3D::Pointer affineTransform1; mitk::AffineTransform3D::OutputVectorType offset1; mitk::AffineTransform3D::Pointer affineTransform2; mitk::AffineTransform3D::OutputVectorType offset2; mitk::AffineTransform3D::MatrixType::InternalMatrixType m1; mitk::AffineTransform3D::MatrixType::InternalMatrixType m2; public: // Set up for variables void setUp() override { // -------------- Setup for Filter --------------------------- /* create helper objects: navigation data with position as origin, zero quaternion, zero error and data valid */ myFilter = mitk::NavigationDataObjectVisualizationFilter::New(); mitk::FillVector3D(initialPos1, 1.1, 2.2, 3.3); mitk::FillVector3D(initialPos2, 5.0, 6.0, 7.0); mitk::FillVector4D(initialOri1, 0.1, 0.2, 0.3, 0.4); mitk::FillVector4D(initialOri2,0.5, 0.6, 0.7, 0.8); initialError1=0.0; initialError2=5.0; initialValid1 = true; initialValid2 = true; //Set Navigation Data nd1 = mitk::NavigationData::New(); nd1->SetPosition(initialPos1); nd1->SetOrientation(initialOri1); nd1->SetPositionAccuracy(initialError1); nd1->SetDataValid(initialValid1); nd2 = mitk::NavigationData::New(); nd2->SetPosition(initialPos2); nd2->SetOrientation(initialOri2); nd2->SetPositionAccuracy(initialError2); nd2->SetDataValid(initialValid2); //Set Input myFilter->SetInput(nd1); myFilter->SetInput(1, nd2); output = myFilter->GetOutput(); // -------------------------- Setup for TestData ---------------------- // Test setting BaseData mitkToolData1 = mitk::Surface::New(); mitkToolData2 = mitk::Surface::New(); + // Test setting BaseData vectors + mitkToolVectorData1.push_back(mitkToolData1.GetPointer()); + mitkToolVectorData2.push_back(mitkToolData2.GetPointer()); + //dummy for test; will not be set but used to test find mitkToolDataDummy = mitk::Surface::New(); + mitkToolVectorDataDummy.push_back(mitkToolDataDummy.GetPointer()); //and the Dummy NavigationData for this mitk::FillVector3D(initialPosDummy, 8.8, 9.9, 10.10); mitk::FillVector4D(initialOriDummy,1.1, 2.2, 3.3, 4.4); initialErrorDummy=10.0; initialValidDummy=true; ndDummy = mitk::NavigationData::New(); ndDummy->SetPosition(initialPosDummy); ndDummy->SetOrientation(initialOriDummy); ndDummy->SetPositionAccuracy(initialErrorDummy); ndDummy->SetDataValid(initialValidDummy); //now we have ndDummy and mitkToolDataDummy to test with } void tearDown() override { } // Test functions void TestInitialize(){ // first test: did this work? CPPUNIT_ASSERT_MESSAGE("Testing instantiation", myFilter.IsNotNull()); } void TestInput(){ //testing the input CPPUNIT_ASSERT_MESSAGE("Testing Set-/GetInput() input 1 without index",myFilter->GetInput() == nd1); CPPUNIT_ASSERT_MESSAGE("Testing Set-/GetInput() input 1", myFilter->GetInput(0) == nd1); CPPUNIT_ASSERT_MESSAGE( "Testing Set-/GetInput() input 2", myFilter->GetInput(1) == nd2); CPPUNIT_ASSERT_MESSAGE("Testing GetNumberOfToolRepresentations()", myFilter->GetNumberOfToolRepresentations() == 0); } void TestOutput(){ //testing getting the output CPPUNIT_ASSERT_MESSAGE("Testing GetOutput()", output != nullptr); CPPUNIT_ASSERT_MESSAGE("Testing GetOutput() == GetOutput()", output == myFilter->GetOutput()); CPPUNIT_ASSERT_MESSAGE("Testing GetOutput() != GetOutput(1)", output != myFilter->GetOutput(1)); } void TestRepresentationObjects(){ //setting nodes - myFilter->SetRepresentationObject(0, mitkToolData1); + myFilter->SetRepresentationObject(0, mitkToolData1.GetPointer()); CPPUNIT_ASSERT_MESSAGE( "Testing SetRepresentationObject()/GetRepresentationObject() node 1", myFilter->GetRepresentationObject(0) == mitkToolData1); CPPUNIT_ASSERT_MESSAGE("Testing GetNumberOfToolRepresentations() after adding first tool", myFilter->GetNumberOfToolRepresentations() == 1); - myFilter->SetRepresentationObject(1, mitkToolData2); + myFilter->SetRepresentationObject(1, mitkToolData2.GetPointer()); CPPUNIT_ASSERT_MESSAGE( "Testing SetRepresentationObject() node 2", myFilter->GetRepresentationObject(1) == mitkToolData2); CPPUNIT_ASSERT_MESSAGE( "Testing GetNumberOfToolRepresentations() after adding second tool", myFilter->GetNumberOfToolRepresentations() == 2); //getting nodes CPPUNIT_ASSERT_MESSAGE("Testing GetRepresentationObject() node 1", myFilter->GetRepresentationObject(0) == mitkToolData1); CPPUNIT_ASSERT_MESSAGE( "Testing GetRepresentationObject() != Dummy node", myFilter->GetRepresentationObject(0) != mitkToolDataDummy); CPPUNIT_ASSERT_MESSAGE( "Testing GetRepresentationObject() node 2", myFilter->GetRepresentationObject(1) == mitkToolData2); CPPUNIT_ASSERT_MESSAGE( "Testing GetRepresentationObject() != Dummy node", myFilter->GetRepresentationObject(1) != mitkToolDataDummy); CPPUNIT_ASSERT_MESSAGE("Testing GetRepresentationObject() with out of range parameter", myFilter->GetRepresentationObject(111) == nullptr); } + void TestAllRepresentationObjects() + { + // setting nodes + myFilter->SetRepresentationObjects(0, mitkToolVectorData1); + CPPUNIT_ASSERT_MESSAGE("Testing SetRepresentationObject()/GetRepresentationObject() node 1", myFilter->GetAllRepresentationObjects(0) == mitkToolVectorData1); + CPPUNIT_ASSERT_MESSAGE("Testing GetNumberOfToolRepresentations() after adding first tool", myFilter->GetNumberOfToolRepresentations() == 1); + + myFilter->SetRepresentationObjects(1, mitkToolVectorData2); + CPPUNIT_ASSERT_MESSAGE("Testing SetRepresentationObject() node 2", myFilter->GetAllRepresentationObjects(1) == mitkToolVectorData2); + CPPUNIT_ASSERT_MESSAGE("Testing GetNumberOfToolRepresentations() after adding second tool", myFilter->GetNumberOfToolRepresentations() == 2); + // getting nodes + CPPUNIT_ASSERT_MESSAGE("Testing GetRepresentationObject() node 1", myFilter->GetAllRepresentationObjects(0) == mitkToolVectorData1); + CPPUNIT_ASSERT_MESSAGE("Testing GetRepresentationObject() != Dummy node", myFilter->GetAllRepresentationObjects(0) != mitkToolVectorDataDummy); + CPPUNIT_ASSERT_MESSAGE("Testing GetRepresentationObject() node 2", myFilter->GetAllRepresentationObjects(1) == mitkToolVectorData2); + CPPUNIT_ASSERT_MESSAGE("Testing GetRepresentationObject() != Dummy node", myFilter->GetAllRepresentationObjects(1) != mitkToolVectorDataDummy); + CPPUNIT_ASSERT_MESSAGE("Testing GetRepresentationObject() with out of range parameter", myFilter->GetAllRepresentationObjects(111).empty() == true); + } + void TestTransforms(){ - myFilter->SetRepresentationObject(0, mitkToolData1); - myFilter->SetRepresentationObject(1, mitkToolData2); + myFilter->SetRepresentationObject(0, mitkToolData1.GetPointer()); + myFilter->SetRepresentationObject(1, mitkToolData2.GetPointer()); //Process myFilter->Update(); affineTransform1 = mitkToolData1->GetGeometry()->GetIndexToWorldTransform(); offset1 = affineTransform1->GetOffset(); affineTransform2 = mitkToolData2->GetGeometry()->GetIndexToWorldTransform(); offset2 = affineTransform2->GetOffset(); m1 = affineTransform1->GetMatrix().GetVnlMatrix(); m2 = affineTransform2->GetMatrix().GetVnlMatrix(); //now check it there are data connected to the nodes with the according orientation and offsets CPPUNIT_ASSERT_MESSAGE("Testing Offset position 1", offset1.GetVnlVector()==initialPos1.GetVnlVector()); CPPUNIT_ASSERT_MESSAGE("Testing Offset position 2", offset2.GetVnlVector()==initialPos2.GetVnlVector()); MITK_TEST_OUTPUT( << "\n initOrient1="<GetVnlMatrix():\n "<< m1); MITK_TEST_OUTPUT( << "\n initOrient2=" << initialOri2 << " affineTransform2->GetVnlMatrix():\n " << m2); } void TestMessWithRepresentationObjects(){ - myFilter->SetRepresentationObject(0, mitkToolData1); - myFilter->SetRepresentationObject(1, mitkToolData2); + myFilter->SetRepresentationObject(0, mitkToolData1.GetPointer()); + myFilter->SetRepresentationObject(1, mitkToolData2.GetPointer()); //Process myFilter->Update(); affineTransform1 = mitkToolData1->GetGeometry()->GetIndexToWorldTransform(); offset1 = affineTransform1->GetOffset(); affineTransform2 = mitkToolData2->GetGeometry()->GetIndexToWorldTransform(); offset2 = affineTransform2->GetOffset(); m1 = affineTransform1->GetMatrix().GetVnlMatrix(); m2 = affineTransform2->GetMatrix().GetVnlMatrix(); //messing with SetRepresentationObject //setting nodes - myFilter->SetRepresentationObject(0, mitkToolData2); + myFilter->SetRepresentationObject(0, mitkToolData2.GetPointer()); CPPUNIT_ASSERT_MESSAGE("Twisting mitkToolData by using SetRepresentationObject() NavigationData 1 with ToolData 2", myFilter->GetRepresentationObject(0) == mitkToolData2); CPPUNIT_ASSERT_MESSAGE( "Testing GetNumberOfToolRepresentations() == 1", myFilter->GetNumberOfToolRepresentations() == 2); - myFilter->SetRepresentationObject(1, mitkToolData1); + myFilter->SetRepresentationObject(1, mitkToolData1.GetPointer()); CPPUNIT_ASSERT_MESSAGE("Twisting mitkToolData by using SetRepresentationObject() NavigationData 2 with ToolData 1", myFilter->GetRepresentationObject(1) == mitkToolData1); CPPUNIT_ASSERT_MESSAGE( "Testing GetNumberOfToolRepresentations() == 2", myFilter->GetNumberOfToolRepresentations() == 2); //getting nodes CPPUNIT_ASSERT_MESSAGE("Testing switched BaseData of NavigationData 1 ", myFilter->GetRepresentationObject(0) == mitkToolData2); CPPUNIT_ASSERT_MESSAGE("Testing GetRepresentationObject() != Dummy node", myFilter->GetRepresentationObject(0) != mitkToolDataDummy); CPPUNIT_ASSERT_MESSAGE("Testing switched BaseData NavigationData 2", myFilter->GetRepresentationObject(1) == mitkToolData1); CPPUNIT_ASSERT_MESSAGE("Testing GetRepresentationObject() != Dummy node", myFilter->GetRepresentationObject(1) != mitkToolDataDummy); //processing update through pipeline myFilter->Update(); //now check it there are data connected to the nodes with the according orientation and offsets mitk::AffineTransform3D::Pointer affineTransform1Second = mitkToolData1->GetGeometry()->GetIndexToWorldTransform(); CPPUNIT_ASSERT_MESSAGE( "Testing affineTransform1 after second update", affineTransform1 == affineTransform1Second); mitk::AffineTransform3D::OutputVectorType offset1Second = affineTransform1->GetOffset(); CPPUNIT_ASSERT_MESSAGE( "Testing offset1 after second update", offset1 == offset1Second); CPPUNIT_ASSERT_MESSAGE("Testing offset1 equals first update", offset1Second.GetVnlVector()==offset1.GetVnlVector()); mitk::AffineTransform3D::Pointer affineTransform2Second = mitkToolData2->GetGeometry()->GetIndexToWorldTransform(); CPPUNIT_ASSERT_MESSAGE("Testing affineTransform2 after second update", affineTransform2 == affineTransform2Second); mitk::AffineTransform3D::OutputVectorType offset2Second = affineTransform2->GetOffset(); CPPUNIT_ASSERT_MESSAGE("Testing offset2 after second update", offset2 == offset2Second); CPPUNIT_ASSERT_MESSAGE("Testing offset2 equals first update", offset2Second.GetVnlVector()==offset2.GetVnlVector()); mitk::AffineTransform3D::MatrixType::InternalMatrixType m1Second= affineTransform1Second->GetMatrix().GetVnlMatrix(); MITK_TEST_OUTPUT( <<"\n after second update initOrient1="<GetVnlMatrix():\n "<< m1Second); mitk::AffineTransform3D::MatrixType::InternalMatrixType m2Second= affineTransform2Second->GetMatrix().GetVnlMatrix(); MITK_TEST_OUTPUT( << "\n after second update initOrient2="<GetVnlMatrix():\n "<< m2Second); } void TestThirdInput(){ - myFilter->SetRepresentationObject(0, mitkToolData1); - myFilter->SetRepresentationObject(1, mitkToolData2); + myFilter->SetRepresentationObject(0, mitkToolData1.GetPointer()); + myFilter->SetRepresentationObject(1, mitkToolData2.GetPointer()); //Process myFilter->Update(); //testing adding a third input myFilter->SetInput(2,ndDummy); CPPUNIT_ASSERT_MESSAGE("Adding new input and testing GetNumberOfInputs == 3", myFilter->GetNumberOfInputs() == 3); CPPUNIT_ASSERT_MESSAGE("testing GetNumberOfOutputs == 3", myFilter->GetNumberOfOutputs() == 3); CPPUNIT_ASSERT_MESSAGE("Testing Input == newly added input", myFilter->GetInput(2) == ndDummy); CPPUNIT_ASSERT_MESSAGE("Testing GetOutput(2) != nullptr", myFilter->GetOutput(2) != nullptr); CPPUNIT_ASSERT_MESSAGE( "Testing GetOutput(2) != GetOutput(1)", myFilter->GetOutput(2) != myFilter->GetOutput(1)); - myFilter->SetRepresentationObject(2, mitkToolDataDummy); + myFilter->SetRepresentationObject(2, mitkToolDataDummy.GetPointer()); CPPUNIT_ASSERT_MESSAGE("Testing GetNumberOfToolRepresentations() after adding latest tool", myFilter->GetNumberOfToolRepresentations() == 3); CPPUNIT_ASSERT_MESSAGE("Testing Set-/GetRepresentationObject() equals was set", myFilter->GetRepresentationObject(2) == mitkToolDataDummy); //last time processing update through pipeline myFilter->Update(); //now check for the new values mitk::AffineTransform3D::Pointer affineTransformDummy = mitkToolDataDummy->GetGeometry()->GetIndexToWorldTransform(); mitk::AffineTransform3D::OutputVectorType offsetDummy = affineTransformDummy->GetOffset(); CPPUNIT_ASSERT_MESSAGE("Testing Offset latest added tool", offsetDummy.GetVnlVector()==initialPosDummy.GetVnlVector()); mitk::AffineTransform3D::MatrixType::InternalMatrixType m1Latest= affineTransformDummy->GetMatrix().GetVnlMatrix(); MITK_TEST_OUTPUT( << "\n latest initOrient="<GetVnlMatrix():\n "<< m1Latest); mitk::Surface::Pointer anotherSurface = mitk::Surface::New(); - myFilter->SetRepresentationObject(0, anotherSurface); + myFilter->SetRepresentationObject(0, anotherSurface.GetPointer()); CPPUNIT_ASSERT_MESSAGE("Overwriting BaseData index 0", myFilter->GetRepresentationObject(0) == anotherSurface); } void TestSetTransformPosition(){ // test Set/GetTransformPosition() myFilter->SetTransformPosition(0,true); CPPUNIT_ASSERT_MESSAGE("test Set/GetTransformPosition(0,true)", myFilter->GetTransformPosition(0)==true); myFilter->SetTransformPosition(1,true); CPPUNIT_ASSERT_MESSAGE("test Set/GetTransformPosition(1,true)", myFilter->GetTransformPosition(1)==true); myFilter->SetTransformPosition(2,true); CPPUNIT_ASSERT_MESSAGE("test Set/GetTransformPosition(2,true)", myFilter->GetTransformPosition(2)==true); myFilter->SetTransformPosition(3,true); CPPUNIT_ASSERT_MESSAGE("test Set/GetTransformPosition(3,true)", myFilter->GetTransformPosition(3)==true); myFilter->SetTransformPosition(0,false); CPPUNIT_ASSERT_MESSAGE("test Set/GetTransformPosition(0,false)", myFilter->GetTransformPosition(0)==false); myFilter->SetTransformPosition(1,false); CPPUNIT_ASSERT_MESSAGE("test Set/GetTransformPosition(1,false)", myFilter->GetTransformPosition(1)==false); myFilter->SetTransformPosition(2,false); CPPUNIT_ASSERT_MESSAGE("test Set/GetTransformPosition(2,false)", myFilter->GetTransformPosition(2)==false); myFilter->SetTransformPosition(3,false); CPPUNIT_ASSERT_MESSAGE("test Set/GetTransformPosition(3,false)", myFilter->GetTransformPosition(3)==false); } void TestSetTransformOrientation(){ // test Set/GetTransformOrientation() myFilter->SetTransformOrientation(0,true); CPPUNIT_ASSERT_MESSAGE("test Set/GetTransformOrientation(0,true)", myFilter->GetTransformOrientation(0)==true); myFilter->SetTransformOrientation(1,true); CPPUNIT_ASSERT_MESSAGE("test Set/GetTransformOrientation(1,true)", myFilter->GetTransformOrientation(1)==true); myFilter->SetTransformOrientation(2,true); CPPUNIT_ASSERT_MESSAGE("test Set/GetTransformOrientation(2,true)", myFilter->GetTransformOrientation(2)==true); myFilter->SetTransformOrientation(3,true); CPPUNIT_ASSERT_MESSAGE("test Set/GetTransformOrientation(3,true)", myFilter->GetTransformOrientation(3)==true); myFilter->SetTransformOrientation(0,false); CPPUNIT_ASSERT_MESSAGE("test Set/GetTransformOrientation(0,false)", myFilter->GetTransformOrientation(0)==false); myFilter->SetTransformOrientation(1,false); CPPUNIT_ASSERT_MESSAGE("test Set/GetTransformOrientation(1,false)", myFilter->GetTransformOrientation(1)==false); myFilter->SetTransformOrientation(2,false); CPPUNIT_ASSERT_MESSAGE("test Set/GetTransformOrientation(2,false)", myFilter->GetTransformOrientation(2)==false); myFilter->SetTransformOrientation(3,false); CPPUNIT_ASSERT_MESSAGE("test Set/GetTransformOrientation(3,false)", myFilter->GetTransformOrientation(3)==false); } void TestConvenienceSetTransformOrientation(){ // test the convenience methods to set/getTransformOrientation/Position myFilter->TransformOrientationOn(0); CPPUNIT_ASSERT_MESSAGE("test TransformOrientationOn()", myFilter->GetTransformOrientation(0)==true); myFilter->TransformOrientationOff(0); CPPUNIT_ASSERT_MESSAGE("test TransformOrientationOff()", myFilter->GetTransformOrientation(0)==false); myFilter->TransformOrientationOff(1); CPPUNIT_ASSERT_MESSAGE("test TransformOrientationOff()", myFilter->GetTransformOrientation(1)==false); myFilter->TransformOrientationOn(1); CPPUNIT_ASSERT_MESSAGE("test TransformOrientationOn()", myFilter->GetTransformOrientation(1)==true); myFilter->TransformOrientationOn(2); CPPUNIT_ASSERT_MESSAGE("test TransformOrientationOn()", myFilter->GetTransformOrientation(2)==true); myFilter->TransformOrientationOff(2); CPPUNIT_ASSERT_MESSAGE("test TransformOrientationOff()", myFilter->GetTransformOrientation(2)==false); myFilter->TransformOrientationOn(3); CPPUNIT_ASSERT_MESSAGE("test TransformOrientationOn()", myFilter->GetTransformOrientation(3)==true); myFilter->TransformOrientationOff(3); CPPUNIT_ASSERT_MESSAGE("test TransformOrientationOff()", myFilter->GetTransformOrientation(3)==false); myFilter->TransformPositionOn(0); CPPUNIT_ASSERT_MESSAGE("test TransformPositionOn()", myFilter->GetTransformPosition(0)==true); myFilter->TransformPositionOff(0); CPPUNIT_ASSERT_MESSAGE("test TransformPositionOff()", myFilter->GetTransformPosition(0)==false); myFilter->TransformPositionOff(1); CPPUNIT_ASSERT_MESSAGE("test TransformPositionOff()", myFilter->GetTransformPosition(1)==false); myFilter->TransformPositionOn(1); CPPUNIT_ASSERT_MESSAGE("test TransformPositionOn()", myFilter->GetTransformPosition(1)==true); myFilter->TransformPositionOn(2); CPPUNIT_ASSERT_MESSAGE("test TransformPositionOn()", myFilter->GetTransformPosition(2)==true); myFilter->TransformPositionOff(2); CPPUNIT_ASSERT_MESSAGE("test TransformPositionOff()", myFilter->GetTransformPosition(2)==false); myFilter->TransformPositionOn(3); CPPUNIT_ASSERT_MESSAGE("test TransformPositionOn()", myFilter->GetTransformPosition(3)==true); myFilter->TransformPositionOff(3); CPPUNIT_ASSERT_MESSAGE("test TransformPositionOff()", myFilter->GetTransformPosition(3)==false); } void TestUpdateOrientation(){ // update position and orientation mitk::NavigationData::PositionType updatedPos1, updatedPos2, zero; mitk::FillVector3D(updatedPos1, 3.2, 1.5, 2.8); mitk::FillVector3D(updatedPos2, 4.3, 5.2, 6.0); mitk::FillVector3D(zero, 0.0, 0.0, 0.0); mitk::NavigationData::OrientationType updatedOri1(0.7, 0.5, 0.1, 0.4); mitk::NavigationData::OrientationType updatedOri2(0.2, 0.7, 0.6, 0.1); updatedOri1.normalize(); updatedOri2.normalize(); nd1->SetPosition(updatedPos1); nd1->SetOrientation(updatedOri1); nd2->SetPosition(updatedPos2); nd2->SetOrientation(updatedOri2); - myFilter->SetRepresentationObject(0,mitkToolData1); - myFilter->SetRepresentationObject(1,mitkToolData2); + myFilter->SetRepresentationObject(0, mitkToolData1.GetPointer()); + myFilter->SetRepresentationObject(1, mitkToolData2.GetPointer()); myFilter->TransformPositionOn(0); myFilter->TransformOrientationOff(0); myFilter->TransformPositionOff(1); myFilter->TransformOrientationOn(1); myFilter->Update(); // test positions and orientations mitk::AffineTransform3D::Pointer updatedAffineTransform1 = mitkToolData1->GetGeometry()->GetIndexToWorldTransform(); mitk::AffineTransform3D::OutputVectorType updatedOffset1 = updatedAffineTransform1->GetOffset(); CPPUNIT_ASSERT_MESSAGE("Testing updated position 1", mitk::Equal(updatedOffset1.GetVnlVector(),updatedPos1.GetVnlVector())); mitk::AffineTransform3D::Pointer updatedAffineTransform2 = mitkToolData2->GetGeometry()->GetIndexToWorldTransform(); mitk::AffineTransform3D::OutputVectorType updatedOffset2 = updatedAffineTransform2->GetOffset(); CPPUNIT_ASSERT_MESSAGE( "Testing updated position 2", mitk::Equal(updatedOffset2.GetVnlVector(),zero.GetVnlVector())); mitk::AffineTransform3D::Pointer identityTransform = mitk::AffineTransform3D::New(); identityTransform->SetIdentity(); mitk::AffineTransform3D::MatrixType identityMatrix = identityTransform->GetMatrix(); mitk::AffineTransform3D::MatrixType uM1 = updatedAffineTransform1->GetMatrix(); CPPUNIT_ASSERT_MESSAGE( "Testing updated orientation 1", mitk::MatrixEqualElementWise(uM1, identityMatrix)); mitk::AffineTransform3D::MatrixType::InternalMatrixType uM2 = updatedAffineTransform2->GetMatrix().GetVnlMatrix(); mitk::AffineTransform3D::MatrixType::InternalMatrixType updatedOriTransform2 = updatedOri2.rotation_matrix_transpose().transpose(); CPPUNIT_ASSERT_MESSAGE("Testing updated orientation 2", mitk::MatrixEqualElementWise(uM2,updatedOriTransform2)); // Test that the second RepresentationObject is updated properly even when // the first RepresentationObject is invalid nd2->Modified(); myFilter->SetRepresentationObject(0, nullptr); mitkToolData2->GetGeometry()->SetIdentity(); myFilter->Update(); CPPUNIT_ASSERT_MESSAGE( "Test that the second repr object is updated correctly when the first repr object is invalid", mitk::MatrixEqualElementWise(mitkToolData2->GetGeometry()->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix(), updatedOri2.rotation_matrix_transpose().transpose())); } };//end class mitkNavigationDataObjectVisualizationFilterTestSuite MITK_TEST_SUITE_REGISTRATION(mitkNavigationDataObjectVisualizationFilter) diff --git a/Modules/IGT/Tutorial/mitkIGTTutorialStep2.cpp b/Modules/IGT/Tutorial/mitkIGTTutorialStep2.cpp index dd74393157..60b968ecfb 100644 --- a/Modules/IGT/Tutorial/mitkIGTTutorialStep2.cpp +++ b/Modules/IGT/Tutorial/mitkIGTTutorialStep2.cpp @@ -1,179 +1,179 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include #include #include #include #include #include #include #include #include #include //The next line starts a snippet to display this code in the documentation. If you don't revise the documentation, don't remove it! //! [What we will do] //************************************************************************* // What we will do... //************************************************************************* // This tutorial shows how to compose navigation datas. Therefore we render two objects. //The first object is a cone that is tracked. The second object is a cylinder at a fixed position //relative to the cone. At the end of the tracking, the cylinder is moved to its new relative position //according to the last output of the tracking device. //In addition to IGT tutorial step 1, the objects are added to a datastorage. Furthermore, a renderwindow //is used for visual output. //! [What we will do] int main(int, char**) { //************************************************************************* // Set up Render Window and Tracking Device //************************************************************************* //! [Render Window] //General code rendering the data in a renderwindow. See MITK Tutorial Step1 for more details. mitk::StandaloneDataStorage::Pointer dataStorage = mitk::StandaloneDataStorage::New(); mitk::RenderWindow::Pointer renderWindow = mitk::RenderWindow::New(); mitk::DataNode::Pointer dataNode = mitk::DataNode::New(); //Here, we want a 3D renderwindow renderWindow->GetRenderer()->SetMapperID(mitk::BaseRenderer::Standard3D); renderWindow->GetVtkRenderWindow()->SetSize(500, 500); renderWindow->GetRenderer()->Resize(500, 500); //Connect datastorage and renderwindow renderWindow->GetRenderer()->SetDataStorage(dataStorage); //! [Render Window] //! [Setup Tracking Device] //Virtual tracking device to generate random positions mitk::VirtualTrackingDevice::Pointer tracker = mitk::VirtualTrackingDevice::New(); //Bounds (within the random numbers are generated) must be set before the tools are added double bound = 10.0; mitk::ScalarType bounds[] = { -bound, bound, -bound, bound, -bound, bound }; tracker->SetBounds(bounds); tracker->AddTool("tool1"); //Tracking device source to get the data mitk::TrackingDeviceSource::Pointer source = mitk::TrackingDeviceSource::New(); source->SetTrackingDevice(tracker); source->Connect(); //! [Setup Tracking Device] //************************************************************************* // Create Objects //************************************************************************* //! [Moving Object] //Cone representation for rendering of the moving object mitk::Cone::Pointer cone = mitk::Cone::New(); dataNode->SetData(cone); dataNode->SetName("My tracked object"); dataNode->SetColor(0.0, 1.0, 1.0); dataStorage->Add(dataNode); //Filter for rendering the cone at correct postion and orientation mitk::NavigationDataObjectVisualizationFilter::Pointer visualizer = mitk::NavigationDataObjectVisualizationFilter::New(); visualizer->SetInput(0, source->GetOutput()); - visualizer->SetRepresentationObject(0, cone); + visualizer->SetRepresentationObject(0, cone.GetPointer()); //! [Moving Object] //! [Fixed Object] //Cylinder representation for rendering of the fixed object mitk::DataNode::Pointer cylinderNode = mitk::DataNode::New(); mitk::Cylinder::Pointer cylinder = mitk::Cylinder::New(); cylinderNode->SetData(cylinder); cylinderNode->SetName("My fixed object"); cylinderNode->SetColor(1.0, 0.0, 0.0); dataStorage->Add(cylinderNode); //Define a rotation and a translation for the fixed object mitk::Matrix3D rotationMatrix; rotationMatrix.SetIdentity(); double alpha = 0.3; rotationMatrix[1][1] = cos(alpha); rotationMatrix[1][2] = -sin(alpha); rotationMatrix[2][1] = sin(alpha); rotationMatrix[2][2] = cos(alpha); mitk::Vector3D offset; offset.Fill(5.0); //Add rotation and translation to affine transform mitk::AffineTransform3D::Pointer affineTransform3D = mitk::AffineTransform3D::New(); affineTransform3D->SetOffset(offset); affineTransform3D->SetMatrix(rotationMatrix); //apply rotation and translation mitk::NavigationData::Pointer fixedNavigationData = mitk::NavigationData::New(affineTransform3D); cylinder->GetGeometry()->SetIndexToWorldTransform(fixedNavigationData->GetAffineTransform3D()); //! [Fixed Object] //************************************************************************* // The Tracking loop //************************************************************************* //! [Initialize views] // Global reinit with the bounds of the virtual tracking device auto timeGeometry = dataStorage->ComputeBoundingGeometry3D(dataStorage->GetAll()); mitk::BaseGeometry::Pointer geometry = timeGeometry->GetGeometryForTimeStep(0); geometry->SetBounds(bounds); mitk::RenderingManager::GetInstance()->InitializeViews(geometry); source->StartTracking(); //! [Initialize views] //! [Tracking] //Generate and render 75 time steps to move the tracked object for (int i = 0; i < 75; ++i) { //Update the cone position visualizer->Update(); //Update rendering renderWindow->GetVtkRenderWindow()->Render(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); MITK_INFO << "Position " << source->GetOutput()->GetPosition(); //Slight delay for the random numbers itksys::SystemTools::Delay(100); } //Stop the tracking device and disconnect it //The tracking is done, now we want to move the fixed object to its correct relative position regarding the tracked object. source->StopTracking(); source->Disconnect(); //! [Tracking] //************************************************************************* // Final Transform //************************************************************************* //! [Calculate Transform] //Now the tracking is finished and we can use the transformation to move //the fixed object to its correct position relative to the new position //of the moving/tracked object. Therefore, we compose the navigation datas. fixedNavigationData->Compose(source->GetOutput(), false); //Update the transformation matrix of the cylinder cylinder->GetGeometry()->SetIndexToWorldTransform(fixedNavigationData->GetAffineTransform3D()); //Update the rendering renderWindow->GetVtkRenderWindow()->Render(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); //Wait a little before closing the renderwindow itksys::SystemTools::Delay(2000); //! [Calculate Transform] } diff --git a/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationMarkerPlacement.cpp b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationMarkerPlacement.cpp index ad2f3dcee0..55c077e88e 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationMarkerPlacement.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.ultrasoundtrackingnavigation/src/internal/QmitkUSNavigationMarkerPlacement.cpp @@ -1,802 +1,802 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "QmitkUSNavigationMarkerPlacement.h" #include "ui_QmitkUSNavigationMarkerPlacement.h" #include "NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.h" #include "NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.h" #include "NavigationStepWidgets/QmitkUSNavigationStepPlacementPlanning.h" #include "NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.h" #include "NavigationStepWidgets/QmitkUSNavigationStepTumourSelection.h" #include "NavigationStepWidgets/QmitkUSNavigationStepZoneMarking.h" #include "SettingsWidgets/QmitkUSNavigationCombinedSettingsWidget.h" #include "mitkAbstractUltrasoundTrackerDevice.h" #include "mitkIRenderingManager.h" #include "mitkNodeDisplacementFilter.h" #include "mitkTrackedUltrasound.h" #include #include "IO/mitkUSNavigationStepTimer.h" #include #include #include #include #include #include #include "QmitkRenderWindow.h" #include "QmitkStdMultiWidget.h" #include "QmitkStdMultiWidgetEditor.h" #include "mitkCameraController.h" #include "mitkLayoutAnnotationRenderer.h" #include // scene serialization #include #include #include #include #include const std::string QmitkUSNavigationMarkerPlacement::VIEW_ID = "org.mitk.views.usmarkerplacement"; const char *QmitkUSNavigationMarkerPlacement::DATANAME_TUMOUR = "Tumour"; const char *QmitkUSNavigationMarkerPlacement::DATANAME_TARGETSURFACE = "Target Surface"; const char *QmitkUSNavigationMarkerPlacement::DATANAME_ZONES = "Zones"; const char *QmitkUSNavigationMarkerPlacement::DATANAME_TARGETS = "Targets"; const char *QmitkUSNavigationMarkerPlacement::DATANAME_TARGETS_PATHS = "Target Paths"; const char *QmitkUSNavigationMarkerPlacement::DATANAME_REACHED_TARGETS = "Reached Targets"; QmitkUSNavigationMarkerPlacement::QmitkUSNavigationMarkerPlacement() : m_Parent(nullptr), m_UpdateTimer(new QTimer(this)), m_ImageAndNavigationDataLoggingTimer(new QTimer(this)), m_StdMultiWidget(nullptr), m_CombinedModality(nullptr), m_ReinitAlreadyDone(false), m_IsExperimentRunning(false), m_CurrentApplicationName(), m_NavigationStepTimer(mitk::USNavigationStepTimer::New()), m_IconRunning(QPixmap(":/USNavigation/record.png")), m_IconNotRunning(QPixmap(":/USNavigation/record-gray.png")), m_ResultsDirectory(), m_ExperimentName(), m_ExperimentResultsSubDirectory(), m_NavigationStepNames(), m_LoggingBackend(), m_USImageLoggingFilter(mitk::USImageLoggingFilter::New()), m_NavigationDataRecorder(mitk::NavigationDataRecorder::New()), m_TargetNodeDisplacementFilter(nullptr), m_AblationZonesDisplacementFilter(mitk::NodeDisplacementFilter::New()), m_ToolVisualizationFilter(nullptr), m_AblationZonesVector(), m_NeedleIndex(0), m_MarkerIndex(1), m_SceneNumber(1), m_WarnOverlay(mitk::TextAnnotation2D::New()), m_NavigationDataSource(nullptr), m_CurrentStorage(nullptr), m_ImageStreamNode(nullptr), ui(new Ui::QmitkUSNavigationMarkerPlacement) { connect(m_UpdateTimer, SIGNAL(timeout()), this, SLOT(OnTimeout())); connect( m_ImageAndNavigationDataLoggingTimer, SIGNAL(timeout()), this, SLOT(OnImageAndNavigationDataLoggingTimeout())); // scale running (and not running) icon the specific height m_IconRunning = m_IconRunning.scaledToHeight(20, Qt::SmoothTransformation); m_IconNotRunning = m_IconNotRunning.scaledToHeight(20, Qt::SmoothTransformation); } QmitkUSNavigationMarkerPlacement::~QmitkUSNavigationMarkerPlacement() { this->GetDataStorage()->Remove(m_InstrumentNode); delete ui; } void QmitkUSNavigationMarkerPlacement::OnChangeAblationZone(int id, int newSize) { if ((static_cast(m_AblationZonesVector.size()) < id) || (id < 0)) { return; } MITK_INFO << "Ablation Zone " << id << " changed, new size: " << newSize; // create a vtk sphere with given radius vtkSmartPointer vtkSphere = vtkSmartPointer::New(); vtkSphere->SetRadius(newSize / 2); vtkSphere->SetCenter(0, 0, 0); vtkSphere->SetPhiResolution(20); vtkSphere->SetThetaResolution(20); vtkSphere->Update(); mitk::Surface::Pointer zoneSurface = dynamic_cast(m_AblationZonesVector.at(id)->GetData()); zoneSurface->SetVtkPolyData(vtkSphere->GetOutput()); } void QmitkUSNavigationMarkerPlacement::OnAddAblationZone(int size) { m_AblationZonesDisplacementFilter->SetInitialReferencePose( m_CombinedModality->GetNavigationDataSource()->GetOutput(m_MarkerIndex)); mitk::DataNode::Pointer NewAblationZone = mitk::DataNode::New(); mitk::Point3D origin = m_CombinedModality->GetNavigationDataSource()->GetOutput(m_NeedleIndex)->GetPosition(); MITK_INFO("USNavigationLogging") << "Ablation Zone Added, initial size: " << size << ", origin: " << origin; mitk::Surface::Pointer zone = mitk::Surface::New(); // create a vtk sphere with given radius vtkSmartPointer vtkSphere = vtkSmartPointer::New(); vtkSphere->SetRadius(size / 2); vtkSphere->SetCenter(0, 0, 0); vtkSphere->SetPhiResolution(20); vtkSphere->SetThetaResolution(20); vtkSphere->Update(); zone->SetVtkPolyData(vtkSphere->GetOutput()); // set vtk sphere and origin to data node (origin must be set // again, because of the new sphere set as data) NewAblationZone->SetData(zone); NewAblationZone->GetData()->GetGeometry()->SetOrigin(origin); mitk::Color SphereColor = mitk::Color(); // default color SphereColor[0] = 102; SphereColor[1] = 0; SphereColor[2] = 204; NewAblationZone->SetColor(SphereColor); NewAblationZone->SetOpacity(0.3); // set name of zone std::stringstream name; name << "Ablation Zone" << m_AblationZonesVector.size(); NewAblationZone->SetName(name.str()); // add zone to filter m_AblationZonesDisplacementFilter->AddNode(NewAblationZone); m_AblationZonesVector.push_back(NewAblationZone); this->GetDataStorage()->Add(NewAblationZone); } void QmitkUSNavigationMarkerPlacement::CreateQtPartControl(QWidget *parent) { m_Parent = parent; ui->setupUi(parent); connect(ui->startExperimentButton, SIGNAL(clicked()), this, SLOT(OnStartExperiment())); connect(ui->finishExperimentButton, SIGNAL(clicked()), this, SLOT(OnFinishExperiment())); connect(ui->m_enableNavigationLayout, SIGNAL(clicked()), this, SLOT(OnChangeLayoutClicked())); connect(ui->m_RenderWindowSelection, SIGNAL(valueChanged(int)), this, SLOT(OnRenderWindowSelection())); connect(ui->m_RefreshView, SIGNAL(clicked()), this, SLOT(OnRefreshView())); m_BaseNode = this->GetDataStorage()->GetNamedNode(QmitkUSAbstractNavigationStep::DATANAME_BASENODE); if (m_BaseNode.IsNull()) { m_BaseNode = mitk::DataNode::New(); m_BaseNode->SetName(QmitkUSAbstractNavigationStep::DATANAME_BASENODE); this->GetDataStorage()->Add(m_BaseNode); } connect(ui->m_CtToUsRegistrationWidget, SIGNAL(GetCursorPosition()), this, SLOT(OnGetCursorPosition())); connect(ui->m_CtToUsRegistrationWidget, SIGNAL(ActualizeCtToUsRegistrationWidget()), this, SLOT(OnActualizeCtToUsRegistrationWidget())); connect(ui->m_initializeCtToUsRegistration, SIGNAL(clicked()), this, SLOT(OnInitializeCtToUsRegistration())); connect(ui->m_initializeTargetMarking, SIGNAL(clicked()), this, SLOT(OnInitializeTargetMarking())); connect(ui->m_initializeCritStructureMarking, SIGNAL(clicked()), this, SLOT(OnInitializeCriticalStructureMarking())); connect(ui->m_initializeNavigation, SIGNAL(clicked()), this, SLOT(OnInitializeNavigation())); // indicate that no experiment is running at start ui->runningLabel->setPixmap(m_IconNotRunning); connect(ui->m_settingsWidget, SIGNAL(SettingsChanged(itk::SmartPointer)), this, SLOT(OnSettingsChanged(itk::SmartPointer))); } void QmitkUSNavigationMarkerPlacement::ReInitializeSettingsNodesAndImageStream() { //If update timer is not stopped (signals stopped), setting the m_CombinedModality // will cause a crash of the workbench in some times. m_UpdateTimer->blockSignals(true); m_UpdateTimer->stop(); m_SettingsNode = mitk::DataNode::New(); ui->m_settingsWidget->OnSetSettingsNode(m_SettingsNode, true); InitImageStream(); m_CombinedModality = ui->m_CombinedModalityCreationWidget->GetSelectedCombinedModality(); // Having set the m_CombinedModality reactivate the update timer again m_UpdateTimer->start(50); // every 50 Milliseconds = 20 Frames/Second m_UpdateTimer->blockSignals(false); } void QmitkUSNavigationMarkerPlacement::OnGetCursorPosition() { mitk::Point3D centroid = this->GetRenderWindowPart()->GetSelectedPosition(); ui->m_CtToUsRegistrationWidget->OnCalculateTRE(centroid); } void QmitkUSNavigationMarkerPlacement::OnActualizeCtToUsRegistrationWidget() { m_SettingsNode = mitk::DataNode::New(); ui->m_settingsWidget->OnSetSettingsNode(m_SettingsNode, true); this->InitImageStream(); if (ui->m_CombinedModalityCreationWidget->GetSelectedCombinedModality().IsNull()) { return; } ui->m_CtToUsRegistrationWidget->SetCombinedModality( ui->m_CombinedModalityCreationWidget->GetSelectedCombinedModality()); m_CombinedModality = ui->m_CombinedModalityCreationWidget->GetSelectedCombinedModality(); if (!m_StdMultiWidget) { // try to get the standard multi widget if it couldn't be got before mitk::IRenderWindowPart *renderWindowPart = this->GetRenderWindowPart(); QmitkStdMultiWidgetEditor *multiWidgetEditor = dynamic_cast(renderWindowPart); // if there is a standard multi widget now, disable the level window and // change the layout to 2D up and 3d down if (multiWidgetEditor) { m_StdMultiWidget = dynamic_cast(multiWidgetEditor->GetMultiWidget()); multiWidgetEditor->ShowLevelWindowWidget(false); SetTwoWindowView(); } } else { this->OnRefreshView(); } m_UpdateTimer->start(50); // every 50 Milliseconds = 20 Frames/Second } void QmitkUSNavigationMarkerPlacement::OnInitializeCtToUsRegistration() { ui->m_CtToUsRegistrationWidget->SetDataStorage(this->GetDataStorage()); ui->m_CtToUsRegistrationWidget->OnSettingsChanged(m_SettingsNode); ui->m_CtToUsRegistrationWidget->OnActivateStep(); ui->m_CtToUsRegistrationWidget->OnStartStep(); ui->m_CtToUsRegistrationWidget->Update(); } void QmitkUSNavigationMarkerPlacement::OnInitializeTargetMarking() { ReInitializeSettingsNodesAndImageStream(); ui->m_TargetMarkingWidget->SetCombinedModality(m_CombinedModality); ui->m_TargetMarkingWidget->SetDataStorage(this->GetDataStorage()); ui->m_TargetMarkingWidget->OnSettingsChanged(m_SettingsNode); ui->m_TargetMarkingWidget->OnActivateStep(); ui->m_TargetMarkingWidget->OnStartStep(); ui->m_TargetMarkingWidget->Update(); } void QmitkUSNavigationMarkerPlacement::OnInitializeCriticalStructureMarking() { ReInitializeSettingsNodesAndImageStream(); ui->m_CriticalStructuresWidget->SetCombinedModality(m_CombinedModality); ui->m_CriticalStructuresWidget->SetDataStorage(this->GetDataStorage()); ui->m_CriticalStructuresWidget->OnSettingsChanged(m_SettingsNode); ui->m_CriticalStructuresWidget->OnActivateStep(); ui->m_CriticalStructuresWidget->OnStartStep(); ui->m_CriticalStructuresWidget->Update(); } void QmitkUSNavigationMarkerPlacement::OnInitializeNavigation() { ReInitializeSettingsNodesAndImageStream(); ui->m_NavigationWidget->SetCombinedModality(m_CombinedModality); ui->m_NavigationWidget->SetDataStorage(this->GetDataStorage()); ui->m_NavigationWidget->OnSettingsChanged(m_SettingsNode); ui->m_NavigationWidget->OnActivateStep(); ui->m_NavigationWidget->OnStartStep(); ui->m_NavigationWidget->Update(); // test if it is tracked US, if yes add visualization filter if (m_CombinedModality->GetIsTrackedUltrasoundActive()) { m_InstrumentNode = mitk::DataNode::New(); m_InstrumentNode->SetName("Tracked US Instrument"); m_InstrumentNode->SetData( m_CombinedModality->GetNavigationDataSource()->GetToolMetaData(0)->GetToolSurface()->Clone()); this->GetDataStorage()->Add(m_InstrumentNode); m_ToolVisualizationFilter = mitk::NavigationDataObjectVisualizationFilter::New(); m_ToolVisualizationFilter->ConnectTo(m_CombinedModality->GetNavigationDataSource()); m_ToolVisualizationFilter->SetRepresentationObject(0, m_InstrumentNode->GetData()); //caution: currently hard coded that instrument has id 0 //set dummy objects to avoid spamming of console mitk::Surface::Pointer dummyObject = mitk::Surface::New(); - m_ToolVisualizationFilter->SetRepresentationObject(1, dummyObject); - m_ToolVisualizationFilter->SetRepresentationObject(2, dummyObject); + m_ToolVisualizationFilter->SetRepresentationObject(1, dummyObject.GetPointer()); + m_ToolVisualizationFilter->SetRepresentationObject(2, dummyObject.GetPointer()); } } void QmitkUSNavigationMarkerPlacement::InitImageStream() { if (m_ImageStreamNode.IsNull()) { m_ImageStreamNode = mitk::DataNode::New(); m_ImageStreamNode->SetName("US Navigation Viewing Stream"); this->GetDataStorage()->Add(m_ImageStreamNode); } } void QmitkUSNavigationMarkerPlacement::OnCombinedModalityPropertyChanged(const std::string &key, const std::string &) { if (key == mitk::USDevice::GetPropertyKeys().US_PROPKEY_BMODE_DEPTH) { m_ReinitAlreadyDone = false; this->ReinitOnImage(); if (m_CombinedModality.IsNotNull() && !m_CombinedModality->GetIsCalibratedForCurrentStatus()) { mitk::LayoutAnnotationRenderer::AddAnnotation( m_WarnOverlay.GetPointer(), "stdmulti.widget0", mitk::LayoutAnnotationRenderer::TopLeft); MITK_WARN << "No calibration available for the selected ultrasound image depth."; } } } void QmitkUSNavigationMarkerPlacement::SetFocus() { this->ReinitOnImage(); } void QmitkUSNavigationMarkerPlacement::OnTimeout() { if (m_CombinedModality.IsNull()) return; m_CombinedModality->Modified(); // shouldn't be nessecary ... fix in abstract ultrasound tracker device! m_CombinedModality->Update(); if (m_ToolVisualizationFilter.IsNotNull()) { m_ToolVisualizationFilter->Update(); } ui->m_CtToUsRegistrationWidget->Update(); ui->m_TargetMarkingWidget->Update(); ui->m_CriticalStructuresWidget->Update(); ui->m_NavigationWidget->Update(); mitk::Image::Pointer image = m_CombinedModality->GetOutput(); // make sure that always the current image is set to the data node if (image.IsNotNull() && m_ImageStreamNode->GetData() != image.GetPointer() && image->IsInitialized()) { m_ImageStreamNode->SetData(image); } if (!m_StdMultiWidget) { // try to get the standard multi widget if it couldn't be got before mitk::IRenderWindowPart *renderWindowPart = this->GetRenderWindowPart(); QmitkStdMultiWidgetEditor *multiWidgetEditor = dynamic_cast(renderWindowPart); // if there is a standard multi widget now, disable the level window and // change the layout to 2D up and 3d down if (multiWidgetEditor) { m_StdMultiWidget = dynamic_cast(multiWidgetEditor->GetMultiWidget()); multiWidgetEditor->ShowLevelWindowWidget(false); SetTwoWindowView(); } this->CreateOverlays(); } if (m_CombinedModality.IsNotNull() && !this->m_CombinedModality->GetIsFreezed()) // if the combined modality is freezed: do nothing { m_AblationZonesDisplacementFilter->Update(); // update the 3D window only every fourth time to speed up the rendering (at least in 2D) this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_2DWINDOWS); // make sure that a reinit was performed on the image this->ReinitOnImage(); } } void QmitkUSNavigationMarkerPlacement::OnEnableNavigationLayout() { MITK_INFO << "Navigation Layout"; // try to get the standard multi widget if it couldn't be got before mitk::IRenderWindowPart *renderWindowPart = this->GetRenderWindowPart(); QmitkStdMultiWidgetEditor *multiWidgetEditor = dynamic_cast(renderWindowPart); // if there is a standard multi widget now, disable the level window and // change the layout to 2D up and 3d down if (multiWidgetEditor) { m_StdMultiWidget = dynamic_cast(multiWidgetEditor->GetMultiWidget()); multiWidgetEditor->ShowLevelWindowWidget(false); SetTwoWindowView(); } } void QmitkUSNavigationMarkerPlacement::OnRenderWindowSelection() { SetTwoWindowView(); } void QmitkUSNavigationMarkerPlacement::OnRefreshView() { if (!ui->m_enableNavigationLayout->isChecked()) OnResetStandardLayout(); else { // Reinit the US Image Stream (this might be broken if there was a global reinit somewhere...) try { mitk::RenderingManager::GetInstance()->InitializeViews( // Reinit this ->GetDataStorage() // GetDataStorage ->GetNamedNode("US Viewing Stream - Image 0") ->GetData() ->GetTimeGeometry()); // GetNode } catch (...) { MITK_DEBUG << "No reinit possible"; } SetTwoWindowView(); } } void QmitkUSNavigationMarkerPlacement::SetTwoWindowView() { if (m_StdMultiWidget) { int i, j, k; switch (this->ui->m_RenderWindowSelection->value()) { case 1: mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3"))->GetCameraController()->SetViewToCaudal(); i = 1; j = 2; // other windows k = 0; break; case 2: mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3"))->GetCameraController()->SetViewToSinister(); i = 0; j = 2; k = 1; break; case 3: mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3"))->GetCameraController()->SetViewToAnterior(); i = 1; j = 0; k = 2; break; default: return; } // get the render window which is defined by index "k" and set it as "current render window widget" // chose the layout that will set the current 2D window as top render window and the 3D windows as bottom render window auto renderWindowWidget = m_StdMultiWidget->GetRenderWindowWidget(m_StdMultiWidget->GetNameFromIndex(k)); m_StdMultiWidget->GetMultiWidgetLayoutManager()->SetCurrentRenderWindowWidget(renderWindowWidget.get()); m_StdMultiWidget->GetMultiWidgetLayoutManager()->SetOneTop3DBottomLayout(); ////Crosshair invisible in 3D view this->GetDataStorage()->GetNamedNode("stdmulti.widget" + std::to_string(i) + ".plane") ->SetBoolProperty("visible", false, mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); this->GetDataStorage()->GetNamedNode("stdmulti.widget" + std::to_string(j) + ".plane") ->SetBoolProperty("visible", false, mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); this->GetDataStorage()->GetNamedNode("stdmulti.widget" + std::to_string(k) + ".plane") ->SetBoolProperty("visible", true, mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); this->GetDataStorage()->GetNamedNode("stdmulti.widget" + std::to_string(i) + ".plane") ->SetIntProperty("Crosshair.Gap Size", 0); this->GetDataStorage()->GetNamedNode("stdmulti.widget" + std::to_string(j) + ".plane") ->SetIntProperty("Crosshair.Gap Size", 0); } } void QmitkUSNavigationMarkerPlacement::OnResetStandardLayout() { if (m_StdMultiWidget) { //reset render windows m_StdMultiWidget->SetCrosshairVisibility(true); m_StdMultiWidget->GetMultiWidgetLayoutManager()->SetDefaultLayout(); } } void QmitkUSNavigationMarkerPlacement::OnChangeLayoutClicked() { if (ui->m_enableNavigationLayout->isChecked()) OnEnableNavigationLayout(); else OnResetStandardLayout(); } void QmitkUSNavigationMarkerPlacement::OnImageAndNavigationDataLoggingTimeout() { // update filter for logging navigation data and ultrasound images if (m_CombinedModality.IsNotNull()) { m_NavigationDataRecorder->Update(); // get last messages for logging filer and store them std::vector messages = m_LoggingBackend.GetNavigationMessages(); std::string composedMessage = ""; for (std::size_t i = 0; i < messages.size(); i++) { composedMessage += messages.at(i); } m_USImageLoggingFilter->AddMessageToCurrentImage(composedMessage); m_LoggingBackend.ClearNavigationMessages(); // update logging filter m_USImageLoggingFilter->Update(); } } void QmitkUSNavigationMarkerPlacement::OnStartExperiment() { // get name for the experiment by a QInputDialog bool ok; if (m_ExperimentName.isEmpty()) { // default: current date m_ExperimentName = QString::number(QDateTime::currentDateTime().date().year()) + "_" + QString::number(QDateTime::currentDateTime().date().month()) + "_" + QString::number(QDateTime::currentDateTime().date().day()) + "_experiment_" + QString::number(QDateTime::currentDateTime().time().hour()) + "." + QString::number(QDateTime::currentDateTime().time().minute()); } m_ExperimentName = QInputDialog::getText( m_Parent, QString("Experiment Name"), QString("Name of the Experiment"), QLineEdit::Normal, m_ExperimentName, &ok); MITK_INFO("USNavigationLogging") << "Experiment started: " << m_ExperimentName.toStdString(); if (ok && !m_ExperimentName.isEmpty()) { // display error message and call the function recursively if a directory // with the given name already exists QDir experimentResultsDir(m_ResultsDirectory + QDir::separator() + m_ExperimentName); if (experimentResultsDir.exists()) { QMessageBox::critical( m_Parent, "Results Directory Exists", "The result directory already exists.\nPlease choose an other name."); this->OnStartExperiment(); } else { QDir(m_ResultsDirectory).mkdir(m_ExperimentName); m_ExperimentResultsSubDirectory = m_ResultsDirectory + QDir::separator() + m_ExperimentName; // experiment is running now ui->runningLabel->setPixmap(m_IconRunning); // (re)start timer for navigation step durations m_NavigationStepTimer->Reset(); m_NavigationStepTimer->SetOutputFileName( QString(m_ExperimentResultsSubDirectory + QDir::separator() + QString("durations.cvs")).toStdString()); m_NavigationStepTimer->SetActiveIndex(0, "Initialization"); ui->finishExperimentButton->setEnabled(true); ui->startExperimentButton->setDisabled(true); // initialize and register logging backend QString loggingFilename = m_ExperimentResultsSubDirectory + QDir::separator() + "logging.txt"; m_LoggingBackend.SetOutputFileName(loggingFilename.toStdString()); mbilog::RegisterBackend(&m_LoggingBackend); // initialize and start navigation data recorder form xml recording m_NavigationDataRecorder->StartRecording(); m_IsExperimentRunning = true; m_ImageAndNavigationDataLoggingTimer->start(1000); } } } void QmitkUSNavigationMarkerPlacement::OnFinishExperiment() { this->WaitCursorOn(); MITK_INFO("USNavigationLogging") << "Experiment finished!"; MITK_INFO("USNavigationLogging") << "Position/Orientation of needle tip: " << (dynamic_cast( m_CombinedModality->GetTrackingDeviceDataSource()->GetOutput(0))) ->GetPosition(); MITK_INFO("USNavigationLogging") << "Position of target: " << m_TargetNodeDisplacementFilter->GetRawDisplacementNavigationData(0)->GetPosition(); MITK_INFO("USNavigationLogging") << "Total duration: " << m_NavigationStepTimer->GetTotalDuration(); m_ImageAndNavigationDataLoggingTimer->stop(); ui->runningLabel->setPixmap(m_IconNotRunning); m_NavigationStepTimer->Stop(); ui->finishExperimentButton->setDisabled(true); ui->startExperimentButton->setEnabled(true); MITK_INFO("USNavigationLogging") << "Writing logging data to " << m_ExperimentResultsSubDirectory.toStdString(); // save ultrasound images to the file system QDir(m_ExperimentResultsSubDirectory).mkdir("ImageStream"); m_USImageLoggingFilter->Update(); m_USImageLoggingFilter->SetImageFilesExtension(".jpg"); m_USImageLoggingFilter->SaveImages( QString(m_ExperimentResultsSubDirectory + QDir::separator() + "ImageStream" + QDir::separator()).toStdString()); m_USImageLoggingFilter = mitk::USImageLoggingFilter::New(); m_NavigationDataRecorder->StopRecording(); // Write data to csv and xml file mitk::IOUtil::Save( m_NavigationDataRecorder->GetNavigationDataSet(), (QString(m_ExperimentResultsSubDirectory + QDir::separator() + "navigation-data.xml").toStdString().c_str())); mitk::IOUtil::Save( m_NavigationDataRecorder->GetNavigationDataSet(), (QString(m_ExperimentResultsSubDirectory + QDir::separator() + "navigation-data.csv").toStdString().c_str())); // write logged navigation data messages to separate file std::stringstream csvNavigationMessagesFilename; csvNavigationMessagesFilename << m_ExperimentResultsSubDirectory.toStdString() << QDir::separator().toLatin1() << "CSVNavigationMessagesLogFile.csv"; MITK_INFO("USNavigationLogging") << "Writing logged navigation messages to separate csv file: " << csvNavigationMessagesFilename.str(); m_LoggingBackend.WriteCSVFileWithNavigationMessages(csvNavigationMessagesFilename.str()); mbilog::UnregisterBackend(&m_LoggingBackend); m_IsExperimentRunning = false; m_ImageAndNavigationDataLoggingTimer->stop(); m_CombinedModality = nullptr; // reset scene number for next experiment m_SceneNumber = 1; this->WaitCursorOff(); MITK_INFO("USNavigationLogging") << "Finished!"; } void QmitkUSNavigationMarkerPlacement::OnSettingsChanged(itk::SmartPointer settings) { // initialize gui according to the experiment mode setting bool experimentMode = false; settings->GetBoolProperty("settings.experiment-mode", experimentMode); ui->startExperimentButton->setVisible(experimentMode); ui->finishExperimentButton->setVisible(experimentMode); ui->runningLabel->setVisible(experimentMode); if (experimentMode && !m_IsExperimentRunning) { ui->runningLabel->setPixmap(m_IconNotRunning); } else if (!experimentMode) { if (m_IsExperimentRunning) { this->OnFinishExperiment(); } } // get the results directory from the settings and use home directory if // there is no results directory configured std::string resultsDirectory; if (settings->GetStringProperty("settings.experiment-results-directory", resultsDirectory)) { m_ResultsDirectory = QString::fromStdString(resultsDirectory); } else { m_ResultsDirectory = QDir::homePath(); } // make sure that the results directory exists QDir resultsDirectoryQDir = QDir(m_ResultsDirectory); if (!resultsDirectoryQDir.exists()) { resultsDirectoryQDir.mkpath(m_ResultsDirectory); } MITK_INFO("USNavigation") << "Results Directory: " << m_ResultsDirectory.toStdString(); } void QmitkUSNavigationMarkerPlacement::ReinitOnImage() { if (!m_ReinitAlreadyDone && m_CombinedModality.IsNotNull()) { // make sure that the output is already calibrated correctly // (if the zoom level was changed recently) m_CombinedModality->Modified(); m_CombinedModality->Update(); mitk::Image::Pointer image = m_CombinedModality->GetOutput(); if (image.IsNotNull() && image->IsInitialized()) { // make a reinit on the ultrasound image mitk::IRenderWindowPart *renderWindowPart = this->GetRenderWindowPart(); if (renderWindowPart != nullptr && image->GetTimeGeometry()->IsValid()) { renderWindowPart->GetRenderingManager()->InitializeViews( image->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); renderWindowPart->GetRenderingManager()->RequestUpdateAll(); } this->RequestRenderWindowUpdate(); m_ReinitAlreadyDone = true; } } } void QmitkUSNavigationMarkerPlacement::Convert2DImagesTo3D(mitk::DataStorage::SetOfObjects::ConstPointer nodes) { for (mitk::DataStorage::SetOfObjects::ConstIterator it = nodes->Begin(); it != nodes->End(); ++it) { if (it->Value()->GetData() && strcmp(it->Value()->GetData()->GetNameOfClass(), "Image") == 0) { // convert image to 3d image if it is 2d at the moment mitk::Image::Pointer image = dynamic_cast(it->Value()->GetData()); if (image.IsNotNull() && image->GetDimension() == 2 && !image->GetGeometry()->Is2DConvertable()) { mitk::Convert2Dto3DImageFilter::Pointer convert2DTo3DImageFilter = mitk::Convert2Dto3DImageFilter::New(); convert2DTo3DImageFilter->SetInput(image); convert2DTo3DImageFilter->Update(); it->Value()->SetData(convert2DTo3DImageFilter->GetOutput()); } } } } void QmitkUSNavigationMarkerPlacement::CreateOverlays() { // initialize warning overlay (and do not display it, yet) m_WarnOverlay->SetText("Warning: No calibration available for current depth."); // set position and font size for the text overlay // (nonesense postition as a layouter is used, but it ignored // the overlay without setting a position here) mitk::Point2D overlayPosition; overlayPosition.SetElement(0, -50.0f); overlayPosition.SetElement(1, -50.0f); m_WarnOverlay->SetPosition2D(overlayPosition); m_WarnOverlay->SetFontSize(22); m_WarnOverlay->SetColor(1, 0, 0); // overlay should be red } void QmitkUSNavigationMarkerPlacement::UpdateToolStorage() { if (m_NavigationDataSource.IsNull()) { m_NavigationDataSource = m_CombinedModality->GetNavigationDataSource(); } if (m_NavigationDataSource.IsNull()) { MITK_WARN << "Found an invalid navigation data source object!"; } us::ModuleContext *context = us::GetModuleContext(); std::string id = m_NavigationDataSource->US_PROPKEY_ID; std::string filter = "(" + mitk::NavigationToolStorage::US_PROPKEY_SOURCE_ID + "=" + id + ")"; // Get Storage std::vector> refs = context->GetServiceReferences(); m_CurrentStorage = context->GetService(refs.front()); if (m_CurrentStorage.IsNull()) { MITK_WARN << "Found an invalid storage object!"; } else if (m_CurrentStorage->GetToolCount() != m_NavigationDataSource->GetNumberOfOutputs()) // there is something wrong with the storage { MITK_WARN << "Found a tool storage, but it has not the same number of tools like the NavigationDataSource. This " "storage won't be used because it isn't the right one."; m_CurrentStorage = nullptr; } } diff --git a/Plugins/org.mitk.gui.qt.igtexamples/src/internal/OpenIGTLinkExample.cpp b/Plugins/org.mitk.gui.qt.igtexamples/src/internal/OpenIGTLinkExample.cpp index 987cc38654..963c4556c3 100644 --- a/Plugins/org.mitk.gui.qt.igtexamples/src/internal/OpenIGTLinkExample.cpp +++ b/Plugins/org.mitk.gui.qt.igtexamples/src/internal/OpenIGTLinkExample.cpp @@ -1,237 +1,237 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkRenderWindow.h" // Qt #include // mitk #include #include #include #include #include // vtk #include // #include "OpenIGTLinkExample.h" //igtl #include "igtlStringMessage.h" #include "igtlTrackingDataMessage.h" const std::string OpenIGTLinkExample::VIEW_ID = "org.mitk.views.OpenIGTLinkExample"; void OpenIGTLinkExample::SetFocus() { } OpenIGTLinkExample::~OpenIGTLinkExample() { this->DestroyPipeline(); if (m_IGTLDeviceSource.IsNotNull()) { m_IGTLDeviceSource->UnRegisterMicroservice(); } } void OpenIGTLinkExample::CreateQtPartControl( QWidget *parent ) { // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi( parent ); // connect the widget items with the methods connect( m_Controls.butStart, SIGNAL(clicked()), this, SLOT(Start()) ); connect( &m_Timer, SIGNAL(timeout()), this, SLOT(UpdatePipeline())); //create a new OpenIGTLinkExample Client m_IGTLClient = mitk::IGTLClient::New(false); m_IGTLClient->SetName("OIGTL Example Client Device"); //create a new OpenIGTLinkExample Device source m_IGTLDeviceSource = mitk::IGTLDeviceSource::New(); //set the client as the source for the device source m_IGTLDeviceSource->SetIGTLDevice(m_IGTLClient); m_IGTLDeviceSource->RegisterAsMicroservice(); } void OpenIGTLinkExample::CreatePipeline() { //create a filter that converts OpenIGTLinkExample messages into navigation data m_IGTLMsgToNavDataFilter = mitk::IGTLMessageToNavigationDataFilter::New(); //create a visualization filter m_VisFilter = mitk::NavigationDataObjectVisualizationFilter::New(); //we expect a tracking data message with three tools. Since we cannot change //the outputs at runtime we have to set it manually. m_IGTLMsgToNavDataFilter->SetNumberOfExpectedOutputs(m_Controls.channelSpinBox->value()); //connect the filters with each other //the OpenIGTLinkExample messages will be passed to the first filter that converts //it to navigation data, then it is passed to the visualization filter that //will visualize the transformation m_IGTLMsgToNavDataFilter->ConnectTo(m_IGTLDeviceSource); m_VisFilter->ConnectTo(m_IGTLMsgToNavDataFilter); //create an object that will be moved respectively to the navigation data for (size_t i = 0; i < m_IGTLMsgToNavDataFilter->GetNumberOfIndexedOutputs(); i++) { mitk::DataNode::Pointer newNode = mitk::DataNode::New(); QString name("DemoNode IGTLProviderExmpl T"); name.append(QString::number(i)); newNode->SetName(name.toStdString()); //create small sphere and use it as surface mitk::Surface::Pointer mySphere = mitk::Surface::New(); vtkSmartPointer vtkSphere = vtkSmartPointer::New(); vtkSphere->SetRadius(2.0f); vtkSphere->SetCenter(0.0, 0.0, 0.0); vtkSphere->Update(); mySphere->SetVtkPolyData(vtkSphere->GetOutput()); newNode->SetData(mySphere); - m_VisFilter->SetRepresentationObject(i, mySphere); + m_VisFilter->SetRepresentationObject(i, mySphere.GetPointer()); m_DemoNodes.append(newNode); } this->ResizeBoundingBox(); } void OpenIGTLinkExample::DestroyPipeline() { m_VisFilter = nullptr; foreach(mitk::DataNode::Pointer node, m_DemoNodes) { this->GetDataStorage()->Remove(node); } this->m_DemoNodes.clear(); } void OpenIGTLinkExample::Start() { if (this->m_Controls.butStart->text().contains("Start Pipeline")) { static bool isFirstTime = true; if (isFirstTime) { //Setup the pipeline this->CreatePipeline(); isFirstTime = false; } m_Timer.setInterval(this->m_Controls.visualizationUpdateRateSpinBox->value()); m_Timer.start(); //this->m_Controls.visualizationUpdateRateSpinBox->setEnabled(true); this->m_Controls.butStart->setText("Stop Pipeline"); } else { m_Timer.stop(); igtl::StopTrackingDataMessage::Pointer stopStreaming = igtl::StopTrackingDataMessage::New(); this->m_IGTLClient->SendMessage(mitk::IGTLMessage::New((igtl::MessageBase::Pointer) stopStreaming)); this->m_Controls.butStart->setText("Start Pipeline"); //this->m_Controls.visualizationUpdateRateSpinBox->setEnabled(false); } } void OpenIGTLinkExample::UpdatePipeline() { if (this->m_Controls.visualizeCheckBox->isChecked()) { //update the pipeline m_VisFilter->Update(); ////update the boundings //mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(this->GetDataStorage()); //Update rendering mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } else { //no visualization so we just update this filter m_IGTLMsgToNavDataFilter->Update(); //record a timestamp if the output is new //static double previousTimestamp; //double curTimestamp = m_IGTLMsgToNavDataFilter->GetOutput()->GetIGTTimeStamp(); //if (previousTimestamp != curTimestamp) static mitk::NavigationData::Pointer previousND = mitk::NavigationData::New(); mitk::NavigationData* curND = m_IGTLMsgToNavDataFilter->GetOutput(); //std::cout << "9: igt timestamp: " << curND->GetIGTTimeStamp() << std::endl; //std::cout << "9: timestamp: " << curND->GetTimeStamp() << std::endl; if ( !mitk::Equal( *(previousND.GetPointer()), *curND ) ) { //previousTimestamp = curTimestamp; previousND->Graft(curND); } } //check if the timer interval changed static int previousValue = 0; int currentValue = this->m_Controls.visualizationUpdateRateSpinBox->value(); if (previousValue != currentValue) { m_Timer.setInterval(currentValue); previousValue = currentValue; } } /** * \brief To initialize the scene to the bounding box of all visible objects */ void OpenIGTLinkExample::ResizeBoundingBox() { // get all nodes mitk::DataStorage::SetOfObjects::ConstPointer rs = this->GetDataStorage()->GetAll(); auto bounds = this->GetDataStorage()->ComputeBoundingGeometry3D(rs); if (bounds.IsNull()) { return; } //expand the bounding box in case the instruments are all at one position mitk::Point3D center = bounds->GetCenterInWorld(); mitk::Geometry3D::BoundsArrayType extended_bounds = bounds->GetGeometryForTimeStep(0)->GetBounds(); for (unsigned int i = 0; i < 3; ++i) { if (bounds->GetExtentInWorld(i) < 500) { // extend the bounding box extended_bounds[i * 2] = center[i] - 500 / 2.0; extended_bounds[i * 2 + 1] = center[i] + 500 / 2.0; } } //set the extended bounds bounds->GetGeometryForTimeStep(0)->SetBounds(extended_bounds); // initialize the views to the bounding geometry mitk::RenderingManager::GetInstance()->InitializeViews(bounds); } diff --git a/Plugins/org.mitk.gui.qt.igtexamples/src/internal/OpenIGTLinkPlugin.cpp b/Plugins/org.mitk.gui.qt.igtexamples/src/internal/OpenIGTLinkPlugin.cpp index 6fedea556c..d32659b08c 100644 --- a/Plugins/org.mitk.gui.qt.igtexamples/src/internal/OpenIGTLinkPlugin.cpp +++ b/Plugins/org.mitk.gui.qt.igtexamples/src/internal/OpenIGTLinkPlugin.cpp @@ -1,197 +1,197 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ // Blueberry #include #include // Qmitk #include "OpenIGTLinkPlugin.h" // Qt #include //mitk image #include //VTK #include const std::string OpenIGTLinkPlugin::VIEW_ID = "org.mitk.views.openigtlinkplugin"; void OpenIGTLinkPlugin::SetFocus() { } void OpenIGTLinkPlugin::CreateQtPartControl(QWidget *parent) { // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi(parent); connect(m_Controls.buttonConnect, SIGNAL(clicked()), this, SLOT(ConnectButtonClicked())); connect(m_Controls.buttonReceive, SIGNAL(clicked()), this, SLOT(ReceivingButtonClicked())); connect(&m_Timer, SIGNAL(timeout()), this, SLOT(UpdatePipeline())); m_Image2dNode = mitk::DataNode::New(); m_State = IDLE; StateChanged(m_State); } void OpenIGTLinkPlugin::UpdatePipeline() { m_NavigationDataObjectVisualizationFilter->Update(); mitk::Image::Pointer image2d = m_ImageFilter2D->GetNextImage().at(0); mitk::Image::Pointer image3d = m_ImageFilter3D->GetNextImage().at(0); m_Image2dNode->SetName("US Image Stream"); m_Image2dNode->SetData(image2d); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void OpenIGTLinkPlugin::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList &) { // iterate all selected objects, adjust warning visibility } void OpenIGTLinkPlugin::ConnectButtonClicked() { bool success; switch (m_State) { case IDLE: m_IGTLClient = mitk::IGTLClient::New(true); m_IGTLClient->SetHostname(m_Controls.textEditHostname->text().toStdString()); m_IGTLClient->SetPortNumber(m_Controls.spinBoxPort->value()); success = m_IGTLClient->OpenConnection(); if (!success) { QMessageBox::warning(nullptr, QString("Connection failed"), QString("Client could not connect to given server."), QMessageBox::Ok, QMessageBox::Abort); } else { m_State = CONNECTED; StateChanged(m_State); } break; case CONNECTED: success = m_IGTLClient->CloseConnection(); m_State = IDLE; StateChanged(m_State); break; case RECEIVING: ReceivingButtonClicked(); success = m_IGTLClient->CloseConnection(); m_State = IDLE; StateChanged(m_State); break; } } void OpenIGTLinkPlugin::ReceivingButtonClicked() { switch (m_State) { case IDLE: QMessageBox::warning(nullptr, QString("Not ready.."), QString("The client must be connected to a server first."), QMessageBox::Ok, QMessageBox::Abort); break; case CONNECTED: m_IGTL2DImageDeviceSource = mitk::IGTL2DImageDeviceSource::New(); m_IGTL3DImageDeviceSource = mitk::IGTL3DImageDeviceSource::New(); m_IGTLTransformDeviceSource = mitk::IGTLTrackingDataDeviceSource::New(); m_IGTL2DImageDeviceSource->SetIGTLDevice(m_IGTLClient); m_IGTL3DImageDeviceSource->SetIGTLDevice(m_IGTLClient); m_IGTLTransformDeviceSource->SetIGTLDevice(m_IGTLClient); this->GetDataStorage()->Add(m_Image2dNode); m_IGTLMessageToNavigationDataFilter = mitk::IGTLMessageToNavigationDataFilter::New(); m_NavigationDataObjectVisualizationFilter = mitk::NavigationDataObjectVisualizationFilter::New(); m_ImageFilter2D = mitk::IGTLMessageToUSImageFilter::New(); m_ImageFilter3D = mitk::IGTLMessageToUSImageFilter::New(); m_IGTLMessageToNavigationDataFilter->SetNumberOfExpectedOutputs(3); m_IGTLMessageToNavigationDataFilter->ConnectTo(m_IGTLTransformDeviceSource); m_NavigationDataObjectVisualizationFilter->ConnectTo(m_IGTLMessageToNavigationDataFilter); m_ImageFilter2D->ConnectTo(m_IGTL2DImageDeviceSource); m_ImageFilter3D->ConnectTo(m_IGTL3DImageDeviceSource); //create an object that will be moved respectively to the navigation data for (size_t i = 0; i < m_IGTLMessageToNavigationDataFilter->GetNumberOfIndexedOutputs(); i++) { mitk::DataNode::Pointer newNode = mitk::DataNode::New(); QString name("DemoNode T"); name.append(QString::number(i)); newNode->SetName(name.toStdString()); //create small sphere and use it as surface mitk::Surface::Pointer mySphere = mitk::Surface::New(); vtkSmartPointer vtkSphere = vtkSmartPointer::New(); vtkSphere->SetRadius(2.0f); vtkSphere->SetCenter(0.0, 0.0, 0.0); vtkSphere->Update(); mySphere->SetProperty("color", mitk::ColorProperty::New(1, 0, 0)); mySphere->SetVtkPolyData(vtkSphere->GetOutput()); newNode->SetData(mySphere); this->GetDataStorage()->Add(newNode); - m_NavigationDataObjectVisualizationFilter->SetRepresentationObject(i, mySphere); + m_NavigationDataObjectVisualizationFilter->SetRepresentationObject(i, mySphere.GetPointer()); } m_IGTLClient->StartCommunication(); m_Timer.setInterval(10); m_Timer.start(); m_State = RECEIVING; StateChanged(m_State); break; case RECEIVING: m_IGTLClient->StopCommunication(); this->GetDataStorage()->Remove(this->GetDataStorage()->GetAll()); m_Timer.stop(); m_State = CONNECTED; StateChanged(m_State); break; } } void OpenIGTLinkPlugin::StateChanged(OpenIGTLinkPlugin::State newState) { switch (newState) { case IDLE: m_Controls.buttonConnect->setText(QString("Connect To Server")); m_Controls.buttonReceive->setText(QString("Start Receiving")); m_Controls.buttonReceive->setDisabled(true); break; case CONNECTED: m_Controls.buttonConnect->setText(QString("Disconnect From Server")); m_Controls.buttonReceive->setText(QString("Start Receiving")); m_Controls.buttonReceive->setDisabled(false); break; case RECEIVING: m_Controls.buttonConnect->setText(QString("Disconnect From Server")); m_Controls.buttonReceive->setText(QString("Stop Receiving")); m_Controls.buttonReceive->setDisabled(false); break; } } diff --git a/Plugins/org.mitk.gui.qt.igtexamples/src/internal/OpenIGTLinkProviderExample.cpp b/Plugins/org.mitk.gui.qt.igtexamples/src/internal/OpenIGTLinkProviderExample.cpp index 3fa7ecc854..584e62060b 100644 --- a/Plugins/org.mitk.gui.qt.igtexamples/src/internal/OpenIGTLinkProviderExample.cpp +++ b/Plugins/org.mitk.gui.qt.igtexamples/src/internal/OpenIGTLinkProviderExample.cpp @@ -1,278 +1,278 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkRenderWindow.h" // Qt #include #include // mitk #include #include //#include #include #include #include // vtk #include // #include "OpenIGTLinkProviderExample.h" //igtl #include "igtlStringMessage.h" const std::string OpenIGTLinkProviderExample::VIEW_ID = "org.mitk.views.OpenIGTLinkProviderExample"; OpenIGTLinkProviderExample::~OpenIGTLinkProviderExample() { this->DestroyPipeline(); if (m_IGTLMessageProvider.IsNotNull()) { m_IGTLMessageProvider->UnRegisterMicroservice(); } if (m_NavDataToIGTLMsgFilter.IsNotNull()) { m_NavDataToIGTLMsgFilter->UnRegisterMicroservice(); } } void OpenIGTLinkProviderExample::SetFocus() { } void OpenIGTLinkProviderExample::CreateQtPartControl( QWidget *parent ) { // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi( parent ); // connect the widget items with the methods connect( m_Controls.butStart, SIGNAL(clicked()), this, SLOT(Start()) ); connect( m_Controls.butOpenNavData, SIGNAL(clicked()), this, SLOT(OnOpenFile()) ); connect( &m_VisualizerTimer, SIGNAL(timeout()), this, SLOT(UpdateVisualization())); //create a new OpenIGTLink Client m_IGTLServer = mitk::IGTLServer::New(false); m_IGTLServer->SetName("OIGTL Provider Example Device"); //create a new OpenIGTLink Device source m_IGTLMessageProvider = mitk::IGTLMessageProvider::New(); //set the OpenIGTLink server as the source for the device source m_IGTLMessageProvider->SetIGTLDevice(m_IGTLServer); //register the provider so that it can be configured with the IGTL manager //plugin. This could be hardcoded but now I already have the fancy plugin. m_IGTLMessageProvider->RegisterAsMicroservice(); } void OpenIGTLinkProviderExample::CreatePipeline() { //create a navigation data player object that will play nav data from a //recorded file m_NavDataPlayer = mitk::NavigationDataSequentialPlayer::New(); //set the currently read navigation data set m_NavDataPlayer->SetNavigationDataSet(m_NavDataSet); //create a filter that converts navigation data into IGTL messages m_NavDataToIGTLMsgFilter = mitk::NavigationDataToIGTLMessageFilter::New(); //connect the filters with each other //the navigation data player reads a file with recorded navigation data, //passes this data to a filter that converts it into a IGTLMessage. //The provider is not connected because it will search for fitting services. //Once it found the filter it will automatically connect to it. m_NavDataToIGTLMsgFilter->ConnectTo(m_NavDataPlayer); //define the operation mode for this filter, we want to send tracking data //messages m_NavDataToIGTLMsgFilter->SetOperationMode( mitk::NavigationDataToIGTLMessageFilter::ModeSendTDataMsg); // mitk::NavigationDataToIGTLMessageFilter::ModeSendTransMsg); //set the name of this filter to identify it easier m_NavDataToIGTLMsgFilter->SetName("Tracking Data Source From Example"); //register this filter as micro service. The message provider looks for //provided IGTLMessageSources, once it found this microservice and someone //requested this data type then the provider will connect with this filter //automatically. m_NavDataToIGTLMsgFilter->RegisterAsMicroservice(); //also create a visualize filter to visualize the data m_NavDataVisualizer = mitk::NavigationDataObjectVisualizationFilter::New(); //create an object that will be moved respectively to the navigation data for (size_t i = 0; i < m_NavDataPlayer->GetNumberOfIndexedOutputs(); i++) { mitk::DataNode::Pointer newNode = mitk::DataNode::New(); QString name("DemoNode IGTLProviderExmpl T"); name.append(QString::number(i)); newNode->SetName(name.toStdString()); //create small sphere and use it as surface mitk::Surface::Pointer mySphere = mitk::Surface::New(); vtkSmartPointer vtkData = vtkSmartPointer::New(); vtkData->SetRadius(2.0f); vtkData->SetCenter(0.0, 0.0, 0.0); vtkData->Update(); mySphere->SetVtkPolyData(vtkData->GetOutput()); newNode->SetData(mySphere); this->GetDataStorage()->Add(newNode); - m_NavDataVisualizer->SetRepresentationObject(i, mySphere); + m_NavDataVisualizer->SetRepresentationObject(i, mySphere.GetPointer()); m_DemoNodes.append(newNode); } //connect the visualization with the navigation data player m_NavDataVisualizer->ConnectTo(m_NavDataPlayer); //start the player this->Start(); //resize the boundaries this->m_NavDataVisualizer->Update(); this->ResizeBoundingBox(); } void OpenIGTLinkProviderExample::DestroyPipeline() { if (m_NavDataPlayer.IsNotNull()) { //m_NavDataPlayer->StopPlaying(); } foreach(mitk::DataNode::Pointer node, m_DemoNodes) { this->GetDataStorage()->Remove(node); } this->m_DemoNodes.clear(); } void OpenIGTLinkProviderExample::Start() { if ( this->m_Controls.butStart->text().contains("Start") ) { m_NavDataPlayer->SetRepeat(true); //m_NavDataPlayer->StartPlaying(); this->m_Controls.butStart->setText("Stop Playing Recorded Navigation Data "); //start the visualization double fps = m_Controls.m_updateRate->value(); double millisecondsPerFrame = 1 / fps * 1000; this->m_VisualizerTimer.start(millisecondsPerFrame); } else { //m_NavDataPlayer->StopPlaying(); this->m_Controls.butStart->setText("Start Playing Recorded Navigation Data "); //stop the visualization this->m_VisualizerTimer.stop(); } } void OpenIGTLinkProviderExample::OnOpenFile(){ // FIXME Filter for correct files and use correct Reader QString filter = tr("NavigationData File (*.csv *.xml)"); QString fileName = QFileDialog::getOpenFileName(nullptr, tr("Open NavigationData Set"), "", filter); if ( fileName.isNull() ) { return; } // user pressed cancel try { m_NavDataSet = dynamic_cast (mitk::IOUtil::Load(fileName.toStdString())[0].GetPointer()); } catch ( const mitk::Exception &e ) { MITK_WARN("NavigationDataPlayerView") << "could not open file " << fileName.toStdString(); QMessageBox::critical(nullptr, "Error Reading File", "The file '" + fileName +"' could not be read.\n" + e.GetDescription() ); return; } this->m_Controls.butStart->setEnabled(true); //Setup the pipeline this->CreatePipeline(); // Update Labels // m_Controls->m_LblFilePath->setText(fileName); // m_Controls->m_LblTools->setText(QString::number(m_NavDataSet->GetNumberOfTools())); } void OpenIGTLinkProviderExample::UpdateVisualization() { this->m_NavDataPlayer->GoToNextSnapshot(); if (this->m_Controls.visualizeCheckBox->isChecked()) { //update the filter this->m_NavDataVisualizer->Update(); ////update the bounds //mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(this->GetDataStorage()); //update rendering mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } /** * \brief To initialize the scene to the bounding box of all visible objects */ void OpenIGTLinkProviderExample::ResizeBoundingBox() { // get all nodes mitk::DataStorage::SetOfObjects::ConstPointer rs = this->GetDataStorage()->GetAll(); auto bounds = this->GetDataStorage()->ComputeBoundingGeometry3D(rs)->Clone(); if (bounds.IsNull()) { return; } //expand the bounding box in case the instruments are all at one position mitk::Point3D center = bounds->GetCenterInWorld(); mitk::Geometry3D::BoundsArrayType extended_bounds = bounds->GetGeometryForTimeStep(0)->GetBounds(); for (unsigned int i = 0; i < 3; ++i) { if (bounds->GetExtentInWorld(i) < 500) { // extend the bounding box extended_bounds[i * 2] = center[i] - 500 / 2.0; extended_bounds[i * 2 + 1] = center[i] + 500 / 2.0; } } //set the extended bounds bounds->GetGeometryForTimeStep(0)->SetBounds(extended_bounds); // initialize the views to the bounding geometry mitk::RenderingManager::GetInstance()->InitializeViews(bounds); } diff --git a/Plugins/org.mitk.gui.qt.igtexamples/src/internal/QmitkIGTTutorialView.cpp b/Plugins/org.mitk.gui.qt.igtexamples/src/internal/QmitkIGTTutorialView.cpp index 12948d7dbb..f5412b58bd 100644 --- a/Plugins/org.mitk.gui.qt.igtexamples/src/internal/QmitkIGTTutorialView.cpp +++ b/Plugins/org.mitk.gui.qt.igtexamples/src/internal/QmitkIGTTutorialView.cpp @@ -1,257 +1,257 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "QmitkIGTTutorialView.h" #include "mitkNDIPassiveTool.h" #include "mitkNDITrackingDevice.h" #include "mitkVirtualTrackingDevice.h" #include "mitkStandardFileLocations.h" #include "mitkSerialCommunication.h" #include "mitkCone.h" #include #include #include "mitkNDIPolarisTypeInformation.h" const std::string QmitkIGTTutorialView::VIEW_ID = "org.mitk.views.igttutorial"; QmitkIGTTutorialView::QmitkIGTTutorialView() : QmitkAbstractView(), m_Controls(nullptr), m_Source(nullptr), m_Visualizer(nullptr), m_Timer(nullptr) { } QmitkIGTTutorialView::~QmitkIGTTutorialView() { } void QmitkIGTTutorialView::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widget m_Controls = new Ui::QmitkIGTTutorialViewControls; m_Controls->setupUi(parent); this->CreateConnections(); } } void QmitkIGTTutorialView::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_StartButton), SIGNAL(clicked()),(QObject*) this, SLOT(OnStartIGT())); connect( (QObject*)(m_Controls->m_StopButton), SIGNAL(clicked()),(QObject*) this, SLOT(OnStopIGT())); } } void QmitkIGTTutorialView::SetFocus() { m_Controls->m_virtualTrackingRadioButton->setFocus(); } //The next line starts a snippet to display this code in the documentation. If you don't revise the documentation, don't remove it! //! [OnStart 1] void QmitkIGTTutorialView::OnStartIGT() { //This method is called when the "Start Image Guided Therapy" button is pressed. Any kind of navigation application will //start with the connection to a tracking system and as we do image guided procedures we want to show //something on the screen. In this tutorial we connect to the NDI Polaris tracking system pr a virtual tracking device and we will //show the movement of a tool as cone in MITK. //! [OnStart 1] //! [OnStart 2] try { if(m_Controls->m_NDITrackingRadioButton->isChecked()) { /**************** Variant 1: Use a NDI Polaris Tracking Device ****************/ //Here we want to use the NDI Polaris tracking device. Therefore we instantiate a object of the class //NDITrackingDevice and make some settings which are necessary for a proper connection to the device. MITK_INFO << "NDI tracking"; QMessageBox::warning ( nullptr, "Warning", "You have to set the parameters for the NDITracking device inside the code (QmitkIGTTutorialView::OnStartIGT()) before you can use it."); mitk::NDITrackingDevice::Pointer tracker = mitk::NDITrackingDevice::New(); //instantiate tracker->SetPortNumber(mitk::SerialCommunication::COM4); //set the comport tracker->SetBaudRate(mitk::SerialCommunication::BaudRate115200); //set the baud rate tracker->SetType(mitk::NDIPolarisTypeInformation::GetTrackingDeviceName()); //set the type there you can choose between Polaris and Aurora //The tools represent the sensors of the tracking device. In this case we have one pointer tool. //The TrackingDevice object it self fills the tool with data. So we have to add the tool to the //TrackingDevice object. // The Polaris system needs a ".rom" file which describes the geometry of the markers related to the tool tip. //NDI provides an own software (NDI architect) to generate those files. tracker->AddTool("MyInstrument", "c:\\myinstrument.rom"); //! [OnStart 2] /**************** End of Variant 1 ****************/ //! [OnStart 3] //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 a 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. m_Source = mitk::TrackingDeviceSource::New(); //We need the filter objects to stay alive, //therefore they must be members. m_Source->SetTrackingDevice(tracker); //Here we set the tracking device to the source of the pipeline. //! [OnStart 3] } //! [OnStart 4] else { /**************** Variant 2: Emulate a Tracking Device with mitk::VirtualTrackingDevice ****************/ // For tests, it is useful to simulate a tracking device in software. This is what mitk::VirtualTrackingDevice does. // It will produce random position, orientation and error values for each tool that is added. MITK_INFO << "virtual tracking"<SetBounds(bounds); tracker->AddTool("MyInstrument"); // add a tool to tracker //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 a 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. m_Source = mitk::TrackingDeviceSource::New(); //We need the filter objects to stay alive, //therefore they must be members. m_Source->SetTrackingDevice(tracker); //Here we set the tracking device to the source of the pipeline. /**************** End of Variant 2 ****************/ } //! [OnStart 4] //! [OnStart 5] m_Source->Connect(); //Now we connect to the tracking system. //Note we do not call this on the TrackingDevice object //! [OnStart 5] //! [OnStart 6] //As we wish to visualize our tool we need to have a PolyData which shows us the movement of our tool. //Here we take a cone shaped PolyData. In MITK you have to add the PolyData as a node into the DataStorage //to show it inside of the rendering windows. After that you can change the properties of the cone //to manipulate rendering, e.g. the position and orientation as in our case. mitk::Cone::Pointer cone = mitk::Cone::New(); //instantiate a new cone double scale[] = {10.0, 10.0, 10.0}; cone->GetGeometry()->SetSpacing(scale); //scale it a little that so we can see something mitk::DataNode::Pointer node = mitk::DataNode::New(); //generate a new node to store the cone into //the DataStorage. node->SetData(cone); //The data of that node is our cone. node->SetName("My tracked object"); //The node has additional properties like a name node->SetColor(1.0, 0.0, 0.0); //or the color. Here we make it red. this->GetDataStorage()->Add(node); //After adding the Node with the cone in it to the //DataStorage, MITK will show the cone in the //render windows. //! [OnStart 6] //! [OnStart 7] //For updating the render windows we use another filter of the MITK-IGT pipeline concept. The //NavigationDataObjectVisualizationFilter needs as input a NavigationData and a //PolyData. In our case the input is the source and the PolyData our cone. //First we create a new filter for the visualization update. m_Visualizer = mitk::NavigationDataObjectVisualizationFilter::New(); m_Visualizer->SetInput(0, m_Source->GetOutput()); //Then we connect to the pipeline. - m_Visualizer->SetRepresentationObject(0, cone); //After that we have to assign the cone to the input + m_Visualizer->SetRepresentationObject(0, cone.GetPointer()); // After that we have to assign the cone to the input //Now this simple pipeline is ready, so we can start the tracking. Here again: We do not call the //StartTracking method from the tracker object itself. Instead we call this method from our source. m_Source->StartTracking(); //! [OnStart 7] //! [OnStart 8] //Now every call of m_Visualizer->Update() will show us the cone at the position and orientation //given from the tracking device. //We use a QTimer object to call this Update() method in a fixed interval. if (m_Timer == nullptr) { m_Timer = new QTimer(this); //create a new timer } connect(m_Timer, SIGNAL(timeout()), this, SLOT(OnTimer())); //connect the timer to the method OnTimer() m_Timer->start(100); //Every 100ms the method OnTimer() is called. -> 10fps //! [OnStart 8] //! [OnStart 8a] //disable the tracking device selection this->m_Controls->m_NDITrackingRadioButton->setDisabled(true); this->m_Controls->m_virtualTrackingRadioButton->setDisabled(true); //! [OnStart 8a] } //! [OnStart 9] catch (std::exception& e) { // add cleanup MITK_INFO << "Error in QmitkIGTTutorial::OnStartIGT():" << e.what(); } //! [OnStart 9] } //![OnTimer] void QmitkIGTTutorialView::OnTimer() { //Here we call the Update() method from the Visualization Filter. Internally the filter checks if //new NavigationData is available. If we have a new NavigationData the cone position and orientation //will be adapted. m_Visualizer->Update(); auto geo = this->GetDataStorage()->ComputeBoundingGeometry3D(this->GetDataStorage()->GetAll()); mitk::RenderingManager::GetInstance()->InitializeViews( geo ); this->RequestRenderWindowUpdate(); } //![OnTimer] //![OnStop] void QmitkIGTTutorialView::OnStopIGT() { //This method is called when the Stop button is pressed. Here we disconnect the pipeline. if (m_Timer == nullptr) { MITK_INFO << "No Timer was set yet!"; return; } //To disconnect the pipeline in a save way we first stop the timer than we disconnect the tracking device. //After that we destroy all filters with changing them to nullptr. m_Timer->stop(); disconnect(m_Timer, SIGNAL(timeout()), this, SLOT(OnTimer())); m_Timer = nullptr; m_Source->StopTracking(); m_Source->Disconnect(); m_Source = nullptr; m_Visualizer = nullptr; m_Source = nullptr; this->GetDataStorage()->Remove(this->GetDataStorage()->GetNamedNode("My tracked object")); //enable the tracking device selection this->m_Controls->m_NDITrackingRadioButton->setEnabled(true); this->m_Controls->m_virtualTrackingRadioButton->setEnabled(true); } //![OnStop] 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 034b7b6183..84d45f917c 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.cpp +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.cpp @@ -1,236 +1,236 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ // Qmitk #include "QmitkNavigationDataPlayerView.h" // QT #include #include //mitk #include #include #include #include #include #include // VTK #include const std::string QmitkNavigationDataPlayerView::VIEW_ID = "org.mitk.views.navigationdataplayer"; QmitkNavigationDataPlayerView::QmitkNavigationDataPlayerView() : m_Controls( nullptr ) { } QmitkNavigationDataPlayerView::~QmitkNavigationDataPlayerView() { } 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->CreateConnections(); // make deselected Player invisible m_Controls->m_TimedWidget->setVisible(false); } } void QmitkNavigationDataPlayerView::SetFocus() { if ( m_Controls ) { m_Controls->m_grpbxControls->setFocus(); } } void QmitkNavigationDataPlayerView::CreateConnections() { 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()) ); connect( m_Controls->m_SequentialWidget, SIGNAL(SignalUpdate()), this, SLOT(OnUpdate()) ); connect( m_Controls->m_TimedWidget, SIGNAL(SignalUpdate()), this, SLOT(OnUpdate()) ); this->SetInteractionComponentsEnabledState(false); } void QmitkNavigationDataPlayerView::OnOpenFile() { mitk::NavigationDataReaderInterface::Pointer reader = nullptr; QString filter = tr("NavigationData File (*.csv *.xml)"); QString fileName = QFileDialog::getOpenFileName(nullptr, tr("Open NavigationData Set"), "", filter); if ( fileName.isNull() ) { return; } // user pressed cancel try { m_Data = dynamic_cast (mitk::IOUtil::Load(fileName.toStdString())[0].GetPointer()); } catch ( const mitk::Exception &e ) { MITK_WARN("NavigationDataPlayerView") << "could not open file " << fileName.toStdString(); QMessageBox::critical(nullptr, "Error Reading File", "The file '" + fileName +"' could not be read.\n" + e.GetDescription() ); return; } if (m_Controls->m_ChkConvertToPointSet->isChecked()) m_Data->ConvertNavigationDataToPointSet(); // 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())); // Initialize Widgets and create Player this->OnSelectPlayer(); this->SetInteractionComponentsEnabledState(true); } void QmitkNavigationDataPlayerView::OnSelectPlayer() { if (m_Controls->m_RdbSequential->isChecked()) { m_Controls->m_SequentialWidget->setVisible(true); m_Controls->m_TimedWidget->setVisible(false); mitk::NavigationDataSequentialPlayer::Pointer seqPlayer = mitk::NavigationDataSequentialPlayer::New(); seqPlayer->SetNavigationDataSet(m_Data); m_Controls->m_SequentialWidget->SetPlayer(seqPlayer); m_Player = seqPlayer; } else { m_Controls->m_SequentialWidget->setVisible(false); m_Controls->m_TimedWidget->setVisible(true); mitk::NavigationDataPlayer::Pointer timedPlayer = mitk::NavigationDataPlayer::New(); timedPlayer->SetNavigationDataSet(m_Data); m_Controls->m_TimedWidget->SetPlayer(timedPlayer); m_Player = timedPlayer; } this->ConfigurePlayer(); // SetupRenderingPipeline this->OnSetDisplay(); } void QmitkNavigationDataPlayerView::ConfigurePlayer() { // set repeat mode according to the checkbox m_Player->SetRepeat( m_Controls->m_chkRepeat->isChecked() ); } void QmitkNavigationDataPlayerView::OnSetRepeat(int checkState) { m_Player->SetRepeat(checkState != 0); } void QmitkNavigationDataPlayerView::OnSetMicroservice(){ if(m_Controls->m_ChkMicroservice->isChecked()) { m_ToolStorage = mitk::NavigationToolStorage::New(); for (itk::ProcessObject::DataObjectPointerArraySizeType i = 0; i < m_Player->GetNumberOfIndexedOutputs(); i++) { 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->SetDataNode(m_RenderingNodes.at(i)); currentDummyTool->SetIdentifier(name.str()); m_ToolStorage->AddTool(currentDummyTool); } m_ToolStorage->SetName("NavigationDataPlayer Tool Storage"); m_Player->SetToolMetaDataCollection(m_ToolStorage); m_Player->RegisterAsMicroservice(); m_ToolStorage->SetSourceID(m_Player->GetMicroserviceID()); //DEPRECATED / not needed anymore because NavigationDataSource now holds a member of its tool storage. Only left for backward compatibility. m_ToolStorage->RegisterAsMicroservice(); } else { if (m_ToolStorage.IsNotNull()) m_ToolStorage->UnRegisterMicroservice(); m_ToolStorage = nullptr; m_Player->UnRegisterMicroservice(); } } void QmitkNavigationDataPlayerView::OnUpdate(){ if (m_VisFilter.IsNotNull()) { m_VisFilter->Update(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkNavigationDataPlayerView::OnSetDisplay(){ DestroyPipeline(); if ( (m_Controls->m_ChkDisplay->isChecked()) && ( m_Player.IsNotNull() )) { CreatePipeline(); } } 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(); vtkSmartPointer vtkData = vtkSmartPointer::New(); vtkData->SetRadius(5.0f); vtkData->SetCenter(0.0, 0.0, 0.0); vtkData->Update(); mySphere->SetVtkPolyData(vtkData->GetOutput()); node->SetData(mySphere); - m_VisFilter->SetRepresentationObject(i, mySphere); + m_VisFilter->SetRepresentationObject(i, mySphere.GetPointer()); // Add Node to DataStorageand to local list of Nodes GetDataStorage()->Add(node); m_RenderingNodes.push_back(node); } m_VisFilter->Update(); mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(GetDataStorage()); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkNavigationDataPlayerView::DestroyPipeline(){ m_VisFilter = nullptr; for (unsigned int i = 0; i < m_RenderingNodes.size(); i++){ this->GetDataStorage()->Remove(m_RenderingNodes[i]); } m_RenderingNodes.clear(); } void QmitkNavigationDataPlayerView::SetInteractionComponentsEnabledState(bool isActive){ m_Controls->m_grpbxSettings->setEnabled(isActive); m_Controls->m_grpbxControls->setEnabled(isActive); }