diff --git a/CMake/BuildConfigurations/mitkNavigationModules.cmake b/CMake/BuildConfigurations/mitkNavigationModules.cmake index ee7b528cc9..456c1c877c 100644 --- a/CMake/BuildConfigurations/mitkNavigationModules.cmake +++ b/CMake/BuildConfigurations/mitkNavigationModules.cmake @@ -1,37 +1,38 @@ message(STATUS "Configuring MITK Navigation Modules Build") set(MITK_CONFIG_PACKAGES ACVD Qt5 BLUEBERRY ) # Enable open cv and open igt link, which is a necessary configuration set(MITK_USE_OpenCV ON CACHE BOOL "MITK Use OpenCV Library" FORCE) set(MITK_USE_OpenIGTLink ON CACHE BOOL "MITK Use OpenIGTLink Library" FORCE) # Enable default plugins and the navigation modules set(MITK_CONFIG_PLUGINS org.mitk.gui.qt.datamanager org.mitk.gui.qt.stdmultiwidgeteditor org.mitk.gui.qt.dicom org.mitk.gui.qt.imagenavigator org.mitk.gui.qt.measurementtoolbox org.mitk.gui.qt.properties org.mitk.gui.qt.segmentation org.mitk.gui.qt.volumevisualization org.mitk.planarfigure org.mitk.gui.qt.moviemaker org.mitk.gui.qt.pointsetinteraction org.mitk.gui.qt.registration org.mitk.gui.qt.remeshing org.mitk.gui.qt.viewnavigator org.mitk.gui.qt.imagecropper org.mitk.gui.qt.igtexamples org.mitk.gui.qt.igttracking org.mitk.gui.qt.igtlplugin + org.mitk.gui.qt.openigtlink org.mitk.gui.qt.ultrasound org.mitk.gui.qt.toftutorial org.mitk.gui.qt.tofutil ) diff --git a/CMake/MITK.vcxproj.user.in b/CMake/MITK.vcxproj.user.in index 48fc5df678..7d974043e4 100644 --- a/CMake/MITK.vcxproj.user.in +++ b/CMake/MITK.vcxproj.user.in @@ -1,15 +1,28 @@ PATH=@MITK_RUNTIME_PATH_REL@;@CUSTOM_RUNTIME_PATH@;@CMAKE_RUNTIME_OUTPUT_DIRECTORY@\@VS_BUILD_TYPE_REL@;@CMAKE_RUNTIME_OUTPUT_DIRECTORY@\plugins\@VS_BUILD_TYPE_REL@;%PATH% WindowsLocalDebugger PATH=@MITK_RUNTIME_PATH_RELDEB@;@CUSTOM_RUNTIME_PATH@;@CMAKE_RUNTIME_OUTPUT_DIRECTORY@\@VS_BUILD_TYPE_RELDEB@;@CMAKE_RUNTIME_OUTPUT_DIRECTORY@\plugins\@VS_BUILD_TYPE_RELDEB@;%PATH% WindowsLocalDebugger PATH=@MITK_RUNTIME_PATH_DEB@;@CUSTOM_RUNTIME_PATH@;@CMAKE_RUNTIME_OUTPUT_DIRECTORY@\@VS_BUILD_TYPE_DEB@;@CMAKE_RUNTIME_OUTPUT_DIRECTORY@\plugins\@VS_BUILD_TYPE_DEB@;%PATH% WindowsLocalDebugger + + + PATH=@MITK_RUNTIME_PATH_REL@;@CUSTOM_RUNTIME_PATH@;@CMAKE_RUNTIME_OUTPUT_DIRECTORY@\@VS_BUILD_TYPE_REL@;@CMAKE_RUNTIME_OUTPUT_DIRECTORY@\plugins\@VS_BUILD_TYPE_REL@;%PATH% + WindowsLocalDebugger + + + PATH=@MITK_RUNTIME_PATH_RELDEB@;@CUSTOM_RUNTIME_PATH@;@CMAKE_RUNTIME_OUTPUT_DIRECTORY@\@VS_BUILD_TYPE_RELDEB@;@CMAKE_RUNTIME_OUTPUT_DIRECTORY@\plugins\@VS_BUILD_TYPE_RELDEB@;%PATH% + WindowsLocalDebugger + + + PATH=@MITK_RUNTIME_PATH_DEB@;@CUSTOM_RUNTIME_PATH@;@CMAKE_RUNTIME_OUTPUT_DIRECTORY@\@VS_BUILD_TYPE_DEB@;@CMAKE_RUNTIME_OUTPUT_DIRECTORY@\plugins\@VS_BUILD_TYPE_DEB@;%PATH% + WindowsLocalDebugger + \ No newline at end of file diff --git a/Modules/US/USNavigation/Filter/mitkNavigationDataPassThroughFilter.cpp b/Modules/IGT/Algorithms/mitkNavigationDataPassThroughFilter.cpp similarity index 100% rename from Modules/US/USNavigation/Filter/mitkNavigationDataPassThroughFilter.cpp rename to Modules/IGT/Algorithms/mitkNavigationDataPassThroughFilter.cpp diff --git a/Modules/US/USNavigation/Filter/mitkNavigationDataPassThroughFilter.h b/Modules/IGT/Algorithms/mitkNavigationDataPassThroughFilter.h similarity index 91% rename from Modules/US/USNavigation/Filter/mitkNavigationDataPassThroughFilter.h rename to Modules/IGT/Algorithms/mitkNavigationDataPassThroughFilter.h index da5563a0c3..42579317f2 100644 --- a/Modules/US/USNavigation/Filter/mitkNavigationDataPassThroughFilter.h +++ b/Modules/IGT/Algorithms/mitkNavigationDataPassThroughFilter.h @@ -1,52 +1,52 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef NAVIGATIONDATAPASSTHROUGHFILTER_H #define NAVIGATIONDATAPASSTHROUGHFILTER_H #include "mitkNavigationDataToNavigationDataFilter.h" -#include "MitkUSNavigationExports.h" +#include "MitkIGTExports.h" namespace mitk { /** * \brief Basis for filters that want to leave the navigation data untouched. * * Subclasses can call the mitk::NavigationDataToNavigationDataFilter::GenerateData() * method in their own GenerateData() implementation to pass through navigation data * from all inputs to the outputs. */ -class MITKUSNAVIGATION_EXPORT NavigationDataPassThroughFilter : public NavigationDataToNavigationDataFilter +class MITKIGT_EXPORT NavigationDataPassThroughFilter : public NavigationDataToNavigationDataFilter { public: mitkClassMacro(NavigationDataPassThroughFilter, NavigationDataToNavigationDataFilter) itkNewMacro(Self) protected: NavigationDataPassThroughFilter(); virtual ~NavigationDataPassThroughFilter(); /** * \brief Passes navigation data from all inputs to all outputs. * If a subclass wants to implement its own version of the GenerateData() * method it should call this method inside its implementation. */ virtual void GenerateData() override; }; } // namespace mitk #endif // NAVIGATIONDATAPASSTHROUGHFILTER_H diff --git a/Modules/US/USNavigation/Filter/mitkNeedleProjectionFilter.cpp b/Modules/IGT/Algorithms/mitkNeedleProjectionFilter.cpp similarity index 99% rename from Modules/US/USNavigation/Filter/mitkNeedleProjectionFilter.cpp rename to Modules/IGT/Algorithms/mitkNeedleProjectionFilter.cpp index 5053bafaec..2ca8c463cd 100644 --- a/Modules/US/USNavigation/Filter/mitkNeedleProjectionFilter.cpp +++ b/Modules/IGT/Algorithms/mitkNeedleProjectionFilter.cpp @@ -1,198 +1,198 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // MITK #include "mitkNeedleProjectionFilter.h" #include -#include "mitkUSCombinedModality.h" +// Vermutung - wird nicht benötigt: #include "mitkUSCombinedModality.h" // VTK #include mitk::NeedleProjectionFilter::NeedleProjectionFilter() : m_Projection(mitk::PointSet::New()), m_OriginalPoints(mitk::PointSet::New()), m_SelectedInput(-1), m_ShowToolAxis(false) { // Tool Coordinates:x axis is chosen as default axis when no axis is specified MITK_DEBUG << "Constructor called"; mitk::Point3D toolAxis; mitk::FillVector3D(toolAxis, 1, 0, 0); m_ToolAxis = toolAxis; InitializeOriginalPoints(toolAxis, m_ShowToolAxis); MITK_DEBUG << "orginal point 0 set constructor" << m_OriginalPoints->GetPoint(0); MITK_DEBUG << "orginal point 1 set constructor" << m_OriginalPoints->GetPoint(1); } void mitk::NeedleProjectionFilter::InitializeOriginalPoints(mitk::Point3D toolAxis, bool showToolAxis) { m_OriginalPoints = mitk::PointSet::New(); mitk::Point3D projectionPoint; projectionPoint.SetElement(0, toolAxis.GetElement(0) * 400); projectionPoint.SetElement(1, toolAxis.GetElement(1) * 400); projectionPoint.SetElement(2, toolAxis.GetElement(2) * 400); m_OriginalPoints->InsertPoint(projectionPoint); mitk::Point3D toolOrigin; toolOrigin.SetElement(0, 0); toolOrigin.SetElement(1, 0); toolOrigin.SetElement(2, 0); m_OriginalPoints->InsertPoint(toolOrigin); if (showToolAxis) { mitk::Point3D axisPoint; axisPoint.SetElement(0, toolAxis.GetElement(0) * -400); axisPoint.SetElement(1, toolAxis.GetElement(1) * -400); axisPoint.SetElement(2, toolAxis.GetElement(2) * -400); m_OriginalPoints->InsertPoint(axisPoint); } } void mitk::NeedleProjectionFilter::ShowToolAxis(bool enabled) { m_ShowToolAxis = enabled; InitializeOriginalPoints(m_ToolAxis,m_ShowToolAxis); } void mitk::NeedleProjectionFilter::SetToolAxisForFilter(mitk::Point3D point) { m_ToolAxis = point; InitializeOriginalPoints(m_ToolAxis, m_ShowToolAxis); MITK_DEBUG << "orginal point 1 set mutator" << m_OriginalPoints->GetPoint(1); MITK_DEBUG << "orginal point 0 set mutator" << m_OriginalPoints->GetPoint(0); } mitk::NeedleProjectionFilter::~NeedleProjectionFilter() { } void mitk::NeedleProjectionFilter::SelectInput(int i) { if (i < 0) mitkThrow() << "Negative Input selected in NeedleProjectionFilter"; if (! (static_cast(i) < this->GetInputs().size())) mitkThrow() << "Selected input index is larger than actual number of inputs in NeedleProjectionFilter"; m_SelectedInput = i; } void mitk::NeedleProjectionFilter::GenerateData() { // copy the navigation data from the inputs to the outputs mitk::NavigationDataPassThroughFilter::GenerateData(); // If no reference has been set yet, warn and abort if (m_SelectedInput == -1) { MITK_INFO << "No input has been selected in NeedleProjection Filter. Only forwarding NavigationData..."; return; } // Cancel, if selected tool is currently not being tracked if (! GetInput(m_SelectedInput)->IsDataValid()) return; // Outputs have been updated, now to calculate the Projection // 1) Generate Pseudo-Geometry for Input mitk::AffineTransform3D::Pointer refTrans = this->NavigationDataToTransform(this->GetInput(m_SelectedInput)); mitk::Geometry3D::Pointer refGeom = this->TransformToGeometry(refTrans); // 2) Transform Original Pointset m_OriginalPoints->SetGeometry(refGeom); // Update Projection (We do not clone, since we want to keep properties alive) m_Projection->SetPoint(0, m_OriginalPoints->GetPoint(0)); m_Projection->SetPoint(1, m_OriginalPoints->GetPoint(1)); if (m_ShowToolAxis) { m_Projection->SetPoint(2, m_OriginalPoints->GetPoint(2)); } // 3a) If no target Plane has been set, then leave it at that if (this->m_TargetPlane.IsNull()) return; // 3b) else, calculate intersection with plane mitk::PlaneGeometry::Pointer plane = mitk::PlaneGeometry::New(); plane->SetIndexToWorldTransform(m_TargetPlane); //plane->TransferItkToVtkTransform(); //included in SetIndexToWorldTransform double t; double x[3]; // Points that define the needle vector double p1[3] = {m_OriginalPoints->GetPoint(0)[0], m_OriginalPoints->GetPoint(0)[1], m_OriginalPoints->GetPoint(0)[2]}; double p2[3] = {m_OriginalPoints->GetPoint(1)[0], m_OriginalPoints->GetPoint(1)[1], m_OriginalPoints->GetPoint(1)[2]}; // Center of image plane and it's normal double center[3] = {plane->GetCenter()[0], plane->GetCenter()[1], plane->GetCenter()[2]}; double normal[3] = {plane->GetNormal()[0], plane->GetNormal()[1], plane->GetNormal()[2]}; vtkPlane::IntersectWithLine(p1, p2, normal, center, t, x); // change (cut) needle path only if the needle points to the image plane; // otherwise the needle path direction would be changed pointing to the image plane if ( t >= 0 ) { // Convert vtk to itk mitk::Point3D intersection; intersection[0] = x[0]; intersection[1] = x[1]; intersection[2] = x[2]; // Replace distant point with image intersection m_Projection->SetPoint(0, intersection); } } mitk::AffineTransform3D::Pointer mitk::NeedleProjectionFilter::NavigationDataToTransform(const mitk::NavigationData * nd) { mitk::AffineTransform3D::Pointer affineTransform = mitk::AffineTransform3D::New(); affineTransform->SetIdentity(); //calculate the transform from the quaternions static itk::QuaternionRigidTransform::Pointer quatTransform = itk::QuaternionRigidTransform::New(); mitk::NavigationData::OrientationType orientation = nd->GetOrientation(); // 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(); /* 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; mitk::TransferMatrix(quatTransform->GetMatrix(), m); affineTransform->SetMatrix(m); /*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(); return affineTransform; } mitk::Geometry3D::Pointer mitk::NeedleProjectionFilter::TransformToGeometry(mitk::AffineTransform3D::Pointer transform){ mitk::Geometry3D::Pointer g3d = mitk::Geometry3D::New(); mitk::ScalarType scale[] = {1.0, 1.0, 1.0}; g3d->SetSpacing(scale); g3d->SetIndexToWorldTransform(transform); //g3d->TransferItkToVtkTransform(); // update VTK Transform for rendering too //included in SetIndexToWorldTransform g3d->Modified(); return g3d; } diff --git a/Modules/US/USNavigation/Filter/mitkNeedleProjectionFilter.h b/Modules/IGT/Algorithms/mitkNeedleProjectionFilter.h similarity index 95% rename from Modules/US/USNavigation/Filter/mitkNeedleProjectionFilter.h rename to Modules/IGT/Algorithms/mitkNeedleProjectionFilter.h index 4bbf1f4eb6..845a2a9b48 100644 --- a/Modules/US/USNavigation/Filter/mitkNeedleProjectionFilter.h +++ b/Modules/IGT/Algorithms/mitkNeedleProjectionFilter.h @@ -1,97 +1,97 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef NEEDLEPROJECTIONFILTER_H_INCLUDED #define NEEDLEPROJECTIONFILTER_H_INCLUDED -#include +#include "MitkIGTExports.h" // MITK #include #include #include #include namespace mitk { /** * \brief This filter projects a needle's path onto a plane. * * To use it, hook it up to a NavigationDataStream, * select an input and set an AffineTransform 3D that represents the target plane. * You can then call GetProjection to retrieve a pointset that represents the projected path. * You may change the PointSet's properties, these changes will not be overwritten. * If no Input is selected, the target Pointset will not update * If no Target Plane is selected, The projection line will always be 40 cm long * Any points you add to the pointSet will be overwritten during the next Update. * The point with index zero is the Tip of the Needle. * The Point with index one is the projection onto the plane. * * Projection will happen onto an extension of the plane as well - the filter does not regard boundaries * This Filter currently only supports projection of one needle. Extension to multiple needles / planes should be easy. * - * \ingroup US + * \ingroup IGT */ - class MITKUSNAVIGATION_EXPORT NeedleProjectionFilter : public NavigationDataPassThroughFilter + class MITKIGT_EXPORT NeedleProjectionFilter : public NavigationDataPassThroughFilter { public: mitkClassMacro(NeedleProjectionFilter, NavigationDataPassThroughFilter); itkNewMacro(Self); virtual void SelectInput(int i); itkGetMacro(TargetPlane, mitk::AffineTransform3D::Pointer); itkSetMacro(TargetPlane, mitk::AffineTransform3D::Pointer); itkGetMacro(Projection, mitk::PointSet::Pointer); /** Sets the tool axis for this filter. The default tool axis is along the x-axis in * tool coordinates. */ void SetToolAxisForFilter(mitk::Point3D point); /** Sets whether the tool axis should be visualized. This is required if no surface is available. * If disabled only the projection and not the axis is shown. It's disabled by default. */ void ShowToolAxis(bool enabled); protected: NeedleProjectionFilter(); virtual ~NeedleProjectionFilter(); virtual void GenerateData() override; mitk::AffineTransform3D::Pointer m_TargetPlane; mitk::PointSet::Pointer m_Projection; mitk::PointSet::Pointer m_OriginalPoints; bool m_ShowToolAxis; mitk::Point3D m_ToolAxis; int m_SelectedInput; /** Internal method for initialization of the projection / tool axis representation * by the point set m_OriginalPoints. */ void InitializeOriginalPoints(mitk::Point3D toolAxis, bool showToolAxis); /** * \brief Creates an Affine Transformation from a Navigation Data Object. */ mitk::AffineTransform3D::Pointer NavigationDataToTransform(const mitk::NavigationData * nd); /** * \brief Creates an Geometry 3D Object from an AffineTransformation. */ mitk::Geometry3D::Pointer TransformToGeometry(mitk::AffineTransform3D::Pointer transform); }; } // namespace mitk #endif diff --git a/Modules/IGT/DataManagement/mitkNavigationTool.cpp b/Modules/IGT/DataManagement/mitkNavigationTool.cpp index 02e48810a0..1763aeecfe 100644 --- a/Modules/IGT/DataManagement/mitkNavigationTool.cpp +++ b/Modules/IGT/DataManagement/mitkNavigationTool.cpp @@ -1,134 +1,336 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkNavigationTool.h" #include "mitkIGTException.h" #include "mitkNavigationData.h" #include "Poco/File.h" #include "mitkUnspecifiedTrackingTypeInformation.h" +#include "mitkInternalTrackingTool.h" + +#include "vtkSphereSource.h" +#include "vtkConeSource.h" +#include "vtkLineSource.h" +#include "vtkCylinderSource.h" +#include "vtkTransformPolyDataFilter.h" +#include +#include "mitkTextAnnotation3D.h" +#include "mitkManualPlacementAnnotationRenderer.h" +#include "mitkBaseRenderer.h" mitk::NavigationTool::NavigationTool() : m_Identifier("None"), - m_Type(mitk::NavigationTool::Unknown), - m_CalibrationFile("none"), - m_SerialNumber(""), - m_TrackingDeviceType(mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName()), - m_ToolRegistrationLandmarks(mitk::PointSet::New()), - m_ToolCalibrationLandmarks(mitk::PointSet::New()), - m_ToolTipOrientation(mitk::Quaternion(0,0,0,1)) - { - m_ToolTipPosition[0] = 0; - m_ToolTipPosition[1] = 0; - m_ToolTipPosition[2] = 0; +m_Type(mitk::NavigationTool::Unknown), +m_CalibrationFile("none"), +m_SerialNumber(""), +m_TrackingDeviceType(mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName()), +m_ToolRegistrationLandmarks(mitk::PointSet::New()), +m_ToolCalibrationLandmarks(mitk::PointSet::New()), +m_ToolTipOrientation(mitk::Quaternion(0, 0, 0, 1)) +{ + m_ToolTipPosition[0] = 0; + m_ToolTipPosition[1] = 0; + m_ToolTipPosition[2] = 0; - m_ToolAxis[0] = 1; - m_ToolAxis[1] = 0; - m_ToolAxis[2] = 0; - } + m_ToolAxis[0] = 1; + m_ToolAxis[1] = 0; + m_ToolAxis[2] = 0; -mitk::NavigationTool::~NavigationTool() - { + SetDefaultSurface(); +} + +itk::LightObject::Pointer mitk::NavigationTool::InternalClone() const +{ + Self::Pointer tool = new Self(*this); + tool->UnRegister(); + return tool.GetPointer(); +} +mitk::NavigationTool::NavigationTool(const NavigationTool &other) + : Superclass() +{ + this->m_Identifier = other.m_Identifier; + this->m_Type = other.m_Type; + if (other.m_DataNode.IsNotNull()) + { + this->m_DataNode = other.m_DataNode->Clone(); + this->m_DataNode->SetName(other.m_DataNode->GetName()); + if (other.m_DataNode->GetData()) + { + this->m_DataNode->SetData(dynamic_cast(other.m_DataNode->GetData()->Clone().GetPointer())); + } } + if (other.m_SpatialObject.IsNotNull()) + this->m_SpatialObject = other.m_SpatialObject->Clone(); + this->m_CalibrationFile = other.m_CalibrationFile; + this->m_SerialNumber = other.m_SerialNumber; + this->m_TrackingDeviceType = other.m_TrackingDeviceType; + if (other.m_ToolRegistrationLandmarks.IsNotNull()) + this->m_ToolRegistrationLandmarks = other.m_ToolRegistrationLandmarks->Clone(); + if (other.m_ToolCalibrationLandmarks.IsNotNull()) + this->m_ToolCalibrationLandmarks = other.m_ToolCalibrationLandmarks->Clone(); + this->m_ToolTipPosition = other.m_ToolTipPosition; + this->m_ToolTipOrientation = other.m_ToolTipOrientation; + this->m_ToolAxis = other.m_ToolAxis; +} + +mitk::NavigationTool::~NavigationTool() +{ +} + mitk::AffineTransform3D::Pointer mitk::NavigationTool::GetToolTipTransform() - { - mitk::NavigationData::Pointer returnValue = mitk::NavigationData::New(); - returnValue->SetPosition(this->m_ToolTipPosition); - returnValue->SetOrientation(this->m_ToolTipOrientation); - return returnValue->GetAffineTransform3D(); - } - -void mitk::NavigationTool::Graft( const DataObject *data ) +{ + mitk::NavigationData::Pointer returnValue = mitk::NavigationData::New(); + returnValue->SetPosition(this->m_ToolTipPosition); + returnValue->SetOrientation(this->m_ToolTipOrientation); + return returnValue->GetAffineTransform3D(); +} + +void mitk::NavigationTool::Graft(const DataObject *data) { // Attempt to cast data to an NavigationData const Self* nd; try { - nd = dynamic_cast( data ); + nd = dynamic_cast(data); } - catch( ... ) + catch (...) { mitkThrowException(mitk::IGTException) << "mitk::NavigationData::Graft cannot cast " << typeid(data).name() << " to " - << typeid(const Self *).name() ; + << typeid(const Self *).name(); } if (!nd) { // pointer could not be cast back down mitkThrowException(mitk::IGTException) << "mitk::NavigationData::Graft cannot cast " << typeid(data).name() << " to " - << typeid(const Self *).name() ; + << typeid(const Self *).name(); } // Now copy anything that is needed m_Identifier = nd->GetIdentifier(); m_Type = nd->GetType(); m_DataNode->SetName(nd->GetDataNode()->GetName()); m_DataNode->SetData(nd->GetDataNode()->GetData()); m_SpatialObject = nd->GetSpatialObject(); - m_TrackingTool = nd->GetTrackingTool(); m_CalibrationFile = nd->GetCalibrationFile(); m_SerialNumber = nd->GetSerialNumber(); m_TrackingDeviceType = nd->GetTrackingDeviceType(); m_ToolRegistrationLandmarks = nd->GetToolRegistrationLandmarks(); m_ToolCalibrationLandmarks = nd->GetToolCalibrationLandmarks(); m_ToolTipPosition = nd->GetToolTipPosition(); m_ToolTipOrientation = nd->GetToolTipOrientation(); m_ToolAxis = nd->GetToolAxis(); - } bool mitk::NavigationTool::IsToolTipSet() - { - if( (m_ToolTipPosition[0] == 0) && +{ + if ((m_ToolTipPosition[0] == 0) && (m_ToolTipPosition[1] == 0) && (m_ToolTipPosition[2] == 0) && (m_ToolTipOrientation.x() == 0) && (m_ToolTipOrientation.y() == 0) && (m_ToolTipOrientation.z() == 0) && (m_ToolTipOrientation.r() == 1)) - return false; + return false; else return true; - } +} void mitk::NavigationTool::SetCalibrationFile(const std::string filename) - { +{ //check if file does exist: - if (filename=="") - { + if (filename == "") + { m_CalibrationFile = "none"; - } + } else - { + { Poco::File myFile(filename); if (myFile.exists()) m_CalibrationFile = filename; else m_CalibrationFile = "none"; - } } +} std::string mitk::NavigationTool::GetToolName() - { - if (this->m_DataNode.IsNull()) {return "";} - else {return m_DataNode->GetName();} - } +{ + if (this->m_DataNode.IsNull()) { return ""; } + else { return m_DataNode->GetName(); } +} mitk::Surface::Pointer mitk::NavigationTool::GetToolSurface() - { - if (this->m_DataNode.IsNull()) {return nullptr;} - else if (this->m_DataNode->GetData() == nullptr) {return nullptr;} - else {return dynamic_cast(m_DataNode->GetData());} - } +{ + if (this->m_DataNode.IsNull()) { return nullptr; } + else if (this->m_DataNode->GetData() == nullptr) { return nullptr; } + else { return dynamic_cast(m_DataNode->GetData()); } +} + +void mitk::NavigationTool::SetDefaultSurface() +{ + if (m_DataNode.IsNull()) + m_DataNode = mitk::DataNode::New(); + + mitk::Surface::Pointer mySphere = mitk::Surface::New(); + + double axisLength = 5.; + + vtkSphereSource *vtkSphere = vtkSphereSource::New(); + vtkConeSource *vtkCone = vtkConeSource::New(); + vtkCylinderSource *vtkCylinder = vtkCylinderSource::New(); + vtkPolyData* axis = vtkPolyData::New(); + vtkLineSource *vtkLine = vtkLineSource::New(); + vtkLineSource *vtkLine2 = vtkLineSource::New(); + vtkLineSource *vtkLine3 = vtkLineSource::New(); + + vtkAppendPolyData* appendPolyData = vtkAppendPolyData::New(); + vtkPolyData* surface = vtkPolyData::New(); + + //Y-Axis (start with y, cause cylinder is oriented in y by vtk default...) + vtkCone->SetDirection(0, 1, 0); + vtkCone->SetHeight(1.0); + vtkCone->SetRadius(0.4f); + vtkCone->SetResolution(16); + vtkCone->SetCenter(0.0, axisLength, 0.0); + vtkCone->Update(); + + vtkCylinder->SetRadius(0.05); + vtkCylinder->SetHeight(axisLength); + vtkCylinder->SetCenter(0.0, 0.5*axisLength, 0.0); + vtkCylinder->Update(); + + appendPolyData->AddInputData(vtkCone->GetOutput()); + appendPolyData->AddInputData(vtkCylinder->GetOutput()); + appendPolyData->Update(); + axis->DeepCopy(appendPolyData->GetOutput()); + + //y symbol + vtkLine->SetPoint1(-0.5, axisLength + 2., 0.0); + vtkLine->SetPoint2(0.0, axisLength + 1.5, 0.0); + vtkLine->Update(); + + vtkLine2->SetPoint1(0.5, axisLength + 2., 0.0); + vtkLine2->SetPoint2(-0.5, axisLength + 1., 0.0); + vtkLine2->Update(); + + appendPolyData->AddInputData(vtkLine->GetOutput()); + appendPolyData->AddInputData(vtkLine2->GetOutput()); + appendPolyData->AddInputData(axis); + appendPolyData->Update(); + surface->DeepCopy(appendPolyData->GetOutput()); + + //X-axis + vtkTransform *XTransform = vtkTransform::New(); + XTransform->RotateZ(-90); + vtkTransformPolyDataFilter *TrafoFilter = vtkTransformPolyDataFilter::New(); + TrafoFilter->SetTransform(XTransform); + TrafoFilter->SetInputData(axis); + TrafoFilter->Update(); + + //x symbol + vtkLine->SetPoint1(axisLength + 2., -0.5, 0.0); + vtkLine->SetPoint2(axisLength + 1., 0.5, 0.0); + vtkLine->Update(); + + vtkLine2->SetPoint1(axisLength + 2., 0.5, 0.0); + vtkLine2->SetPoint2(axisLength + 1., -0.5, 0.0); + vtkLine2->Update(); + + appendPolyData->AddInputData(vtkLine->GetOutput()); + appendPolyData->AddInputData(vtkLine2->GetOutput()); + appendPolyData->AddInputData(TrafoFilter->GetOutput()); + appendPolyData->AddInputData(surface); + appendPolyData->Update(); + surface->DeepCopy(appendPolyData->GetOutput()); + + //Z-axis + vtkTransform *ZTransform = vtkTransform::New(); + ZTransform->RotateX(90); + TrafoFilter->SetTransform(ZTransform); + TrafoFilter->SetInputData(axis); + TrafoFilter->Update(); + + //z symbol + vtkLine->SetPoint1(-0.5, 0.0, axisLength + 2.); + vtkLine->SetPoint2(0.5, 0.0, axisLength + 2.); + vtkLine->Update(); + + vtkLine2->SetPoint1(-0.5, 0.0, axisLength + 2.); + vtkLine2->SetPoint2(0.5, 0.0, axisLength + 1.); + vtkLine2->Update(); + + vtkLine3->SetPoint1(0.5, 0.0, axisLength + 1.); + vtkLine3->SetPoint2(-0.5, 0.0, axisLength + 1.); + vtkLine3->Update(); + + appendPolyData->AddInputData(vtkLine->GetOutput()); + appendPolyData->AddInputData(vtkLine2->GetOutput()); + appendPolyData->AddInputData(vtkLine3->GetOutput()); + appendPolyData->AddInputData(TrafoFilter->GetOutput()); + appendPolyData->AddInputData(surface); + appendPolyData->Update(); + surface->DeepCopy(appendPolyData->GetOutput()); + + //Center + vtkSphere->SetRadius(0.5f); + vtkSphere->SetCenter(0.0, 0.0, 0.0); + vtkSphere->Update(); + + appendPolyData->AddInputData(vtkSphere->GetOutput()); + appendPolyData->AddInputData(surface); + appendPolyData->Update(); + surface->DeepCopy(appendPolyData->GetOutput()); + + //Scale + vtkTransform *ScaleTransform = vtkTransform::New(); + ScaleTransform->Scale(20., 20., 20.); + + TrafoFilter->SetTransform(ScaleTransform); + TrafoFilter->SetInputData(surface); + TrafoFilter->Update(); + + mySphere->SetVtkPolyData(TrafoFilter->GetOutput()); + + vtkCone->Delete(); + vtkSphere->Delete(); + vtkLine->Delete(); + vtkLine2->Delete(); + vtkLine3->Delete(); + vtkCylinder->Delete(); + ZTransform->Delete(); + XTransform->Delete(); + ScaleTransform->Delete(); + TrafoFilter->Delete(); + appendPolyData->Delete(); + surface->Delete(); + + this->GetDataNode()->SetData(mySphere); +} + +std::string mitk::NavigationTool::GetStringWithAllToolInformation() const +{ + std::stringstream _info; + _info << " Identifier: " << this->m_Identifier << "\n" + << " NavigationToolType: " << m_Type << "\n" + << " Calibration file: " << m_CalibrationFile << "\n" + << " Serial number: " << m_SerialNumber << "\n" + << " TrackingDeviceType: " << m_TrackingDeviceType << "\n" + << " ToolTip Position: " << m_ToolTipPosition << "\n" + << " ToolTip Orientation: " << m_ToolTipOrientation << "\n" + << " ToolTip Axis: " << m_ToolAxis; + + return _info.str(); +} \ No newline at end of file diff --git a/Modules/IGT/DataManagement/mitkNavigationTool.h b/Modules/IGT/DataManagement/mitkNavigationTool.h index 04ce577314..d77d3ea8de 100644 --- a/Modules/IGT/DataManagement/mitkNavigationTool.h +++ b/Modules/IGT/DataManagement/mitkNavigationTool.h @@ -1,206 +1,212 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef NAVIGATIONTOOL_H_INCLUDED #define NAVIGATIONTOOL_H_INCLUDED //itk headers #include #include #include //mitk headers #include #include #include #include #include #include #include namespace mitk { /**Documentation * \brief An object of this class represents a navigation tool in the view of the software. * A few informations like an identifier, a toolname, a surface and a itk spatial * object are stored in such an object. The classes NavigationToolReader and * are availiable to write/read tools to/from the harddisc. If you need a collection * of navigation tools the class NavigationToolStorage could be used. * * \ingroup IGT */ class MITKIGT_EXPORT NavigationTool : public itk::DataObject { public: mitkClassMacroItkParent(NavigationTool,itk::DataObject); itkFactorylessNewMacro(Self) itkCloneMacro(Self) enum NavigationToolType {Instrument, Fiducial, Skinmarker, Unknown}; //## getter and setter ## //NavigationToolType: itkGetConstMacro(Type,NavigationToolType); itkSetMacro(Type,NavigationToolType); //Identifier: itkGetConstMacro(Identifier,std::string); itkSetMacro(Identifier,std::string); //Datatreenode: itkGetConstMacro(DataNode,mitk::DataNode::Pointer); itkSetMacro(DataNode,mitk::DataNode::Pointer); //SpatialObject: itkGetConstMacro(SpatialObject,itk::SpatialObject<3>::Pointer); itkSetMacro(SpatialObject,itk::SpatialObject<3>::Pointer); - //TrackingTool: - itkGetConstMacro(TrackingTool,mitk::TrackingTool::Pointer); - itkSetMacro(TrackingTool,mitk::TrackingTool::Pointer); - //CalibrationFile: itkGetConstMacro(CalibrationFile,std::string); void SetCalibrationFile(const std::string filename); //Tool tip definition: itkGetConstMacro(ToolTipPosition,mitk::Point3D); itkSetMacro(ToolTipPosition,mitk::Point3D); itkGetConstMacro(ToolTipOrientation,mitk::Quaternion); itkSetMacro(ToolTipOrientation,mitk::Quaternion); //Tool Axis definition: //default tool axis is along x axis, the tool axis must be normalized itkGetConstMacro(ToolAxis, mitk::Point3D); itkSetMacro(ToolAxis, mitk::Point3D); /** @return Returns the tooltip as transform object. */ mitk::AffineTransform3D::Pointer GetToolTipTransform(); /** @return Returns true if a tooltip is set, false if not. */ bool IsToolTipSet(); //Tool Landmarks: /** For overview, here are descriptons of the two types of tool landmarks: * * tool calibration landmarks: These landmarks may be used clearly define the tools pose only by * using landmarks in the tool coordinate system. E.g., two landmarks for a 5DoF tool and three * landmarks for a 6DoF tool. These landmarks may be used, e.g., for a point based registration * of a tool from image space to tracking space. * * tool registration landmarks: These landmarks are designed for representing defined landmarks * on a tools surface. The number of these landmarks might exeed the number of tool calibration * landmarks for reasons of redundancy and averaging. They are used for, e.g., manually registering * the pose of a tool by visual markers in a CT scan. If you would use these landmarks to do a * point based registration from image space to tracking space later, you might overweight the * tool because of two many landmarks compared to other markers. * * @return Returns the tool registration landmarks which represent markers / special points on a * tool that can be used for registration. The landmarks should be given in tool coordinates. * If there are no landmarks defined for this tool the method returns an empty point set. */ itkGetConstMacro(ToolRegistrationLandmarks,mitk::PointSet::Pointer); /** @brief Sets the tool registration landmarks which represent markers / special points on a * tool that can be used for registration. The landmarks should be given in tool coordinates. */ itkSetMacro(ToolRegistrationLandmarks,mitk::PointSet::Pointer); /** @return Returns the tool calibration landmarks for calibration of the defined points in the * tool coordinate system, e.g. 2 landmarks for a 5DoF tool and 3 landmarks for a 6DoF tool. */ itkGetConstMacro(ToolCalibrationLandmarks,mitk::PointSet::Pointer); /** @brief Sets the tool calibration landmarks for calibration of defined points in the * tool coordinate system, e.g. 2 landmarks for a 5DoF tool and 3 landmarks for a 6DoF tool. */ itkSetMacro(ToolCalibrationLandmarks,mitk::PointSet::Pointer); //SerialNumber: itkGetConstMacro(SerialNumber,std::string); itkSetMacro(SerialNumber,std::string); //TrackingDeviceType: itkGetConstMacro(TrackingDeviceType,mitk::TrackingDeviceType); itkSetMacro(TrackingDeviceType,mitk::TrackingDeviceType); //ToolName (only getter): /** @return Returns the name of this navigation tool. Returns an empty string if there is * no name (for example because the data node has not been set yet). * * Note: There is no setter for the name, * because the name of the corresponding data node is used as tool name. So if you * want to modify the name of this navigation tool only get the data node and modify * its name. */ std::string GetToolName(); //ToolSurface (only getter): /** @return Returns the surface of this navigation tool. Returns nullptr if there is * no surface (for example because the data node has not been set yet). * * Note: There is no setter for the surface, * because the surface is the data of the corresponding data node. So if you * want to set a new surface only get the data node and modify its data. */ mitk::Surface::Pointer GetToolSurface(); /** * \brief Graft the data and information from one NavigationTool to another. * * Copies the content of data into this object. * This is a convenience method to setup a second NavigationTool object with all the meta * information of another NavigationTool object. * Note that this method is different than just using two * SmartPointers to the same NavigationTool object since separate DataObjects are * still maintained. */ virtual void Graft(const DataObject *data) override; + + + /** + * Return all relevant information as string, e.g. to display all tool information + */ + std::string GetStringWithAllToolInformation() const; + + + void SetDefaultSurface(); + //####################### protected: NavigationTool(); + NavigationTool(const NavigationTool &other); ~NavigationTool(); + virtual itk::LightObject::Pointer InternalClone() const override; //## data structure of a navigation tool object ## std::string m_Identifier; NavigationToolType m_Type; /** @brief This DataNode holds a toolname and a tool surface */ mitk::DataNode::Pointer m_DataNode; /** @brief This member variable holds a mathamatical description of the tool */ itk::SpatialObject<3>::Pointer m_SpatialObject; - /** @brief This member variable holds a pointer to the corresponding tracking tool in the hardware. */ - mitk::TrackingTool::Pointer m_TrackingTool; /** @brief The path to the calibration file of the tool. */ std::string m_CalibrationFile; /** @brief A unique serial number of the tool which is needed to identify the tool correctly. This is very important * in case of the NDI Aurora System. */ std::string m_SerialNumber; /** @brief This member holds the tracking device type of the tool. */ mitk::TrackingDeviceType m_TrackingDeviceType; /** @brief Holds landmarks for tool registration. */ mitk::PointSet::Pointer m_ToolRegistrationLandmarks; /** @brief Holds landmarks for calibration of the defined points in the tool coordinate system, * e.g. 2 landmarks for a 5DoF tool and 3 landmarks for a 6DoF tool. */ mitk::PointSet::Pointer m_ToolCalibrationLandmarks; /** @brief Holds the position of the tool tip. */ mitk::Point3D m_ToolTipPosition; /** @brief Holds the orientation of the tool tip. */ mitk::Quaternion m_ToolTipOrientation; /** @brief Holds the axis of the tool. */ mitk::Point3D m_ToolAxis; //################################################# }; } // namespace mitk #endif //NAVIGATIONTOOL diff --git a/Modules/IGT/DataManagement/mitkNavigationToolStorage.cpp b/Modules/IGT/DataManagement/mitkNavigationToolStorage.cpp index ad52921aa2..45ea224a70 100644 --- a/Modules/IGT/DataManagement/mitkNavigationToolStorage.cpp +++ b/Modules/IGT/DataManagement/mitkNavigationToolStorage.cpp @@ -1,230 +1,239 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkNavigationToolStorage.h" //Microservices #include #include #include const std::string mitk::NavigationToolStorage::US_INTERFACE_NAME = "org.mitk.services.NavigationToolStorage"; // Name of the interface const std::string mitk::NavigationToolStorage::US_PROPKEY_SOURCE_ID = US_INTERFACE_NAME + ".sourceID"; const std::string mitk::NavigationToolStorage::US_PROPKEY_STORAGE_NAME = US_INTERFACE_NAME + ".name"; mitk::NavigationToolStorage::NavigationToolStorage() : m_ToolCollection(std::vector()), m_DataStorage(nullptr), m_storageLocked(false) { this->SetName("ToolStorage (no name given)"); } mitk::NavigationToolStorage::NavigationToolStorage(mitk::DataStorage::Pointer ds) : m_storageLocked(false) { m_ToolCollection = std::vector(); this->m_DataStorage = ds; this->SetName("Tool Storage (no name given)"); } void mitk::NavigationToolStorage::SetName(std::string n) { m_Name = n; m_props[US_PROPKEY_STORAGE_NAME] = m_Name; } std::string mitk::NavigationToolStorage::GetName() const { return m_Name; } void mitk::NavigationToolStorage::UpdateMicroservice() { if (m_ServiceRegistration) { m_ServiceRegistration.SetProperties(m_props); } } mitk::NavigationToolStorage::~NavigationToolStorage() { if (m_DataStorage.IsNotNull()) //remove all nodes from the data storage { for (std::vector::iterator it = m_ToolCollection.begin(); it != m_ToolCollection.end(); it++) m_DataStorage->Remove((*it)->GetDataNode()); } } -void mitk::NavigationToolStorage::RegisterAsMicroservice(std::string sourceID){ - if (sourceID.empty()) mitkThrow() << "Empty or null string passed to NavigationToolStorage::registerAsMicroservice()."; - +void mitk::NavigationToolStorage::RegisterAsMicroservice(){ // Get Context us::ModuleContext* context = us::GetModuleContext(); // Define ServiceProps - m_props[US_PROPKEY_SOURCE_ID] = sourceID; m_ServiceRegistration = context->RegisterService(this, m_props); //Tell all widgets, that there is a new toolStorage registered, e.g. the old one might have changed. UpdateMicroservice(); } void mitk::NavigationToolStorage::UnRegisterMicroservice(){ if (!m_ServiceRegistration) { MITK_WARN("NavigationToolStorage") << "Cannot unregister microservice as it wasn't registered before."; return; } m_ServiceRegistration.Unregister(); m_ServiceRegistration = 0; } bool mitk::NavigationToolStorage::DeleteTool(int number) { if (m_storageLocked) { MITK_WARN << "Storage is locked, cannot modify it!"; return false; } else if ((unsigned int)number > m_ToolCollection.size()) { MITK_WARN << "Tool no " << number << "doesn't exist, can't delete it!"; return false; } std::vector::iterator it = m_ToolCollection.begin() + number; if (m_DataStorage.IsNotNull()) m_DataStorage->Remove((*it)->GetDataNode()); m_ToolCollection.erase(it); //This line is important so that other widgets can get a notice that the toolStorage has changed! this->UpdateMicroservice(); return true; } bool mitk::NavigationToolStorage::DeleteAllTools() { if (m_storageLocked) { MITK_WARN << "Storage is locked, cannot modify it!"; return false; } while (m_ToolCollection.size() > 0) if (!DeleteTool(0)) return false; return true; } bool mitk::NavigationToolStorage::AddTool(mitk::NavigationTool::Pointer tool) { if (m_storageLocked) { MITK_WARN << "Storage is locked, cannot modify it!"; return false; } else if (GetTool(tool->GetIdentifier()).IsNotNull()) { MITK_WARN << "Tool ID already exists in storage, can't add!"; return false; } else { m_ToolCollection.push_back(tool); if (m_DataStorage.IsNotNull()) { if (!m_DataStorage->Exists(tool->GetDataNode())) m_DataStorage->Add(tool->GetDataNode()); } //This line is important so that other widgets can get a notice that the toolStorage has changed! this->UpdateMicroservice(); return true; } } mitk::NavigationTool::Pointer mitk::NavigationToolStorage::GetTool(int number) { return m_ToolCollection.at(number); } mitk::NavigationTool::Pointer mitk::NavigationToolStorage::GetTool(std::string identifier) { for (int i = 0; i < GetToolCount(); i++) if ((GetTool(i)->GetIdentifier()) == identifier) return GetTool(i); return nullptr; } mitk::NavigationTool::Pointer mitk::NavigationToolStorage::GetToolByName(std::string name) { for (int i = 0; i < GetToolCount(); i++) if ((GetTool(i)->GetToolName()) == name) return GetTool(i); return nullptr; } int mitk::NavigationToolStorage::GetToolCount() { return m_ToolCollection.size(); } bool mitk::NavigationToolStorage::isEmpty() { return m_ToolCollection.empty(); } void mitk::NavigationToolStorage::LockStorage() { m_storageLocked = true; } void mitk::NavigationToolStorage::UnLockStorage() { m_storageLocked = false; } bool mitk::NavigationToolStorage::isLocked() { return m_storageLocked; } bool mitk::NavigationToolStorage::AssignToolNumber(std::string identifier1, int number2) { if (this->GetTool(identifier1).IsNull()) { MITK_WARN << "Identifier does not exist, cannot assign new number"; return false; } if ((number2 >= static_cast(m_ToolCollection.size())) || (number2 < 0)) { MITK_WARN << "Invalid number, cannot assign new number"; return false; } mitk::NavigationTool::Pointer tool2 = m_ToolCollection.at(number2); int number1 = -1; for(int i = 0; i(m_ToolCollection.size()); i++) { if (m_ToolCollection.at(i)->GetIdentifier() == identifier1) { number1 = i; } } m_ToolCollection[number2] = m_ToolCollection.at(number1); m_ToolCollection[number1] = tool2; MITK_DEBUG << "Swapped tool " << number2 << " with tool " << number1; //This line is important so that other widgets can get a notice that the toolStorage has changed! this->UpdateMicroservice(); return true; +} + +void mitk::NavigationToolStorage::SetSourceID(std::string _id) +{ + m_SourceID = _id; + m_props[US_PROPKEY_SOURCE_ID] = m_SourceID; +} + +/** @return Returns the name of this storage. */ +std::string mitk::NavigationToolStorage::GetSourceID() const +{ + return m_SourceID; } \ No newline at end of file diff --git a/Modules/IGT/DataManagement/mitkNavigationToolStorage.h b/Modules/IGT/DataManagement/mitkNavigationToolStorage.h index 874d419218..e31e804a3f 100644 --- a/Modules/IGT/DataManagement/mitkNavigationToolStorage.h +++ b/Modules/IGT/DataManagement/mitkNavigationToolStorage.h @@ -1,186 +1,201 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef NAVIGATIONTOOLSTORAGE_H_INCLUDED #define NAVIGATIONTOOLSTORAGE_H_INCLUDED //itk headers #include //mitk headers #include #include #include "mitkNavigationTool.h" #include // Microservices #include #include #include namespace mitk { /**Documentation * \brief An object of this class represents a collection of navigation tools. * You may add/delete navigation tools or store/load the whole collection * to/from the harddisc by using the class NavigationToolStorageSerializer * and NavigationToolStorageDeserializer. * * \ingroup IGT */ class MITKIGT_EXPORT NavigationToolStorage : public itk::Object { public: mitkClassMacroItkParent(NavigationToolStorage,itk::Object); /** @brief Constructs a NavigationToolStorage without reference to a DataStorage. The Data Nodes of tools have to be added and removed to a data storage outside this class. * Normaly the other constructor should be used. */ itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** @brief Constructs a NavigationToolStorage with reference to a DataStorage. The Data Nodes of tools are added and removed automatically to this data storage. */ mitkNewMacro1Param(Self,mitk::DataStorage::Pointer); /** *\brief Registers this object as a Microservice, making it available to every module and/or plugin. * To unregister, call UnregisterMicroservice(). Make sure to pass the id of the Device that this tool is connected to. */ - virtual void RegisterAsMicroservice(std::string sourceID); + virtual void RegisterAsMicroservice(); /** *\brief Registers this object as a Microservice, making it available to every module and/or plugin. */ virtual void UnRegisterMicroservice(); /** *\brief Returns the id that this device is registered with. The id will only be valid, if the * NavigationDataSource has been registered using RegisterAsMicroservice(). */ std::string GetMicroserviceID(); /** *\brief These constants are used in conjunction with Microservices */ - static const std::string US_INTERFACE_NAME; // Name of the interface - static const std::string US_PROPKEY_SOURCE_ID; // ID of the device this ToolStorage is associated with - static const std::string US_PROPKEY_STORAGE_NAME; // name of the storage + // Name of the interface + static const std::string US_INTERFACE_NAME; + // ID of the NavigationDataSource this ToolStorage is associated with. Can be empty ("") and changed with SetSourceID(). + static const std::string US_PROPKEY_SOURCE_ID; + // name of the storage + static const std::string US_PROPKEY_STORAGE_NAME; /** * @brief Adds a tool to the storage. Be sure that the tool has a unique * identifier which is not already part of this storage. * @return Returns true if the tool was added to the storage, false if not * (false can be returned if the identifier already exists in this storage * for example). */ bool AddTool(mitk::NavigationTool::Pointer tool); /** * @return Returns the tracking tool at the position "number" * in the storage. Returns nullptr if there is no * tracking tool at this position. */ mitk::NavigationTool::Pointer GetTool(int number); /** * @return Returns the tracking tool with the given identifier. * Returns nullptr if there is no * tracking tool with this identifier in the storage. */ mitk::NavigationTool::Pointer GetTool(std::string identifier); /** * @return Returns the tracking tool with the given name. * Returns nullptr if there is no * tracking tool with this name in the storage. */ mitk::NavigationTool::Pointer GetToolByName(std::string name); /** Assigns the given number to the tool with the given identifier. This means the tool is swapped with another tool in the internal tool vector. * @return Returns true if the assignment was successfull. Returns false if assignment is not possible, e.g. because the identifier does not exist or if the given number is not available. **/ bool AssignToolNumber(std::string identifier1, int number2); /** * @brief Deletes a tool from the collection. * Warning, this method operates on the data storage and is not thread save. Calling it from outside the main thread may cause crashes. */ bool DeleteTool(int number); /** * @brief Deletes all tools from the collection. * Warning, this method operates on the data storage and is not thread save. Calling it from outside the main thread may cause crashes. */ bool DeleteAllTools(); /** * @return Returns the number of tools stored in the storage. */ int GetToolCount(); /** * @return Returns true if the storage is empty, false if not. */ bool isEmpty(); /** * @return Returns the corresponding data storage if one is set to this NavigationToolStorage. * Returns nullptr if none is set. */ itkGetMacro(DataStorage,mitk::DataStorage::Pointer); /** Sets the name of this storage. The name should be understandable for the user. * Something like "NDI Aurora Tool Storage". If a storage is loaded from the harddisk * the name might be the filename. */ void SetName(std::string); /** @return Returns the name of this storage. */ std::string GetName() const; + /** Sets the name of this storage. The name should be understandable for the user. + * Something like "NDI Aurora Tool Storage". If a storage is loaded from the harddisk + * the name might be the filename. + * @warning: if your microservice is already registered, you need to call UpdateMicroservice after changing the ID. + * This can't be done inside this functions, as we might use different threads. + */ + void SetSourceID(std::string); + + /** @return Returns the name of this storage. */ + std::string GetSourceID() const; + /** Locks the storage. A logged storage may not be modified. * If a method tries to modify the storage anyway a waring message is given. * The storage is unlocked by default. A Storage might be locked when a * tracking device is active and needs the storage to stay consistent. */ void LockStorage(); /** Unlocks the storage again. */ void UnLockStorage(); /** @return Returns true if the storage is locked at the moment, false if not. */ bool isLocked(); /** Sets the properties which causes the microservice to emit an update signal. */ void UpdateMicroservice(); protected: NavigationToolStorage(); NavigationToolStorage(mitk::DataStorage::Pointer); ~NavigationToolStorage(); std::vector m_ToolCollection; mitk::DataStorage::Pointer m_DataStorage; std::string m_Name; + std::string m_SourceID; bool m_storageLocked; private: us::ServiceRegistration m_ServiceRegistration; us::ServiceProperties m_props; }; } // namespace mitk MITK_DECLARE_SERVICE_INTERFACE(mitk::NavigationToolStorage, "org.mitk.services.NavigationToolStorage") #endif //NAVIGATIONTOOLSTORAGE diff --git a/Modules/IGT/TrackingDevices/mitkInternalTrackingTool.cpp b/Modules/IGT/TrackingDevices/mitkInternalTrackingTool.cpp index d9676fca30..128eabfc47 100644 --- a/Modules/IGT/TrackingDevices/mitkInternalTrackingTool.cpp +++ b/Modules/IGT/TrackingDevices/mitkInternalTrackingTool.cpp @@ -1,270 +1,279 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkInternalTrackingTool.h" #include typedef itk::MutexLockHolder MutexLockHolder; mitk::InternalTrackingTool::InternalTrackingTool() : TrackingTool(), m_TrackingError(0.0f), m_Enabled(true), m_DataValid(false), m_ToolTipSet(false) { m_Position[0] = 0.0f; m_Position[1] = 0.0f; m_Position[2] = 0.0f; m_Orientation[0] = 0.0f; m_Orientation[1] = 0.0f; m_Orientation[2] = 0.0f; m_Orientation[3] = 0.0f; // this should not be necessary as the tools bring their own tooltip transformation m_ToolTip[0] = 0.0f; m_ToolTip[1] = 0.0f; m_ToolTip[2] = 0.0f; m_ToolTipRotation[0] = 0.0f; m_ToolTipRotation[1] = 0.0f; m_ToolTipRotation[2] = 0.0f; m_ToolTipRotation[3] = 1.0f; } mitk::InternalTrackingTool::~InternalTrackingTool() { } void mitk::InternalTrackingTool::PrintSelf(std::ostream& os, itk::Indent indent) const { Superclass::PrintSelf(os, indent); os << indent << "Position: " << m_Position << std::endl; os << indent << "Orientation: " << m_Orientation << std::endl; os << indent << "TrackingError: " << m_TrackingError << std::endl; os << indent << "Enabled: " << m_Enabled << std::endl; os << indent << "DataValid: " << m_DataValid << std::endl; os << indent << "ToolTip: " << m_ToolTip << std::endl; os << indent << "ToolTipRotation: " << m_ToolTipRotation << std::endl; os << indent << "ToolTipSet: " << m_ToolTipSet << std::endl; } void mitk::InternalTrackingTool::SetToolName(const char* _arg) { itkDebugMacro("setting m_ToolName to " << _arg); MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex if ( _arg && (_arg == this->m_ToolName) ) { return; } if (_arg) { this->m_ToolName= _arg; } else { this->m_ToolName= ""; } this->Modified(); } void mitk::InternalTrackingTool::SetToolName( const std::string _arg ) { this->SetToolName(_arg.c_str()); } void mitk::InternalTrackingTool::GetPosition(mitk::Point3D& position) const { MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex if (m_ToolTipSet) { // Compute the position of tool tip in the coordinate frame of the // tracking device: Rotate the position of the tip into the tracking // device coordinate frame then add to the position of the tracking // sensor vnl_vector pos_vnl = m_Position.GetVnlVector() + m_Orientation.rotate( m_ToolTip.GetVnlVector() ) ; position[0] = pos_vnl[0]; position[1] = pos_vnl[1]; position[2] = pos_vnl[2]; } else { position[0] = m_Position[0]; position[1] = m_Position[1]; position[2] = m_Position[2]; } this->Modified(); } void mitk::InternalTrackingTool::SetPosition(mitk::Point3D position) { itkDebugMacro("setting m_Position to " << position); MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex m_Position = position; this->Modified(); } void mitk::InternalTrackingTool::GetOrientation(mitk::Quaternion& orientation) const { MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex if (m_ToolTipSet) { // Compute the orientation of the tool tip in the coordinate frame of // the tracking device. // // * m_Orientation is the orientation of the sensor relative to the transmitter // * m_ToolTipRotation is the orientation of the tool tip relative to the sensor orientation = m_Orientation * m_ToolTipRotation; } else { orientation = m_Orientation; } } void mitk::InternalTrackingTool::SetToolTip(mitk::Point3D toolTipPosition, mitk::Quaternion orientation, mitk::ScalarType eps) { if ( !Equal(m_ToolTip, toolTipPosition, eps) || !Equal(m_ToolTipRotation, orientation, eps) ) { if( (toolTipPosition[0] == 0) && (toolTipPosition[1] == 0) && (toolTipPosition[2] == 0) && (orientation.x() == 0) && (orientation.y() == 0) && (orientation.z() == 0) && (orientation.r() == 1)) { m_ToolTipSet = false; } else { m_ToolTipSet = true; } m_ToolTip = toolTipPosition; m_ToolTipRotation = orientation; this->Modified(); } } +mitk::Point3D mitk::InternalTrackingTool::GetToolTip() const +{ + return m_ToolTip; +} +mitk::Quaternion mitk::InternalTrackingTool::GetToolTipOrientation() const +{ + return m_ToolTipRotation; +} + void mitk::InternalTrackingTool::SetOrientation(mitk::Quaternion orientation) { itkDebugMacro("setting m_Orientation to " << orientation); MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex m_Orientation = orientation; this->Modified(); } void mitk::InternalTrackingTool::SetTrackingError(float error) { itkDebugMacro("setting m_TrackingError to " << error); MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex if (error == m_TrackingError) { return; } m_TrackingError = error; this->Modified(); } float mitk::InternalTrackingTool::GetTrackingError() const { MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex float r = m_TrackingError; return r; } bool mitk::InternalTrackingTool::Enable() { MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex if (m_Enabled == false) { this->m_Enabled = true; this->Modified(); } return true; } bool mitk::InternalTrackingTool::Disable() { MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex if (m_Enabled == true) { this->m_Enabled = false; this->Modified(); } return true; } bool mitk::InternalTrackingTool::IsEnabled() const { MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex return m_Enabled; } bool mitk::InternalTrackingTool::IsTooltipSet() const { MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex return m_ToolTipSet; } bool mitk::InternalTrackingTool::IsDataValid() const { MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex return m_DataValid; } void mitk::InternalTrackingTool::SetDataValid(bool _arg) { itkDebugMacro("setting m_DataValid to " << _arg); if (this->m_DataValid != _arg) { MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex this->m_DataValid = _arg; this->Modified(); } } void mitk::InternalTrackingTool::SetErrorMessage(const char* _arg) { itkDebugMacro("setting m_ErrorMessage to " << _arg); MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex if ((_arg == nullptr) || (_arg == this->m_ErrorMessage)) return; if (_arg != nullptr) this->m_ErrorMessage = _arg; else this->m_ErrorMessage = ""; this->Modified(); } diff --git a/Modules/IGT/TrackingDevices/mitkInternalTrackingTool.h b/Modules/IGT/TrackingDevices/mitkInternalTrackingTool.h index de952cf0b8..d0a34cc476 100644 --- a/Modules/IGT/TrackingDevices/mitkInternalTrackingTool.h +++ b/Modules/IGT/TrackingDevices/mitkInternalTrackingTool.h @@ -1,80 +1,82 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKINTERNALTRACKINGTOOL_H_HEADER_INCLUDED_ #define MITKINTERNALTRACKINGTOOL_H_HEADER_INCLUDED_ #include #include #include #include namespace mitk { /**Documentation * \brief implements TrackingTool interface * * This class is a complete TrackingTool implementation. It can either be used directly by * TrackingDevices, or be subclassed for more specific implementations. * mitk::MicroBirdTrackingDevice uses this class to manage its tools. Other tracking devices * uses specialized versions of this class (e.g. mitk::NDITrackingTool) * * \ingroup IGT */ class MITKIGT_EXPORT InternalTrackingTool : public TrackingTool { friend class MicroBirdTrackingDevice; // Add all TrackingDevice subclasses that use InternalTrackingDevice directly public: mitkClassMacro(InternalTrackingTool, TrackingTool); virtual void PrintSelf(std::ostream& os, itk::Indent indent) const override; virtual void GetPosition(Point3D& position) const override; ///< returns the current position of the tool as an array of three floats (in the tracking device coordinate system) virtual void GetOrientation(Quaternion& orientation) const override; ///< returns the current orientation of the tool as a quaternion (in the tracking device coordinate system) virtual bool Enable() override; ///< enablea the tool, so that it will be tracked. Returns true if enabling was successfull virtual bool Disable() override; ///< disables the tool, so that it will not be tracked anymore. Returns true if disabling was successfull virtual bool IsEnabled() const override; ///< returns whether the tool is enabled or disabled virtual bool IsDataValid() const override; ///< returns true if the current position data is valid (no error during tracking, tracking error below threshold, ...) virtual float GetTrackingError() const override; ///< return one value that corresponds to the overall tracking error. The dimension of this value is specific to each tracking device virtual bool IsTooltipSet() const; ///< returns true if a tooltip is set, false if not virtual void SetToolName(const std::string _arg); ///< Sets the name of the tool virtual void SetToolName(const char* _arg); ///< Sets the name of the tool virtual void SetPosition(Point3D position); ///< sets the position virtual void SetOrientation(Quaternion orientation); ///< sets the orientation as a quaternion virtual void SetTrackingError(float error); ///< sets the tracking error virtual void SetDataValid(bool _arg); ///< sets if the tracking data (position & Orientation) is valid virtual void SetErrorMessage(const char* _arg); ///< sets the error message virtual void SetToolTip(Point3D toolTipPosition, Quaternion orientation = Quaternion(0,0,0,1), ScalarType eps=0.0) override; ///< defines a tool tip for this tool in tool coordinates. GetPosition() and GetOrientation() return the data of the tool tip if it is defined. By default no tooltip is defined. + Point3D GetToolTip() const; //Returns the tool tip in tool coordinates, which where set by SetToolTip + Quaternion GetToolTipOrientation() const;//Returns the tool tip orientation in tool coordinates, which where set by SetToolTip protected: itkFactorylessNewMacro(Self) itkCloneMacro(Self) InternalTrackingTool(); virtual ~InternalTrackingTool(); Point3D m_Position; ///< holds the position of the tool Quaternion m_Orientation; ///< holds the orientation of the tool float m_TrackingError; ///< holds the tracking error of the tool bool m_Enabled; ///< if true, tool is enabled and should receive tracking updates from the tracking device bool m_DataValid; ///< if true, data in m_Position and m_Orientation is valid, e.g. true tracking data Point3D m_ToolTip; Quaternion m_ToolTipRotation; bool m_ToolTipSet; }; } // namespace mitk #endif /* MITKINTERNALTRACKINGTOOL_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/TrackingDevices/mitkNDITrackingDevice.cpp b/Modules/IGT/TrackingDevices/mitkNDITrackingDevice.cpp index f274dbee55..9f3e895a38 100644 --- a/Modules/IGT/TrackingDevices/mitkNDITrackingDevice.cpp +++ b/Modules/IGT/TrackingDevices/mitkNDITrackingDevice.cpp @@ -1,1324 +1,1314 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkNDITrackingDevice.h" #include "mitkIGTTimeStamp.h" #include "mitkIGTHardwareException.h" #include #include #include #include #include #include // vtk #include typedef itk::MutexLockHolder MutexLockHolder; const unsigned char CR = 0xD; // == '\r' - carriage return const unsigned char LF = 0xA; // == '\n' - line feed mitk::NDITrackingDevice::NDITrackingDevice() : TrackingDevice(), m_DeviceName(""), m_PortNumber(mitk::SerialCommunication::COM5), m_BaudRate(mitk::SerialCommunication::BaudRate9600), m_DataBits(mitk::SerialCommunication::DataBits8), m_Parity(mitk::SerialCommunication::None), m_StopBits(mitk::SerialCommunication::StopBits1), m_HardwareHandshake(mitk::SerialCommunication::HardwareHandshakeOff), m_IlluminationActivationRate(Hz20), m_DataTransferMode(TX), m_6DTools(), m_ToolsMutex(nullptr), m_SerialCommunication(nullptr), m_SerialCommunicationMutex(nullptr), m_DeviceProtocol(nullptr), m_MultiThreader(nullptr), m_ThreadID(0), m_OperationMode(ToolTracking6D), m_MarkerPointsMutex(nullptr), m_MarkerPoints() { m_Data = mitk::UnspecifiedTrackingTypeInformation::GetDeviceDataUnspecified(); m_6DTools.clear(); m_SerialCommunicationMutex = itk::FastMutexLock::New(); m_DeviceProtocol = NDIProtocol::New(); m_DeviceProtocol->SetTrackingDevice(this); m_DeviceProtocol->UseCRCOn(); m_MultiThreader = itk::MultiThreader::New(); m_ToolsMutex = itk::FastMutexLock::New(); m_MarkerPointsMutex = itk::FastMutexLock::New(); m_MarkerPoints.reserve(50); // a maximum of 50 marker positions can be reported by the tracking device } bool mitk::NDITrackingDevice::UpdateTool(mitk::TrackingTool* tool) { if (this->GetState() != Setup) { mitk::NDIPassiveTool* ndiTool = dynamic_cast(tool); if (ndiTool == nullptr) return false; std::string portHandle = ndiTool->GetPortHandle(); //return false if the SROM Data has not been set if (ndiTool->GetSROMData() == nullptr) return false; NDIErrorCode returnvalue; returnvalue = m_DeviceProtocol->PVWR(&portHandle, ndiTool->GetSROMData(), ndiTool->GetSROMDataLength()); if (returnvalue != NDIOKAY) return false; returnvalue = m_DeviceProtocol->PINIT(&portHandle); if (returnvalue != NDIOKAY) return false; returnvalue = m_DeviceProtocol->PENA(&portHandle, ndiTool->GetTrackingPriority()); // Enable tool if (returnvalue != NDIOKAY) return false; return true; } else { return false; } } void mitk::NDITrackingDevice::SetRotationMode(RotationMode r) { m_RotationMode = r; } mitk::NDITrackingDevice::~NDITrackingDevice() { /* stop tracking and disconnect from tracking device */ if (GetState() == Tracking) { this->StopTracking(); } if (GetState() == Ready) { this->CloseConnection(); } /* cleanup tracking thread */ if ((m_ThreadID != 0) && (m_MultiThreader.IsNotNull())) { m_MultiThreader->TerminateThread(m_ThreadID); } m_MultiThreader = nullptr; /* free serial communication interface */ if (m_SerialCommunication.IsNotNull()) { m_SerialCommunication->ClearReceiveBuffer(); m_SerialCommunication->ClearSendBuffer(); m_SerialCommunication->CloseConnection(); m_SerialCommunication = nullptr; } } void mitk::NDITrackingDevice::SetPortNumber(const PortNumber _arg) { if (this->GetState() != Setup) return; itkDebugMacro("setting PortNumber to " << _arg); if (this->m_PortNumber != _arg) { this->m_PortNumber = _arg; this->Modified(); } } void mitk::NDITrackingDevice::SetDeviceName(std::string _arg) { if (this->GetState() != Setup) return; itkDebugMacro("setting eviceName to " << _arg); if (this->m_DeviceName != _arg) { this->m_DeviceName = _arg; this->Modified(); } } void mitk::NDITrackingDevice::SetBaudRate(const BaudRate _arg) { if (this->GetState() != Setup) return; itkDebugMacro("setting BaudRate to " << _arg); if (this->m_BaudRate != _arg) { this->m_BaudRate = _arg; this->Modified(); } } void mitk::NDITrackingDevice::SetDataBits(const DataBits _arg) { if (this->GetState() != Setup) return; itkDebugMacro("setting DataBits to " << _arg); if (this->m_DataBits != _arg) { this->m_DataBits = _arg; this->Modified(); } } void mitk::NDITrackingDevice::SetParity(const Parity _arg) { if (this->GetState() != Setup) return; itkDebugMacro("setting Parity to " << _arg); if (this->m_Parity != _arg) { this->m_Parity = _arg; this->Modified(); } } void mitk::NDITrackingDevice::SetStopBits(const StopBits _arg) { if (this->GetState() != Setup) return; itkDebugMacro("setting StopBits to " << _arg); if (this->m_StopBits != _arg) { this->m_StopBits = _arg; this->Modified(); } } void mitk::NDITrackingDevice::SetHardwareHandshake(const HardwareHandshake _arg) { if (this->GetState() != Setup) return; itkDebugMacro("setting HardwareHandshake to " << _arg); if (this->m_HardwareHandshake != _arg) { this->m_HardwareHandshake = _arg; this->Modified(); } } void mitk::NDITrackingDevice::SetIlluminationActivationRate(const IlluminationActivationRate _arg) { if (this->GetState() == Tracking) return; itkDebugMacro("setting IlluminationActivationRate to " << _arg); if (this->m_IlluminationActivationRate != _arg) { this->m_IlluminationActivationRate = _arg; this->Modified(); if (this->GetState() == Ready) // if the connection to the tracking system is established, send the new rate to the tracking device too m_DeviceProtocol->IRATE(this->m_IlluminationActivationRate); } } void mitk::NDITrackingDevice::SetDataTransferMode(const DataTransferMode _arg) { itkDebugMacro("setting DataTransferMode to " << _arg); if (this->m_DataTransferMode != _arg) { this->m_DataTransferMode = _arg; this->Modified(); } } mitk::NDIErrorCode mitk::NDITrackingDevice::Send(const std::string* input, bool addCRC) { if (input == nullptr) return SERIALSENDERROR; std::string message; if (addCRC == true) message = *input + CalcCRC(input) + std::string(1, CR); else message = *input + std::string(1, CR); //unsigned int messageLength = message.length() + 1; // +1 for CR // Clear send buffer this->ClearSendBuffer(); // Send the date to the device MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex long returnvalue = m_SerialCommunication->Send(message); if (returnvalue == 0) return SERIALSENDERROR; else return NDIOKAY; } mitk::NDIErrorCode mitk::NDITrackingDevice::Receive(std::string* answer, unsigned int numberOfBytes) { if (answer == nullptr) return SERIALRECEIVEERROR; MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex long returnvalue = m_SerialCommunication->Receive(*answer, numberOfBytes); // never read more bytes than the device has send, the function will block until enough bytes are send... if (returnvalue == 0) return SERIALRECEIVEERROR; else return NDIOKAY; } mitk::NDIErrorCode mitk::NDITrackingDevice::ReceiveByte(char* answer) { if (answer == nullptr) return SERIALRECEIVEERROR; std::string m; MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex long returnvalue = m_SerialCommunication->Receive(m, 1); if ((returnvalue == 0) || (m.size() != 1)) return SERIALRECEIVEERROR; *answer = m.at(0); return NDIOKAY; } mitk::NDIErrorCode mitk::NDITrackingDevice::ReceiveLine(std::string* answer) { if (answer == nullptr) return SERIALRECEIVEERROR; std::string m; MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex do { long returnvalue = m_SerialCommunication->Receive(m, 1); if ((returnvalue == 0) || (m.size() != 1)) return SERIALRECEIVEERROR; *answer += m; } while (m.at(0) != LF); return NDIOKAY; } void mitk::NDITrackingDevice::ClearSendBuffer() { MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex m_SerialCommunication->ClearSendBuffer(); } void mitk::NDITrackingDevice::ClearReceiveBuffer() { MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex m_SerialCommunication->ClearReceiveBuffer(); } const std::string mitk::NDITrackingDevice::CalcCRC(const std::string* input) { if (input == nullptr) return ""; /* the crc16 calculation code is taken from the NDI API guide example code section */ static int oddparity[16] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 }; unsigned int data; // copy of the input string's current character unsigned int crcValue = 0; // the crc value is stored here unsigned int* puCRC16 = &crcValue; // the algorithm uses a pointer to crcValue, so it's easier to provide that than to change the algorithm for (unsigned int i = 0; i < input->length(); i++) { data = (*input)[i]; data = (data ^ (*(puCRC16)& 0xff)) & 0xff; *puCRC16 >>= 8; if (oddparity[data & 0x0f] ^ oddparity[data >> 4]) { *(puCRC16) ^= 0xc001; } data <<= 6; *puCRC16 ^= data; data <<= 1; *puCRC16 ^= data; } // crcValue contains now the CRC16 value. Convert it to a string and return it char returnvalue[13]; sprintf(returnvalue, "%04X", crcValue); // 4 hexadecimal digit with uppercase format return std::string(returnvalue); } bool mitk::NDITrackingDevice::OpenConnection() { //this->m_ModeMutex->Lock(); if (this->GetState() != Setup) { mitkThrowException(mitk::IGTException) << "Can only try to open the connection if in setup mode"; } m_SerialCommunication = mitk::SerialCommunication::New(); /* init local com port to standard com settings for a NDI tracking device: 9600 baud, 8 data bits, no parity, 1 stop bit, no hardware handshake */ if (m_DeviceName.empty()) m_SerialCommunication->SetPortNumber(m_PortNumber); else m_SerialCommunication->SetDeviceName(m_DeviceName); m_SerialCommunication->SetBaudRate(mitk::SerialCommunication::BaudRate9600); m_SerialCommunication->SetDataBits(mitk::SerialCommunication::DataBits8); m_SerialCommunication->SetParity(mitk::SerialCommunication::None); m_SerialCommunication->SetStopBits(mitk::SerialCommunication::StopBits1); m_SerialCommunication->SetSendTimeout(5000); m_SerialCommunication->SetReceiveTimeout(5000); if (m_SerialCommunication->OpenConnection() == 0) // 0 == ERROR_VALUE { m_SerialCommunication->CloseConnection(); m_SerialCommunication = nullptr; mitkThrowException(mitk::IGTHardwareException) << "Can not open serial port"; } /* Reset Tracking device by sending a serial break for 500ms */ m_SerialCommunication->SendBreak(400); /* Read answer from tracking device (RESETBE6F) */ static const std::string reset("RESETBE6F\r"); std::string answer = ""; this->Receive(&answer, reset.length()); // read answer (should be RESETBE6F) this->ClearReceiveBuffer(); // flush the receive buffer of all remaining data (carriage return, strings other than reset if (reset.compare(answer) != 0) // check for RESETBE6F { if (m_SerialCommunication.IsNotNull()) { m_SerialCommunication->CloseConnection(); m_SerialCommunication = nullptr; } mitkThrowException(mitk::IGTHardwareException) << "Hardware Reset of tracking device did not work"; } /* Now the tracking device isSetData reset, start initialization */ NDIErrorCode returnvalue; /* set device com settings to new values and wait for the device to change them */ returnvalue = m_DeviceProtocol->COMM(m_BaudRate, m_DataBits, m_Parity, m_StopBits, m_HardwareHandshake); if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << "Could not set comm settings in trackingdevice"; } //after changing COMM wait at least 100ms according to NDI Api documentation page 31 itksys::SystemTools::Delay(500); /* now change local com settings accordingly */ m_SerialCommunication->CloseConnection(); m_SerialCommunication->SetBaudRate(m_BaudRate); m_SerialCommunication->SetDataBits(m_DataBits); m_SerialCommunication->SetParity(m_Parity); m_SerialCommunication->SetStopBits(m_StopBits); m_SerialCommunication->SetHardwareHandshake(m_HardwareHandshake); m_SerialCommunication->SetSendTimeout(5000); m_SerialCommunication->SetReceiveTimeout(5000); m_SerialCommunication->OpenConnection(); /* initialize the tracking device */ returnvalue = m_DeviceProtocol->INIT(); if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << "Could not initialize the tracking device"; } if (this->GetType() == mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName()) // if the type of tracking device is not specified, try to query the connected device { mitk::TrackingDeviceType deviceType; returnvalue = m_DeviceProtocol->VER(deviceType); if ((returnvalue != NDIOKAY) || (deviceType == mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName())) { mitkThrowException(mitk::IGTHardwareException) << "Could not determine tracking device type. Please set manually and try again."; } this->SetType(deviceType); } /**** Optional Polaris specific code, Work in progress // start diagnostic mode returnvalue = m_DeviceProtocol->DSTART(); if (returnvalue != NDIOKAY) { this->SetErrorMessage("Could not start diagnostic mode"); return false; } else // we are in diagnostic mode { // initialize extensive IR checking returnvalue = m_DeviceProtocol->IRINIT(); if (returnvalue != NDIOKAY) { this->SetErrorMessage("Could not initialize intense infrared light checking"); return false; } bool intenseIR = false; returnvalue = m_DeviceProtocol->IRCHK(&intenseIR); if (returnvalue != NDIOKAY) { this->SetErrorMessage("Could not execute intense infrared light checking"); return false; } if (intenseIR == true) // do something - warn the user, raise exception, write to protocol or similar std::cout << "Warning: Intense infrared light detected. Accurate tracking will probably not be possible.\n"; // stop diagnictic mode returnvalue = m_DeviceProtocol->DSTOP(); if (returnvalue != NDIOKAY) { this->SetErrorMessage("Could not stop diagnostic mode"); return false; } } *** end of optional polaris code ***/ /** * now add tools to the tracking system **/ /* First, check if the tracking device has port handles that need to be freed and free them */ returnvalue = FreePortHandles(); // non-critical, therefore no error handling /** * POLARIS: initialize the tools that were added manually **/ { MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex std::string portHandle; auto endIt = m_6DTools.end(); for (auto it = m_6DTools.begin(); it != endIt; ++it) { /* get a port handle for the tool */ returnvalue = m_DeviceProtocol->PHRQ(&portHandle); if (returnvalue == NDIOKAY) { (*it)->SetPortHandle(portHandle.c_str()); /* now write the SROM file of the tool to the tracking system using PVWR */ if (this->m_Data.Line == mitk::NDIPolarisTypeInformation::GetTrackingDeviceName()) { returnvalue = m_DeviceProtocol->PVWR(&portHandle, (*it)->GetSROMData(), (*it)->GetSROMDataLength()); if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not write SROM file for tool '") + (*it)->GetToolName() + std::string("' to tracking device")).c_str(); } returnvalue = m_DeviceProtocol->PINIT(&portHandle); if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not initialize tool '") + (*it)->GetToolName()).c_str(); } if ((*it)->IsEnabled() == true) { returnvalue = m_DeviceProtocol->PENA(&portHandle, (*it)->GetTrackingPriority()); // Enable tool if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not enable port '") + portHandle + std::string("' for tool '") + (*it)->GetToolName() + std::string("'")).c_str(); } } } } } } // end of toolsmutexlockholder scope /* check for wired tools and add them too */ if (this->DiscoverWiredTools() == false) // query the tracking device for wired tools and add them to our tool list return false; // \TODO: could we continue anyways? /*POLARIS: set the illuminator activation rate */ if (this->m_Data.Line == mitk::NDIPolarisTypeInformation::GetTrackingDeviceName()) { returnvalue = m_DeviceProtocol->IRATE(this->m_IlluminationActivationRate); if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << "Could not set the illuminator activation rate"; } } /* finish - now all tools should be added, initialized and enabled, so that tracking can be started */ this->SetState(Ready); try { SetVolume(this->m_Data); } catch (mitk::IGTHardwareException e) { MITK_WARN << e.GetDescription(); } return true; } bool mitk::NDITrackingDevice::InitializeWiredTools() { NDIErrorCode returnvalue; std::string portHandle; returnvalue = m_DeviceProtocol->PHSR(OCCUPIED, &portHandle); if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << "Could not obtain a list of port handles that are connected"; } /* if there are port handles that need to be initialized, initialize them. Furthermore instantiate tools for each handle that has no tool yet. */ std::string ph; for (unsigned int i = 0; i < portHandle.size(); i += 2) { ph = portHandle.substr(i, 2); mitk::NDIPassiveTool* pt = this->GetInternalTool(ph); if (pt == nullptr) // if we don't have a tool, something is wrong. Tools should be discovered first by calling DiscoverWiredTools() continue; if (pt->GetSROMData() == nullptr) continue; returnvalue = m_DeviceProtocol->PVWR(&ph, pt->GetSROMData(), pt->GetSROMDataLength()); if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not write SROM file for tool '") + pt->GetToolName() + std::string("' to tracking device")).c_str(); } returnvalue = m_DeviceProtocol->PINIT(&ph); if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not initialize tool '") + pt->GetToolName()).c_str(); } if (pt->IsEnabled() == true) { returnvalue = m_DeviceProtocol->PENA(&ph, pt->GetTrackingPriority()); // Enable tool if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not enable port '") + portHandle + std::string("' for tool '") + pt->GetToolName() + std::string("'")).c_str(); } } } return true; } mitk::TrackingDeviceType mitk::NDITrackingDevice::TestConnection() { if (this->GetState() != Setup) { return mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName(); } m_SerialCommunication = mitk::SerialCommunication::New(); //m_DeviceProtocol = mitk::NDIProtocol::New(); //m_DeviceProtocol->SetTrackingDevice(this); //m_DeviceProtocol->UseCRCOn(); /* init local com port to standard com settings for a NDI tracking device: 9600 baud, 8 data bits, no parity, 1 stop bit, no hardware handshake */ if (m_DeviceName.empty()) m_SerialCommunication->SetPortNumber(m_PortNumber); else m_SerialCommunication->SetDeviceName(m_DeviceName); m_SerialCommunication->SetBaudRate(mitk::SerialCommunication::BaudRate9600); m_SerialCommunication->SetDataBits(mitk::SerialCommunication::DataBits8); m_SerialCommunication->SetParity(mitk::SerialCommunication::None); m_SerialCommunication->SetStopBits(mitk::SerialCommunication::StopBits1); m_SerialCommunication->SetSendTimeout(5000); m_SerialCommunication->SetReceiveTimeout(5000); if (m_SerialCommunication->OpenConnection() == 0) // error { m_SerialCommunication = nullptr; return mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName(); } /* Reset Tracking device by sending a serial break for 500ms */ m_SerialCommunication->SendBreak(400); /* Read answer from tracking device (RESETBE6F) */ static const std::string reset("RESETBE6F\r"); std::string answer = ""; this->Receive(&answer, reset.length()); // read answer (should be RESETBE6F) this->ClearReceiveBuffer(); // flush the receive buffer of all remaining data (carriage return, strings other than reset if (reset.compare(answer) != 0) // check for RESETBE6F { m_SerialCommunication->CloseConnection(); m_SerialCommunication = nullptr; mitkThrowException(mitk::IGTHardwareException) << "Hardware Reset of tracking device did not work"; } /* Now the tracking device is reset, start initialization */ NDIErrorCode returnvalue; /* initialize the tracking device */ //returnvalue = m_DeviceProtocol->INIT(); //if (returnvalue != NDIOKAY) //{ // this->SetErrorMessage("Could not initialize the tracking device"); // return mitk::TrackingSystemNotSpecified; //} mitk::TrackingDeviceType deviceType; returnvalue = m_DeviceProtocol->VER(deviceType); if ((returnvalue != NDIOKAY) || (deviceType == mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName())) { m_SerialCommunication = nullptr; return mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName(); } m_SerialCommunication = nullptr; return deviceType; } bool mitk::NDITrackingDevice::CloseConnection() { if (this->GetState() != Setup) { //init before closing to force the field generator from aurora to switch itself off m_DeviceProtocol->INIT(); /* close the serial connection */ m_SerialCommunication->CloseConnection(); /* invalidate all tools */ this->InvalidateAll(); /* return to setup mode */ this->SetState(Setup); m_SerialCommunication = nullptr; } return true; } ITK_THREAD_RETURN_TYPE mitk::NDITrackingDevice::ThreadStartTracking(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; if (pInfo == nullptr) { return ITK_THREAD_RETURN_VALUE; } if (pInfo->UserData == nullptr) { return ITK_THREAD_RETURN_VALUE; } NDITrackingDevice *trackingDevice = (NDITrackingDevice*)pInfo->UserData; if (trackingDevice != nullptr) { if (trackingDevice->GetOperationMode() == ToolTracking6D) trackingDevice->TrackTools(); // call TrackTools() from the original object else if (trackingDevice->GetOperationMode() == MarkerTracking3D) trackingDevice->TrackMarkerPositions(); // call TrackMarkerPositions() from the original object else if (trackingDevice->GetOperationMode() == ToolTracking5D) trackingDevice->TrackMarkerPositions(); // call TrackMarkerPositions() from the original object else if (trackingDevice->GetOperationMode() == HybridTracking) { trackingDevice->TrackToolsAndMarkers(); } } trackingDevice->m_ThreadID = 0; // erase thread id, now that this thread will end. return ITK_THREAD_RETURN_VALUE; } bool mitk::NDITrackingDevice::StartTracking() { if (this->GetState() != Ready) return false; this->SetState(Tracking); // go to mode Tracking this->m_StopTrackingMutex->Lock(); // update the local copy of m_StopTracking this->m_StopTracking = false; this->m_StopTrackingMutex->Unlock(); m_ThreadID = m_MultiThreader->SpawnThread(this->ThreadStartTracking, this); // start a new thread that executes the TrackTools() method mitk::IGTTimeStamp::GetInstance()->Start(this); return true; } void mitk::NDITrackingDevice::TrackTools() { /* lock the TrackingFinishedMutex to signal that the execution rights are now transfered to the tracking thread */ MutexLockHolder trackingFinishedLockHolder(*m_TrackingFinishedMutex); // keep lock until end of scope if (this->GetState() != Tracking) return; NDIErrorCode returnvalue; returnvalue = m_DeviceProtocol->TSTART(); if (returnvalue != NDIOKAY) return; bool localStopTracking; // Because m_StopTracking is used by two threads, access has to be guarded by a mutex. To minimize thread locking, a local copy is used here this->m_StopTrackingMutex->Lock(); // update the local copy of m_StopTracking localStopTracking = this->m_StopTracking; this->m_StopTrackingMutex->Unlock(); while ((this->GetState() == Tracking) && (localStopTracking == false)) { if (this->m_DataTransferMode == TX) { returnvalue = this->m_DeviceProtocol->TX(); if (!((returnvalue == NDIOKAY) || (returnvalue == NDICRCERROR) || (returnvalue == NDICRCDOESNOTMATCH))) // right now, do not stop on crc errors break; } else { returnvalue = this->m_DeviceProtocol->BX(); if (returnvalue != NDIOKAY) break; } /* Update the local copy of m_StopTracking */ this->m_StopTrackingMutex->Lock(); localStopTracking = m_StopTracking; this->m_StopTrackingMutex->Unlock(); } /* StopTracking was called, thus the mode should be changed back to Ready now that the tracking loop has ended. */ returnvalue = m_DeviceProtocol->TSTOP(); if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << "An error occured while tracking tools."; } return; // returning from this function (and ThreadStartTracking()) this will end the thread and transfer control back to main thread by releasing trackingFinishedLockHolder } void mitk::NDITrackingDevice::TrackMarkerPositions() { MutexLockHolder trackingFinishedLockHolder(*m_TrackingFinishedMutex); // keep lock until end of scope if (m_OperationMode == ToolTracking6D) return; if (this->GetState() != Tracking) return; NDIErrorCode returnvalue; returnvalue = m_DeviceProtocol->DSTART(); // Start Diagnostic Mode if (returnvalue != NDIOKAY) return; bool localStopTracking; // Because m_StopTracking is used by two threads, access has to be guarded by a mutex. To minimize thread locking, a local copy is used here this->m_StopTrackingMutex->Lock(); // update the local copy of m_StopTracking localStopTracking = this->m_StopTracking; this->m_StopTrackingMutex->Unlock(); while ((this->GetState() == Tracking) && (localStopTracking == false)) { m_MarkerPointsMutex->Lock(); // lock points data structure returnvalue = this->m_DeviceProtocol->POS3D(&m_MarkerPoints); // update points data structure with new position data from tracking device m_MarkerPointsMutex->Unlock(); if (!((returnvalue == NDIOKAY) || (returnvalue == NDICRCERROR) || (returnvalue == NDICRCDOESNOTMATCH))) // right now, do not stop on crc errors { std::cout << "Error in POS3D: could not read data. Possibly no markers present." << std::endl; } /* Update the local copy of m_StopTracking */ this->m_StopTrackingMutex->Lock(); localStopTracking = m_StopTracking; this->m_StopTrackingMutex->Unlock(); itksys::SystemTools::Delay(1); } /* StopTracking was called, thus the mode should be changed back to Ready now that the tracking loop has ended. */ returnvalue = m_DeviceProtocol->DSTOP(); if (returnvalue != NDIOKAY) return; // how can this thread tell the application, that an error has occured? this->SetState(Ready); return; // returning from this function (and ThreadStartTracking()) this will end the thread } void mitk::NDITrackingDevice::TrackToolsAndMarkers() { MutexLockHolder trackingFinishedLockHolder(*m_TrackingFinishedMutex); // keep lock until end of scope if (m_OperationMode != HybridTracking) return; NDIErrorCode returnvalue; returnvalue = m_DeviceProtocol->TSTART(); // Start Diagnostic Mode if (returnvalue != NDIOKAY) return; bool localStopTracking; // Because m_StopTracking is used by two threads, access has to be guarded by a mutex. To minimize thread locking, a local copy is used here this->m_StopTrackingMutex->Lock(); // update the local copy of m_StopTracking localStopTracking = this->m_StopTracking; this->m_StopTrackingMutex->Unlock(); while ((this->GetState() == Tracking) && (localStopTracking == false)) { m_MarkerPointsMutex->Lock(); // lock points data structure returnvalue = this->m_DeviceProtocol->TX(true, &m_MarkerPoints); // update points data structure with new position data from tracking device m_MarkerPointsMutex->Unlock(); if (!((returnvalue == NDIOKAY) || (returnvalue == NDICRCERROR) || (returnvalue == NDICRCDOESNOTMATCH))) // right now, do not stop on crc errors { std::cout << "Error in TX: could not read data. Possibly no markers present." << std::endl; } /* Update the local copy of m_StopTracking */ this->m_StopTrackingMutex->Lock(); localStopTracking = m_StopTracking; this->m_StopTrackingMutex->Unlock(); } /* StopTracking was called, thus the mode should be changed back to Ready now that the tracking loop has ended. */ returnvalue = m_DeviceProtocol->TSTOP(); if (returnvalue != NDIOKAY) return; // how can this thread tell the application, that an error has occurred? this->SetState(Ready); return; // returning from this function (and ThreadStartTracking()) this will end the thread } mitk::TrackingTool* mitk::NDITrackingDevice::GetTool(unsigned int toolNumber) const { MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex if (toolNumber < m_6DTools.size()) return m_6DTools.at(toolNumber); return nullptr; } mitk::TrackingTool* mitk::NDITrackingDevice::GetToolByName(std::string name) const { MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex auto end = m_6DTools.end(); for (auto iterator = m_6DTools.begin(); iterator != end; ++iterator) if (name.compare((*iterator)->GetToolName()) == 0) return *iterator; return nullptr; } mitk::NDIPassiveTool* mitk::NDITrackingDevice::GetInternalTool(std::string portHandle) { MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex auto end = m_6DTools.end(); for (auto iterator = m_6DTools.begin(); iterator != end; ++iterator) if (portHandle.compare((*iterator)->GetPortHandle()) == 0) return *iterator; return nullptr; } unsigned int mitk::NDITrackingDevice::GetToolCount() const { MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex return m_6DTools.size(); } bool mitk::NDITrackingDevice::Beep(unsigned char count) { if (this->GetState() != Setup) { return (m_DeviceProtocol->BEEP(count) == NDIOKAY); } else { return false; } } mitk::TrackingTool* mitk::NDITrackingDevice::AddTool(const char* toolName, const char* fileName, TrackingPriority p /*= NDIPassiveTool::Dynamic*/) { mitk::NDIPassiveTool::Pointer t = mitk::NDIPassiveTool::New(); if (t->LoadSROMFile(fileName) == false) return nullptr; t->SetToolName(toolName); t->SetTrackingPriority(p); if (this->InternalAddTool(t) == false) return nullptr; return t.GetPointer(); } bool mitk::NDITrackingDevice::InternalAddTool(mitk::NDIPassiveTool* tool) { if (tool == nullptr) return false; NDIPassiveTool::Pointer p = tool; /* if the connection to the tracking device is already established, add the new tool to the device now */ if (this->GetState() == Ready) { /* get a port handle for the tool */ std::string newPortHandle; NDIErrorCode returnvalue; returnvalue = m_DeviceProtocol->PHRQ(&newPortHandle); if (returnvalue == NDIOKAY) { p->SetPortHandle(newPortHandle.c_str()); /* now write the SROM file of the tool to the tracking system using PVWR */ returnvalue = m_DeviceProtocol->PVWR(&newPortHandle, p->GetSROMData(), p->GetSROMDataLength()); if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not write SROM file for tool '") + p->GetToolName() + std::string("' to tracking device")).c_str(); } /* initialize the port handle */ returnvalue = m_DeviceProtocol->PINIT(&newPortHandle); if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not initialize port '") + newPortHandle + std::string("' for tool '") + p->GetToolName() + std::string("'")).c_str(); } /* enable the port handle */ if (p->IsEnabled() == true) { returnvalue = m_DeviceProtocol->PENA(&newPortHandle, p->GetTrackingPriority()); // Enable tool if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not enable port '") + newPortHandle + std::string("' for tool '") + p->GetToolName() + std::string("'")).c_str(); } } } /* now that the tool is added to the device, add it to list too */ m_ToolsMutex->Lock(); this->m_6DTools.push_back(p); m_ToolsMutex->Unlock(); this->Modified(); return true; } else if (this->GetState() == Setup) { /* In Setup mode, we only add it to the list, so that OpenConnection() can add it later */ m_ToolsMutex->Lock(); this->m_6DTools.push_back(p); m_ToolsMutex->Unlock(); this->Modified(); return true; } else // in Tracking mode, no tools can be added return false; } bool mitk::NDITrackingDevice::RemoveTool(mitk::TrackingTool* tool) { mitk::NDIPassiveTool* ndiTool = dynamic_cast(tool); if (ndiTool == nullptr) return false; std::string portHandle = ndiTool->GetPortHandle(); /* a valid portHandle has length 2. If a valid handle exists, the tool is already added to the tracking device, so we have to remove it there if the connection to the tracking device has already been established. */ if ((portHandle.length() == 2) && (this->GetState() == Ready)) // do not remove a tool in tracking mode { NDIErrorCode returnvalue; returnvalue = m_DeviceProtocol->PHF(&portHandle); if (returnvalue != NDIOKAY) return false; /* Now that the tool is removed from the tracking device, remove it from our tool list too */ MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex (scope is inside the if-block auto end = m_6DTools.end(); for (auto iterator = m_6DTools.begin(); iterator != end; ++iterator) { if (iterator->GetPointer() == ndiTool) { m_6DTools.erase(iterator); this->Modified(); return true; } } return false; } else if (this->GetState() == Setup) // in Setup Mode, we are not connected to the tracking device, so we can just remove the tool from the tool list { MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex auto end = m_6DTools.end(); for (auto iterator = m_6DTools.begin(); iterator != end; ++iterator) { if ((*iterator).GetPointer() == ndiTool) { m_6DTools.erase(iterator); this->Modified(); return true; } } return false; } return false; } void mitk::NDITrackingDevice::InvalidateAll() { MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex auto end = m_6DTools.end(); for (auto iterator = m_6DTools.begin(); iterator != end; ++iterator) (*iterator)->SetDataValid(false); } bool mitk::NDITrackingDevice::SetOperationMode(OperationMode mode) { if (GetState() == Tracking) return false; m_OperationMode = mode; return true; } mitk::OperationMode mitk::NDITrackingDevice::GetOperationMode() { return m_OperationMode; } bool mitk::NDITrackingDevice::GetMarkerPositions(MarkerPointContainerType* markerpositions) { m_MarkerPointsMutex->Lock(); *markerpositions = m_MarkerPoints; // copy the internal vector to the one provided m_MarkerPointsMutex->Unlock(); return (markerpositions->size() != 0); } bool mitk::NDITrackingDevice::DiscoverWiredTools() { /* First, check for disconnected tools and remove them */ this->FreePortHandles(); /* check for new tools, add and initialize them */ NDIErrorCode returnvalue; std::string portHandle; returnvalue = m_DeviceProtocol->PHSR(OCCUPIED, &portHandle); if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << "Could not obtain a list of port handles that are connected"; } /* if there are port handles that need to be initialized, initialize them. Furthermore instantiate tools for each handle that has no tool yet. */ std::string ph; /* we need to remember the ports which are occupied to be able to readout the serial numbers of the connected tools later */ std::vector occupiedPorts = std::vector(); int numberOfToolsAtStart = this->GetToolCount(); //also remember the number of tools at start to identify the automatically detected tools later for (unsigned int i = 0; i < portHandle.size(); i += 2) { ph = portHandle.substr(i, 2); if (this->GetInternalTool(ph) != nullptr) // if we already have a tool with this handle continue; // then skip the initialization //instantiate an object for each tool that is connected mitk::NDIPassiveTool::Pointer newTool = mitk::NDIPassiveTool::New(); newTool->SetPortHandle(ph.c_str()); newTool->SetTrackingPriority(mitk::NDIPassiveTool::Dynamic); //set a name for identification newTool->SetToolName((std::string("Port ") + ph).c_str()); returnvalue = m_DeviceProtocol->PINIT(&ph); if (returnvalue != NDIINITIALIZATIONFAILED) //if the initialization failed (AURORA) it can not be enabled. A srom file will have to be specified manually first. Still return true to be able to continue { if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not initialize port '") + ph + std::string("' for tool '") + newTool->GetToolName() + std::string("'")).c_str(); } /* enable the port handle */ returnvalue = m_DeviceProtocol->PENA(&ph, newTool->GetTrackingPriority()); // Enable tool if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not enable port '") + ph + std::string("' for tool '") + newTool->GetToolName() + std::string("'")).c_str(); } } //we have to temporarily unlock m_ModeMutex here to avoid a deadlock with another lock inside InternalAddTool() if (this->InternalAddTool(newTool) == false) { mitkThrowException(mitk::IGTException) << "Error while adding new tool"; } else occupiedPorts.push_back(i); } // after initialization readout serial numbers of automatically detected tools for (unsigned int i = 0; i < occupiedPorts.size(); i++) { ph = portHandle.substr(occupiedPorts.at(i), 2); std::string portInfo; NDIErrorCode returnvaluePort = m_DeviceProtocol->PHINF(ph, &portInfo); if ((returnvaluePort == NDIOKAY) && (portInfo.size()>31)) dynamic_cast(this->GetTool(i + numberOfToolsAtStart))->SetSerialNumber(portInfo.substr(23, 8)); itksys::SystemTools::Delay(10); } return true; } mitk::NDIErrorCode mitk::NDITrackingDevice::FreePortHandles() { /* first search for port handles that need to be freed: e.g. because of a reset of the tracking system */ NDIErrorCode returnvalue = NDIOKAY; std::string portHandle; returnvalue = m_DeviceProtocol->PHSR(FREED, &portHandle); if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << "Could not obtain a list of port handles that need to be freed"; } /* if there are port handles that need to be freed, free them */ if (portHandle.empty() == true) return returnvalue; std::string ph; for (unsigned int i = 0; i < portHandle.size(); i += 2) { ph = portHandle.substr(i, 2); mitk::NDIPassiveTool* t = this->GetInternalTool(ph); if (t != nullptr) // if we have a tool for the port handle that needs to be freed { if (this->RemoveTool(t) == false) // remove it (this will free the port too) returnvalue = NDIERROR; } else // we don't have a tool, the port handle exists only in the tracking device { returnvalue = m_DeviceProtocol->PHF(&ph); // free it there // What to do if port handle could not be freed? This seems to be a non critical error if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << "Could not free all port handles"; } } } return returnvalue; } int mitk::NDITrackingDevice::GetMajorFirmwareRevisionNumber() { std::string revision; if (m_DeviceProtocol->APIREV(&revision) != mitk::NDIOKAY || revision.empty() || (revision.size() != 9)) { MITK_ERROR << "Could not receive firmware revision number!"; return 0; } const std::string majrevno = revision.substr(2, 3); //cut out "004" from "D.004.001" return std::atoi(majrevno.c_str()); } const char* mitk::NDITrackingDevice::GetFirmwareRevisionNumber() { static std::string revision; if (m_DeviceProtocol->APIREV(&revision) != mitk::NDIOKAY || revision.empty() || (revision.size() != 9)) { MITK_ERROR << "Could not receive firmware revision number!"; revision = ""; return revision.c_str(); } return revision.c_str(); } bool mitk::NDITrackingDevice::AutoDetectToolsAvailable() { if (this->GetType() == mitk::NDIAuroraTypeInformation::GetTrackingDeviceName()) { return true; } else { return false; } } bool mitk::NDITrackingDevice::AddSingleToolIsAvailable() { //For Aurora, only AutoDetecion or loading of toolStorage should be used. It is not possible to add a single tool. if (this->GetType() == mitk::NDIAuroraTypeInformation::GetTrackingDeviceName()) { return false; } //For Polaris, a single tool can be added, there is no autoDetection. else { return true; } } mitk::NavigationToolStorage::Pointer mitk::NDITrackingDevice::AutoDetectTools() { mitk::NavigationToolStorage::Pointer autoDetectedStorage = mitk::NavigationToolStorage::New(); if (this->GetType() == mitk::NDIAuroraTypeInformation::GetTrackingDeviceName()) { try { this->OpenConnection(); this->StartTracking(); } catch (mitk::Exception& e) { MITK_WARN << "Warning, can not auto-detect tools! (" << e.GetDescription() << ")"; return autoDetectedStorage; } for (unsigned int i = 0; i < this->GetToolCount(); i++) { //create a navigation tool with sphere as surface std::stringstream toolname; toolname << "AutoDetectedTool" << i; mitk::NavigationTool::Pointer newTool = mitk::NavigationTool::New(); newTool->SetSerialNumber(dynamic_cast(this->GetTool(i))->GetSerialNumber()); newTool->SetIdentifier(toolname.str()); newTool->SetTrackingDeviceType(mitk::NDIAuroraTypeInformation::GetTrackingDeviceName()); - mitk::DataNode::Pointer newNode = mitk::DataNode::New(); - mitk::Surface::Pointer mySphere = mitk::Surface::New(); - vtkSphereSource *vtkData = vtkSphereSource::New(); - vtkData->SetRadius(3.0f); - vtkData->SetCenter(0.0, 0.0, 0.0); - vtkData->Update(); - mySphere->SetVtkPolyData(vtkData->GetOutput()); - vtkData->Delete(); - newNode->SetData(mySphere); - newNode->SetName(toolname.str()); - newTool->SetDataNode(newNode); + newTool->GetDataNode()->SetName(toolname.str()); autoDetectedStorage->AddTool(newTool); } this->StopTracking(); this->CloseConnection(); } return autoDetectedStorage; } bool mitk::NDITrackingDevice::GetSupportedVolumes(unsigned int* numberOfVolumes, mitk::NDITrackingDevice::NDITrackingVolumeContainerType* volumes, mitk::NDITrackingDevice::TrackingVolumeDimensionType* volumesDimensions) { if (numberOfVolumes == nullptr || volumes == nullptr || volumesDimensions == nullptr) return false; static std::string info; if (m_DeviceProtocol->SFLIST(&info) != mitk::NDIOKAY || info.empty()) { MITK_ERROR << "Could not receive tracking volume information of tracking system!"; return false; } /*info contains the following: (+n times:) */ (*numberOfVolumes) = (unsigned int)std::atoi(info.substr(0, 1).c_str()); for (unsigned int i = 0; i < (*numberOfVolumes); i++) { //e.g. for cube: "9-025000+025000-025000+025000-055000-005000+000000+000000+000000+00000011" //for dome: "A+005000+048000+005000+066000+000000+000000+000000+000000+000000+00000011" std::string::size_type offset, end; offset = (i * 73) + 1; end = 73 + (i * 73); std::string currentVolume = info.substr(offset, end);//i=0: from 1 to 73 characters; i=1: from 75 to 148 char; // if i>0 then we have a return statement infront if (i > 0) currentVolume = currentVolume.substr(1, currentVolume.size()); if (currentVolume.compare(0, 1, NDIPolarisTypeInformation::GetDeviceDataPolarisOldModel().HardwareCode) == 0) volumes->push_back(NDIPolarisTypeInformation::GetDeviceDataPolarisOldModel().Model); if (currentVolume.compare(0, 3, NDIPolarisTypeInformation::GetDeviceDataPolarisSpectra().HardwareCode) == 0) volumes->push_back(NDIPolarisTypeInformation::GetDeviceDataPolarisSpectra().Model); if (currentVolume.compare(1, 3, NDIPolarisTypeInformation::GetDeviceDataSpectraExtendedPyramid().HardwareCode) == 0) { currentVolume = currentVolume.substr(1, currentVolume.size()); volumes->push_back(NDIPolarisTypeInformation::GetDeviceDataSpectraExtendedPyramid().Model); } if (currentVolume.compare(0, 1, NDIPolarisTypeInformation::GetDeviceDataPolarisVicra().HardwareCode) == 0) volumes->push_back(NDIPolarisTypeInformation::GetDeviceDataPolarisVicra().Model); else if (currentVolume.compare(0, 1, mitk::NDIAuroraTypeInformation::GetDeviceDataAuroraPlanarCube().HardwareCode) == 0) volumes->push_back(mitk::NDIAuroraTypeInformation::GetDeviceDataAuroraPlanarCube().Model);//alias cube else if (currentVolume.compare(0, 1, mitk::NDIAuroraTypeInformation::GetDeviceDataAuroraPlanarDome().HardwareCode) == 0) volumes->push_back(mitk::NDIAuroraTypeInformation::GetDeviceDataAuroraPlanarDome().Model); //fill volumesDimensions for (unsigned int index = 0; index < 10; index++) { std::string::size_type offD, endD; offD = 1 + (index * 7); //7 digits per dimension and the first is the type of volume endD = offD + 7; int dimension = std::atoi(currentVolume.substr(offD, endD).c_str()); dimension /= 100; //given in mm. 7 digits are xxxx.xx according to NDI //strange, the last two digits (11) also for the metal flag get read also... volumesDimensions->push_back(dimension); } } return true; } bool mitk::NDITrackingDevice::SetVolume(mitk::TrackingDeviceData volume) { if (m_DeviceProtocol->VSEL(volume) != mitk::NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << "Could not set volume!"; } return true; } \ No newline at end of file diff --git a/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTrackingDevice.cpp b/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTrackingDevice.cpp index 954ec5487f..fc5dffae3d 100644 --- a/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTrackingDevice.cpp +++ b/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTrackingDevice.cpp @@ -1,524 +1,508 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkOpenIGTLinkTrackingDevice.h" #include "mitkOpenIGTLinkTrackingTool.h" #include "mitkIGTConfig.h" #include "mitkIGTTimeStamp.h" #include "mitkIGTHardwareException.h" #include "mitkTrackingTypes.h" #include #include #include #include #include #include //sleep headers #include #include typedef itk::MutexLockHolder MutexLockHolder; mitk::OpenIGTLinkTrackingDevice::OpenIGTLinkTrackingDevice() : mitk::TrackingDevice(), m_UpdateRate(60) { //set the type of this tracking device this->m_Data = mitk::OpenIGTLinkTypeInformation::GetDeviceDataOpenIGTLinkTrackingDeviceConnection(); m_OpenIGTLinkClient = mitk::IGTLClient::New(true); m_OpenIGTLinkClient->SetName("OpenIGTLink Tracking Device"); m_OpenIGTLinkClient->EnableNoBufferingMode(false); m_IGTLDeviceSource = mitk::IGTLTrackingDataDeviceSource::New(); m_IGTLDeviceSource->SetIGTLDevice(m_OpenIGTLinkClient); } mitk::OpenIGTLinkTrackingDevice::~OpenIGTLinkTrackingDevice() { } int mitk::OpenIGTLinkTrackingDevice::GetPortNumber() { return m_OpenIGTLinkClient->GetPortNumber(); } bool mitk::OpenIGTLinkTrackingDevice::AutoDetectToolsAvailable() { return true; } mitk::NavigationToolStorage::Pointer mitk::OpenIGTLinkTrackingDevice::AutoDetectTools() { mitk::NavigationToolStorage::Pointer returnValue = mitk::NavigationToolStorage::New(); if (m_OpenIGTLinkClient->GetPortNumber() == -1) { MITK_WARN << "Connection not initialized, aborting (invalid port number)."; return mitk::NavigationToolStorage::New(); } //open connection try { m_IGTLDeviceSource->Connect(); m_IGTLDeviceSource->StartCommunication(); } catch (std::runtime_error &e) { MITK_WARN << "AutoDetection: Open IGT Link device retruned an error while trying to connect: " << e.what(); return mitk::NavigationToolStorage::New(); } //get a message to find out type m_IGTLDeviceSource->SettrackingDataType(mitk::IGTLTrackingDataDeviceSource::UNKNOWN); mitk::IGTLMessage::Pointer receivedMessage = ReceiveMessage(100); const char* msgType = receivedMessage->GetIGTLMessageType(); if (std::string(msgType).empty()) { MITK_INFO << "Did not receive a message. Do you have to start the stream manually at the server?"; MITK_INFO << "Waiting for 10 seconds ..."; receivedMessage = ReceiveMessage(10000); msgType = receivedMessage->GetIGTLMessageType(); } MITK_INFO << "################# got message type: " << msgType; mitk::OpenIGTLinkTrackingDevice::TrackingMessageType type = GetMessageTypeFromString(msgType); switch (type) { case UNKNOWN: m_IGTLDeviceSource->SettrackingDataType(mitk::IGTLTrackingDataDeviceSource::UNKNOWN); break; case TDATA: m_IGTLDeviceSource->SettrackingDataType(mitk::IGTLTrackingDataDeviceSource::TDATA); break; case QTDATA: m_IGTLDeviceSource->SettrackingDataType(mitk::IGTLTrackingDataDeviceSource::QTDATA); break; case TRANSFORM: m_IGTLDeviceSource->SettrackingDataType(mitk::IGTLTrackingDataDeviceSource::TRANSFORM); break; } returnValue = DiscoverToolsAndConvertToNavigationTools(type); //close connection try { m_IGTLDeviceSource->StopCommunication(); m_IGTLDeviceSource->Disconnect(); } catch (std::runtime_error &e) { MITK_WARN << "AutoDetection: Open IGT Link device retruned an error while trying to disconnect: " << e.what(); return mitk::NavigationToolStorage::New(); } return returnValue; } mitk::NavigationToolStorage::Pointer mitk::OpenIGTLinkTrackingDevice::DiscoverToolsAndConvertToNavigationTools(mitk::OpenIGTLinkTrackingDevice::TrackingMessageType type, int NumberOfMessagesToWait) { MITK_INFO << "Start discovering tools by " << type << " messages"; mitk::NavigationToolStorage::Pointer returnValue = mitk::NavigationToolStorage::New(); std::map toolNameMap; for (int j = 0; jUpdate(); switch (type) { case TRANSFORM: { igtl::TransformMessage::Pointer msg = dynamic_cast(m_IGTLDeviceSource->GetOutput()->GetMessage().GetPointer()); if (msg == nullptr || msg.IsNull()) { MITK_INFO << "Received message is invalid / null. Skipping.."; continue; } int count = toolNameMap[msg->GetDeviceName()]; if (count == 0) { toolNameMap[msg->GetDeviceName()] = 1; } else { toolNameMap[msg->GetDeviceName()]++; } } break; case TDATA: { igtl::TrackingDataMessage::Pointer msg = dynamic_cast(m_IGTLDeviceSource->GetOutput()->GetMessage().GetPointer()); if (msg == nullptr || msg.IsNull()) { MITK_INFO << "Received message is invalid / null. Skipping.."; continue; } for (int k = 0; k < msg->GetNumberOfTrackingDataElements(); k++) { igtl::TrackingDataElement::Pointer tde; msg->GetTrackingDataElement(k, tde); if (tde.IsNotNull()) { int count = toolNameMap[tde->GetName()]; if (count == 0) { toolNameMap[tde->GetName()] = 1; } else { toolNameMap[tde->GetName()]++; } } } } break; default: MITK_WARN << "Only TRANSFORM and TDATA is currently supported, skipping!"; break; } } int i = 0; for (std::map::iterator it = toolNameMap.begin(); it != toolNameMap.end(); ++it) { MITK_INFO << "Found tool: " << it->first; std::stringstream name; name << it->first; std::stringstream identifier; identifier << "AutoDetectedTool-" << i; i++; mitk::NavigationTool::Pointer newTool = ConstructDefaultOpenIGTLinkTool(name.str(), identifier.str()); returnValue->AddTool(newTool); } return returnValue; } std::string mitk::OpenIGTLinkTrackingDevice::GetHostname() { return m_OpenIGTLinkClient->GetHostname(); } void mitk::OpenIGTLinkTrackingDevice::SetPortNumber(int portNumber) { m_OpenIGTLinkClient->SetPortNumber(portNumber); } void mitk::OpenIGTLinkTrackingDevice::SetHostname(std::string hostname) { m_OpenIGTLinkClient->SetHostname(hostname); } bool mitk::OpenIGTLinkTrackingDevice::IsDeviceInstalled() { return true; } mitk::TrackingTool* mitk::OpenIGTLinkTrackingDevice::AddTool(const char*, const char*) { mitk::OpenIGTLinkTrackingTool::Pointer t;// = mitk::OpenIGTLinkTrackingTool::New(); //TODO: Implement if (this->InternalAddTool(t) == false) return nullptr; return t.GetPointer(); } bool mitk::OpenIGTLinkTrackingDevice::InternalAddTool(OpenIGTLinkTrackingTool::Pointer tool) { m_AllTools.push_back(tool); return true; } bool mitk::OpenIGTLinkTrackingDevice::DiscoverTools(int waitingTime) { if (m_OpenIGTLinkClient->GetPortNumber() == -1) { MITK_WARN << "Connection not initialized, aborting (invalid port number)."; return false; } try { m_IGTLDeviceSource->Connect(); m_IGTLDeviceSource->StartCommunication(); } catch (std::runtime_error &e) { MITK_WARN << "Open IGT Link device retruned an error while trying to connect: " << e.what(); return false; } mitk::IGTLMessage::Pointer receivedMessage = ReceiveMessage(waitingTime); //check the tracking stream for the number and type of tools //igtl::MessageBase::Pointer receivedMessage = m_OpenIGTLinkClient->GetNextMessage(); if (receivedMessage.IsNull()) { MITK_WARN << "No message was received. Is there really a server?"; return false; } else if (!receivedMessage->IsDataValid()) { MITK_WARN << "Received invalid message."; return false; } const char* msgType = receivedMessage->GetIGTLMessageType(); mitk::OpenIGTLinkTrackingDevice::TrackingMessageType type = GetMessageTypeFromString(msgType); mitk::NavigationToolStorage::Pointer foundTools = this->DiscoverToolsAndConvertToNavigationTools(type); if (foundTools.IsNull() || (foundTools->GetToolCount() == 0)) { return false; } for (int i = 0; i < foundTools->GetToolCount(); i++) { AddNewToolForName(foundTools->GetTool(i)->GetToolName(), i); } MITK_INFO << "Found tools: " << foundTools->GetToolCount(); return true; } mitk::IGTLMessage::Pointer mitk::OpenIGTLinkTrackingDevice::ReceiveMessage(int waitingTime) { mitk::IGTLMessage::Pointer receivedMessage; //send a message to the server: start tracking stream mitk::IGTLMessageFactory::Pointer msgFactory = m_OpenIGTLinkClient->GetMessageFactory(); std::string message[2] = {"STT_QTDATA","STT_TDATA"}; for (int i = 0; i < 2; i++) { igtl::MessageBase::Pointer sttMsg = msgFactory->CreateInstance(message[i]); //TODO: Fix this to dynamically get this from GUI ((igtl::StartTrackingDataMessage*)sttMsg.GetPointer())->SetResolution(m_UpdateRate); m_OpenIGTLinkClient->SendMessage(mitk::IGTLMessage::New(sttMsg)); } std::chrono::high_resolution_clock::time_point time = std::chrono::high_resolution_clock::now(); std::chrono::milliseconds d = std::chrono::milliseconds(waitingTime); while (!(receivedMessage.IsNotNull() && receivedMessage->IsDataValid())) { m_IGTLDeviceSource->Update(); receivedMessage = m_IGTLDeviceSource->GetOutput(); if ((time + d) < std::chrono::high_resolution_clock::now()) break; std::this_thread::sleep_for(std::chrono::milliseconds(100)); } return receivedMessage; } void mitk::OpenIGTLinkTrackingDevice::AddNewToolForName(std::string name, int i) { mitk::OpenIGTLinkTrackingTool::Pointer newTool = mitk::OpenIGTLinkTrackingTool::New(); if (name == "") //if no name was given create a default name { std::stringstream defaultName; defaultName << "OpenIGTLinkTool#" << i; name = defaultName.str(); } MITK_INFO << "Added tool " << name << " to tracking device."; newTool->SetToolName(name); InternalAddTool(newTool); } mitk::NavigationTool::Pointer mitk::OpenIGTLinkTrackingDevice::ConstructDefaultOpenIGTLinkTool(std::string name, std::string identifier) { - mitk::DataNode::Pointer newNode = mitk::DataNode::New(); - - newNode->SetName(name); - - mitk::Surface::Pointer myCone = mitk::Surface::New(); - vtkConeSource *vtkData = vtkConeSource::New(); - vtkData->SetAngle(5.0); - vtkData->SetResolution(50); - vtkData->SetHeight(6.0f); - vtkData->SetRadius(2.0f); - vtkData->SetCenter(0.0, 0.0, 0.0); - vtkData->Update(); - myCone->SetVtkPolyData(vtkData->GetOutput()); - vtkData->Delete(); - newNode->SetData(myCone); - mitk::NavigationTool::Pointer newTool = mitk::NavigationTool::New(); - newTool->SetDataNode(newNode); + newTool->GetDataNode()->SetName(name); newTool->SetIdentifier(identifier); newTool->SetTrackingDeviceType(mitk::OpenIGTLinkTypeInformation::GetDeviceDataOpenIGTLinkTrackingDeviceConnection().Line); return newTool; } void mitk::OpenIGTLinkTrackingDevice::UpdateTools() { if (this->GetState() != Tracking) { MITK_ERROR << "Method was called in the wrong state, something went wrong!"; return; } m_IGTLMsgToNavDataFilter->Update(); for (std::size_t j = 0; j < m_IGTLMsgToNavDataFilter->GetNumberOfIndexedOutputs(); ++j) { mitk::NavigationData::Pointer currentNavData = m_IGTLMsgToNavDataFilter->GetOutput(j); const char* name = currentNavData->GetName(); for (std::size_t i = 0; i < m_AllTools.size(); i++) { if (strcmp(m_AllTools.at(i)->GetToolName(), name) == 0) { m_AllTools.at(i)->SetDataValid(currentNavData->IsDataValid()); m_AllTools.at(i)->SetPosition(currentNavData->GetPosition()); m_AllTools.at(i)->SetOrientation(currentNavData->GetOrientation()); m_AllTools.at(i)->SetIGTTimeStamp(currentNavData->GetIGTTimeStamp()); } } } } bool mitk::OpenIGTLinkTrackingDevice::StartTracking() { //check tracking state if (this->GetState() != Ready) { MITK_WARN << "Cannot start tracking, device is not ready!"; return false; } try { m_IGTLDeviceSource->StartCommunication(); //send a message to the server: start tracking stream mitk::IGTLMessageFactory::Pointer msgFactory = m_OpenIGTLinkClient->GetMessageFactory(); std::string message = "STT_TDATA"; //m_OpenIGTLinkClient->SendMessage(msgFactory->CreateInstance(message)); } catch (std::runtime_error &e) { MITK_WARN << "Open IGT Link device retruned an error while starting communication: " << e.what(); return false; } //create internal igtl pipeline m_IGTLMsgToNavDataFilter = mitk::IGTLMessageToNavigationDataFilter::New(); m_IGTLMsgToNavDataFilter->SetNumberOfExpectedOutputs(this->GetToolCount()); m_IGTLMsgToNavDataFilter->ConnectTo(m_IGTLDeviceSource); //connect itk events typedef itk::SimpleMemberCommand< mitk::OpenIGTLinkTrackingDevice > CurCommandType; CurCommandType::Pointer messageReceivedCommand = CurCommandType::New(); messageReceivedCommand->SetCallbackFunction(this, &mitk::OpenIGTLinkTrackingDevice::UpdateTools); m_MessageReceivedObserverTag = m_OpenIGTLinkClient->AddObserver(mitk::MessageReceivedEvent(), messageReceivedCommand); m_OpenIGTLinkClient->EnableNoBufferingMode(true); this->SetState(Tracking); return true; } bool mitk::OpenIGTLinkTrackingDevice::StopTracking() { //check tracking state if (this->GetState() != Tracking) { MITK_WARN << "Cannot open connection, device is already connected!"; return false; } m_OpenIGTLinkClient->RemoveObserver(m_MessageReceivedObserverTag); //disconnect itk events try { m_IGTLDeviceSource->StopCommunication(); } catch (std::runtime_error &e) { MITK_WARN << "Open IGT Link device retruned an error while stopping communication: " << e.what(); return false; } m_OpenIGTLinkClient->EnableNoBufferingMode(false); this->SetState(Ready); return true; } unsigned int mitk::OpenIGTLinkTrackingDevice::GetToolCount() const { return (unsigned int)this->m_AllTools.size(); } mitk::TrackingTool* mitk::OpenIGTLinkTrackingDevice::GetTool(unsigned int toolNumber) const { if (toolNumber >= this->GetToolCount()) return nullptr; else return this->m_AllTools[toolNumber]; } bool mitk::OpenIGTLinkTrackingDevice::OpenConnection() { //check tracking state if (this->GetState() != Setup) { MITK_WARN << "Cannot open connection, device is already connected!"; return false; } try { m_IGTLDeviceSource->Connect(); } catch (std::runtime_error &e) { MITK_WARN << "Open IGT Link device retruned an error while trying to connect: " << e.what(); return false; } this->SetState(Ready); return true; } bool mitk::OpenIGTLinkTrackingDevice::CloseConnection() { //check tracking state if (this->GetState() != Ready) { MITK_WARN << "Cannot close connection, device is in the wrong state!"; return false; } try { m_IGTLDeviceSource->Disconnect(); } catch (std::runtime_error &e) { MITK_WARN << "Open IGT Link device retruned an error while trying to disconnect: " << e.what(); return false; } this->SetState(Setup); return true; } std::vector mitk::OpenIGTLinkTrackingDevice::GetAllTools() { return this->m_AllTools; } mitk::OpenIGTLinkTrackingDevice::TrackingMessageType mitk::OpenIGTLinkTrackingDevice::GetMessageTypeFromString(const char* messageTypeString) { if (strcmp(messageTypeString, "TDATA") == 0) { return mitk::OpenIGTLinkTrackingDevice::TrackingMessageType::TDATA; } else if (strcmp(messageTypeString, "QTDATA") == 0) { return mitk::OpenIGTLinkTrackingDevice::TrackingMessageType::QTDATA; } else if (strcmp(messageTypeString, "TRANSFORM") == 0) { return mitk::OpenIGTLinkTrackingDevice::TrackingMessageType::TRANSFORM; } else { return mitk::OpenIGTLinkTrackingDevice::TrackingMessageType::UNKNOWN; } } diff --git a/Modules/IGT/TrackingDevices/mitkPolhemusTrackingDevice.cpp b/Modules/IGT/TrackingDevices/mitkPolhemusTrackingDevice.cpp index 95ceb41457..7121391bfe 100644 --- a/Modules/IGT/TrackingDevices/mitkPolhemusTrackingDevice.cpp +++ b/Modules/IGT/TrackingDevices/mitkPolhemusTrackingDevice.cpp @@ -1,332 +1,317 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkPolhemusTrackingDevice.h" #include "mitkPolhemusTool.h" #include "mitkIGTConfig.h" #include "mitkIGTTimeStamp.h" #include "mitkIGTHardwareException.h" #include #include #include #include "mitkPolhemusTrackerTypeInformation.h" -#include typedef itk::MutexLockHolder MutexLockHolder; mitk::PolhemusTrackingDevice::PolhemusTrackingDevice() : mitk::TrackingDevice() { //set the type of this tracking device this->m_Data = mitk::PolhemusTrackerTypeInformation::GetDeviceDataPolhemusTrackerLiberty(); this->m_MultiThreader = itk::MultiThreader::New(); m_ThreadID = 0; m_Device = mitk::PolhemusInterface::New(); } mitk::PolhemusTrackingDevice::~PolhemusTrackingDevice() { } bool mitk::PolhemusTrackingDevice::IsDeviceInstalled() { return true; } mitk::TrackingTool* mitk::PolhemusTrackingDevice::AddTool(const char* toolName, int toolPort) { //Only add tool if port isn't already used. for (auto _tool : m_AllTools) { if (_tool->GetToolPort() == toolPort) { MITK_DEBUG << "There is already a tool connected to this port. Returning existing tool"; return _tool; } } mitk::PolhemusTool::Pointer t = mitk::PolhemusTool::New(); t->SetToolName(toolName); t->SetToolPort(toolPort); if (this->InternalAddTool(t) == false) return nullptr; return t.GetPointer(); } bool mitk::PolhemusTrackingDevice::InternalAddTool(PolhemusTool::Pointer tool) { m_AllTools.push_back(tool); return true; } bool mitk::PolhemusTrackingDevice::StartTracking() { bool success = m_Device->StartTracking(); if (success) { mitk::IGTTimeStamp::GetInstance()->Start(this); this->SetState(Tracking); this->m_StopTrackingMutex->Lock(); this->m_StopTracking = false; this->m_StopTrackingMutex->Unlock(); m_ThreadID = m_MultiThreader->SpawnThread(this->ThreadStartTracking, this); // start a new thread that executes the TrackTools() method return true; } else { this->SetState(Ready); mitkThrowException(mitk::IGTHardwareException) << "Error while trying to start the device!"; } return success; } bool mitk::PolhemusTrackingDevice::StopTracking() { m_Device->StopTracking(); return Superclass::StopTracking(); } unsigned int mitk::PolhemusTrackingDevice::GetToolCount() const { return (unsigned int)this->m_AllTools.size(); } mitk::TrackingTool* mitk::PolhemusTrackingDevice::GetTool(unsigned int toolNumber) const { if (toolNumber >= this->GetToolCount()) return nullptr; else return this->m_AllTools[toolNumber]; } bool mitk::PolhemusTrackingDevice::OpenConnection() { //reset everything if (m_Device.IsNull()) { m_Device = mitk::PolhemusInterface::New(); } if (!m_Device->Connect()) //Connect the device, if it fails, throw an error. { MITK_ERROR << "Cannot connect Polhemus device!"; CloseConnection(); return false; } //Ready must be set here, 'cause if tools don't match we need to be able to disconnect. this->SetState(Ready); //check if connected ports of Polhemus matches the tools in the toolStorage. std::vector toolPorts = m_Device->GetToolPorts(); //first, check size. if (this->GetToolCount() != toolPorts.size()) { MITK_ERROR << "Cannot connect device, number of tools in toolstorage doesn't match the number of tools connected to Polhemus device!"; CloseConnection(); return false; } //second, check if toolStorage identifier is included in this port. for (auto _tool : m_AllTools) { if (std::find(toolPorts.begin(), toolPorts.end(), _tool->GetToolPort()) == toolPorts.end()) { MITK_ERROR << "Cannot connect device, tool " << _tool->GetToolPort() << " is not connected to its port."; CloseConnection(); return false; } else { //erase this port to avoid that two tools want to connect to the same port. toolPorts.erase(std::find(toolPorts.begin(), toolPorts.end(), _tool->GetToolPort())); } } m_Device->SetHemisphereTrackingEnabled(m_HemisphereTrackingEnabled); return true; } bool mitk::PolhemusTrackingDevice::CloseConnection() { bool returnValue = true; if (this->GetState() == Setup) return true; returnValue = m_Device->Disconnect(); this->SetState(Setup); return returnValue; } mitk::PolhemusInterface* mitk::PolhemusTrackingDevice::GetDevice() { return m_Device; } std::vector mitk::PolhemusTrackingDevice::GetAllTools() { return this->m_AllTools; } void mitk::PolhemusTrackingDevice::TrackTools() { try { /* lock the TrackingFinishedMutex to signal that the execution rights are now transfered to the tracking thread */ MutexLockHolder trackingFinishedLockHolder(*m_TrackingFinishedMutex); // keep lock until end of scope bool localStopTracking; // Because m_StopTracking is used by two threads, access has to be guarded by a mutex. To minimize thread locking, a local copy is used here this->m_StopTrackingMutex->Lock(); // update the local copy of m_StopTracking localStopTracking = this->m_StopTracking; this->m_StopTrackingMutex->Unlock(); Sleep(100);//Wait a bit until the tracker is ready... while ((this->GetState() == Tracking) && (localStopTracking == false)) { std::vector lastData = this->GetDevice()->GetLastFrame(); if (lastData.size() != m_AllTools.size()) { - MITK_WARN << "Tool count is corrupt. Aborting!"; + MITK_WARN << "Tool count is corrupt. Hardware gives " << lastData.size() << " tools, MITK expects " << m_AllTools.size() << " tools. Aborting!"; } else { std::vector allTools = this->GetAllTools(); for (int i = 0; i < allTools.size(); i++) { mitk::PolhemusTool::Pointer currentTool = allTools.at(i); currentTool->SetDataValid(true); currentTool->SetPosition(lastData.at(i).pos); currentTool->SetOrientation(lastData.at(i).rot); currentTool->SetIGTTimeStamp(mitk::IGTTimeStamp::GetInstance()->GetElapsed()); } } /* Update the local copy of m_StopTracking */ this->m_StopTrackingMutex->Lock(); localStopTracking = m_StopTracking; this->m_StopTrackingMutex->Unlock(); } } catch (...) { this->StopTracking(); mitkThrowException(mitk::IGTHardwareException) << "Error while trying to track tools. Thread stopped."; } } ITK_THREAD_RETURN_TYPE mitk::PolhemusTrackingDevice::ThreadStartTracking(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; if (pInfo == nullptr) { return ITK_THREAD_RETURN_VALUE; } if (pInfo->UserData == nullptr) { return ITK_THREAD_RETURN_VALUE; } PolhemusTrackingDevice *trackingDevice = (PolhemusTrackingDevice*)pInfo->UserData; if (trackingDevice != nullptr) trackingDevice->TrackTools(); return ITK_THREAD_RETURN_VALUE; } bool mitk::PolhemusTrackingDevice::AutoDetectToolsAvailable() { return true; } mitk::NavigationToolStorage::Pointer mitk::PolhemusTrackingDevice::AutoDetectTools() { std::vector singeFrameData = this->m_Device->AutoDetectTools(); MITK_INFO << "Found " << singeFrameData.size() << " tools."; mitk::NavigationToolStorage::Pointer returnValue = mitk::NavigationToolStorage::New(); for each (mitk::PolhemusInterface::trackingData t in singeFrameData) { - mitk::DataNode::Pointer newNode = mitk::DataNode::New(); + mitk::NavigationTool::Pointer newTool = mitk::NavigationTool::New(); + std::stringstream name; name << "Sensor-" << ((int)t.id); - newNode->SetName(name.str()); - - mitk::Surface::Pointer myCone = mitk::Surface::New(); - vtkConeSource *vtkData = vtkConeSource::New(); - vtkData->SetAngle(5.0); - vtkData->SetResolution(50); - vtkData->SetHeight(6.0f); - vtkData->SetRadius(2.0f); - vtkData->SetCenter(0.0, 0.0, 0.0); - vtkData->Update(); - myCone->SetVtkPolyData(vtkData->GetOutput()); - vtkData->Delete(); - newNode->SetData(myCone); - - mitk::NavigationTool::Pointer newTool = mitk::NavigationTool::New(); - newTool->SetDataNode(newNode); + newTool->GetDataNode()->SetName(name.str()); //The identifier defines, which plug is used (e.g. "Sens 2" --> 2). std::stringstream identifier; identifier << ((int)t.id); newTool->SetIdentifier(identifier.str()); newTool->SetTrackingDeviceType(mitk::PolhemusTrackerTypeInformation::GetDeviceDataPolhemusTrackerLiberty().Line); returnValue->AddTool(newTool); } return returnValue; } void mitk::PolhemusTrackingDevice::SetHemisphereTrackingEnabled(bool _HemisphereTrackingEnabled) { //We need to remember if HemisphereTracking is switch on for this reason: /* m_Device->SetHemi works only if the device is connected. However, GUI can also change if it is not connected. In this case, we remember it in the m_HemisphereTrackingEnabled variable. And when connecting, we know, which status is wanted from the user by GUI. */ m_HemisphereTrackingEnabled = _HemisphereTrackingEnabled; this->m_Device->SetHemisphereTrackingEnabled(_HemisphereTrackingEnabled); } void mitk::PolhemusTrackingDevice::ToggleHemisphere(int _tool) { this->m_Device->ToggleHemisphere(_tool); } void mitk::PolhemusTrackingDevice::SetHemisphere(int _tool, mitk::Vector3D _hemisphere) { //If you set a hemisphere vector which is unequal (0|0|0), this means, that there is no hemisphere tracking any more //disable the option, so that it can be reactivated... Also if it is just a single tool. if (_hemisphere.GetNorm() != 0) m_HemisphereTrackingEnabled = false; this->m_Device->SetHemisphere(_tool, _hemisphere); } mitk::Vector3D mitk::PolhemusTrackingDevice::GetHemisphere(int _tool) { return this->m_Device->GetHemisphere(_tool); } bool mitk::PolhemusTrackingDevice::GetHemisphereTrackingEnabled(int _tool) { return this->m_Device->GetHemisphereTrackingEnabled(_tool); } void mitk::PolhemusTrackingDevice::AdjustHemisphere(int _tool) { return this->m_Device->AdjustHemisphere(_tool); } \ No newline at end of file diff --git a/Modules/IGT/files.cmake b/Modules/IGT/files.cmake index 8d9ec0bc9e..f9b80c1194 100644 --- a/Modules/IGT/files.cmake +++ b/Modules/IGT/files.cmake @@ -1,113 +1,115 @@ set(CPP_FILES TestingHelper/mitkNavigationToolStorageTestHelper.cpp Algorithms/mitkNavigationDataDelayFilter.cpp Algorithms/mitkNavigationDataDisplacementFilter.cpp Algorithms/mitkNavigationDataEvaluationFilter.cpp Algorithms/mitkNavigationDataLandmarkTransformFilter.cpp + Algorithms/mitkNavigationDataPassThroughFilter.cpp Algorithms/mitkNavigationDataReferenceTransformFilter.cpp Algorithms/mitkNavigationDataSmoothingFilter.cpp Algorithms/mitkNavigationDataToMessageFilter.cpp Algorithms/mitkNavigationDataToNavigationDataFilter.cpp Algorithms/mitkNavigationDataToPointSetFilter.cpp Algorithms/mitkNavigationDataTransformFilter.cpp Algorithms/mitkNavigationDataToIGTLMessageFilter.cpp Algorithms/mitkIGTLMessageToNavigationDataFilter.cpp + Algorithms/mitkNeedleProjectionFilter.cpp Algorithms/mitkPivotCalibration.cpp Common/mitkIGTTimeStamp.cpp Common/mitkSerialCommunication.cpp DataManagement/mitkNavigationDataSource.cpp DataManagement/mitkNavigationTool.cpp DataManagement/mitkNavigationToolStorage.cpp DataManagement/mitkTrackingDeviceSourceConfigurator.cpp DataManagement/mitkTrackingDeviceSource.cpp DataManagement/mitkTrackingDeviceTypeCollection.cpp ExceptionHandling/mitkIGTException.cpp ExceptionHandling/mitkIGTHardwareException.cpp ExceptionHandling/mitkIGTIOException.cpp IO/mitkNavigationDataPlayer.cpp IO/mitkNavigationDataPlayerBase.cpp IO/mitkNavigationDataRecorder.cpp IO/mitkNavigationDataRecorderDeprecated.cpp IO/mitkNavigationDataSequentialPlayer.cpp IO/mitkNavigationToolReader.cpp IO/mitkNavigationToolStorageSerializer.cpp IO/mitkNavigationToolStorageDeserializer.cpp IO/mitkNavigationToolWriter.cpp IO/mitkNavigationDataReaderInterface.cpp Rendering/mitkCameraVisualization.cpp Rendering/mitkNavigationDataObjectVisualizationFilter.cpp Rendering/mitkNavigationDataSliceVisualization.cpp TrackingDevices/mitkClaronTool.cpp TrackingDevices/mitkClaronTrackingDevice.cpp TrackingDevices/mitkInternalTrackingTool.cpp TrackingDevices/mitkNDIPassiveTool.cpp TrackingDevices/mitkNDIProtocol.cpp TrackingDevices/mitkNDITrackingDevice.cpp TrackingDevices/mitkTrackingDevice.cpp TrackingDevices/mitkTrackingTool.cpp TrackingDevices/mitkTrackingVolumeGenerator.cpp TrackingDevices/mitkVirtualTrackingDevice.cpp TrackingDevices/mitkVirtualTrackingTool.cpp TrackingDevices/mitkOptitrackErrorMessages.cpp TrackingDevices/mitkOptitrackTrackingDevice.cpp TrackingDevices/mitkOptitrackTrackingTool.cpp TrackingDevices/mitkOpenIGTLinkTrackingDevice.cpp TrackingDevices/mitkOpenIGTLinkTrackingTool.cpp TrackingDevices/mitkNDIAuroraTypeInformation.cpp TrackingDevices/mitkNDIPolarisTypeInformation.cpp TrackingDevices/mitkNPOptitrackTrackingTypeInformation.cpp TrackingDevices/mitkVirtualTrackerTypeInformation.cpp TrackingDevices/mitkMicronTrackerTypeInformation.cpp TrackingDevices/mitkOpenIGTLinkTypeInformation.cpp TrackingDevices/mitkUnspecifiedTrackingTypeInformation.cpp # TrackingDevices/mitkPolhemusTrackingDevice.cpp # TrackingDevices/mitkPolhemusTool.cpp # TrackingDevices/mitkPolhemusTrackerTypeInformation.cpp ) set(H_FILES DataManagement/mitkTrackingDeviceTypeInformation.h Common/mitkTrackingTypes.h ) set(RESOURCE_FILES ClaronMicron.stl IntuitiveDaVinci.stl NDIAurora.stl NDIAurora_Dome.stl NDIAuroraCompactFG_Dome.stl NDIAuroraPlanarFG_Dome.stl NDIAuroraTabletopFG_Dome.stl NDIAuroraTabletopFG_Prototype_Dome.stl NDIPolarisOldModel.stl NDIPolarisSpectra.stl NDIPolarisSpectraExtendedPyramid.stl NDIPolarisVicra.stl ) if(MITK_USE_MICRON_TRACKER) set(CPP_FILES ${CPP_FILES} TrackingDevices/mitkClaronInterface.cpp) else() set(CPP_FILES ${CPP_FILES} TrackingDevices/mitkClaronInterfaceStub.cpp) endif(MITK_USE_MICRON_TRACKER) if(MITK_USE_MICROBIRD_TRACKER) set(CPP_FILES ${CPP_FILES} TrackingDevices/mitkMicroBirdTrackingDevice.cpp) endif(MITK_USE_MICROBIRD_TRACKER) if(MITK_USE_POLHEMUS_TRACKER) set(CPP_FILES ${CPP_FILES} TrackingDevices/mitkPolhemusInterface.cpp TrackingDevices/mitkPolhemusTrackingDevice.cpp TrackingDevices/mitkPolhemusTool.cpp TrackingDevices/mitkPolhemusTrackerTypeInformation.cpp ) endif(MITK_USE_POLHEMUS_TRACKER) diff --git a/Modules/IGTUI/Qmitk/QmitkAbstractTrackingDeviceWidget.h b/Modules/IGTUI/Qmitk/QmitkAbstractTrackingDeviceWidget.h index a55b543335..74f1aeaec6 100644 --- a/Modules/IGTUI/Qmitk/QmitkAbstractTrackingDeviceWidget.h +++ b/Modules/IGTUI/Qmitk/QmitkAbstractTrackingDeviceWidget.h @@ -1,175 +1,175 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkAbstractTrackingDeviceWidget_H #define QmitkAbstractTrackingDeviceWidget_H #include #include "MitkIGTUIExports.h" #include "mitkTrackingDevice.h" #include #include "QmitkTrackingDeviceConfigurationWidgetConnectionWorker.h" //itk headers /** Documentation: * \brief Abstract class to configure a tracking device. * Inherited widgets should be registered in the Microservice (TrackingDeviceCollectionWidget), * If done so, they will be included in the QmitkTrackingDeviceConfigurationWidget of the Tracking Toolbox. * * - Each implementation of this class must have a method to get a TrackingDevice * - Each implementation handles itself, if a new TrackingDevice needs to be constructed. * Attention: In former MITK versions, there was no pure virtual GetTrackingDevice function but a pure virtual ConstructTrackingDevice function. * You can simply rename these, but you should give it a thought, if each time "Construct" was called, a new device needs to be constructed, * or if you can store your TrackingDevice in a member variable and return this. Up to you. * - Please create the UI elements in a function like CreateQtPartControl (e.g. see QmitkVitrualTrackerWidget). * - You might want to use own buttons etc., please connect them in a private CreateConnections (e.g. see QmitkVitrualTrackerWidget). * - Due to initialization of qt during autoloading of the IGT module, you constructor should be as slim as possible and only contain a call * of the QmitkAbstractTrackingDeviceWidget constructor and simple variable initialization. * - For the initialization, you must write an Iniltialize() function, which must include a call of InitializeSuperclassWidget() and should contain * calls of your private CreateConnections / CreateQtPartControl (if you implemented these). * - For integration into the TrackingToolbox, a clone function is needed. Here, a new widget should be created, Initialize() needs to be called, * and all settings of your widget should be copied. * * You can Load and Store previous settings of your GUI elements (e.g. see QmitkNDIPolarisWidget). * Also, you can add an output textbox to your widget to display information about your device status. It's optional, see e.g. QmitkNDIAuroraWidget. * Some Devices need the information if drivers are installed on your computer. If this is necessary for your device to avoid crashes, * please override IsDeviceInstalled. The default return value is true otherwise. * * \ingroup IGTUI */ class MITKIGTUI_EXPORT QmitkAbstractTrackingDeviceWidget : public QWidget { Q_OBJECT public: static const std::string VIEW_ID; QmitkAbstractTrackingDeviceWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); ~QmitkAbstractTrackingDeviceWidget() override; /** * \brief Return pointer to copy of the object. * Internally use of QmitkUSAbstractCustomWidget::Clone() with additionaly * setting an internal flag that the object was really cloned. */ QmitkAbstractTrackingDeviceWidget* CloneForQt(QWidget* parent = 0) const; /** * \brief Subclass must implement this method to return a pointer to a copy of the object. * Please don't forget to call InitializeSuperclassWidget(), CreateQtPartControl and optionally CreateConnections during this function. */ virtual void Initialize() = 0; bool IsInitialized() const { return isInitialized; } signals: void ConnectionTested(bool connected, QString output); protected slots: void TestConnectionFinished(bool connected, QString output); /* @brief This method is called when the user presses the button "test connection". The method will then create a temporary tracking device, * try to open a connection and start tracking. The user can see the result of the connection test on the small output window. */ void TestConnection(); private: /// \brief Creation of the connections. You might implement the same function again in your inherited widget. void CreateConnections(); protected: PERSISTENCE_GET_SERVICE_METHOD_MACRO void InitializeSuperclassWidget(); QmitkTrackingDeviceConfigurationWidgetConnectionWorker* m_TestConnectionWorker; QThread* m_TestConnectionWorkerThread; /** * \brief Subclass must implement this method to return a pointer to a copy of the object. * Please don't forget to call Initialize() during this function and copy all of your settings. */ virtual QmitkAbstractTrackingDeviceWidget* Clone(QWidget* parent = 0) const = 0; public: /** * \brief Optional method to add output to a small screen in the trackingToolbox (see QmitkNDIPolarisWidget) */ virtual void ResetOutput() {} /** * \brief Optional method to add output to a small screen in the trackingToolbox (see QmitkNDIPolarisWidget) */ virtual void AddOutput(std::string) {} virtual mitk::TrackingDevice::Pointer GetTrackingDevice() = 0; /** * \brief Optional method to store and load settings of your widget (see QmitkNDIPolarisWidget) */ virtual void StoreUISettings() {} /** * \brief Optional method to store and load settings of your widget (see QmitkNDIPolarisWidget) */ virtual void LoadUISettings() {} /** * \brief Optional method to investigate if drivers etc for your device are installed. * The default value is "true" as most devices don't need this information. * Others however migth crash, and for these you might implement this function (see QmitkMicronTrackerWidget) */ virtual bool IsDeviceInstalled() { return true; } /** * \brief This function is called, when in the TrackingToolboxView "Connect" was clicked and the device is successful connected. * Can e.g. be used to activate options of a tracking device only when it is connected. */ - virtual void OnConnected(bool _success) {}; + virtual void OnConnected(bool) {} /** * \brief This function is called, when in the TrackingToolboxView "Disconnect" was clicked and the device is successful disconnected. * Can e.g. be used to activate/disactivate options of a tracking device. */ - virtual void OnDisconnected(bool _success) {}; + virtual void OnDisconnected(bool) {} /** * \brief This function is called, when in the TrackingToolboxView "Start Tracking" was clicked and the device successfully started tracking. * Can e.g. be used to activate options of a tracking device only when tracking is started. */ - virtual void OnStartTracking(bool _success){}; + virtual void OnStartTracking(bool) {} /** * \brief This function is called, when in the TrackingToolboxView "Stop Tracking" was clicked and the device successful stopped tracking. * Can e.g. be used to activate/disactivate options when device is not tracking. */ - virtual void OnStopTracking(bool _success) {}; + virtual void OnStopTracking(bool) {} /** * \brief This function is called, when anything in the ToolStorage changed, e.g. AddTool or EditTool. * ServiceListener is connected in the QmitkMITKIGTTrackingToolboxView. */ - virtual void OnToolStorageChanged() {}; + virtual void OnToolStorageChanged() {} std::string m_ErrorMessage; ///< current problem description private: /** * \warning Don't touch this variable if you don't know what you are doing! */ bool isInitialized; }; #endif diff --git a/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidget.cpp b/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidget.cpp index ce2de57c70..d4f603c349 100644 --- a/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidget.cpp @@ -1,287 +1,300 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkInteractiveTransformationWidget.h" // mitk includes #include "mitkRenderingManager.h" +#include "mitkBaseRenderer.h" #include "mitkNavigationData.h" // vtk includes #include "vtkMatrix4x4.h" #include "vtkLinearTransform.h" const std::string QmitkInteractiveTransformationWidget::VIEW_ID = "org.mitk.views.interactivetransformationwidget"; QmitkInteractiveTransformationWidget::QmitkInteractiveTransformationWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f), m_Controls(nullptr), m_Geometry(nullptr), m_ResetGeometry(nullptr) { CreateQtPartControl(this); CreateConnections(); - m_TranslationVector.Fill(0.0f); - m_RotateSliderPos.Fill(0.0f); + + m_ResetGeometry = mitk::Geometry3D::New(); + + + this->setWindowTitle("Edit Tool Tip and Tool Orientation"); } QmitkInteractiveTransformationWidget::~QmitkInteractiveTransformationWidget() { } void QmitkInteractiveTransformationWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkInteractiveTransformationWidgetControls; m_Controls->setupUi(parent); } } void QmitkInteractiveTransformationWidget::CreateConnections() { - if ( m_Controls ) + if (m_Controls) { // translations - connect( (QObject*)(m_Controls->m_XTransSlider), SIGNAL(valueChanged(int)), this, SLOT(OnXTranslationValueChanged(int)) ); - connect( (QObject*)(m_Controls->m_XTransSpinBox), SIGNAL(valueChanged(int)), this, SLOT(OnXTranslationValueChanged(int)) ); - connect( (QObject*)(m_Controls->m_YTransSlider), SIGNAL(valueChanged(int)), this, SLOT(OnYTranslationValueChanged(int)) ); - connect( (QObject*)(m_Controls->m_YTransSpinBox), SIGNAL(valueChanged(int)), this, SLOT(OnYTranslationValueChanged(int)) ); - connect( (QObject*)(m_Controls->m_ZTransSlider), SIGNAL(valueChanged(int)), this, SLOT(OnZTranslationValueChanged(int)) ); - connect( (QObject*)(m_Controls->m_ZTransSpinBox), SIGNAL(valueChanged(int)), this, SLOT(OnZTranslationValueChanged(int)) ); + connect(m_Controls->m_XTransSpinBox, static_cast(&QDoubleSpinBox::valueChanged), this, &QmitkInteractiveTransformationWidget::OnXTranslationValueChanged); + connect(m_Controls->m_XTransSlider, &QSlider::valueChanged, this, &QmitkInteractiveTransformationWidget::OnXTranslationValueChanged); + + connect(m_Controls->m_YTransSpinBox, static_cast(&QDoubleSpinBox::valueChanged), this, &QmitkInteractiveTransformationWidget::OnYTranslationValueChanged); + connect(m_Controls->m_YTransSlider, &QSlider::valueChanged, this, &QmitkInteractiveTransformationWidget::OnYTranslationValueChanged); + + connect(m_Controls->m_ZTransSpinBox, static_cast(&QDoubleSpinBox::valueChanged), this, &QmitkInteractiveTransformationWidget::OnZTranslationValueChanged); + connect(m_Controls->m_ZTransSlider, &QSlider::valueChanged, this, &QmitkInteractiveTransformationWidget::OnZTranslationValueChanged); // rotations - connect( (QObject*)(m_Controls->m_XRotSlider), SIGNAL(valueChanged(int)), this, SLOT(OnXRotationValueChanged(int)) ); - connect( (QObject*)(m_Controls->m_XRotSpinBox), SIGNAL(valueChanged(int)), this, SLOT(OnXRotationValueChanged(int)) ); - connect( (QObject*)(m_Controls->m_YRotSlider), SIGNAL(valueChanged(int)), this, SLOT(OnYRotationValueChanged(int)) ); - connect( (QObject*)(m_Controls->m_YRotSpinBox), SIGNAL(valueChanged(int)), this, SLOT(OnYRotationValueChanged(int)) ); - connect( (QObject*)(m_Controls->m_ZRotSlider), SIGNAL(valueChanged(int)), this, SLOT(OnZRotationValueChanged(int)) ); - connect( (QObject*)(m_Controls->m_ZRotSpinBox), SIGNAL(valueChanged(int)), this, SLOT(OnZRotationValueChanged(int)) ); - - connect( (QObject*)(m_Controls->m_ResetPB), SIGNAL(clicked()), this, SLOT(OnResetGeometry()) ); - connect( (QObject*)(m_Controls->m_UseManipulatedToolTipPB), SIGNAL(clicked()), this, SLOT(OnApplyManipulatedToolTip()) ); + connect(m_Controls->m_XRotSpinBox, static_cast(&QDoubleSpinBox::valueChanged), this, &QmitkInteractiveTransformationWidget::OnXRotationValueChanged); + connect(m_Controls->m_XRotSlider, &QSlider::valueChanged, this, &QmitkInteractiveTransformationWidget::OnXRotationValueChanged); + + connect(m_Controls->m_YRotSpinBox, static_cast(&QDoubleSpinBox::valueChanged), this, &QmitkInteractiveTransformationWidget::OnYRotationValueChanged); + connect(m_Controls->m_YRotSlider, &QSlider::valueChanged, this, &QmitkInteractiveTransformationWidget::OnYRotationValueChanged); + + connect(m_Controls->m_ZRotSpinBox, static_cast(&QDoubleSpinBox::valueChanged), this, &QmitkInteractiveTransformationWidget::OnZRotationValueChanged); + connect(m_Controls->m_ZRotSlider, &QSlider::valueChanged, this, &QmitkInteractiveTransformationWidget::OnZRotationValueChanged); + + connect((QObject*)(m_Controls->m_ResetPB), SIGNAL(clicked()), this, SLOT(OnResetGeometryToIdentity())); + connect((QObject*)(m_Controls->m_RevertChanges), SIGNAL(clicked()), this, SLOT(OnRevertChanges())); + connect((QObject*)(m_Controls->m_UseManipulatedToolTipPB), SIGNAL(clicked()), this, SLOT(OnApplyManipulatedToolTip())); + connect((QObject*)(m_Controls->m_Cancel), SIGNAL(clicked()), this, SLOT(OnCancel())); } } -void QmitkInteractiveTransformationWidget::SetGeometry( mitk::BaseGeometry::Pointer geometry, mitk::BaseGeometry::Pointer defaultValues ) +void QmitkInteractiveTransformationWidget::SetToolToEdit(const mitk::NavigationTool::Pointer _tool) { - m_Geometry = geometry; - m_ResetGeometry = geometry->Clone(); - - //set default values - if (defaultValues.IsNotNull()) - { - //first: some conversion - mitk::NavigationData::Pointer transformConversionHelper = mitk::NavigationData::New(defaultValues->GetIndexToWorldTransform()); - double eulerAlphaDegrees = transformConversionHelper->GetOrientation().rotation_euler_angles()[0] / vnl_math::pi * 180; - double eulerBetaDegrees = transformConversionHelper->GetOrientation().rotation_euler_angles()[1] / vnl_math::pi * 180; - double eulerGammaDegrees = transformConversionHelper->GetOrientation().rotation_euler_angles()[2] / vnl_math::pi * 180; - - //set translation - OnXTranslationValueChanged(defaultValues->GetIndexToWorldTransform()->GetOffset()[0]); - OnYTranslationValueChanged(defaultValues->GetIndexToWorldTransform()->GetOffset()[1]); - OnZTranslationValueChanged(defaultValues->GetIndexToWorldTransform()->GetOffset()[2]); - - //set rotation - OnXRotationValueChanged(eulerAlphaDegrees); - OnYRotationValueChanged(eulerBetaDegrees); - OnZRotationValueChanged(eulerGammaDegrees); - } - else - { - //reset everything - OnXTranslationValueChanged(0); - OnYTranslationValueChanged(0); - OnZTranslationValueChanged(0); - OnXRotationValueChanged(0); - OnYRotationValueChanged(0); - OnZRotationValueChanged(0); - } + //If there is already a tool, remove it's node first. + if (m_ToolToEdit) + mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetDataStorage() + ->Remove(m_ToolToEdit->GetDataNode()); + + m_ToolToEdit = _tool->Clone(); + mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetDataStorage() + ->Add(m_ToolToEdit->GetDataNode()); + m_ToolToEdit->GetDataNode()->SetName("Tool Tip to be edited"); + + //change color to red + m_ToolToEdit->GetDataNode()->SetProperty("color", mitk::ColorProperty::New(1, 0, 0)); + + //use the set-fuction via vtk matrix, 'cause this garantees a deep copy and not just sharing a pointer. + m_Geometry = m_ToolToEdit->GetDataNode()->GetData()->GetGeometry(); + m_ResetGeometry->SetIndexToWorldTransformByVtkMatrix(m_Geometry->GetVtkMatrix()); //Remember the original values to be able to reset and abort everything } -mitk::BaseGeometry::Pointer QmitkInteractiveTransformationWidget::GetGeometry() +void QmitkInteractiveTransformationWidget::SetDefaultOffset(const mitk::Point3D _defaultValues) { - return m_Geometry; + m_Geometry->SetOrigin(_defaultValues); + m_ResetGeometry->SetOrigin(_defaultValues); //Remember the original values to be able to reset and abort everything + SetValuesToGUI(m_Geometry->GetIndexToWorldTransform()); } +void QmitkInteractiveTransformationWidget::SetDefaultRotation(const mitk::Quaternion _defaultValues) +{ + // Conversion to navigation data / transform + mitk::NavigationData::Pointer rotationTransform = mitk::NavigationData::New(m_Geometry->GetIndexToWorldTransform()); + rotationTransform->SetOrientation(_defaultValues); + m_Geometry->SetIndexToWorldTransform(rotationTransform->GetAffineTransform3D()); + //For ResetGeometry, use the set-fuction via vtk matrix, 'cause this garantees a deep copy and not just sharing a pointer. + m_ResetGeometry->SetIndexToWorldTransformByVtkMatrix(m_Geometry->GetVtkMatrix()); //Remember the original values to be able to reset and abort everything + SetValuesToGUI(m_Geometry->GetIndexToWorldTransform()); +} +void QmitkInteractiveTransformationWidget::SetValuesToGUI(const mitk::AffineTransform3D::Pointer _defaultValues) +{ + //Set toolTip values in gui + m_Controls->m_XTransSlider->setValue(_defaultValues->GetOffset()[0]); + m_Controls->m_YTransSlider->setValue(_defaultValues->GetOffset()[1]); + m_Controls->m_ZTransSlider->setValue(_defaultValues->GetOffset()[2]); -///////////////////////////////////////////////////////////////////////////////////////////// -// Section to allow interactive positioning of the moving surface -///////////////////////////////////////////////////////////////////////////////////////////// + //first: some conversion + mitk::NavigationData::Pointer transformConversionHelper = mitk::NavigationData::New(_defaultValues); + double eulerAlphaDegrees = transformConversionHelper->GetOrientation().rotation_euler_angles()[0] / vnl_math::pi * 180; + double eulerBetaDegrees = transformConversionHelper->GetOrientation().rotation_euler_angles()[1] / vnl_math::pi * 180; + double eulerGammaDegrees = transformConversionHelper->GetOrientation().rotation_euler_angles()[2] / vnl_math::pi * 180; -void QmitkInteractiveTransformationWidget::OnXTranslationValueChanged( int v ) -{ - mitk::Vector3D translationParams; - translationParams[0] = v; - translationParams[1] = m_Controls->m_YTransSlider->value(); - translationParams[2] = m_Controls->m_ZTransSlider->value(); - SetSliderX(v); - this->Translate(translationParams); -} + m_Controls->m_XRotSpinBox->setValue(eulerAlphaDegrees); + m_Controls->m_YRotSpinBox->setValue(eulerBetaDegrees); + m_Controls->m_ZRotSpinBox->setValue(eulerGammaDegrees); -void QmitkInteractiveTransformationWidget::SetSliderX(int v) -{ - m_Controls->m_XTransSlider->setValue(v); - m_Controls->m_XTransSpinBox->setValue(v); + //Update view + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } -void QmitkInteractiveTransformationWidget::OnYTranslationValueChanged( int v ) +void QmitkInteractiveTransformationWidget::SetSynchronizedVauesToSliderAndSpinbox(QDoubleSpinBox* _spinbox, QSlider* _slider, double _value) { - mitk::Vector3D translationParams; - translationParams[0] = m_Controls->m_XTransSlider->value(); - translationParams[1] = v; - translationParams[2] = m_Controls->m_ZTransSlider->value(); - SetSliderY(v); - this->Translate(translationParams); +//block signals to avoid loop between slider and spinbox. Unblock at the end of the function! + _spinbox->blockSignals(true); + _slider->blockSignals(true); + _spinbox->setValue(_value); + _slider->setValue(_value); +//unblock signals. See above, don't remove this line. Unblock at the end of the function! + _spinbox->blockSignals(false);// + _slider->blockSignals(false);// } -void QmitkInteractiveTransformationWidget::SetSliderY(int v) +void QmitkInteractiveTransformationWidget::OnXTranslationValueChanged(double v) { - m_Controls->m_YTransSlider->setValue(v); - m_Controls->m_YTransSpinBox->setValue(v); -} + //Set values to member variable + mitk::Point3D translationParams = m_Geometry->GetOrigin(); + translationParams[0] = v; + m_Geometry->SetOrigin(translationParams); + + SetSynchronizedVauesToSliderAndSpinbox(m_Controls->m_XTransSpinBox, m_Controls->m_XTransSlider, v); + + //Update view + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); -void QmitkInteractiveTransformationWidget::OnZTranslationValueChanged( int v ) -{ - mitk::Vector3D translationParams; - translationParams[0] = m_Controls->m_XTransSlider->value(); - translationParams[1] = m_Controls->m_YTransSlider->value(); - translationParams[2] = v; - SetSliderZ(v); - this->Translate(translationParams); } -void QmitkInteractiveTransformationWidget::SetSliderZ(int v) +void QmitkInteractiveTransformationWidget::OnYTranslationValueChanged(double v) { - m_Controls->m_ZTransSlider->setValue(v); - m_Controls->m_ZTransSpinBox->setValue(v); + //Set values to member variable + mitk::Point3D translationParams = m_Geometry->GetOrigin(); + translationParams[1] = v; + m_Geometry->SetOrigin(translationParams); + + SetSynchronizedVauesToSliderAndSpinbox(m_Controls->m_YTransSpinBox, m_Controls->m_YTransSlider, v); + + //Update view + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } -void QmitkInteractiveTransformationWidget::Translate( mitk::Vector3D translateVector) +void QmitkInteractiveTransformationWidget::OnZTranslationValueChanged(double v) { - mitk::Vector3D translateVec; - - // transform the translation vector - translateVec[0] = translateVector[0] - m_TranslationVector[0]; - translateVec[1] = translateVector[1] - m_TranslationVector[1]; - translateVec[2] = translateVector[2] - m_TranslationVector[2]; + //Set values to member variable + mitk::Point3D translationParams = m_Geometry->GetOrigin(); + translationParams[2] = v; + m_Geometry->SetOrigin(translationParams); - // set the new translation vector to member variable - m_TranslationVector[0] = translateVector[0]; - m_TranslationVector[1] = translateVector[1]; - m_TranslationVector[2] = translateVector[2]; + SetSynchronizedVauesToSliderAndSpinbox(m_Controls->m_ZTransSpinBox, m_Controls->m_ZTransSlider, v); - m_Geometry->Translate( translateVec ); - qApp->processEvents(); + //Update view mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } -void QmitkInteractiveTransformationWidget::OnXRotationValueChanged( int v ) +void QmitkInteractiveTransformationWidget::OnXRotationValueChanged(double v) { mitk::Vector3D rotationParams; rotationParams[0] = v; - rotationParams[1] = m_Controls->m_YRotSlider->value(); - rotationParams[2] = m_Controls->m_ZRotSlider->value(); + rotationParams[1] = m_Controls->m_YRotSpinBox->value(); + rotationParams[2] = m_Controls->m_ZRotSpinBox->value(); - m_Controls->m_XRotSlider->setValue(v); - m_Controls->m_XRotSpinBox->setValue(v); + SetSynchronizedVauesToSliderAndSpinbox(m_Controls->m_XRotSpinBox, m_Controls->m_XRotSlider, v); this->Rotate(rotationParams); } -void QmitkInteractiveTransformationWidget::OnYRotationValueChanged( int v ) +void QmitkInteractiveTransformationWidget::OnYRotationValueChanged(double v) { mitk::Vector3D rotationParams; - rotationParams[0] = m_Controls->m_XRotSlider->value(); + rotationParams[0] = m_Controls->m_XRotSpinBox->value(); rotationParams[1] = v; - rotationParams[2] = m_Controls->m_ZRotSlider->value(); + rotationParams[2] = m_Controls->m_ZRotSpinBox->value(); - m_Controls->m_YRotSlider->setValue(v); - m_Controls->m_YRotSpinBox->setValue(v); + SetSynchronizedVauesToSliderAndSpinbox(m_Controls->m_YRotSpinBox, m_Controls->m_YRotSlider, v); this->Rotate(rotationParams); } -void QmitkInteractiveTransformationWidget::OnZRotationValueChanged( int v ) +void QmitkInteractiveTransformationWidget::OnZRotationValueChanged(double v) { mitk::Vector3D rotationParams; - rotationParams[0]=m_Controls->m_XRotSlider->value(); - rotationParams[1]=m_Controls->m_YRotSlider->value(); - rotationParams[2]=v; - m_Controls->m_ZRotSlider->setValue(v); - m_Controls->m_ZRotSpinBox->setValue(v); + rotationParams[0] = m_Controls->m_XRotSpinBox->value(); + rotationParams[1] = m_Controls->m_YRotSpinBox->value(); + rotationParams[2] = v; + + SetSynchronizedVauesToSliderAndSpinbox(m_Controls->m_ZRotSpinBox, m_Controls->m_ZRotSlider, v); this->Rotate(rotationParams); } void QmitkInteractiveTransformationWidget::Rotate(mitk::Vector3D rotateVector) { //0: from degrees to radians double radianX = rotateVector[0] * vnl_math::pi / 180; double radianY = rotateVector[1] * vnl_math::pi / 180; double radianZ = rotateVector[2] * vnl_math::pi / 180; //1: from euler angles to quaternion - mitk::Quaternion rotation(radianX,radianY,radianZ); + mitk::Quaternion rotation(radianX, radianY, radianZ); //2: Conversion to navigation data / transform - mitk::NavigationData::Pointer rotationTransform = mitk::NavigationData::New(); + mitk::NavigationData::Pointer rotationTransform = mitk::NavigationData::New(m_Geometry->GetIndexToWorldTransform()); rotationTransform->SetOrientation(rotation); - //3: Apply transform + m_Geometry->SetIndexToWorldTransform(rotationTransform->GetAffineTransform3D()); - //also remember old transform, but without rotation, because rotation is completely stored in the sliders - mitk::NavigationData::Pointer oldTransform = mitk::NavigationData::New(m_Geometry->GetIndexToWorldTransform()); - mitk::Quaternion identity(0,0,0,1); - oldTransform->SetOrientation(identity); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); +} - //compose old transform with the new one - rotationTransform->Compose(oldTransform); +void QmitkInteractiveTransformationWidget::OnResetGeometryToIdentity() +{ + // reset the input to its initial state. + m_Geometry->SetIdentity(); - //and apply it... - m_Geometry->SetIndexToWorldTransform(rotationTransform->GetAffineTransform3D()); - qApp->processEvents(); + //Update Sliders + this->SetValuesToGUI(m_Geometry->GetIndexToWorldTransform()); + //Refresh view mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } -void QmitkInteractiveTransformationWidget::OnResetGeometry() +void QmitkInteractiveTransformationWidget::OnRevertChanges() { - m_Controls->m_XRotSlider->setValue(0); - m_Controls->m_YRotSlider->setValue(0); - m_Controls->m_ZRotSlider->setValue(0); - m_Controls->m_XRotSpinBox->setValue(0); - m_Controls->m_YRotSpinBox->setValue(0); - m_Controls->m_ZRotSpinBox->setValue(0); - - m_Controls->m_XTransSlider->setValue(0); - m_Controls->m_YTransSlider->setValue(0); - m_Controls->m_ZTransSlider->setValue(0); - m_Controls->m_XTransSpinBox->setValue(0); - m_Controls->m_YTransSpinBox->setValue(0); - m_Controls->m_ZTransSpinBox->setValue(0); - qApp->processEvents(); - // reset the input to its initial state. - m_Geometry->SetIdentity(); - m_Geometry->Compose(m_ResetGeometry->GetVtkTransform()->GetMatrix()); + m_Geometry->SetIndexToWorldTransformByVtkMatrix(m_ResetGeometry->GetVtkMatrix()); + + //Update Sliders + this->SetValuesToGUI(m_Geometry->GetIndexToWorldTransform()); + //Refresh view mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkInteractiveTransformationWidget::OnApplyManipulatedToolTip() { - emit ApplyManipulatedToolTip(); + mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetDataStorage() + ->Remove(m_ToolToEdit->GetDataNode()); + + mitk::AffineTransform3D::Pointer toolTip = m_Geometry->GetIndexToWorldTransform(); + emit EditToolTipFinished(toolTip); + this->close(); +} + +void QmitkInteractiveTransformationWidget::reject() +{ + OnCancel(); } + +void QmitkInteractiveTransformationWidget::OnCancel() +{ + QDialog::reject(); + + mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetDataStorage() + ->Remove(m_ToolToEdit->GetDataNode()); + + emit EditToolTipFinished(nullptr); +} \ No newline at end of file diff --git a/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidget.h b/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidget.h index f4a93e5f95..bbab6d819d 100644 --- a/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidget.h +++ b/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidget.h @@ -1,94 +1,102 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkInteractiveTransformationWidget_H #define QmitkInteractiveTransformationWidget_H //QT headers -#include +#include //Mitk headers #include "MitkIGTUIExports.h" #include "mitkVector.h" #include "mitkGeometry3D.h" +#include "mitkNavigationTool.h" //ui header #include "ui_QmitkInteractiveTransformationWidgetControls.h" /** Documentation: * \brief An object of this class offers an UI to create a widget to access the advance tool creation options. * * * \ingroup IGTUI */ -class MITKIGTUI_EXPORT QmitkInteractiveTransformationWidget : public QWidget +class MITKIGTUI_EXPORT QmitkInteractiveTransformationWidget : public QDialog { Q_OBJECT public: static const std::string VIEW_ID; QmitkInteractiveTransformationWidget(QWidget* parent = nullptr, Qt::WindowFlags f = nullptr); ~QmitkInteractiveTransformationWidget() override; - /** Sets the geometry which will be modified by this widget. Default values may be - * provided by the second variable. These values will be applied to the geometry - * in the beginning and the UI will also hold these values. + /** This tool will be copied to m_ToolToEdit. It will not be changed. + To apply any changes made by this widget, you will need to connect to the signal + EditToolTipFinished(mitk::AffineTransform3D::Pointer toolTip) and set this transfrom + as calibrated tool tip. + We do not directly modify the tool to allow to cancel/exit this widget without doing + any harm. */ - void SetGeometry(mitk::BaseGeometry::Pointer geometry, mitk::BaseGeometry::Pointer defaultValues = nullptr); + void SetToolToEdit(const mitk::NavigationTool::Pointer _tool); - mitk::BaseGeometry::Pointer GetGeometry(); + /** The sliders and spinboxes will be set to these values. + When clicking "Revert Changes", sliders will be reseted to these values. + */ + void SetDefaultOffset(const mitk::Point3D _defaultValues); + void SetDefaultRotation(const mitk::Quaternion _defaultValues); protected slots: - void OnZTranslationValueChanged( int v ); - void OnYTranslationValueChanged( int v ); - void OnXTranslationValueChanged( int v ); - void OnZRotationValueChanged( int v ); - void OnYRotationValueChanged( int v ); - void OnXRotationValueChanged( int v ); - void OnResetGeometry(); + void OnZTranslationValueChanged( double v ); + void OnYTranslationValueChanged(double v); + void OnXTranslationValueChanged(double v); + void OnZRotationValueChanged(double v); + void OnYRotationValueChanged(double v); + void OnXRotationValueChanged(double v); + void OnResetGeometryToIdentity(); + void OnRevertChanges(); void OnApplyManipulatedToolTip(); + void OnCancel(); signals: - void ApplyManipulatedToolTip(); + void EditToolTipFinished(mitk::AffineTransform3D::Pointer toolTip); protected: + void reject(); + virtual void CreateConnections(); virtual void CreateQtPartControl(QWidget *parent); - void SetSliderX(int v); - void SetSliderY(int v); - void SetSliderZ(int v); - - /*! \brief Method performs the translation. - \params translateVector New translation to be combine with geometry. */ - void Translate( mitk::Vector3D translateVector); - /*! \brief Method performs the rotation. \params rotateVector New rotation to be combined with geometry. */ void Rotate(mitk::Vector3D rotateVector); // Member variables Ui::QmitkInteractiveTransformationWidgetControls* m_Controls; - mitk::BaseGeometry::Pointer m_Geometry; ///< \brief Initial geometry that is manipulated - mitk::BaseGeometry::Pointer m_ResetGeometry; ///< \brief Lifeline to reset to the initial geometry - mitk::Vector3D m_TranslationVector; ///< \brief Accumulated translation vector - mitk::Vector3D m_RotateSliderPos; ///< \brief Accumulated rotation vector (holds degree around x,y,z direction) + mitk::NavigationTool::Pointer m_ToolToEdit; ///< \brief this mamber holds a copy of the tool that should be edited for visualization + mitk::BaseGeometry::Pointer m_Geometry; ///< \brief The geometry that is manipulated + mitk::BaseGeometry::Pointer m_ResetGeometry; ///< \brief Lifeline to reset to the original geometry + +private: + void SetValuesToGUI(const mitk::AffineTransform3D::Pointer _defaultValues); + void SetSynchronizedVauesToSliderAndSpinbox(QDoubleSpinBox* _spinbox, QSlider* _slider, double _value); + }; #endif // QmitkInteractiveTransformationWidget_H diff --git a/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidgetControls.ui b/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidgetControls.ui index 62f0938a91..6daf485458 100644 --- a/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidgetControls.ui +++ b/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidgetControls.ui @@ -1,433 +1,463 @@ QmitkInteractiveTransformationWidgetControls 0 0 - 374 - 380 + 435 + 381 Form - + Interactive Translation 50 false x-Direction (Frontal): false 0 0 ArrowCursor -500 500 1 Qt::Horizontal - true + false false QSlider::TicksAbove 100 - + + + 1 + - -500 + -500.000000000000000 - 500 + 500.000000000000000 50 false y-Direction (Sagittal): false 0 0 -500 500 Qt::Horizontal - true + false QSlider::TicksAbove 100 - + + + 1 + - -500 + -500.000000000000000 - 500 - - - 0 + 500.000000000000000 50 false z-Direction (Transversal): false 0 0 -500 500 0 Qt::Horizontal - true + false QSlider::TicksAbove 100 - + + + 1 + - -500 + -500.000000000000000 - 500 - - - 1 + 500.000000000000000 - + Interactive Rotation 50 false x-Axis (Frontal): false 0 0 ArrowCursor -180 180 Qt::Horizontal QSlider::TicksAbove 45 - + + + 1 + - -180 + -180.000000000000000 - 180 + 180.000000000000000 50 false y-Axis (Sagittal): false 0 0 -180 180 Qt::Horizontal QSlider::TicksAbove 45 - + + + 1 + - -180 + -180.000000000000000 - 180 + 180.000000000000000 50 false z-Axis (Transversal): false 0 0 -180 180 Qt::Horizontal QSlider::TicksAbove 45 - + + + 1 + - -180 + -180.000000000000000 - 180 + 180.000000000000000 + + + + + + Use Manipulated ToolTip + + + + + + + Reset To Identity + + + + + + + Revert Changes + + + + + + + Cancel + + + + + - - - - Reset To Identity - - - - - - - Use Manipulated ToolTip - - - diff --git a/Modules/IGTUI/Qmitk/QmitkNDIAuroraWidget.ui b/Modules/IGTUI/Qmitk/QmitkNDIAuroraWidget.ui index e0dd4013c3..24cc19d363 100644 --- a/Modules/IGTUI/Qmitk/QmitkNDIAuroraWidget.ui +++ b/Modules/IGTUI/Qmitk/QmitkNDIAuroraWidget.ui @@ -1,190 +1,177 @@ QmitkNDIAuroraWidget 0 0 400 153 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" text-decoration: underline;">Aurora</span></p></body></html> Com Port: COM Auto Scan Qt::Horizontal 40 20 Port Type: /dev/ttyUSB /dev/ttyS Qt::Horizontal 40 20 Qt::Vertical 20 40 120 50 120 80 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;" bgcolor="#000000"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;" bgcolor="#000000"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; text-decoration: underline; color:#ffffff;">output:</span><span style=" font-size:8pt;"> </span></p></body></html> Qt::NoTextInteraction 120 0 120 16777215 Test Connection - - - - Qt::Vertical - - - - 20 - 40 - - - - diff --git a/Modules/IGTUI/Qmitk/QmitkNDIPolarisWidget.ui b/Modules/IGTUI/Qmitk/QmitkNDIPolarisWidget.ui index 44dc177df1..6b05398793 100644 --- a/Modules/IGTUI/Qmitk/QmitkNDIPolarisWidget.ui +++ b/Modules/IGTUI/Qmitk/QmitkNDIPolarisWidget.ui @@ -1,243 +1,230 @@ QmitkNDIPolarisWidget 0 0 408 191 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" text-decoration: underline;">Polaris</span></p></body></html> Com Port: COM Auto Scan Qt::Horizontal 40 20 Port Type: /dev/ttyUSB /dev/ttyS Qt::Horizontal 40 20 Frame Rate: 20 Hz 30 Hz 60 Hz Qt::Horizontal 40 20 Qt::Vertical 20 40 120 50 120 80 120 0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;" bgcolor="#000000"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;" bgcolor="#000000"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:7pt; text-decoration: underline; color:#ffffff;">output:</span><span style=" font-size:8pt;"> </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:7pt; color:#ffffff;">NDI Polaris selected</span><span style=" font-size:8pt;"> </span></p></body></html> Qt::NoTextInteraction 120 0 120 16777215 Test Connection - - - - Qt::Vertical - - - - 20 - 40 - - - - diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationDataSourceSelectionWidget.cpp b/Modules/IGTUI/Qmitk/QmitkNavigationDataSourceSelectionWidget.cpp index 4eb7d3b3b5..131bf68838 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationDataSourceSelectionWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkNavigationDataSourceSelectionWidget.cpp @@ -1,140 +1,137 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkNavigationDataSourceSelectionWidget.h" //mitk headers #include #include #include QmitkNavigationDataSourceSelectionWidget::QmitkNavigationDataSourceSelectionWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) { m_Controls = nullptr; CreateQtPartControl(this); CreateConnections(); } QmitkNavigationDataSourceSelectionWidget::~QmitkNavigationDataSourceSelectionWidget() { } void QmitkNavigationDataSourceSelectionWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkNavigationDataSourceSelectionWidgetControls; m_Controls->setupUi(parent); std::string empty = ""; m_Controls->m_NavigationDataSourceWidget->Initialize(mitk::NavigationDataSource::US_PROPKEY_DEVICENAME,empty); } } void QmitkNavigationDataSourceSelectionWidget::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_NavigationDataSourceWidget), SIGNAL(ServiceSelectionChanged(us::ServiceReferenceU)), this, SLOT(NavigationDataSourceSelected(us::ServiceReferenceU)) ); connect((QObject*)(m_Controls->m_ToolView), SIGNAL(currentRowChanged(int)), this, SLOT(NavigationToolSelected(int))); } } void QmitkNavigationDataSourceSelectionWidget::NavigationToolSelected(int selection) { emit NavigationToolSelected(this->m_CurrentStorage->GetTool(selection)); } void QmitkNavigationDataSourceSelectionWidget::NavigationDataSourceSelected(us::ServiceReferenceU s) { if (!s) //no device selected { //reset everything m_CurrentSource = nullptr; m_CurrentStorage = nullptr; emit NavigationDataSourceSelected(m_CurrentSource); return; } // Get Source us::ModuleContext* context = us::GetModuleContext(); m_CurrentSource = context->GetService(s); - std::string id = s.GetProperty(mitk::NavigationDataSource::US_PROPKEY_ID).ToString(); // clear tool list before filling it m_Controls->m_ToolView->clear(); //Fill tool list MITK_INFO<<"no outputs: "<GetNumberOfOutputs(); for(std::size_t i = 0; i < m_CurrentSource->GetNumberOfOutputs(); i++) { new QListWidgetItem(tr(m_CurrentSource->GetOutput(i)->GetName()), m_Controls->m_ToolView); } - - // Create Filter for ToolStorage - std::string filter = "("+ mitk::NavigationToolStorage::US_PROPKEY_SOURCE_ID + "=" + id + ")"; - // Get Storage + std::string filter = "(" + mitk::NavigationToolStorage::US_PROPKEY_SOURCE_ID + "=" + m_CurrentSource->GetMicroserviceID() + ")"; std::vector > refs = context->GetServiceReferences(filter); if (refs.empty()) return; //no storage was found m_CurrentStorage = context->GetService(refs.front()); + if (m_CurrentStorage.IsNull()) { MITK_WARN << "Found an invalid storage object!"; return; } if (m_CurrentStorage->GetToolCount() != static_cast(m_CurrentSource->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; } emit NavigationDataSourceSelected(m_CurrentSource); } mitk::NavigationDataSource::Pointer QmitkNavigationDataSourceSelectionWidget::GetSelectedNavigationDataSource() { return this->m_CurrentSource; } int QmitkNavigationDataSourceSelectionWidget::GetSelectedToolID() { return this->m_Controls->m_ToolView->currentIndex().row(); } mitk::NavigationTool::Pointer QmitkNavigationDataSourceSelectionWidget::GetSelectedNavigationTool() { if (this->m_CurrentStorage.IsNull()) return nullptr; if (m_Controls->m_ToolView->currentIndex().row() >= m_CurrentStorage->GetToolCount()) return nullptr; return this->m_CurrentStorage->GetTool(m_Controls->m_ToolView->currentIndex().row()); } mitk::NavigationToolStorage::Pointer QmitkNavigationDataSourceSelectionWidget::GetNavigationToolStorageOfSource() { return this->m_CurrentStorage; } diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationAdvancedWidget.cpp b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationAdvancedWidget.cpp deleted file mode 100644 index c39a795386..0000000000 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationAdvancedWidget.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/*=================================================================== - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. - -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. - -See LICENSE.txt or http://www.mitk.org for details. - -===================================================================*/ - -#include "QmitkNavigationToolCreationAdvancedWidget.h" -#include "QmitkNavigationToolCreationWidget.h" - -// mitk includes -#include -#include -#include - -// vtk includes -#include -#include - -const std::string QmitkNavigationToolCreationAdvancedWidget::VIEW_ID = "org.mitk.views.navigationtoolcreationadvancedwidget"; - -QmitkNavigationToolCreationAdvancedWidget::QmitkNavigationToolCreationAdvancedWidget(QWidget* parent, Qt::WindowFlags f) - : QDialog(parent, f), m_Controls(nullptr), m_DataStorage(nullptr), m_ToolTipSurface(nullptr), m_ManipulatedToolTip(nullptr), - m_SurfaceNodeName("") -{ - CreateQtPartControl(this); - CreateConnections(); -} - -QmitkNavigationToolCreationAdvancedWidget::~QmitkNavigationToolCreationAdvancedWidget() -{ -} - -void QmitkNavigationToolCreationAdvancedWidget::CreateQtPartControl(QWidget *parent) - { - if (!m_Controls) - { - // create GUI widgets - m_Controls = new Ui::QmitkNavigationToolCreationAdvancedWidgetControls; - m_Controls->setupUi(parent); - } - } - -void QmitkNavigationToolCreationAdvancedWidget::CreateConnections() - { - if ( m_Controls ) - { - connect( (QObject*)(this), SIGNAL(finished(int)), this, SLOT(OnClose())); - connect( (QObject*)(m_Controls->m_InteractiveTransformation), SIGNAL(ApplyManipulatedToolTip()), this, SLOT(OnApplyManipulatedToolTip())); - } - } - -void QmitkNavigationToolCreationAdvancedWidget::OnClose() -{ - //clean the data storage - if(m_DataStorage->Exists(m_DataStorage->GetNamedNode("StandardToolTip"))) - { - m_DataStorage->Remove(m_DataStorage->GetNamedNode("StandardToolTip")); - } - - if(m_DataStorage.IsNotNull() && m_DataStorage->Exists(m_DataStorage->GetNamedNode("ManipulatedToolTip"))) - { - m_DataStorage->Remove(m_DataStorage->GetNamedNode("ManipulatedToolTip")); - } - - emit DialogCloseRequested(); -} - -void QmitkNavigationToolCreationAdvancedWidget::SetDataStorage( mitk::DataStorage::Pointer dataStorage ) -{ - m_DataStorage = dataStorage; -} - -void QmitkNavigationToolCreationAdvancedWidget::ReInitialize() -{ - if (m_DataStorage.IsNull()) return; - - //reset some variables - m_ManipulatedToolTip = nullptr; - m_ToolTipSurface = nullptr; - m_SurfaceNodeName = ""; - mitk::Geometry3D::Pointer geo3d = mitk::Geometry3D::New(); - mitk::BaseGeometry::Pointer emptyGeo = dynamic_cast(geo3d.GetPointer()); - m_Controls->m_InteractiveTransformation->SetGeometry(emptyGeo,emptyGeo); - - //call initialization method - this->RetrieveAndInitializeDataForTooltipManipulation(); - - //care for new data nodes - mitk::DataNode::Pointer manipulatedTipNode = nullptr; - if(!m_DataStorage->Exists(m_DataStorage->GetNamedNode("ManipulatedToolTip"))) - { - manipulatedTipNode = mitk::DataNode::New(); - manipulatedTipNode->SetData(m_ManipulatedToolTip); - manipulatedTipNode->SetName("ManipulatedToolTip"); - manipulatedTipNode->SetColor(1.0, 0.0, 0.0); - manipulatedTipNode->SetOpacity(0.5); - m_DataStorage->Add(manipulatedTipNode); - } - else - { - manipulatedTipNode = m_DataStorage->GetNamedNode("ManipulatedToolTip"); - manipulatedTipNode->SetData(m_ManipulatedToolTip); - } - - // reinit the views with the new nodes - mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(m_DataStorage); -} - -void QmitkNavigationToolCreationAdvancedWidget::RetrieveAndInitializeDataForTooltipManipulation() -{ - // we need the tooltip surface (point or stl) - emit RetrieveDataForManualToolTipManipulation(); - - if(m_ToolTipSurface.IsNotNull()) - { - mitk::DataNode::Pointer toolTipNode = nullptr; - - if(m_SurfaceNodeName.empty()) - { - m_SurfaceNodeName = "StandardToolTip"; - } - - if(!m_DataStorage->Exists(m_DataStorage->GetNamedNode(m_SurfaceNodeName))) - { - toolTipNode = mitk::DataNode::New(); - toolTipNode->SetName(m_SurfaceNodeName); - toolTipNode->SetData(m_ToolTipSurface); - m_DataStorage->Add(toolTipNode); - - } - else - { - toolTipNode = m_DataStorage->GetNamedNode(m_SurfaceNodeName); - toolTipNode->SetData(m_ToolTipSurface); - } - - m_ManipulatedToolTip = m_ToolTipSurface->Clone(); - - mitk::BaseGeometry::Pointer defaultGeo = dynamic_cast (mitk::Geometry3D::New().GetPointer()); - defaultGeo->SetIndexToWorldTransform(m_DefaultToolTip); - - m_Controls->m_InteractiveTransformation->SetGeometry(m_ManipulatedToolTip->GetGeometry(),defaultGeo); - } - else - { - mitkThrow() << "No tooltip surface specified, operation aborted"; - } -} - -void QmitkNavigationToolCreationAdvancedWidget::SetDefaultTooltip(mitk::AffineTransform3D::Pointer defaultToolTip) -{ - m_DefaultToolTip = defaultToolTip; -} - -void QmitkNavigationToolCreationAdvancedWidget::SetToolTipSurface( bool cone, mitk::DataNode::Pointer node /*= nullptr*/ ) -{ - m_ToolTipSurface = nullptr; - if(cone) - { - m_ToolTipSurface = mitk::Surface::New(); - vtkConeSource *vtkData = vtkConeSource::New(); - vtkData->SetAngle(5.0); - vtkData->SetResolution(50); - vtkData->SetHeight(6.0f); - vtkData->SetRadius(2.0f); - vtkData->SetCenter(0.0, 0.0, 0.0); - - vtkData->Update(); - m_ToolTipSurface->SetVtkPolyData(vtkData->GetOutput()); - - vtkData->Delete(); - m_SurfaceNodeName =""; - } - else if(!cone && node.IsNotNull()) - { - m_ToolTipSurface = dynamic_cast(node->GetData()); - m_SurfaceNodeName = node->GetName(); - } -} - -void QmitkNavigationToolCreationAdvancedWidget::OnApplyManipulatedToolTip() -{ - //save manipulated surface object, which holds the tooltip as geometry - m_ManipulatedToolTip = dynamic_cast(m_DataStorage->GetNamedNode("ManipulatedToolTip")->GetData()->Clone().GetPointer()); - //then close the window - OnClose(); -} - -mitk::AffineTransform3D::Pointer QmitkNavigationToolCreationAdvancedWidget::GetManipulatedToolTip() -{ - mitk::AffineTransform3D::Pointer returnValue = mitk::AffineTransform3D::New(); - if (m_ManipulatedToolTip.IsNotNull()) returnValue = m_ManipulatedToolTip->GetGeometry()->GetIndexToWorldTransform(); - else returnValue->SetIdentity(); - return returnValue; -} diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationAdvancedWidget.h b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationAdvancedWidget.h deleted file mode 100644 index d770553b75..0000000000 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationAdvancedWidget.h +++ /dev/null @@ -1,109 +0,0 @@ -/*=================================================================== - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. - -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. - -See LICENSE.txt or http://www.mitk.org for details. - -===================================================================*/ - -#ifndef QmitkNavigationToolCreationAdvancedWidget_H -#define QmitkNavigationToolCreationAdvancedWidget_H - -//QT headers -#include - -//Mitk headers -#include "MitkIGTUIExports.h" -#include "mitkDataStorage.h" -#include "mitkSurface.h" - -// Qmitk headers -#include "QmitkInteractiveTransformationWidget.h" - -//ui header -#include "ui_QmitkNavigationToolCreationAdvancedWidgetControls.h" - - /** Documentation: - * \brief An object of this class offers an UI to modify a tooltip of an IGT navigation tool. - * - * The user can modify translation and orientation of the tooltip. The current tooltip - * might be provided as default data, then the widget starts with the given values for - * translation and orientation. - * - * As long as the UI is open, there will also be a (temporary) preview data node, so - * the user can see the effect of his manipulations. - * - * Please call the method SetDataStorage to initialize the UI with the data storage - * of the current application. - * - * \ingroup IGTUI - */ -class MITKIGTUI_EXPORT QmitkNavigationToolCreationAdvancedWidget : public QDialog -{ - Q_OBJECT - - public: - static const std::string VIEW_ID; - - QmitkNavigationToolCreationAdvancedWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); - ~QmitkNavigationToolCreationAdvancedWidget() override; - - /** Initializes the view with the a data storage. This data storage is needed for the - * preview node during tooltip manipulation. - */ - void SetDataStorage(mitk::DataStorage::Pointer dataStorage); - - /** Sets the current tooltip surface, also for preview purposes (the preview node - * will be a clone of this surface). If there is no surface, a simple cone can be used. - * Please set cone to true in this case. - */ - void SetToolTipSurface(bool cone, mitk::DataNode::Pointer node = nullptr); - - /** Sets a default tooltip transform, which will shown in the beginning. - * If the windows is already open, the transform will be set to default - * immediately. - */ - void SetDefaultTooltip(mitk::AffineTransform3D::Pointer defaultToolTip); - - /** @return Returns the manipulated tip transform. Returns an identity transform if - * nothing was manipulated. - */ - mitk::AffineTransform3D::Pointer GetManipulatedToolTip(); - - /** Reinitializes the view, e.g. after it was closed. - */ - void ReInitialize(); - -signals: - void DialogCloseRequested(); - void RetrieveDataForManualToolTipManipulation(); - - protected slots: - void OnClose(); - void OnApplyManipulatedToolTip(); - - protected: - - virtual void CreateConnections(); - - virtual void CreateQtPartControl(QWidget *parent); - void RetrieveAndInitializeDataForTooltipManipulation(); - // Member variables - Ui::QmitkNavigationToolCreationAdvancedWidgetControls* m_Controls; - - mitk::AffineTransform3D::Pointer m_DefaultToolTip; - - mitk::DataStorage::Pointer m_DataStorage; - mitk::Surface::Pointer m_ToolTipSurface; - mitk::Surface::Pointer m_ManipulatedToolTip; ///< manipulated surface object, which holds the tooltip as geometry - std::string m_SurfaceNodeName; -}; -#endif // QmitkNavigationToolCreationAdvancedWidget_H diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationAdvancedWidgetControls.ui b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationAdvancedWidgetControls.ui deleted file mode 100644 index d3db69929f..0000000000 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationAdvancedWidgetControls.ui +++ /dev/null @@ -1,52 +0,0 @@ - - - QmitkNavigationToolCreationAdvancedWidgetControls - - - - 0 - 0 - 462 - 429 - - - - Form - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - 0 - 400 - - - - - - - - - QmitkInteractiveTransformationWidget - QWidget -
QmitkInteractiveTransformationWidget.h
- 1 -
-
- - -
diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.cpp b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.cpp index ceae19d863..34bc646437 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.cpp @@ -1,347 +1,399 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkNavigationToolCreationWidget.h" //mitk headers #include #include #include #include #include "mitkTrackingDeviceTypeCollection.h" //qt headers #include #include -#include #include #include +#include //poco headers #include // vtk #include #include const std::string QmitkNavigationToolCreationWidget::VIEW_ID = "org.mitk.views.navigationtoolcreationwizardwidget"; QmitkNavigationToolCreationWidget::QmitkNavigationToolCreationWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) { + m_Controls = NULL; + m_ToolToBeEdited = mitk::NavigationTool::New(); + m_FinalTool = mitk::NavigationTool::New(); + m_ToolTransformationWidget = new QmitkInteractiveTransformationWidget(); m_Controls = nullptr; - m_AdvancedWidget = new QmitkNavigationToolCreationAdvancedWidget(this); - m_AdvancedWidget->setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint); - m_AdvancedWidget->setWindowTitle("Tool Creation Advanced Options"); - m_AdvancedWidget->setModal(false); + CreateQtPartControl(this); CreateConnections(); -RefreshTrackingDeviceCollection(); + this->InitializeUIToolLandmarkLists(); + Initialize(nullptr, ""); + + //Default values, which are not stored in tool + m_Controls->m_CalibrationFileName->setText("none"); + m_Controls->m_Surface_Use_Sphere->setChecked(true); + + m_Controls->m_CalibrationLandmarksList->EnableEditButton(false); + m_Controls->m_RegistrationLandmarksList->EnableEditButton(false); + + RefreshTrackingDeviceCollection(); } QmitkNavigationToolCreationWidget::~QmitkNavigationToolCreationWidget() { m_Controls->m_CalibrationLandmarksList->SetPointSetNode(nullptr); m_Controls->m_RegistrationLandmarksList->SetPointSetNode(nullptr); - delete m_AdvancedWidget; + delete m_ToolTransformationWidget; } void QmitkNavigationToolCreationWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkNavigationToolCreationWidgetControls; m_Controls->setupUi(parent); } } void QmitkNavigationToolCreationWidget::CreateConnections() { - if ( m_Controls ) + if (m_Controls) { - connect( (QObject*)(m_Controls->m_cancel), SIGNAL(clicked()), this, SLOT(OnCancel()) ); - connect( (QObject*)(m_Controls->m_finished), SIGNAL(clicked()), this, SLOT(OnFinished()) ); - connect( (QObject*)(m_Controls->m_LoadSurface), SIGNAL(clicked()), this, SLOT(OnLoadSurface()) ); - connect( (QObject*)(m_Controls->m_LoadCalibrationFile), SIGNAL(clicked()), this, SLOT(OnLoadCalibrationFile()) ); - connect( (QObject*)(m_Controls->m_ShowAdvancedOptionsPB), SIGNAL(toggled(bool)), this, SLOT(OnShowAdvancedOptions(bool)) ); - connect( (QObject*)(m_AdvancedWidget), SIGNAL(DialogCloseRequested()), this, SLOT(OnProcessDialogCloseRequest()) ); - connect( (QObject*)(m_AdvancedWidget), SIGNAL(RetrieveDataForManualToolTipManipulation()), this, SLOT(OnRetrieveDataForManualTooltipManipulation()) ); - - connect( m_Controls->m_Surface_Use_Other, SIGNAL(toggled(bool)), this, SLOT(OnSurfaceUseOtherToggled(bool))); + connect((QObject*)(m_Controls->m_TrackingDeviceTypeChooser), SIGNAL(currentIndexChanged(int)), this, SLOT(GetValuesFromGuiElements())); + connect((QObject*)(m_Controls->m_ToolNameEdit), SIGNAL(textChanged(const QString)), this, SLOT(GetValuesFromGuiElements())); + connect((QObject*)(m_Controls->m_ToolTypeChooser), SIGNAL(currentIndexChanged(int)), this, SLOT(GetValuesFromGuiElements())); + connect((QObject*)(m_Controls->m_IdentifierEdit), SIGNAL(textChanged(const QString)), this, SLOT(GetValuesFromGuiElements())); + connect((QObject*)(m_Controls->m_SerialNumberEdit), SIGNAL(textChanged(const QString)), this, SLOT(GetValuesFromGuiElements())); + connect((QObject*)(m_Controls->m_ToolAxisX), SIGNAL(valueChanged(int)), this, SLOT(GetValuesFromGuiElements())); + connect((QObject*)(m_Controls->m_ToolAxisY), SIGNAL(valueChanged(int)), this, SLOT(GetValuesFromGuiElements())); + connect((QObject*)(m_Controls->m_ToolAxisZ), SIGNAL(valueChanged(int)), this, SLOT(GetValuesFromGuiElements())); + + //Buttons + connect((QObject*)(m_Controls->m_LoadCalibrationFile), SIGNAL(clicked()), this, SLOT(OnLoadCalibrationFile())); + connect(m_Controls->m_Surface_Use_Other, SIGNAL(toggled(bool)), this, SLOT(OnSurfaceUseOtherToggled())); + connect((QObject*)(m_Controls->m_LoadSurface), SIGNAL(clicked()), this, SLOT(OnLoadSurface())); + connect((QObject*)(m_Controls->m_EditToolTip), SIGNAL(clicked()), this, SLOT(OnEditToolTip())); + + connect((QObject*)(m_ToolTransformationWidget), SIGNAL(EditToolTipFinished(mitk::AffineTransform3D::Pointer)), this, + SLOT(OnEditToolTipFinished(mitk::AffineTransform3D::Pointer))); + + connect((QObject*)(m_Controls->m_cancel), SIGNAL(clicked()), this, SLOT(OnCancel())); + connect((QObject*)(m_Controls->m_finished), SIGNAL(clicked()), this, SLOT(OnFinished())); } } void QmitkNavigationToolCreationWidget::Initialize(mitk::DataStorage* dataStorage, const std::string& supposedIdentifier, const std::string& supposedName) { m_DataStorage = dataStorage; - //initialize UI components m_Controls->m_SurfaceChooser->SetDataStorage(m_DataStorage); m_Controls->m_SurfaceChooser->SetAutoSelectNewItems(true); m_Controls->m_SurfaceChooser->SetPredicate(mitk::NodePredicateDataType::New("Surface")); - //set default data - m_Controls->m_ToolNameEdit->setText(supposedName.c_str()); - m_Controls->m_CalibrationFileName->setText("none"); - m_Controls->m_Surface_Use_Sphere->setChecked(true); - m_AdvancedWidget->SetDataStorage(m_DataStorage); - m_Controls->m_IdentifierEdit->setText(supposedIdentifier.c_str()); - this->InitializeUIToolLandmarkLists(); - m_Controls->m_CalibrationLandmarksList->EnableEditButton(false); - m_Controls->m_RegistrationLandmarksList->EnableEditButton(false); + //Create new tool, which should be edited/created + m_ToolToBeEdited = nullptr;//Reset + m_ToolToBeEdited = mitk::NavigationTool::New();//Reinitialize + m_ToolToBeEdited->SetIdentifier(supposedIdentifier); + + m_ToolToBeEdited->GetDataNode()->SetName(supposedName); + + this->SetDefaultData(m_ToolToBeEdited); } -void QmitkNavigationToolCreationWidget::SetTrackingDeviceType(mitk::TrackingDeviceType type, bool) +void QmitkNavigationToolCreationWidget::ShowToolPreview(std::string _name) { - int index = m_Controls->m_TrackingDeviceTypeChooser->findText(QString::fromStdString(type)); + m_DataStorage->Add(m_ToolToBeEdited->GetDataNode()); + m_ToolToBeEdited->GetDataNode()->SetName(_name); - if (index >= 0) - { - m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(index); - } -} + //change color to blue + m_ToolToBeEdited->GetDataNode()->SetProperty("color", mitk::ColorProperty::New(0, 0, 1)); + //Global Reinit to show new tool + mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(m_DataStorage); +} -mitk::NavigationTool::Pointer QmitkNavigationToolCreationWidget::GetCreatedTool() +void QmitkNavigationToolCreationWidget::SetDefaultData(mitk::NavigationTool::Pointer DefaultTool) { - return m_CreatedTool; -} + //Set Members. This can either be the new initialized tool from call of Initialize() or a tool which already exists in the toolStorage + m_ToolToBeEdited = DefaultTool->Clone(); -//################################################################################## -//############################## slots ############################ -//################################################################################## + //Set all gui variables + SetGuiElements(); +} -void QmitkNavigationToolCreationWidget::OnFinished() +void QmitkNavigationToolCreationWidget::SetGuiElements() { - //here we create a new tool - m_CreatedTool = mitk::NavigationTool::New(); - - //create DataNode... - mitk::DataNode::Pointer newNode = mitk::DataNode::New(); - if(m_Controls->m_Surface_Use_Sphere->isChecked()) - { - //create small sphere and use it as surface - mitk::Surface::Pointer mySphere = mitk::Surface::New(); - vtkConeSource *vtkData = vtkConeSource::New(); - vtkData->SetAngle(5.0); - vtkData->SetResolution(50); - vtkData->SetHeight(6.0f); - vtkData->SetRadius(2.0f); - vtkData->SetCenter(0.0, 0.0, 0.0); - vtkData->Update(); - mySphere->SetVtkPolyData(vtkData->GetOutput()); - vtkData->Delete(); - newNode->SetData(mySphere); - } - else + //Block signals, so that we don't call SetGuiElements again. This is undone at the end of this function! + m_Controls->m_TrackingDeviceTypeChooser->blockSignals(true); + m_Controls->m_ToolNameEdit->blockSignals(true); + m_Controls->m_ToolTypeChooser->blockSignals(true); + m_Controls->m_IdentifierEdit->blockSignals(true); + m_Controls->m_SerialNumberEdit->blockSignals(true); + m_Controls->m_ToolAxisX->blockSignals(true); + m_Controls->m_ToolAxisY->blockSignals(true); + m_Controls->m_ToolAxisZ->blockSignals(true); + + //DeviceType + int index = m_Controls->m_TrackingDeviceTypeChooser->findText(QString::fromStdString(m_ToolToBeEdited->GetTrackingDeviceType())); + if (index >= 0) { - newNode->SetData(m_Controls->m_SurfaceChooser->GetSelectedNode()->GetData()); + m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(index); } - newNode->SetName(m_Controls->m_ToolNameEdit->text().toLatin1()); - - m_CreatedTool->SetDataNode(newNode); - //fill NavigationTool object - m_CreatedTool->SetCalibrationFile(m_Controls->m_CalibrationFileName->text().toLatin1().data()); - m_CreatedTool->SetIdentifier(m_Controls->m_IdentifierEdit->text().toLatin1().data()); - m_CreatedTool->SetSerialNumber(m_Controls->m_SerialNumberEdit->text().toLatin1().data()); + m_Controls->m_ToolNameEdit->setText(QString(m_ToolToBeEdited->GetToolName().c_str())); + m_Controls->m_CalibrationFileName->setText(QString(m_ToolToBeEdited->GetCalibrationFile().c_str())); -//Tracking Device -m_CreatedTool->SetTrackingDeviceType(m_Controls->m_TrackingDeviceTypeChooser->currentText().toStdString()); + m_Controls->m_SurfaceChooser->SetSelectedNode(m_ToolToBeEdited->GetDataNode()); + FillUIToolLandmarkLists(m_ToolToBeEdited->GetToolCalibrationLandmarks(), m_ToolToBeEdited->GetToolRegistrationLandmarks()); - //ToolType - if (m_Controls->m_ToolTypeChooser->currentText()=="Instrument") m_CreatedTool->SetType(mitk::NavigationTool::Instrument); - else if (m_Controls->m_ToolTypeChooser->currentText()=="Fiducial") m_CreatedTool->SetType(mitk::NavigationTool::Fiducial); - else if (m_Controls->m_ToolTypeChooser->currentText()=="Skinmarker") m_CreatedTool->SetType(mitk::NavigationTool::Skinmarker); - else m_CreatedTool->SetType(mitk::NavigationTool::Unknown); - - //Tool Tip - mitk::NavigationData::Pointer tempND = mitk::NavigationData::New(m_AdvancedWidget->GetManipulatedToolTip()); - m_CreatedTool->SetToolTipOrientation(tempND->GetOrientation()); - m_CreatedTool->SetToolTipPosition(tempND->GetPosition()); - - //Tool Landmarks - mitk::PointSet::Pointer toolCalLandmarks, toolRegLandmarks; - GetUIToolLandmarksLists(toolCalLandmarks,toolRegLandmarks); - m_CreatedTool->SetToolCalibrationLandmarks(toolCalLandmarks); - m_CreatedTool->SetToolRegistrationLandmarks(toolRegLandmarks); - - //Tool Axis - mitk::Point3D toolAxis; - toolAxis.SetElement(0, (m_Controls->m_ToolAxisX->value())); - toolAxis.SetElement(1, (m_Controls->m_ToolAxisY->value())); - toolAxis.SetElement(2, (m_Controls->m_ToolAxisZ->value())); - m_CreatedTool->SetToolAxis(toolAxis); + switch (m_ToolToBeEdited->GetType()) + { + case mitk::NavigationTool::Instrument: + m_Controls->m_ToolTypeChooser->setCurrentIndex(0); break; + case mitk::NavigationTool::Fiducial: + m_Controls->m_ToolTypeChooser->setCurrentIndex(1); break; + case mitk::NavigationTool::Skinmarker: + m_Controls->m_ToolTypeChooser->setCurrentIndex(2); break; + case mitk::NavigationTool::Unknown: + m_Controls->m_ToolTypeChooser->setCurrentIndex(3); break; + } - emit NavigationToolFinished(); + m_Controls->m_IdentifierEdit->setText(QString(m_ToolToBeEdited->GetIdentifier().c_str())); + m_Controls->m_SerialNumberEdit->setText(QString(m_ToolToBeEdited->GetSerialNumber().c_str())); + + m_Controls->m_ToolAxisX->setValue(m_ToolToBeEdited->GetToolAxis()[0]); + m_Controls->m_ToolAxisY->setValue(m_ToolToBeEdited->GetToolAxis()[1]); + m_Controls->m_ToolAxisZ->setValue(m_ToolToBeEdited->GetToolAxis()[2]); + QString _label = "(" + + QString::number(m_ToolToBeEdited->GetToolTipPosition()[0], 'f', 1) + ", " + + QString::number(m_ToolToBeEdited->GetToolTipPosition()[1], 'f', 1) + ", " + + QString::number(m_ToolToBeEdited->GetToolTipPosition()[2], 'f', 1) + "), quat: [" + + QString::number(m_ToolToBeEdited->GetToolTipOrientation()[0], 'f', 2) + ", " + + QString::number(m_ToolToBeEdited->GetToolTipOrientation()[1], 'f', 2) + ", " + + QString::number(m_ToolToBeEdited->GetToolTipOrientation()[2], 'f', 2) + ", " + + QString::number(m_ToolToBeEdited->GetToolTipOrientation()[3], 'f', 2) + "]"; + m_Controls->m_ToolTipLabel->setText(_label); + + //Undo block signals. Don't remove it, if signals are still blocked at the beginning of this function! + m_Controls->m_TrackingDeviceTypeChooser->blockSignals(false); + m_Controls->m_ToolNameEdit->blockSignals(false); + m_Controls->m_ToolTypeChooser->blockSignals(false); + m_Controls->m_IdentifierEdit->blockSignals(false); + m_Controls->m_SerialNumberEdit->blockSignals(false); + m_Controls->m_ToolAxisX->blockSignals(false); + m_Controls->m_ToolAxisY->blockSignals(false); + m_Controls->m_ToolAxisZ->blockSignals(false); } -void QmitkNavigationToolCreationWidget::OnCancel() +void QmitkNavigationToolCreationWidget::OnSurfaceUseOtherToggled() { - m_CreatedTool = nullptr; + m_Controls->m_LoadSurface->setEnabled(m_Controls->m_Surface_Use_Other->isChecked()); + if (m_Controls->m_Surface_Use_Sphere->isChecked()) + m_ToolToBeEdited->SetDefaultSurface(); - emit Canceled(); + //Global Reinit to show tool surface preview + mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(m_DataStorage); } void QmitkNavigationToolCreationWidget::OnLoadSurface() { - std::string filename = QFileDialog::getOpenFileName(nullptr,tr("Open Surface"), QmitkIGTCommonHelper::GetLastFileLoadPath(), tr("STL (*.stl)")).toLatin1().data(); + std::string filename = QFileDialog::getOpenFileName(nullptr, tr("Open Surface"), QmitkIGTCommonHelper::GetLastFileLoadPath(), tr("STL (*.stl)")).toLatin1().data(); QmitkIGTCommonHelper::SetLastFileLoadPathByFileName(QString::fromStdString(filename)); + mitk::Surface::Pointer surface; try { - mitk::IOUtil::Load(filename.c_str(), *m_DataStorage); + surface = mitk::IOUtil::LoadSurface(filename.c_str()); } catch (mitk::Exception &e) { MITK_ERROR << "Exception occured: " << e.what(); + return; } + + m_ToolToBeEdited->GetDataNode()->SetData(surface); + + //Global Reinit to show tool surface or preview + mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(m_DataStorage); } void QmitkNavigationToolCreationWidget::OnLoadCalibrationFile() { - QString fileName = QFileDialog::getOpenFileName(nullptr,tr("Open Calibration File"), QmitkIGTCommonHelper::GetLastFileLoadPath(), "*.*"); + QString fileName = QFileDialog::getOpenFileName(nullptr, tr("Open Calibration File"), QmitkIGTCommonHelper::GetLastFileLoadPath(), "*.*"); QmitkIGTCommonHelper::SetLastFileLoadPathByFileName(fileName); m_Controls->m_CalibrationFileName->setText(fileName); + m_ToolToBeEdited->SetCalibrationFile(fileName.toStdString()); } - -void QmitkNavigationToolCreationWidget::SetDefaultData(mitk::NavigationTool::Pointer DefaultTool) +void QmitkNavigationToolCreationWidget::GetValuesFromGuiElements() { -m_Controls->m_ToolNameEdit->setText(QString(DefaultTool->GetDataNode()->GetName().c_str())); -m_Controls->m_IdentifierEdit->setText(QString(DefaultTool->GetIdentifier().c_str())); -m_Controls->m_SerialNumberEdit->setText(QString(DefaultTool->GetSerialNumber().c_str())); -m_AdvancedWidget->SetDefaultTooltip( DefaultTool->GetToolTipTransform() ); -int index = m_Controls->m_TrackingDeviceTypeChooser->findText(QString::fromStdString(DefaultTool->GetTrackingDeviceType())); + //Tracking Device + m_ToolToBeEdited->SetTrackingDeviceType(m_Controls->m_TrackingDeviceTypeChooser->currentText().toStdString()); + m_ToolToBeEdited->GetDataNode()->SetName(m_Controls->m_ToolNameEdit->text().toStdString()); + + //Tool Landmarks + mitk::PointSet::Pointer toolCalLandmarks, toolRegLandmarks; + GetUIToolLandmarksLists(toolCalLandmarks, toolRegLandmarks); + m_ToolToBeEdited->SetToolCalibrationLandmarks(toolCalLandmarks); + m_ToolToBeEdited->SetToolRegistrationLandmarks(toolRegLandmarks); + + //Advanced + if (m_Controls->m_ToolTypeChooser->currentText() == "Instrument") m_ToolToBeEdited->SetType(mitk::NavigationTool::Instrument); + else if (m_Controls->m_ToolTypeChooser->currentText() == "Fiducial") m_ToolToBeEdited->SetType(mitk::NavigationTool::Fiducial); + else if (m_Controls->m_ToolTypeChooser->currentText() == "Skinmarker") m_ToolToBeEdited->SetType(mitk::NavigationTool::Skinmarker); + else m_FinalTool->SetType(mitk::NavigationTool::Unknown); + + m_ToolToBeEdited->SetIdentifier(m_Controls->m_IdentifierEdit->text().toLatin1().data()); + m_ToolToBeEdited->SetSerialNumber(m_Controls->m_SerialNumberEdit->text().toLatin1().data()); -if (index >= 0) + //Tool Axis + mitk::Point3D toolAxis; + toolAxis.SetElement(0, (m_Controls->m_ToolAxisX->value())); + toolAxis.SetElement(1, (m_Controls->m_ToolAxisY->value())); + toolAxis.SetElement(2, (m_Controls->m_ToolAxisZ->value())); + m_ToolToBeEdited->SetToolAxis(toolAxis); +} + +mitk::NavigationTool::Pointer QmitkNavigationToolCreationWidget::GetCreatedTool() { - m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(index); + return m_FinalTool; } -m_Controls->m_CalibrationFileName->setText(QString(DefaultTool->GetCalibrationFile().c_str())); -m_Controls->m_Surface_Use_Other->setChecked(true); -switch(DefaultTool->GetType()) +void QmitkNavigationToolCreationWidget::OnFinished() { -case mitk::NavigationTool::Instrument: -m_Controls->m_ToolTypeChooser->setCurrentIndex(0); break; -case mitk::NavigationTool::Fiducial: -m_Controls->m_ToolTypeChooser->setCurrentIndex(1); break; -case mitk::NavigationTool::Skinmarker: -m_Controls->m_ToolTypeChooser->setCurrentIndex(2); break; -case mitk::NavigationTool::Unknown: -m_Controls->m_ToolTypeChooser->setCurrentIndex(3); break; + //here we create a new tool + m_FinalTool = m_ToolToBeEdited->Clone(); + //Set the correct name of data node, cause the m_ToolToBeEdited was called "Tool preview" + m_FinalTool->GetDataNode()->SetName(m_Controls->m_ToolNameEdit->text().toStdString()); + + emit NavigationToolFinished(); } - m_Controls->m_SurfaceChooser->SetSelectedNode(DefaultTool->GetDataNode()); - FillUIToolLandmarkLists(DefaultTool->GetToolCalibrationLandmarks(),DefaultTool->GetToolRegistrationLandmarks()); +void QmitkNavigationToolCreationWidget::OnCancel() +{ + Initialize(nullptr, "");//Reset everything to a fresh tool, like it was done in the constructor + emit Canceled(); } +void QmitkNavigationToolCreationWidget::SetTrackingDeviceType(mitk::TrackingDeviceType type, bool changeable /*= true*/) +{ + //Adapt Gui + int index = m_Controls->m_TrackingDeviceTypeChooser->findText(QString::fromStdString(type)); + + if (index >= 0) + { + m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(index); + } + + m_Controls->m_TrackingDeviceTypeChooser->setEditable(changeable); + + //Set data to member + m_ToolToBeEdited->SetTrackingDeviceType(type); +} //################################################################################## //############################## internal help methods ############################# //################################################################################## void QmitkNavigationToolCreationWidget::MessageBox(std::string s) { QMessageBox msgBox; msgBox.setText(s.c_str()); msgBox.exec(); } -void QmitkNavigationToolCreationWidget::OnShowAdvancedOptions(bool state) +void QmitkNavigationToolCreationWidget::OnEditToolTip() { - if(state) - { - m_AdvancedWidget->show(); - m_AdvancedWidget->SetDefaultTooltip(m_AdvancedWidget->GetManipulatedToolTip()); //use the last one, if there is one - m_AdvancedWidget->ReInitialize(); - - // reinit the views with the new nodes - mitk::DataStorage::SetOfObjects::ConstPointer rs = m_DataStorage->GetAll(); - mitk::TimeGeometry::Pointer bounds = m_DataStorage->ComputeBoundingGeometry3D(rs, "visible"); // initialize the views to the bounding geometry - mitk::RenderingManager::GetInstance()->InitializeViews(bounds); - } - else - { - m_AdvancedWidget->hide(); - } -} + m_ToolTransformationWidget->SetToolToEdit(m_ToolToBeEdited); + m_ToolTransformationWidget->SetDefaultRotation(m_ToolToBeEdited->GetToolTipOrientation()); + m_ToolTransformationWidget->SetDefaultOffset(m_ToolToBeEdited->GetToolTipPosition()); -void QmitkNavigationToolCreationWidget::OnProcessDialogCloseRequest() -{ - m_AdvancedWidget->hide(); - m_Controls->m_ShowAdvancedOptionsPB->setChecked(false); + m_ToolTransformationWidget->open(); } -void QmitkNavigationToolCreationWidget::OnRetrieveDataForManualTooltipManipulation() +void QmitkNavigationToolCreationWidget::OnEditToolTipFinished(mitk::AffineTransform3D::Pointer toolTip) { - if(m_Controls->m_Surface_Use_Sphere->isChecked()) + //if user pressed cancle, nullptr is returned. Do nothing. Else, set values. + if (toolTip) { - m_AdvancedWidget->SetToolTipSurface(true); + m_ToolToBeEdited->SetToolTipPosition(toolTip->GetOffset()); + mitk::NavigationData::Pointer tempND = mitk::NavigationData::New(toolTip);//Convert to Navigation data for simple transversion to quaternion + m_ToolToBeEdited->SetToolTipOrientation(tempND->GetOrientation()); + + //Update Label + QString _label = "(" + + QString::number(m_ToolToBeEdited->GetToolTipPosition()[0], 'f', 1) + ", " + + QString::number(m_ToolToBeEdited->GetToolTipPosition()[1], 'f', 1) + ", " + + QString::number(m_ToolToBeEdited->GetToolTipPosition()[2], 'f', 1) + "), quat: [" + + QString::number(m_ToolToBeEdited->GetToolTipOrientation()[0], 'f', 2) + ", " + + QString::number(m_ToolToBeEdited->GetToolTipOrientation()[1], 'f', 2) + ", " + + QString::number(m_ToolToBeEdited->GetToolTipOrientation()[2], 'f', 2) + ", " + + QString::number(m_ToolToBeEdited->GetToolTipOrientation()[3], 'f', 2) + "]"; + m_Controls->m_ToolTipLabel->setText(_label); } - else - { - m_AdvancedWidget->SetToolTipSurface(false, - dynamic_cast(m_Controls->m_SurfaceChooser->GetSelectedNode().GetPointer())); - } -} - -void QmitkNavigationToolCreationWidget::OnSurfaceUseOtherToggled(bool checked) -{ - m_Controls->m_LoadSurface->setEnabled(checked); } void QmitkNavigationToolCreationWidget::FillUIToolLandmarkLists(mitk::PointSet::Pointer calLandmarks, mitk::PointSet::Pointer regLandmarks) { m_calLandmarkNode->SetData(calLandmarks); m_regLandmarkNode->SetData(regLandmarks); m_Controls->m_CalibrationLandmarksList->SetPointSetNode(m_calLandmarkNode); m_Controls->m_RegistrationLandmarksList->SetPointSetNode(m_regLandmarkNode); } void QmitkNavigationToolCreationWidget::GetUIToolLandmarksLists(mitk::PointSet::Pointer& calLandmarks, mitk::PointSet::Pointer& regLandmarks) { calLandmarks = dynamic_cast(m_calLandmarkNode->GetData()); regLandmarks = dynamic_cast(m_regLandmarkNode->GetData()); } void QmitkNavigationToolCreationWidget::InitializeUIToolLandmarkLists() { m_calLandmarkNode = mitk::DataNode::New(); m_regLandmarkNode = mitk::DataNode::New(); - FillUIToolLandmarkLists(mitk::PointSet::New(),mitk::PointSet::New()); + FillUIToolLandmarkLists(mitk::PointSet::New(), mitk::PointSet::New()); } void QmitkNavigationToolCreationWidget::RefreshTrackingDeviceCollection() { us::ModuleContext* context = us::GetModuleContext(); std::vector > refs = context->GetServiceReferences(); if (refs.empty()) { MITK_WARN << "No tracking device service found!"; return; } mitk::TrackingDeviceTypeCollection* _DeviceTypeCollection = context->GetService(refs.front()); for (auto name : _DeviceTypeCollection->GetTrackingDeviceTypeNames()) { //if the device is not included yet, add name to comboBox and widget to stackedWidget if (m_Controls->m_TrackingDeviceTypeChooser->findText(QString::fromStdString(name)) == -1) { m_Controls->m_TrackingDeviceTypeChooser->addItem(QString::fromStdString(name)); } } -} +} \ No newline at end of file diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.h b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.h index 8be1dfc25b..bb0215ed0f 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.h +++ b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.h @@ -1,132 +1,145 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkNavigationToolCreationWidget_H #define QmitkNavigationToolCreationWidget_H //QT headers #include //mitk headers #include "MitkIGTUIExports.h" #include #include #include +#include "QmitkInteractiveTransformationWidget.h" + +#include //Microservices #include #include #include #include -// Qmitk headers -#include "QmitkNavigationToolCreationAdvancedWidget.h" - //ui header #include "ui_QmitkNavigationToolCreationWidget.h" - /** Documentation: - * \brief An object of this class offers an UI to create or modify NavigationTools. - * - * Be sure to call the initialize method before you start the widget - * otherwise some errors might occure. - * - * \ingroup IGTUI - */ +/** Documentation: + * \brief An object of this class offers an UI to create or modify NavigationTools. + * + * Be sure to call the initialize method before you start the widget + * otherwise some errors might occure. + * + * \ingroup IGTUI + */ class MITKIGTUI_EXPORT QmitkNavigationToolCreationWidget : public QWidget { Q_OBJECT - public: - static const std::string VIEW_ID; +public: + static const std::string VIEW_ID; - /** @brief Initializes the widget. - * @param dataStorage The data storage is needed to offer the possibility to choose surfaces from the data storage for tool visualization. - * @param supposedIdentifier This Identifier is supposed for the user. It is needed because every identifier in a navigation tool storage must be unique and we don't know the others. - */ - void Initialize(mitk::DataStorage* dataStorage, const std::string &supposedIdentifier, const std::string &supposedName = "NewTool"); + /** @brief Initializes the widget. + * @param dataStorage The data storage is needed to offer the possibility to choose surfaces from the data storage for tool visualization. + * @param supposedIdentifier This Identifier is supposed for the user. It is needed because every identifier in a navigation tool storage must be unique and we don't know the others. + */ + void Initialize(mitk::DataStorage* dataStorage, const std::string &supposedIdentifier, const std::string &supposedName = "NewTool"); - /** @brief Sets the default tracking device type. You may also define if it is changeable or not.*/ - void SetTrackingDeviceType(mitk::TrackingDeviceType type, bool changeable = true); + /** @brief This Function will add a new node to the Data Manager with given name to enable a preview of the m_ToolToBeEdited + */ + void ShowToolPreview(std::string _name); - /** @brief Sets the default data of all input fields. The default data is used from the default tool which is given as parameter. */ - void SetDefaultData(mitk::NavigationTool::Pointer DefaultTool); + /** @brief Sets the default tracking device type. You may also define if it is changeable or not.*/ + void SetTrackingDeviceType(mitk::TrackingDeviceType type, bool changeable = true); QmitkNavigationToolCreationWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); ~QmitkNavigationToolCreationWidget() override; + /** @brief Sets the default data of all input fields. The default data is used from the default tool which is given as parameter. */ + void SetDefaultData(mitk::NavigationTool::Pointer DefaultTool); /** @return Returns the created tool. Returns nullptr if no tool was created yet. */ mitk::NavigationTool::Pointer GetCreatedTool(); - signals: +signals: - /** @brief This signal is emitted if the user finished the creation of the tool. */ - void NavigationToolFinished(); + /** @brief This signal is emitted if the user finished the creation of the tool. */ + void NavigationToolFinished(); - /** @brief This signal is emitted if the user canceled the creation of the tool. */ - void Canceled(); + /** @brief This signal is emitted if the user canceled the creation of the tool. */ + void Canceled(); protected slots: - void OnCancel(); - void OnFinished(); - void OnLoadSurface(); - void OnLoadCalibrationFile(); - void OnShowAdvancedOptions(bool state); - void OnProcessDialogCloseRequest(); - void OnRetrieveDataForManualTooltipManipulation(); - void OnSurfaceUseOtherToggled(bool checked); - protected: + void OnLoadCalibrationFile(); + void OnSurfaceUseOtherToggled(); + void OnLoadSurface(); + void OnEditToolTip(); + void OnEditToolTipFinished(mitk::AffineTransform3D::Pointer toolTip); + + void OnCancel(); + void OnFinished(); - /// \brief Creation of the connections - virtual void CreateConnections(); + void GetValuesFromGuiElements(); + +private: + + //############## private help methods ####################### + /** Shows a message box with the given message s. */ + void MessageBox(std::string s); + + /** Set the tool landmark lists in the UI.*/ + void FillUIToolLandmarkLists(mitk::PointSet::Pointer calLandmarks, mitk::PointSet::Pointer regLandmarks); + + /** Returns the tool landmark lists from the UI. + * @param[out] calLandmarks Returns a pointer to the calibration landmarks point set. + * @param[out] regLandmarks Returns a pointer to the registration landmarks point set. + */ + void GetUIToolLandmarksLists(mitk::PointSet::Pointer& calLandmarks, mitk::PointSet::Pointer& regLandmarks); - virtual void CreateQtPartControl(QWidget *parent); + /** Initializes the tool landmark lists in the UI. */ + void InitializeUIToolLandmarkLists(); + void RefreshTrackingDeviceCollection(); - Ui::QmitkNavigationToolCreationWidgetControls* m_Controls; + void SetGuiElements(); - QmitkNavigationToolCreationAdvancedWidget* m_AdvancedWidget; +protected: + /// \brief Creation of the connections + virtual void CreateConnections(); - /** @brief holds the DataStorage */ - mitk::DataStorage* m_DataStorage; + virtual void CreateQtPartControl(QWidget *parent); - /** @brief this pointer holds the tool which is created */ - mitk::NavigationTool::Pointer m_CreatedTool; + Ui::QmitkNavigationToolCreationWidgetControls* m_Controls; - //############## private help methods ####################### - /** Shows a message box with the given message s. */ - void MessageBox(std::string s); + /** @brief this pointer holds the tool which is edited. If finished is clicked, it will be copied to the final tool, if it is cancled, it is reseted and not used. + This can be regarded as the clipboard for all changes. */ + mitk::NavigationTool::Pointer m_ToolToBeEdited; - /** Hold the data nodes which are needed for the landmark widgets. */ - mitk::DataNode::Pointer m_calLandmarkNode, m_regLandmarkNode; + /** @brief this pointer holds the tool which is created and returned */ + mitk::NavigationTool::Pointer m_FinalTool; - /** Set the tool landmark lists in the UI.*/ - void FillUIToolLandmarkLists(mitk::PointSet::Pointer calLandmarks, mitk::PointSet::Pointer regLandmarks); + QmitkInteractiveTransformationWidget* m_ToolTransformationWidget; - /** Returns the tool landmark lists from the UI. - * @param[out] calLandmarks Returns a pointer to the calibration landmarks point set. - * @param[out] regLandmarks Returns a pointer to the registration landmarks point set. - */ - void GetUIToolLandmarksLists(mitk::PointSet::Pointer& calLandmarks, mitk::PointSet::Pointer& regLandmarks); + /** @brief holds the DataStorage */ + mitk::DataStorage* m_DataStorage; - /** Initializes the tool landmark lists in the UI. */ - void InitializeUIToolLandmarkLists(); - void RefreshTrackingDeviceCollection(); + /** Hold the data nodes which are needed for the landmark widgets. */ + mitk::DataNode::Pointer m_calLandmarkNode, m_regLandmarkNode; }; #endif diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.ui b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.ui index d65184df95..2e65bfc0e7 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.ui +++ b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.ui @@ -1,571 +1,578 @@ QmitkNavigationToolCreationWidgetControls 0 0 - 255 - 309 + 415 + 351 Form Device Type: 150 0 150 16777215 - 0 + 3 0 0 - 236 - 90 + 397 + 157 Basic Information 100 0 Name: NewTool 100 0 Calibration File: none 40 16777215 Load Qt::Vertical 20 40 0 0 - 310 - 113 + 397 + 157 Tool Visualization Use Simple Cone true Use Surface: Qt::Horizontal QSizePolicy::Fixed 25 20 200 0 150 16777215 false 40 16777215 Load Qt::Horizontal 40 20 Qt::Vertical 20 8 0 0 - 157 - 84 + 397 + 157 Tool Landmarks 1 Calibration Landmarks Registration Landmarks 0 - 0 - 286 - 183 + -3 + 380 + 161 Advanced 100 0 Tool Type: 150 0 150 16777215 Instrument Fiducial Skinmarker Unkown 100 0 Identifier: <not given> 100 0 Serial Number: <not given> Tooltip: + + + + + + + Qt::Horizontal 40 20 - + Edit Tooltip true Qt::Vertical 20 40 Tool Axis: Qt::Horizontal 40 20 QAbstractSpinBox::CorrectToPreviousValue -9999 9999 1 -9999 9999 -9999 9999 Qt::Horizontal Qt::Horizontal 40 20 Cancel Finished QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
1
QmitkPointListWidget QWidget
QmitkPointListWidget.h
1
diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.cpp b/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.cpp index 888f590105..d8d423865e 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.cpp @@ -1,412 +1,442 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkNavigationToolManagementWidget.h" //mitk headers #include "mitkTrackingTypes.h" #include #include #include #include #include #include #include //qt headers #include #include #include #include //poco headers #include const std::string QmitkNavigationToolManagementWidget::VIEW_ID = "org.mitk.views.navigationtoolmanagementwidget"; QmitkNavigationToolManagementWidget::QmitkNavigationToolManagementWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) { m_Controls = nullptr; CreateQtPartControl(this); CreateConnections(); } QmitkNavigationToolManagementWidget::~QmitkNavigationToolManagementWidget() { } void QmitkNavigationToolManagementWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkNavigationToolManagementWidgetControls; m_Controls->setupUi(parent); } //Disable StorageControls in the beginning, because there is no storage to edit DisableStorageControls(); } void QmitkNavigationToolManagementWidget::OnLoadTool() { if (m_NavigationToolStorage->isLocked()) { MessageBox("Storage is locked, cannot modify it. Maybe the tracking device which uses this storage is connected. If you want to modify the storage please disconnect the device first."); return; } mitk::NavigationToolReader::Pointer myReader = mitk::NavigationToolReader::New(); std::string filename = QFileDialog::getOpenFileName(nullptr,tr("Add Navigation Tool"), QmitkIGTCommonHelper::GetLastFileLoadPath(), "*.IGTTool").toLatin1().data(); QmitkIGTCommonHelper::SetLastFileLoadPathByFileName(QString::fromStdString(filename)); if (filename == "") return; mitk::NavigationTool::Pointer readTool = myReader->DoRead(filename); if (readTool.IsNull()) MessageBox("Error: " + myReader->GetErrorMessage()); else { if (!m_NavigationToolStorage->AddTool(readTool)) { MessageBox("Error: Can't add tool!"); m_DataStorage->Remove(readTool->GetDataNode()); } UpdateToolTable(); } } void QmitkNavigationToolManagementWidget::OnSaveTool() { //if no item is selected, show error message: if (m_Controls->m_ToolList->currentItem() == nullptr) { MessageBox("Error: Please select tool first!"); return; } mitk::NavigationToolWriter::Pointer myWriter = mitk::NavigationToolWriter::New(); std::string filename = QFileDialog::getSaveFileName(nullptr,tr("Save Navigation Tool"), QmitkIGTCommonHelper::GetLastFileSavePath(), "*.IGTTool").toLatin1().data(); QmitkIGTCommonHelper::SetLastFileSavePathByFileName(QString::fromStdString(filename)); if (filename == "") return; std::string fileExt = Poco::Path(filename).getExtension(); if (fileExt == "") { filename.append(".IGTTool"); } if (!myWriter->DoWrite(filename,m_NavigationToolStorage->GetTool(m_Controls->m_ToolList->currentIndex().row()))) MessageBox("Error: "+ myWriter->GetErrorMessage()); } void QmitkNavigationToolManagementWidget::CreateConnections() { if (m_Controls) { //main widget page: connect((QObject*)(m_Controls->m_AddTool), SIGNAL(clicked()), this, SLOT(OnAddTool())); connect((QObject*)(m_Controls->m_DeleteTool), SIGNAL(clicked()), this, SLOT(OnDeleteTool())); connect((QObject*)(m_Controls->m_EditTool), SIGNAL(clicked()), this, SLOT(OnEditTool())); connect((QObject*)(m_Controls->m_MoveToolUp), SIGNAL(clicked()), this, SLOT(OnMoveToolUp())); connect((QObject*)(m_Controls->m_MoveToolDown), SIGNAL(clicked()), this, SLOT(OnMoveToolDown())); connect((QObject*)(m_Controls->m_LoadStorage), SIGNAL(clicked()), this, SLOT(OnLoadStorage())); connect((QObject*)(m_Controls->m_SaveStorage), SIGNAL(clicked()), this, SLOT(OnSaveStorage())); connect((QObject*)(m_Controls->m_LoadTool), SIGNAL(clicked()), this, SLOT(OnLoadTool())); connect((QObject*)(m_Controls->m_SaveTool), SIGNAL(clicked()), this, SLOT(OnSaveTool())); connect((QObject*)(m_Controls->m_CreateNewStorage), SIGNAL(clicked()), this, SLOT(OnCreateStorage())); + connect((QObject*)(m_Controls->m_ToolList), SIGNAL(itemClicked(QListWidgetItem *)), this, SLOT(OnToolSelected())); + //widget page "add tool": connect((QObject*)(m_Controls->m_ToolCreationWidget), SIGNAL(Canceled()), this, SLOT(OnAddToolCancel())); connect((QObject*)(m_Controls->m_ToolCreationWidget), SIGNAL(NavigationToolFinished()), this, SLOT(OnAddToolSave())); } } void QmitkNavigationToolManagementWidget::Initialize(mitk::DataStorage* dataStorage) { m_DataStorage = dataStorage; m_Controls->m_ToolCreationWidget->Initialize(m_DataStorage, "Tool0"); } void QmitkNavigationToolManagementWidget::LoadStorage(mitk::NavigationToolStorage::Pointer storageToLoad) { if (storageToLoad.IsNotNull()) { m_NavigationToolStorage = storageToLoad; m_Controls->m_StorageName->setText(m_NavigationToolStorage->GetName().c_str()); EnableStorageControls(); } else { m_NavigationToolStorage = nullptr; DisableStorageControls(); } UpdateToolTable(); } //################################################################################## //############################## slots: main widget ################################ //################################################################################## void QmitkNavigationToolManagementWidget::OnMoveToolUp() { if (m_NavigationToolStorage.IsNotNull()) { + //Proof, if the NavigationToolStorage is locked. If it is locked, show MessageBox to user. + if( m_NavigationToolStorage->isLocked() ) + { + MessageBox("The storage is locked and it cannot be modified. Maybe the tracking device which " \ + "uses this storage is connected. If you want to modify the storage please " \ + "disconnect the device first."); + return; + } int toolIndex = m_Controls->m_ToolList->currentIndex().row(); if (toolIndex >= 0) { mitk::NavigationTool::Pointer currentNavigationTool = m_NavigationToolStorage->GetTool(toolIndex); if (currentNavigationTool.IsNotNull()) { std::string currentIdentifier = currentNavigationTool->GetIdentifier(); int NewNumber = m_Controls->m_ToolList->currentIndex().row() - 1; if (NewNumber < 0) { MITK_WARN << "Cannot move tool up because it is on the top!"; } else { m_NavigationToolStorage->AssignToolNumber(currentIdentifier, NewNumber); } UpdateToolTable(); } } } } void QmitkNavigationToolManagementWidget::OnMoveToolDown() { if (m_NavigationToolStorage.IsNotNull()) { + //Proof, if the NavigationToolStorage is locked. If it is locked, show MessageBox to user. + if( m_NavigationToolStorage->isLocked() ) + { + MessageBox("The storage is locked and it cannot be modified. Maybe the tracking device which " \ + "uses this storage is connected. If you want to modify the storage please " \ + "disconnect the device first."); + return; + } int toolIndex = m_Controls->m_ToolList->currentIndex().row(); if (toolIndex >= 0) { mitk::NavigationTool::Pointer currentNavigationTool = m_NavigationToolStorage->GetTool(toolIndex); if (currentNavigationTool.IsNotNull()) { std::string currentIdentifier = currentNavigationTool->GetIdentifier(); int NewNumber = m_Controls->m_ToolList->currentIndex().row() + 1; if (NewNumber >= m_NavigationToolStorage->GetToolCount()) { MITK_WARN << "Cannot move tool down because it is the last tool in this storage!"; } else { m_NavigationToolStorage->AssignToolNumber(currentIdentifier, NewNumber); } UpdateToolTable(); } } } } void QmitkNavigationToolManagementWidget::OnAddTool() { if (m_NavigationToolStorage->isLocked()) { MessageBox("Storage is locked, cannot modify it. Maybe the tracking device which uses this storage is connected. If you want to modify the storage please disconnect the device first."); return; } QString defaultIdentifier = "NavigationTool#" + QString::number(m_NavigationToolStorage->GetToolCount()); QString defaultName = "NavigationTool" + QString::number(m_NavigationToolStorage->GetToolCount()); m_Controls->m_ToolCreationWidget->Initialize(m_DataStorage, defaultIdentifier.toStdString(), defaultName.toStdString()); + m_Controls->m_ToolCreationWidget->ShowToolPreview("Tool preview"); m_edit = false; m_Controls->m_MainWidgets->setCurrentIndex(1); } void QmitkNavigationToolManagementWidget::OnDeleteTool() { //first: some checks if (m_NavigationToolStorage->isLocked()) { MessageBox("Storage is locked, cannot modify it. Maybe the tracking device which uses this storage is connected. If you want to modify the storage please disconnect the device first."); return; } else if (m_Controls->m_ToolList->currentItem() == nullptr) //if no item is selected, show error message: { MessageBox("Error: Please select tool first!"); return; } m_DataStorage->Remove(m_NavigationToolStorage->GetTool(m_Controls->m_ToolList->currentIndex().row())->GetDataNode()); m_NavigationToolStorage->DeleteTool(m_Controls->m_ToolList->currentIndex().row()); UpdateToolTable(); } void QmitkNavigationToolManagementWidget::OnEditTool() { if (m_NavigationToolStorage->isLocked()) { MessageBox("Storage is locked, cannot modify it. Maybe the tracking device which uses this storage is connected. If you want to modify the storage please disconnect the device first."); return; } else if (m_Controls->m_ToolList->currentItem() == nullptr) //if no item is selected, show error message: { MessageBox("Error: Please select tool first!"); return; } mitk::NavigationTool::Pointer selectedTool = m_NavigationToolStorage->GetTool(m_Controls->m_ToolList->currentIndex().row()); + m_Controls->m_ToolCreationWidget->Initialize(m_DataStorage, "", ""); //Initialize once again, might be called here for the first time after autodetection m_Controls->m_ToolCreationWidget->SetDefaultData(selectedTool); - m_NavigationToolStorage->SetName("test"); + m_Controls->m_ToolCreationWidget->ShowToolPreview("Tool preview"); m_edit = true; m_Controls->m_MainWidgets->setCurrentIndex(1); } void QmitkNavigationToolManagementWidget::OnCreateStorage() { QString storageName = QInputDialog::getText(nullptr, "Storage Name", "Name of the new tool storage:"); if (storageName.isNull()) return; m_NavigationToolStorage = mitk::NavigationToolStorage::New(this->m_DataStorage); m_NavigationToolStorage->SetName(storageName.toStdString()); m_Controls->m_StorageName->setText(m_NavigationToolStorage->GetName().c_str()); EnableStorageControls(); emit NewStorageAdded(m_NavigationToolStorage, storageName.toStdString()); } void QmitkNavigationToolManagementWidget::OnLoadStorage() { mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(m_DataStorage); - std::string filename = QFileDialog::getOpenFileName(nullptr, tr("Open Navigation Tool Storage"), "/", tr("IGT Tool Storage (*.IGTToolStorage)")).toStdString(); + std::string filename = QFileDialog::getOpenFileName(nullptr, tr("Open Navigation Tool Storage"), QmitkIGTCommonHelper::GetLastFileLoadPath(), tr("IGT Tool Storage (*.IGTToolStorage)")).toStdString(); if (filename == "") return; + QmitkIGTCommonHelper::SetLastFileLoadPathByFileName(QString::fromStdString(filename)); try { - mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(m_DataStorage); - std::string filename = QFileDialog::getOpenFileName(NULL, tr("Open Navigation Tool Storage"), QmitkIGTCommonHelper::GetLastFileLoadPath(), tr("IGT Tool Storage (*.IGTToolStorage)")).toStdString(); - if (filename == "") return; - - QmitkIGTCommonHelper::SetLastFileLoadPathByFileName(QString::fromStdString(filename)); + mitk::NavigationToolStorage::Pointer tempStorage = myDeserializer->Deserialize(filename); - try + if (tempStorage.IsNull()) MessageBox("Error" + myDeserializer->GetErrorMessage()); + else { - mitk::NavigationToolStorage::Pointer tempStorage = myDeserializer->Deserialize(filename); - - if (tempStorage.IsNull()) MessageBox("Error" + myDeserializer->GetErrorMessage()); - else - { - Poco::Path myPath = Poco::Path(filename.c_str()); - tempStorage->SetName(myPath.getFileName()); //set the filename as name for the storage, so the user can identify it - this->LoadStorage(tempStorage); - emit NewStorageAdded(m_NavigationToolStorage,myPath.getFileName()); - } - } - catch (const mitk::Exception& exception) - { - MessageBox(exception.GetDescription()); + Poco::Path myPath = Poco::Path(filename.c_str()); + tempStorage->SetName(myPath.getFileName()); //set the filename as name for the storage, so the user can identify it + this->LoadStorage(tempStorage); + emit NewStorageAdded(m_NavigationToolStorage,myPath.getFileName()); } } catch (const mitk::Exception& exception) { MessageBox(exception.GetDescription()); } } void QmitkNavigationToolManagementWidget::OnSaveStorage() { QFileDialog *fileDialog = new QFileDialog; fileDialog->setDefaultSuffix("IGTToolStorage"); QString suffix = "IGT Tool Storage (*.IGTToolStorage)"; QString filename = fileDialog->getSaveFileName(nullptr, tr("Save Navigation Tool Storage"), QmitkIGTCommonHelper::GetLastFileSavePath(), suffix, &suffix); if (filename.isEmpty()) return; //canceled by the user // check file suffix QFileInfo file(filename); if(file.suffix().isEmpty()) filename += ".IGTToolStorage"; //serialize tool storage mitk::NavigationToolStorageSerializer::Pointer mySerializer = mitk::NavigationToolStorageSerializer::New(); if (!mySerializer->Serialize(filename.toStdString(), m_NavigationToolStorage)) { MessageBox("Error: " + mySerializer->GetErrorMessage()); return; QmitkIGTCommonHelper::SetLastFileSavePath(file.absolutePath()); } Poco::Path myPath = Poco::Path(filename.toStdString()); m_Controls->m_StorageName->setText(QString::fromStdString(myPath.getFileName())); } //################################################################################## //############################## slots: add tool widget ############################ //################################################################################## void QmitkNavigationToolManagementWidget::OnAddToolSave() { + //Proof, if the NavigationToolStorage is locked. If it is locked, show MessageBox to user. + if( m_NavigationToolStorage->isLocked() ) + { + MessageBox( "The storage is locked and it cannot be modified. Maybe the tracking device which " \ + "uses this storage is connected. If you want to modify the storage please " \ + "disconnect the device first."); + return; + } + mitk::NavigationTool::Pointer newTool = m_Controls->m_ToolCreationWidget->GetCreatedTool(); if (m_edit) //here we edit a existing tool { mitk::NavigationTool::Pointer editedTool = m_NavigationToolStorage->GetTool(m_Controls->m_ToolList->currentIndex().row()); editedTool->Graft(newTool); //Keep this line, 'cause otherwise, the NavigationToolStorage wouldn't notice, that the toolStorage changed. m_NavigationToolStorage->UpdateMicroservice(); } else //here we create a new tool { m_NavigationToolStorage->AddTool(newTool); } + //Remove tool preview + m_DataStorage->Remove(m_DataStorage->GetNamedNode("Tool preview")); + UpdateToolTable(); m_Controls->m_MainWidgets->setCurrentIndex(0); + m_Controls->m_ToolInformation->setText(""); } void QmitkNavigationToolManagementWidget::OnAddToolCancel() { m_Controls->m_MainWidgets->setCurrentIndex(0); + //Remove tool preview + m_DataStorage->Remove(m_DataStorage->GetNamedNode("Tool preview")); +} + +void QmitkNavigationToolManagementWidget::OnToolSelected() +{ + QString _label = "Information for tool " + m_Controls->m_ToolList->currentItem()->text() + "\n"; + _label.append(QString(m_NavigationToolStorage->GetTool(m_Controls->m_ToolList->currentIndex().row())->GetStringWithAllToolInformation().c_str())); + m_Controls->m_ToolInformation->setText(_label); } //################################################################################## //############################## private help methods ############################## //################################################################################## void QmitkNavigationToolManagementWidget::UpdateToolTable() { m_Controls->m_ToolList->clear(); if (m_NavigationToolStorage.IsNull()) return; for (int i = 0; i < m_NavigationToolStorage->GetToolCount(); i++) { - QString currentTool = "Tool" + QString::number(i) + ": " + QString(m_NavigationToolStorage->GetTool(i)->GetDataNode()->GetName().c_str()) + " "; + QString currentTool = "Tool" + QString::number(i) + ": " + QString(m_NavigationToolStorage->GetTool(i)->GetToolName().c_str()) + " "; currentTool += "(" + QString::fromStdString(m_NavigationToolStorage->GetTool(i)->GetTrackingDeviceType()) + "/"; switch (m_NavigationToolStorage->GetTool(i)->GetType()) { case mitk::NavigationTool::Instrument: currentTool += "Instrument)"; break; case mitk::NavigationTool::Fiducial: currentTool += "Fiducial)"; break; case mitk::NavigationTool::Skinmarker: currentTool += "Skinmarker)"; break; default: currentTool += "Unknown)"; } m_Controls->m_ToolList->addItem(currentTool); } } void QmitkNavigationToolManagementWidget::MessageBox(std::string s) { QMessageBox msgBox; msgBox.setText(s.c_str()); msgBox.exec(); } void QmitkNavigationToolManagementWidget::DisableStorageControls() { m_Controls->m_StorageName->setText(""); m_Controls->m_AddTool->setEnabled(false); m_Controls->m_LoadTool->setEnabled(false); m_Controls->m_MoveToolUp->setEnabled(false); m_Controls->m_MoveToolDown->setEnabled(false); m_Controls->m_selectedLabel->setEnabled(false); m_Controls->m_DeleteTool->setEnabled(false); m_Controls->m_EditTool->setEnabled(false); m_Controls->m_SaveTool->setEnabled(false); m_Controls->m_ToolList->setEnabled(false); m_Controls->m_SaveStorage->setEnabled(false); m_Controls->m_ToolLabel->setEnabled(false); } void QmitkNavigationToolManagementWidget::EnableStorageControls() { m_Controls->m_AddTool->setEnabled(true); m_Controls->m_LoadTool->setEnabled(true); m_Controls->m_MoveToolUp->setEnabled(true); m_Controls->m_MoveToolDown->setEnabled(true); m_Controls->m_selectedLabel->setEnabled(true); m_Controls->m_DeleteTool->setEnabled(true); m_Controls->m_EditTool->setEnabled(true); m_Controls->m_SaveTool->setEnabled(true); m_Controls->m_ToolList->setEnabled(true); m_Controls->m_SaveStorage->setEnabled(true); m_Controls->m_ToolLabel->setEnabled(true); } diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.h b/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.h index c8bef65e8a..260a9eece9 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.h +++ b/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.h @@ -1,112 +1,113 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKNAVIGATIONTOOLMANAGEMENTWIDGET_H #define QMITKNAVIGATIONTOOLMANAGEMENTWIDGET_H //QT headers #include //mitk headers #include "MitkIGTUIExports.h" #include "mitkNavigationTool.h" #include //ui header #include "ui_QmitkNavigationToolManagementWidgetControls.h" /** Documentation: * \brief An object of this class offers an UI to manage NavigationTools and * NavigationToolStorages. This means a user may create, save and load * single NavigationTools and/or NavigationToolStorages with this widget. * * Be sure to call the Initialize-methode before you start the widget * otherwise some errors might occure. * * \ingroup IGTUI */ class MITKIGTUI_EXPORT QmitkNavigationToolManagementWidget : public QWidget { Q_OBJECT public: static const std::string VIEW_ID; /** Initializes the widget. Has to be called before any action, otherwise errors might occur. */ void Initialize(mitk::DataStorage* dataStorage); /** Loads a storage to the widget. The old storage storage is dropped, so be careful, if the * storage is not saved somewhere else it might be lost. You might want to ask the user if he * wants to save the storage to the harddisk before calling this method. * @param storageToLoad This storage will be loaded and might be modified by the user. */ void LoadStorage(mitk::NavigationToolStorage::Pointer storageToLoad); QmitkNavigationToolManagementWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); ~QmitkNavigationToolManagementWidget() override; signals: /** This signal is emmited if a new storage was added by the widget itself, e.g. because * a storage was loaded from the harddisk. * @param newStorage Holds the new storage which was added. * @param storageName Name of the new storage (e.g. filename) */ void NewStorageAdded(mitk::NavigationToolStorage::Pointer newStorage, std::string storageName); protected slots: //main widget page: void OnAddTool(); void OnDeleteTool(); void OnEditTool(); void OnLoadTool(); void OnSaveTool(); void OnMoveToolUp(); void OnMoveToolDown(); void OnLoadStorage(); void OnSaveStorage(); void OnCreateStorage(); + void OnToolSelected(); //widget page "add tool": void OnAddToolCancel(); void OnAddToolSave(); protected: /// \brief Creation of the connections virtual void CreateConnections(); virtual void CreateQtPartControl(QWidget *parent); Ui::QmitkNavigationToolManagementWidgetControls* m_Controls; /** @brief holds the DataStorage */ mitk::DataStorage* m_DataStorage; /** @brief holds the NavigationToolStorage we are working with. */ mitk::NavigationToolStorage::Pointer m_NavigationToolStorage; /** @brief shows if we are in edit mode, if not we create new navigation tool objects. */ bool m_edit; //############## private help methods ####################### void MessageBox(std::string s); void UpdateToolTable(); void DisableStorageControls(); void EnableStorageControls(); }; #endif diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidgetControls.ui b/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidgetControls.ui index a80055349a..b246da95c5 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidgetControls.ui +++ b/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidgetControls.ui @@ -1,308 +1,315 @@ QmitkNavigationToolManagementWidgetControls 0 0 443 781 Form Qt::Horizontal 40 20 Whole Storage: Create New Load Save Qt::Horizontal 0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Storage Name:</span></p></body></html> <none> Qt::Horizontal 40 20 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Tools:</span></p></body></html> Qt::Horizontal 40 20 50 16777215 Add 50 16777215 Load <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Selected:</span></p></body></html> 50 16777215 Up 50 16777215 Down 50 16777215 Delete 50 16777215 Edit 50 16777215 Save Qt::Vertical 20 40 0 150 Qt::Vertical 20 40 + + + + + + + QmitkNavigationToolCreationWidget QWidget
QmitkNavigationToolCreationWidget.h
1
diff --git a/Modules/IGTUI/Qmitk/QmitkOpenIGTLinkWidget.ui b/Modules/IGTUI/Qmitk/QmitkOpenIGTLinkWidget.ui index a587c5fa52..d79cfdb81f 100644 --- a/Modules/IGTUI/Qmitk/QmitkOpenIGTLinkWidget.ui +++ b/Modules/IGTUI/Qmitk/QmitkOpenIGTLinkWidget.ui @@ -1,129 +1,133 @@ QmitkOpenIGTLinkWidget 0 0 294 - 169 + 140 <html><head/><body><p><span style=" text-decoration: underline;">Open IGT Link Connection</span></p></body></html> - - - Hostname: - - - - - - - 127.0.0.1 - - - - - + - + - Port: + Hostname: - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 50 - 16777215 - - + - 18944 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + 127.0.0.1 - - - - - - - Update Rate: - - + + + + + Port: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 50 + 16777215 + + + + 18944 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + Update Rate: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 1 + + + 999 + + + 60 + + + + - + - Qt::Horizontal + Qt::Vertical - 40 - 20 + 20 + 40 - - - - 1 - - - 999 - - - 60 - - - - - - - Qt::Vertical - - - - 20 - 66 - - - - diff --git a/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.cpp b/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.cpp index 1196c0c290..3ef829be6d 100644 --- a/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.cpp @@ -1,271 +1,299 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkPolhemusTrackerWidget.h" #include #include #include #include #include #include #include #include #include "vtkRenderer.h" #include "vtkCamera.h" const std::string QmitkPolhemusTrackerWidget::VIEW_ID = "org.mitk.views.PolhemusTrackerWidget"; QmitkPolhemusTrackerWidget::QmitkPolhemusTrackerWidget(QWidget* parent, Qt::WindowFlags f) : QmitkAbstractTrackingDeviceWidget(parent, f) , m_Controls(nullptr) { } void QmitkPolhemusTrackerWidget::Initialize() { InitializeSuperclassWidget(); CreateQtPartControl(this); SetAdvancedSettingsEnabled(false); on_m_AdvancedSettings_clicked(); //hide advanced settings on setup } QmitkPolhemusTrackerWidget::~QmitkPolhemusTrackerWidget() { delete m_Controls; } void QmitkPolhemusTrackerWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkPolhemusTrackerWidget; m_Controls->setupUi(parent); } } void QmitkPolhemusTrackerWidget::OnToolStorageChanged() { this->m_TrackingDevice = nullptr; MITK_DEBUG<<"Resetting Polhemus Tracking Device, because tool storage changed."; } void QmitkPolhemusTrackerWidget::CreateConnections() { if (m_Controls) { connect((QObject*)(m_Controls->m_hemisphereTracking), SIGNAL(clicked()), this, SLOT(on_m_hemisphereTracking_clicked())); connect((QObject*)(m_Controls->m_ToggleHemisphere), SIGNAL(clicked()), this, SLOT(on_m_ToggleHemisphere_clicked())); connect((QObject*)(m_Controls->m_SetHemisphere), SIGNAL(clicked()), this, SLOT(on_m_SetHemisphere_clicked())); connect((QObject*)(m_Controls->m_GetHemisphere), SIGNAL(clicked()), this, SLOT(on_m_GetHemisphere_clicked())); connect((QObject*)(m_Controls->m_AdjustHemisphere), SIGNAL(clicked()), this, SLOT(on_m_AdjustHemisphere_clicked())); connect((QObject*)(m_Controls->m_AdvancedSettings), SIGNAL(clicked()), this, SLOT(on_m_AdvancedSettings_clicked())); + connect((QObject*)(m_Controls->m_ToggleToolTipCalibration), SIGNAL(clicked()), this, SLOT(on_m_ToggleToolTipCalibration_clicked())); } } mitk::TrackingDevice::Pointer QmitkPolhemusTrackerWidget::GetTrackingDevice() { if (m_TrackingDevice.IsNull()) { m_TrackingDevice = mitk::PolhemusTrackingDevice::New(); m_TrackingDevice->SetHemisphereTrackingEnabled(m_Controls->m_hemisphereTracking->isChecked()); } return static_cast(m_TrackingDevice); } QmitkPolhemusTrackerWidget* QmitkPolhemusTrackerWidget::Clone(QWidget* parent) const { QmitkPolhemusTrackerWidget* clonedWidget = new QmitkPolhemusTrackerWidget(parent); clonedWidget->Initialize(); return clonedWidget; } void QmitkPolhemusTrackerWidget::on_m_hemisphereTracking_clicked() { m_TrackingDevice->SetHemisphereTrackingEnabled(m_Controls->m_hemisphereTracking->isChecked()); } void QmitkPolhemusTrackerWidget::on_m_ToggleHemisphere_clicked() { // Index 0 == All Tools == -1 for Polhemus interface; Index 2 == Tool 2 == 1 for Polhemus; etc... m_TrackingDevice->ToggleHemisphere(GetSelectedToolIndex()); MITK_INFO << "Toggle Hemisphere for tool " << m_Controls->m_ToolSelection->currentText().toStdString(); } void QmitkPolhemusTrackerWidget::on_m_SetHemisphere_clicked() { mitk::Vector3D _hemisphere; mitk::FillVector3D(_hemisphere, m_Controls->m_Hemisphere_X->value(), m_Controls->m_Hemisphere_Y->value(), m_Controls->m_Hemisphere_Z->value()); m_TrackingDevice->SetHemisphere(GetSelectedToolIndex(), _hemisphere); //If you set a hemisphere vector which is unequal (0|0|0), this means, that there is no hemisphere tracking any more //disable the checkbox in case it was on before, so that it can be reactivated... if (_hemisphere.GetNorm() != 0) m_Controls->m_hemisphereTracking->setChecked(false); MITK_INFO << "Hemisphere set for tool " << m_Controls->m_ToolSelection->currentText().toStdString(); } void QmitkPolhemusTrackerWidget::on_m_GetHemisphere_clicked() { mitk::Vector3D _hemisphere = m_TrackingDevice->GetHemisphere(GetSelectedToolIndex()); m_Controls->m_Hemisphere_X->setValue(_hemisphere[0]); m_Controls->m_Hemisphere_Y->setValue(_hemisphere[1]); m_Controls->m_Hemisphere_Z->setValue(_hemisphere[2]); QString label; if (m_TrackingDevice->GetHemisphereTrackingEnabled(GetSelectedToolIndex())) { label = "HemisphereTracking is ON for tool "; label.append(m_Controls->m_ToolSelection->currentText()); } + else if (GetSelectedToolIndex() == -1) + { + label = "HemisphereTracking is OFF for at least one tool."; + } else { label = "HemisphereTracking is OFF for tool "; label.append(m_Controls->m_ToolSelection->currentText()); } m_Controls->m_StatusLabelHemisphereTracking->setText(label); MITK_INFO << "Updated SpinBox for Hemisphere of tool " << m_Controls->m_ToolSelection->currentText().toStdString(); } void QmitkPolhemusTrackerWidget::on_m_AdjustHemisphere_clicked() { int _tool = GetSelectedToolIndex(); QMessageBox msgBox; QString _text; if (_tool == -1) { _text.append("Adjusting hemisphere for all tools."); msgBox.setText(_text); _text.clear(); _text = tr("Please make sure, that the entire tools (including tool tip AND sensor) are placed in the positive x hemisphere. Press 'Adjust hemisphere' if you are ready."); msgBox.setInformativeText(_text); } else { _text.append("Adjusting hemisphere for tool '"); _text.append(m_Controls->m_ToolSelection->currentText()); _text.append(tr("' at port %2.").arg(_tool)); msgBox.setText(_text); _text.clear(); _text = tr("Please make sure, that the entire tool (including tool tip AND sensor) is placed in the positive x hemisphere. Press 'Adjust hemisphere' if you are ready."); msgBox.setInformativeText(_text); } QPushButton *adjustButton = msgBox.addButton(tr("Adjust hemisphere"), QMessageBox::ActionRole); QPushButton *cancelButton = msgBox.addButton(QMessageBox::Cancel); msgBox.exec(); if (msgBox.clickedButton() == adjustButton) { // adjust m_TrackingDevice->AdjustHemisphere(_tool); MITK_INFO << "Adjusting Hemisphere for tool " << m_Controls->m_ToolSelection->currentText().toStdString(); } else if (msgBox.clickedButton() == cancelButton) { // abort MITK_INFO << "Cancel 'Adjust hemisphere'. No harm done..."; } } +void QmitkPolhemusTrackerWidget::on_m_ToggleToolTipCalibration_clicked() +{ + if (m_Controls->m_ToolSelection->currentIndex() != 0) + { + mitk::PolhemusTool* _tool = dynamic_cast (this->m_TrackingDevice->GetToolByName(m_Controls->m_ToolSelection->currentText().toStdString())); + mitk::Point3D tip = _tool->GetToolTip().GetVectorFromOrigin()*(-1.); + mitk::Quaternion quat = _tool->GetToolTipOrientation().inverse(); + _tool->SetToolTip(tip, quat); + } + else + { + for (int i = 0; i < m_TrackingDevice->GetToolCount(); ++i) + { + mitk::PolhemusTool* _tool = dynamic_cast (this->m_TrackingDevice->GetTool(i)); + mitk::Point3D tip = _tool->GetToolTip().GetVectorFromOrigin()*(-1.); + mitk::Quaternion quat = _tool->GetToolTipOrientation().inverse(); + _tool->SetToolTip(tip, quat); + } + } +} + void QmitkPolhemusTrackerWidget::OnConnected(bool _success) { if (!_success) { this->m_TrackingDevice = nullptr; return; } SetAdvancedSettingsEnabled(true); if (m_TrackingDevice->GetToolCount() != m_Controls->m_ToolSelection->count()) { m_Controls->m_ToolSelection->clear(); m_Controls->m_ToolSelection->addItem("All Tools"); for (int i = 0; i < m_TrackingDevice->GetToolCount(); ++i) { m_Controls->m_ToolSelection->addItem(m_TrackingDevice->GetTool(i)->GetToolName()); } } } void QmitkPolhemusTrackerWidget::OnStartTracking(bool _success) { if (!_success) return; //Rotate mitk standard multi widget, so that the view matches the sensor. Positive x == right, y == front, z == down; mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetCameraController()->SetViewToPosterior(); mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetVtkRenderer()->GetActiveCamera()->SetViewUp(0, 0, -1); } void QmitkPolhemusTrackerWidget::OnDisconnected(bool _success) { if (!_success) return; SetAdvancedSettingsEnabled(false); } void QmitkPolhemusTrackerWidget::SetAdvancedSettingsEnabled(bool _enable) { m_Controls->m_ToolSelection->setEnabled(_enable); m_Controls->label_toolsToChange->setEnabled(_enable); m_Controls->label_UpdateOnRequest->setEnabled(_enable); m_Controls->m_GetHemisphere->setEnabled(_enable); m_Controls->m_Hemisphere_X->setEnabled(_enable); m_Controls->m_Hemisphere_Y->setEnabled(_enable); m_Controls->m_Hemisphere_Z->setEnabled(_enable); m_Controls->m_SetHemisphere->setEnabled(_enable); m_Controls->m_ToggleHemisphere->setEnabled(_enable); m_Controls->m_AdjustHemisphere->setEnabled(_enable); + m_Controls->m_ToggleToolTipCalibration->setEnabled(_enable); } void QmitkPolhemusTrackerWidget::on_m_AdvancedSettings_clicked() { bool _enable = m_Controls->m_AdvancedSettings->isChecked(); m_Controls->m_ToolSelection->setVisible(_enable); m_Controls->label_toolsToChange->setVisible(_enable); m_Controls->label_UpdateOnRequest->setVisible(_enable); m_Controls->m_GetHemisphere->setVisible(_enable); m_Controls->m_Hemisphere_X->setVisible(_enable); m_Controls->m_Hemisphere_Y->setVisible(_enable); m_Controls->m_Hemisphere_Z->setVisible(_enable); m_Controls->m_SetHemisphere->setVisible(_enable); m_Controls->m_ToggleHemisphere->setVisible(_enable); m_Controls->m_AdjustHemisphere->setVisible(_enable); + m_Controls->m_ToggleToolTipCalibration->setVisible(_enable); m_Controls->m_StatusLabelHemisphereTracking->setVisible(_enable); } int QmitkPolhemusTrackerWidget::GetSelectedToolIndex() { // Index 0 == All Tools == -1 for Polhemus interface; Index 1 == Tool 1 == 1 for Polhemus Interface; etc... int _index = m_Controls->m_ToolSelection->currentIndex() - 1; if (_index != -1) { //we need to find the internal Polhemus index for this tool. This is stored in the identifier of a navigation tool or as Port in PolhemusTool. mitk::PolhemusTool* _tool = dynamic_cast(m_TrackingDevice->GetToolByName(m_Controls->m_ToolSelection->currentText().toStdString())); _index = _tool->GetToolPort(); } return _index; } \ No newline at end of file diff --git a/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.h b/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.h index d2e7bbe970..56c0595f3d 100644 --- a/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.h +++ b/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.h @@ -1,95 +1,96 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkPolhemusTrackerWidget_H #define QmitkPolhemusTrackerWidget_H #include "ui_QmitkPolhemusTrackerWidget.h" #include "QmitkAbstractTrackingDeviceWidget.h" #include /** Documentation: * \brief Implementation of a configuration widget for Polhemus Tracking Devices. * * \ingroup IGTUI */ class MITKIGTUI_EXPORT QmitkPolhemusTrackerWidget : public QmitkAbstractTrackingDeviceWidget { Q_OBJECT // this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) public: static const std::string VIEW_ID; QmitkPolhemusTrackerWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); ~QmitkPolhemusTrackerWidget(); virtual void Initialize(); signals: protected slots : void on_m_hemisphereTracking_clicked(); void on_m_ToggleHemisphere_clicked(); void on_m_SetHemisphere_clicked(); void on_m_GetHemisphere_clicked(); void on_m_AdjustHemisphere_clicked(); void on_m_AdvancedSettings_clicked(); + void on_m_ToggleToolTipCalibration_clicked(); private: /// \brief Creation of the connections void CreateConnections(); void CreateQtPartControl(QWidget *parent); void SetAdvancedSettingsEnabled(bool _enable); int GetSelectedToolIndex(); protected: virtual QmitkPolhemusTrackerWidget* Clone(QWidget* parent) const; Ui::QmitkPolhemusTrackerWidget* m_Controls; mitk::PolhemusTrackingDevice::Pointer m_TrackingDevice; public: virtual mitk::TrackingDevice::Pointer GetTrackingDevice(); /** * \brief This function is called, when in the TrackingToolboxView "Connect" was clicked and the device is successful connected. * Can e.g. be used to activate options of a tracking device only when it is connected. */ virtual void OnConnected( bool _success); /** * \brief This function is called, when in the TrackingToolboxView "Disconnect" was clicked and the device is successful disconnected. * Can e.g. be used to activate/disactivate options of a tracking device. */ virtual void OnDisconnected(bool _success); /** * \brief This function is called, when in the TrackingToolboxView "Start Tracking" was clicked and the device successfully started tracking. * Can e.g. be used to activate options of a tracking device only when tracking is started. */ virtual void OnStartTracking(bool _success); /** * \brief This function is called, when anything in the ToolStorage changed, e.g. AddTool or EditTool. * ServiceListener is connected in the QmitkMITKIGTTrackingToolboxView. */ virtual void OnToolStorageChanged(); }; #endif diff --git a/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.ui b/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.ui index 4203265d33..eca4075ca9 100644 --- a/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.ui +++ b/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.ui @@ -1,167 +1,174 @@ QmitkPolhemusTrackerWidget 0 0 475 324 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" text-decoration: underline;">Polhemus Tracker</span></p></body></html> Enable hemisphere tracking (for all tools) true Show Advanced Settings Qt::Horizontal Tools to change: Spinbox values and label are only updated on request (click 'Get Hemisphere'). Get Hemisphere -10 10 -10 10 -10 10 Set Hemisphere Toggle Hemisphere Adjust Hemisphere + + + + Toggle Tool Tip Calibration + + + Qt::Vertical 20 40 diff --git a/Modules/IGTUI/Qmitk/QmitkToolTrackingStatusWidget.cpp b/Modules/IGTUI/Qmitk/QmitkToolTrackingStatusWidget.cpp index 8e188a48d3..f75837b771 100644 --- a/Modules/IGTUI/Qmitk/QmitkToolTrackingStatusWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkToolTrackingStatusWidget.cpp @@ -1,272 +1,273 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkToolTrackingStatusWidget.h" #include QmitkToolTrackingStatusWidget::QmitkToolTrackingStatusWidget(QWidget* parent) : QWidget(parent), m_Controls(nullptr), m_StatusLabels(nullptr), m_NavigationDatas(nullptr), m_NavDatasNewFlag(false) { m_ShowPositions = false; m_ShowQuaternions = false; m_Alignment = Qt::AlignHCenter; m_Style = QmitkToolTrackingStatusWidget::VerticalUpperStyle; CreateQtPartControl( this ); } void QmitkToolTrackingStatusWidget::SetStyle(QmitkToolTrackingStatusWidget::Style newStyle) { //set new style m_Style = newStyle; //update current labels to show them in the new style Refresh(); } void QmitkToolTrackingStatusWidget::SetShowPositions(bool enable) { m_ShowPositions = enable; //update current labels Refresh(); } void QmitkToolTrackingStatusWidget::SetShowQuaternions(bool enable) { m_ShowQuaternions = enable; //update current labels Refresh(); } void QmitkToolTrackingStatusWidget::SetTextAlignment(Qt::AlignmentFlag alignment) { m_Alignment = alignment; //update current labels Refresh(); } QmitkToolTrackingStatusWidget::~QmitkToolTrackingStatusWidget() { //m_Controls = nullptr; if (m_StatusLabels!=nullptr) {delete m_StatusLabels;} if (m_NavigationDatas != nullptr) { m_NavigationDatas->clear(); if (m_NavDatasNewFlag) { delete m_NavigationDatas; } } } void QmitkToolTrackingStatusWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkToolTrackingStatusWidgetControls; m_Controls->setupUi(parent); this->CreateConnections(); //add empty label AddEmptyLabel(); } m_Context = us::GetModuleContext(); std::string m_Filter = "(" + us::ServiceConstants::OBJECTCLASS() + "=" + "org.mitk.services.NavigationToolStorage" + ")"; m_Context->AddServiceListener(this, &QmitkToolTrackingStatusWidget::OnServiceEvent, m_Filter); } void QmitkToolTrackingStatusWidget::OnServiceEvent(const us::ServiceEvent event) { if ((event.GetType() == us::ServiceEvent::MODIFIED) && (m_previewToolStorage.IsNotNull())) {this->PreShowTools(m_previewToolStorage);} } void QmitkToolTrackingStatusWidget::CreateConnections() { } void QmitkToolTrackingStatusWidget::SetNavigationDatas(std::vector* navDatas) { m_NavigationDatas = navDatas; m_previewToolStorage = nullptr; } void QmitkToolTrackingStatusWidget::AddNavigationData(mitk::NavigationData::Pointer nd) { if(m_NavigationDatas == nullptr) { m_NavigationDatas = new std::vector(); m_NavDatasNewFlag = true; m_previewToolStorage = nullptr; } m_NavigationDatas->push_back(nd); } void QmitkToolTrackingStatusWidget::Refresh(int posPrecision, int quatPrecision) { if(m_NavigationDatas == nullptr || m_NavigationDatas->size() <= 0) { RemoveGuiLabels(); AddEmptyLabel(); return; } mitk::NavigationData* navData; for(unsigned int i = 0; i < m_NavigationDatas->size(); i++) { navData = m_NavigationDatas->at(i).GetPointer(); QString name(navData->GetName()); QString pos = ""; QString quat = ""; if (m_ShowPositions) { mitk::Point3D position = navData->GetPosition(); pos = " [" + QString::number(position[0],'f',posPrecision) + ";" + QString::number(position[1],'f',posPrecision) + ";" + QString::number(position[2],'f',posPrecision) + "]"; } if (m_ShowQuaternions) { mitk::Quaternion quaternion = navData->GetOrientation(); quat = " / [qx:" + QString::number(quaternion.x(),'f',quatPrecision) + ";qy:" + QString::number(quaternion.y(),'f',quatPrecision) + ";qz:" + QString::number(quaternion.z(),'f',quatPrecision) + ";qr:" + QString::number(quaternion.r()) + "]"; } if(!(m_StatusLabels->at(i)->text() == name+pos+quat)) m_StatusLabels->at(i)->setText(name+pos+quat); if(navData->IsDataValid()) m_StatusLabels->at(i)->setStyleSheet("QLabel{background-color: #8bff8b }"); else m_StatusLabels->at(i)->setStyleSheet("QLabel{background-color: #ff7878 }"); } } void QmitkToolTrackingStatusWidget::ShowStatusLabels() { RemoveGuiLabels(); if(m_NavigationDatas == nullptr || m_NavigationDatas->size() <= 0) { RemoveGuiLabels(); AddEmptyLabel(); return; } m_StatusLabels = new QVector(); mitk::NavigationData* navData; QLabel* label; for(unsigned int i = 0; i < m_NavigationDatas->size(); i++) { navData = m_NavigationDatas->at(i).GetPointer(); QString name(navData->GetName()); label = new QLabel(name, this); label->setObjectName(name); label->setAlignment(m_Alignment | Qt::AlignVCenter); label->setFrameStyle(QFrame::Panel | QFrame::Sunken); m_StatusLabels->append(label); - if (m_Style == QmitkToolTrackingStatusWidget::VerticalUpperStyle) m_Controls->m_VerticalLayout->addWidget(m_StatusLabels->at(i)); - else m_Controls->m_GridLayout->addWidget(m_StatusLabels->at(i),0,i); + if (m_Style == QmitkToolTrackingStatusWidget::VerticalUpperStyle) + m_Controls->m_VerticalLayout->addWidget(m_StatusLabels->at(i)); + else m_Controls->m_GridLayout->addWidget(m_StatusLabels->at(i),i,0); } } void QmitkToolTrackingStatusWidget::PreShowTools(mitk::NavigationToolStorage::Pointer toolStorage) { RemoveGuiLabels(); QLabel* label; for(int i = 0; i < toolStorage->GetToolCount(); i++) { QString name(toolStorage->GetTool(i)->GetToolName().c_str()); label = new QLabel(name, this); label->setObjectName(name); label->setAlignment(m_Alignment | Qt::AlignVCenter); label->setFrameStyle(QFrame::Panel | QFrame::Sunken); label->setStyleSheet("QLabel{background-color: #dddddd }"); if (m_Style == QmitkToolTrackingStatusWidget::VerticalUpperStyle) m_Controls->m_VerticalLayout->addWidget(label); else m_Controls->m_GridLayout->addWidget(label); } m_previewToolStorage = toolStorage; } void QmitkToolTrackingStatusWidget::RemoveStatusLabels() { //remove GUI elements RemoveGuiLabels(); //clear members if(m_StatusLabels != nullptr && m_StatusLabels->size() > 0) { delete m_StatusLabels; m_StatusLabels = new QVector< QLabel* >(); } if(m_NavigationDatas != nullptr && m_NavigationDatas->size() > 0) { if (m_NavDatasNewFlag) { delete m_NavigationDatas; m_NavDatasNewFlag = false; } m_NavigationDatas = new std::vector(); m_NavDatasNewFlag = true; } //add empty label AddEmptyLabel(); } void QmitkToolTrackingStatusWidget::RemoveGuiLabels() { while(m_Controls->m_GridLayout->count() > 0 || m_Controls->m_VerticalLayout->count() > 0) { if (m_Controls->m_GridLayout->count() > 0) { QWidget* actWidget = m_Controls->m_GridLayout->itemAt(0)->widget(); m_Controls->m_GridLayout->removeWidget(actWidget); delete actWidget; } else if (m_Controls->m_VerticalLayout->count() > 0) { QWidget* actWidget = m_Controls->m_VerticalLayout->itemAt(0)->widget(); m_Controls->m_VerticalLayout->removeWidget(actWidget); delete actWidget; } } } void QmitkToolTrackingStatusWidget::AddEmptyLabel() { //add a label which tells that no tools are loaded yet QLabel* label = new QLabel("No tools loaded yet.", this); label->setObjectName("No tools loaded yet."); label->setAlignment(m_Alignment | Qt::AlignVCenter); label->setFrameStyle(QFrame::Panel | QFrame::Sunken); label->setStyleSheet("QLabel{background-color: #dddddd }"); if (m_Style == QmitkToolTrackingStatusWidget::VerticalUpperStyle) m_Controls->m_VerticalLayout->addWidget(label); else m_Controls->m_GridLayout->addWidget(label); } diff --git a/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidgetControls.ui b/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidgetControls.ui index 2ea0ff23ac..31c9b7103b 100644 --- a/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidgetControls.ui +++ b/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidgetControls.ui @@ -1,218 +1,74 @@ QmitkTrackingDeviceConfigurationWidgetControls 0 0 - 366 - 536 + 446 + 603 0 0 Form - - - 0 - - - 0 - - - - - - - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Tracking Device Configuration</span></p></body></html> - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Qt::Horizontal - - - - 128 - 20 - - - - - - - - - 0 - 0 - - - - - - - - - - Qt::Horizontal - - - - - - - true - - - -1 - - - - - - - Qt::Vertical - - - - 20 - 50 - - - - - - - - - - - - - - 0 - + - - - - Qt::Vertical + + + + + 0 + 0 + - - - 20 - 289 - - - - - - - - - - - - true - - - - - 0 - 0 - 98 - 31 - - - - - - - - - - Qt::Vertical - - - - 20 - 269 - - - - - - - - - - - - - - 16777215 - 0 - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - + + + + + Qt::Horizontal + + + + + + + true + + + -1 + + + + diff --git a/Modules/IGTUI/Qmitk/QmitkVirtualTrackerWidget.ui b/Modules/IGTUI/Qmitk/QmitkVirtualTrackerWidget.ui index 38a69d6c0a..df33c99c8d 100644 --- a/Modules/IGTUI/Qmitk/QmitkVirtualTrackerWidget.ui +++ b/Modules/IGTUI/Qmitk/QmitkVirtualTrackerWidget.ui @@ -1,117 +1,121 @@ QmitkVirtualTrackerWidget 0 0 - 320 - 220 + 294 + 143 0 0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" text-decoration: underline;">Virtual Tracker</span></p></body></html> - - - Simulate Jitter - - - - - + - + - Mean Distribution Parameter + Simulate Jitter - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - false - - + + + + + Mean Distribution Parameter + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + false + + + + - - - - - - - Deviation Distribution Parameter - - + + + + + Deviation Distribution Parameter + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + false + + + + - + - Qt::Horizontal + Qt::Vertical - 40 - 20 + 20 + 40 - - - - false - - - - - - - Qt::Vertical - - - - 20 - 81 - - - - diff --git a/Modules/IGTUI/files.cmake b/Modules/IGTUI/files.cmake index df2e5e6088..5773331a13 100644 --- a/Modules/IGTUI/files.cmake +++ b/Modules/IGTUI/files.cmake @@ -1,116 +1,113 @@ set(CPP_FILES Qmitk/QmitkTrackingDeviceWidget.cpp Qmitk/QmitkTrackingDeviceConfigurationWidget.cpp Qmitk/QmitkNDIConfigurationWidget.cpp Qmitk/QmitkFiducialRegistrationWidget.cpp Qmitk/QmitkNDIToolDelegate.cpp Qmitk/QmitkNavigationToolManagementWidget.cpp Qmitk/QmitkIGTLoggerWidget.cpp Qmitk/QmitkUpdateTimerWidget.cpp Qmitk/QmitkToolDistanceWidget.cpp Qmitk/QmitkToolTrackingStatusWidget.cpp Qmitk/QmitkTrackingSourcesCheckBoxPanelWidget.cpp Qmitk/QmitkIGTPlayerWidget.cpp Qmitk/QmitkIGTConnectionWidget.cpp Qmitk/QmitkToolSelectionWidget.cpp Qmitk/QmitkNavigationToolCreationWidget.cpp - Qmitk/QmitkNavigationToolCreationAdvancedWidget.cpp Qmitk/QmitkNavigationDataSourceSelectionWidget.cpp Qmitk/QmitkInteractiveTransformationWidget.cpp Qmitk/QmitkNavigationToolStorageSelectionWidget.cpp Qmitk/QmitkNavigationDataPlayerControlWidget.cpp Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.cpp Qmitk/QmitkNDIAuroraWidget.cpp Qmitk/QmitkNDIPolarisWidget.cpp Qmitk/QmitkMicronTrackerWidget.cpp Qmitk/QmitkNPOptitrackWidget.cpp Qmitk/QmitkVirtualTrackerWidget.cpp Qmitk/QmitkOpenIGTLinkWidget.cpp Qmitk/mitkTrackingDeviceWidgetCollection.cpp Qmitk/QmitkTrackingDeviceConfigurationWidgetScanPortsWorker.cpp Qmitk/QmitkTrackingDeviceConfigurationWidgetConnectionWorker.cpp Qmitk/QmitkNDIAbstractDeviceWidget.cpp Qmitk/QmitkAbstractTrackingDeviceWidget.cpp Qmitk/QmitkIGTCommonHelper.cpp ) set(UI_FILES Qmitk/QmitkNavigationToolManagementWidgetControls.ui Qmitk/QmitkTrackingDeviceConfigurationWidgetControls.ui Qmitk/QmitkNDIConfigurationWidget.ui Qmitk/QmitkFiducialRegistrationWidget.ui Qmitk/QmitkIGTLoggerWidgetControls.ui Qmitk/QmitkUpdateTimerWidgetControls.ui Qmitk/QmitkToolDistanceWidgetControls.ui Qmitk/QmitkToolTrackingStatusWidgetControls.ui Qmitk/QmitkTrackingSourcesCheckBoxPanelWidgetControls.ui Qmitk/QmitkIGTPlayerWidgetControls.ui Qmitk/QmitkIGTConnectionWidgetControls.ui Qmitk/QmitkToolSelectionWidgetControls.ui Qmitk/QmitkNavigationToolCreationWidget.ui - Qmitk/QmitkNavigationToolCreationAdvancedWidgetControls.ui Qmitk/QmitkNavigationDataSourceSelectionWidgetControls.ui Qmitk/QmitkInteractiveTransformationWidgetControls.ui Qmitk/QmitkNavigationToolStorageSelectionWidgetControls.ui Qmitk/QmitkNavigationDataPlayerControlWidget.ui Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.ui Qmitk/QmitkNDIAuroraWidget.ui Qmitk/QmitkNDIPolarisWidget.ui Qmitk/QmitkMicronTrackerWidget.ui Qmitk/QmitkNPOptitrackWidget.ui Qmitk/QmitkVirtualTrackerWidget.ui Qmitk/QmitkOpenIGTLinkWidget.ui ) set(MOC_H_FILES Qmitk/QmitkNavigationToolManagementWidget.h Qmitk/QmitkTrackingDeviceWidget.h Qmitk/QmitkTrackingDeviceConfigurationWidget.h Qmitk/QmitkNDIConfigurationWidget.h Qmitk/QmitkFiducialRegistrationWidget.h Qmitk/QmitkNDIToolDelegate.h Qmitk/QmitkIGTLoggerWidget.h Qmitk/QmitkUpdateTimerWidget.h Qmitk/QmitkToolDistanceWidget.h Qmitk/QmitkToolTrackingStatusWidget.h Qmitk/QmitkTrackingSourcesCheckBoxPanelWidget.h Qmitk/QmitkIGTPlayerWidget.h Qmitk/QmitkIGTConnectionWidget.h Qmitk/QmitkToolSelectionWidget.h Qmitk/QmitkNavigationToolCreationWidget.h - Qmitk/QmitkNavigationToolCreationAdvancedWidget.h Qmitk/QmitkNavigationDataSourceSelectionWidget.h Qmitk/QmitkInteractiveTransformationWidget.h Qmitk/QmitkNavigationToolStorageSelectionWidget.h Qmitk/QmitkNavigationDataPlayerControlWidget.h Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.h Qmitk/QmitkNDIAuroraWidget.h Qmitk/QmitkNDIPolarisWidget.h Qmitk/QmitkMicronTrackerWidget.h Qmitk/QmitkNPOptitrackWidget.h Qmitk/QmitkVirtualTrackerWidget.h Qmitk/QmitkOpenIGTLinkWidget.h Qmitk/QmitkTrackingDeviceConfigurationWidgetScanPortsWorker.h Qmitk/QmitkTrackingDeviceConfigurationWidgetConnectionWorker.h Qmitk/QmitkNDIAbstractDeviceWidget.h Qmitk/QmitkAbstractTrackingDeviceWidget.h Qmitk/QmitkIGTCommonHelper.h ) if(MITK_USE_POLHEMUS_TRACKER) set(CPP_FILES ${CPP_FILES} Qmitk/QmitkPolhemusTrackerWidget.cpp) set(UI_FILES ${UI_FILES} Qmitk/QmitkPolhemusTrackerWidget.ui) set(MOC_H_FILES ${MOC_H_FILES} Qmitk/QmitkPolhemusTrackerWidget.h) endif(MITK_USE_POLHEMUS_TRACKER) set(QRC_FILES resources/IGTUI.qrc ) diff --git a/Modules/US/USNavigation/files.cmake b/Modules/US/USNavigation/files.cmake index 7fdc9ef27f..b240daaede 100644 --- a/Modules/US/USNavigation/files.cmake +++ b/Modules/US/USNavigation/files.cmake @@ -1,7 +1,5 @@ SET(CPP_FILES mitkUSCombinedModality.cpp - Filter/mitkNavigationDataPassThroughFilter.cpp - Filter/mitkNeedleProjectionFilter.cpp Filter/mitkNodeDisplacementFilter.cpp ) diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.cpp b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.cpp index 2cf1445a20..0266b86fee 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.cpp @@ -1,415 +1,427 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkUSNavigationStepCombinedModality.h" #include "ui_QmitkUSNavigationStepCombinedModality.h" #include "mitkUSCombinedModality.h" #include "../Widgets/QmitkUSCombinedModalityEditWidget.h" #include #include #include +#include "mitkBaseRenderer.h" + QmitkUSNavigationStepCombinedModality::QmitkUSNavigationStepCombinedModality(QWidget *parent) : QmitkUSAbstractNavigationStep(parent), m_LastCalibrationFilename(""), m_CalibrationLoadedNecessary(true), m_ListenerDeviceChanged(this, &QmitkUSNavigationStepCombinedModality::OnDevicePropertyChanged), ui(new Ui::QmitkUSNavigationStepCombinedModality) { ui->setupUi(this); // combined modality create widget should only be visible after button press ui->combinedModalityCreateWidget->setVisible(false); ui->combinedModalityEditWidget->setVisible(false); connect(ui->combinedModalityListWidget, SIGNAL(ServiceSelectionChanged(us::ServiceReferenceU)), this, SLOT(OnDeviceSelectionChanged())); connect(ui->combinedModalityListWidget, SIGNAL(ServiceModified(us::ServiceReferenceU)), this, SLOT(OnDeviceSelectionChanged())); connect(ui->combinedModalityCreateWidget, SIGNAL(SignalAborted()), this, SLOT(OnCombinedModalityCreationExit())); connect(ui->combinedModalityCreateWidget, SIGNAL(SignalCreated()), this, SLOT(OnCombinedModalityCreationExit())); connect(ui->combinedModalityEditWidget, SIGNAL(SignalAborted()), this, SLOT(OnCombinedModalityEditExit())); connect(ui->combinedModalityEditWidget, SIGNAL(SignalSaved()), this, SLOT(OnCombinedModalityEditExit())); std::string filterOnlyCombinedModalities = "(&(" + us::ServiceConstants::OBJECTCLASS() + "=" + "org.mitk.services.USCombinedModality)(" + mitk::USCombinedModality::GetPropertyKeys().US_PROPKEY_CLASS + "=" + mitk::USCombinedModality::DeviceClassIdentifier + "))"; //std::string filter = "(&(" + us::ServiceConstants::OBJECTCLASS() + "=" + "org.mitk.services.UltrasoundDevice))"; ui->combinedModalityListWidget->Initialize(mitk::USCombinedModality::US_PROPKEY_DEVICENAME); ui->combinedModalityListWidget->SetAutomaticallySelectFirstEntry(true); //try to load UI settings QSettings settings; settings.beginGroup(QString::fromStdString("QmitkUSNavigationStepCombinedModality")); m_LastCalibrationFilename = settings.value("LastCalibrationFilename", QVariant("")).toString().toStdString(); MITK_DEBUG << "PERSISTENCE load: " << m_LastCalibrationFilename; settings.endGroup(); } QmitkUSNavigationStepCombinedModality::~QmitkUSNavigationStepCombinedModality() { ui->combinedModalityListWidget->blockSignals(true); //save UI settings QSettings settings; settings.beginGroup(QString::fromStdString("QmitkUSNavigationStepCombinedModality")); settings.setValue("LastCalibrationFilename", QVariant(m_LastCalibrationFilename.c_str())); settings.endGroup(); MITK_DEBUG << "PERSISTENCE save: " << m_LastCalibrationFilename; //delete UI delete ui; } void QmitkUSNavigationStepCombinedModality::OnDeviceSelectionChanged() { mitk::USCombinedModality::Pointer combinedModality = this->GetSelectedCombinedModality(); bool combinedModalitySelected = combinedModality.IsNotNull(); ui->calibrationGroupBox->setEnabled(combinedModalitySelected); ui->combinedModalityDeleteButton->setEnabled(combinedModalitySelected); ui->combinedModalitEditButton->setEnabled(combinedModalitySelected); if (!combinedModalitySelected || m_CombinedModality != combinedModality) { emit SignalNoLongerReadyForNextStep(); if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice().IsNotNull()) { m_CombinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_ListenerDeviceChanged); } if (combinedModalitySelected && combinedModality->GetUltrasoundDevice().IsNotNull()) { combinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_ListenerDeviceChanged); } } m_CombinedModality = combinedModality; if (combinedModalitySelected) { bool calibrated = this->UpdateCalibrationState(); if (!m_CalibrationLoadedNecessary) { emit SignalReadyForNextStep(); } else { if (calibrated) { emit SignalReadyForNextStep(); } else { emit SignalNoLongerReadyForNextStep(); } } // enable disconnect button only if combined modality is connected or active ui->combinedModalityDistconnectButton->setEnabled(combinedModality->GetDeviceState() >= mitk::USCombinedModality::State_Connected); ui->combinedModalityActivateButton->setEnabled(combinedModality->GetDeviceState() < mitk::USCombinedModality::State_Activated); this->UpdateTrackingToolNames(); } else { ui->combinedModalityDistconnectButton->setEnabled(false); ui->combinedModalityActivateButton->setEnabled(false); } } void QmitkUSNavigationStepCombinedModality::OnLoadCalibration() { QString filename = QFileDialog::getOpenFileName(QApplication::activeWindow(), "Load Calibration", m_LastCalibrationFilename.c_str(), "Calibration files *.cal"); m_LastCalibrationFilename = filename.toStdString(); mitk::USCombinedModality::Pointer combinedModality = this->GetSelectedCombinedModality(); if (combinedModality.IsNull()) { ui->calibrationLoadStateLabel->setText("Selected device is no USCombinedModality."); emit SignalNoLongerReadyForNextStep(); return; } if (filename.isEmpty()) { bool calibrated = this->UpdateCalibrationState(); if (!calibrated) { emit SignalNoLongerReadyForNextStep(); } return; } QFile file(filename); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { MITK_WARN << "Cannot open file '" << filename.toStdString() << "' for reading."; ui->calibrationLoadStateLabel->setText("Cannot open file '" + filename + "' for reading."); emit SignalNoLongerReadyForNextStep(); return; } QTextStream inStream(&file); m_LoadedCalibration = inStream.readAll().toStdString(); if (m_LoadedCalibration.empty()) { MITK_WARN << "Failed to load file. Unsupported format?"; ui->calibrationLoadStateLabel->setText("Failed to load file. Unsupported format?"); emit SignalNoLongerReadyForNextStep(); return; } try { combinedModality->DeserializeCalibration(m_LoadedCalibration); } catch (const mitk::Exception& /*exception*/) { MITK_WARN << "Failed to deserialize calibration. Unsuppoerted format?"; ui->calibrationLoadStateLabel->setText("Failed to deserialize calibration. Unsuppoerted format?"); emit SignalNoLongerReadyForNextStep(); return; } ui->calibrationLoadStateLabel->setText("Loaded calibration : " + filename); m_CombinedModality = combinedModality; emit SignalReadyForNextStep(); } void QmitkUSNavigationStepCombinedModality::OnCombinedModalityCreateNewButtonClicked() { this->SetCombinedModalityCreateWidgetEnabled(true); } void QmitkUSNavigationStepCombinedModality::OnCombinedModalityCreationExit() { this->SetCombinedModalityCreateWidgetEnabled(false); + try + { + mitk::RenderingManager::GetInstance()->InitializeViews(//Reinit + mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetDataStorage()//GetDataStorage + ->GetNamedNode("US Support Viewing Stream")->GetData()->GetTimeGeometry());//GetNode + } + catch (...) + { + MITK_DEBUG << "No reinit possible"; + } } void QmitkUSNavigationStepCombinedModality::OnCombinedModalityEditExit() { this->SetCombinedModalityEditWidgetEnabled(false); ui->combinedModalityEditWidget->SetCombinedModality(0); } void QmitkUSNavigationStepCombinedModality::OnDeleteButtonClicked() { mitk::USCombinedModality::Pointer combinedModality = this->GetSelectedCombinedModality(); if (combinedModality.IsNotNull()) { combinedModality->RemoveAllObservers(); combinedModality->UnregisterOnService(); } } void QmitkUSNavigationStepCombinedModality::OnCombinedModalityEditButtonClicked() { ui->combinedModalityEditWidget->SetCombinedModality(m_CombinedModality); this->SetCombinedModalityEditWidgetEnabled(true); } void QmitkUSNavigationStepCombinedModality::OnActivateButtonClicked() { mitk::USCombinedModality::Pointer combinedModality = this->GetSelectedCombinedModality(); if (combinedModality.IsNotNull()) { if (!combinedModality->GetIsConnected()) { combinedModality->Connect(); } if (!combinedModality->GetIsActive()) { combinedModality->Activate(); } } } void QmitkUSNavigationStepCombinedModality::OnDisconnectButtonClicked() { mitk::USCombinedModality::Pointer combinedModality = this->GetSelectedCombinedModality(); if (combinedModality.IsNotNull()) { if (combinedModality->GetIsActive()) { combinedModality->Deactivate(); } if (combinedModality->GetIsConnected()) { combinedModality->Disconnect(); } } } bool QmitkUSNavigationStepCombinedModality::OnStartStep() { return true; } bool QmitkUSNavigationStepCombinedModality::OnRestartStep() { return true; } bool QmitkUSNavigationStepCombinedModality::OnFinishStep() { mitk::USCombinedModality::Pointer combinedModality = this->GetSelectedCombinedModality(); if (combinedModality.IsNotNull()) { QApplication::setOverrideCursor(Qt::WaitCursor); // make sure that the combined modality is in connected state before using it if (combinedModality->GetDeviceState() < mitk::USDevice::State_Connected) { combinedModality->Connect(); } if (combinedModality->GetDeviceState() < mitk::USDevice::State_Activated) { combinedModality->Activate(); } QApplication::restoreOverrideCursor(); } emit SignalCombinedModalityChanged(combinedModality); this->CreateCombinedModalityResultAndSignalIt(); return true; } bool QmitkUSNavigationStepCombinedModality::OnActivateStep() { // make sure that device selection status is up-to-date this->OnDeviceSelectionChanged(); return true; } void QmitkUSNavigationStepCombinedModality::OnUpdate() { } QString QmitkUSNavigationStepCombinedModality::GetTitle() { return "Selection of Combined Modality"; } bool QmitkUSNavigationStepCombinedModality::GetIsRestartable() { return false; } void QmitkUSNavigationStepCombinedModality::SetCombinedModalityCreateWidgetEnabled(bool enabled) { ui->combinedModalityLabel->setVisible(!enabled); ui->combinedModalityListWidget->setVisible(!enabled); ui->combinedModalityCreateButton->setVisible(!enabled); ui->combinedModalityDeleteButton->setVisible(!enabled); ui->combinedModalitEditButton->setVisible(!enabled); ui->combinedModalityActivateButton->setVisible(!enabled); ui->combinedModalityDistconnectButton->setVisible(!enabled); ui->helpLabel->setVisible(!enabled); ui->calibrationGroupBox->setVisible(!enabled); ui->combinedModalityCreateWidget->setVisible(enabled); } void QmitkUSNavigationStepCombinedModality::SetCombinedModalityEditWidgetEnabled(bool enabled) { ui->combinedModalityLabel->setVisible(!enabled); ui->combinedModalityListWidget->setVisible(!enabled); ui->combinedModalityCreateButton->setVisible(!enabled); ui->combinedModalityDeleteButton->setVisible(!enabled); ui->combinedModalitEditButton->setVisible(!enabled); ui->combinedModalityActivateButton->setVisible(!enabled); ui->combinedModalityDistconnectButton->setVisible(!enabled); ui->helpLabel->setVisible(!enabled); ui->calibrationGroupBox->setVisible(!enabled); ui->combinedModalityEditWidget->setVisible(enabled); } void QmitkUSNavigationStepCombinedModality::CreateCombinedModalityResultAndSignalIt() { mitk::USCombinedModality::Pointer combinedModality = this->GetCombinedModality(); mitk::USDevice::Pointer usDevice = combinedModality->GetUltrasoundDevice(); // save identifiers and calibration to a result object mitk::DataNode::Pointer combinedModalityResult = mitk::DataNode::New(); combinedModalityResult->SetName("CombinedModalityResult"); combinedModalityResult->SetStringProperty("USNavigation::CombinedModality", std::string(combinedModality->GetManufacturer() + ": " + combinedModality->GetName() + " (" + combinedModality->GetComment() + ")").c_str()); combinedModalityResult->SetStringProperty("USNavigation::UltrasoundDevice", std::string(usDevice->GetManufacturer() + ": " + usDevice->GetName() + " (" + usDevice->GetComment() + ")").c_str()); combinedModalityResult->SetStringProperty("USNavigation::TrackingDevice", combinedModality->GetNavigationDataSource()->GetName().c_str()); combinedModalityResult->SetStringProperty("USNavigation::Calibration", combinedModality->SerializeCalibration().c_str()); emit SignalIntermediateResult(combinedModalityResult); } bool QmitkUSNavigationStepCombinedModality::UpdateCalibrationState() { if (m_CombinedModality.IsNull()) { return false; } bool calibrated = m_CombinedModality->GetContainsAtLeastOneCalibration(); if (calibrated) { ui->calibrationLoadStateLabel->setText("Selected device contains at least one calibration."); } else { ui->calibrationLoadStateLabel->setText("Selected device is not calibrated."); } return calibrated; } mitk::USCombinedModality::Pointer QmitkUSNavigationStepCombinedModality::GetSelectedCombinedModality() { // nothing more to do if no device is selected at the moment if (!ui->combinedModalityListWidget->GetIsServiceSelected()) { return 0; } mitk::USCombinedModality::Pointer combinedModality = ui->combinedModalityListWidget->GetSelectedService(); if (combinedModality.IsNull()) { MITK_WARN << "Selected device is no USCombinedModality."; } return combinedModality; } void QmitkUSNavigationStepCombinedModality::SetCalibrationLoadedNecessary(bool necessary) { m_CalibrationLoadedNecessary = necessary; } void QmitkUSNavigationStepCombinedModality::OnDevicePropertyChanged(const std::string& key, const std::string&) { // property changes only matter if the navigation step is currently active // (being sensitive to them in other states may even be dangerous) if (this->GetNavigationStepState() < QmitkUSAbstractNavigationStep::State_Active) { return; } // calibration state could have changed if the depth was changed if (key == mitk::USDevice::GetPropertyKeys().US_PROPKEY_BMODE_DEPTH) { bool calibrated = this->UpdateCalibrationState(); if (calibrated) { emit SignalReadyForNextStep(); } else { emit SignalNoLongerReadyForNextStep(); } } } void QmitkUSNavigationStepCombinedModality::UpdateTrackingToolNames() { //check if everything is initialized if (m_CombinedModality.IsNull()) { return; } mitk::NavigationDataSource::Pointer navigationDataSource = m_CombinedModality->GetNavigationDataSource(); if (navigationDataSource.IsNull()) { return; } if (GetDataStorage(false).IsNull()) { return; } // get the settings node mitk::DataNode::Pointer settingsNode = this->GetNamedDerivedNode(DATANAME_SETTINGS, DATANAME_BASENODE); std::string needleNames; itk::ProcessObject::DataObjectPointerArray outputs = navigationDataSource->GetOutputs(); for (itk::ProcessObject::DataObjectPointerArray::iterator it = outputs.begin(); it != outputs.end(); ++it) { needleNames += std::string((static_cast(it->GetPointer()))->GetName()) + ";"; } // change the settings node only if the settings changed std::string oldProperty; if (!settingsNode->GetStringProperty("settings.needle-names", oldProperty) || oldProperty != needleNames || !settingsNode->GetStringProperty("settings.reference-names", oldProperty) || oldProperty != needleNames) { settingsNode->SetStringProperty("settings.needle-names", needleNames.c_str()); settingsNode->SetStringProperty("settings.reference-names", needleNames.c_str()); emit SignalSettingsNodeChanged(settingsNode); } } diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.cpp b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.cpp index 9b4f363713..80c1c2231a 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.cpp @@ -1,808 +1,863 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "USNavigationMarkerPlacement.h" #include "ui_USNavigationMarkerPlacement.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 "mitkIRenderingManager.h" #include "mitkNodeDisplacementFilter.h" #include "mitkUSCombinedModality.h" #include #include "IO/mitkUSNavigationExperimentLogging.h" #include "IO/mitkUSNavigationStepTimer.h" #include #include #include #include #include #include #include "QmitkRenderWindow.h" #include "QmitkStdMultiWidget.h" #include "QmitkStdMultiWidgetEditor.h" #include "mitkLayoutAnnotationRenderer.h" +#include "mitkCameraController.h" // scene serialization #include #include #include #include #include const std::string USNavigationMarkerPlacement::VIEW_ID = "org.mitk.views.usmarkerplacement"; const char *USNavigationMarkerPlacement::DATANAME_TUMOUR = "Tumour"; const char *USNavigationMarkerPlacement::DATANAME_TARGETSURFACE = "Target Surface"; const char *USNavigationMarkerPlacement::DATANAME_ZONES = "Zones"; const char *USNavigationMarkerPlacement::DATANAME_TARGETS = "Targets"; const char *USNavigationMarkerPlacement::DATANAME_TARGETS_PATHS = "Target Paths"; const char *USNavigationMarkerPlacement::DATANAME_REACHED_TARGETS = "Reached Targets"; USNavigationMarkerPlacement::USNavigationMarkerPlacement() : m_Parent(nullptr), m_UpdateTimer(new QTimer(this)), m_ImageAndNavigationDataLoggingTimer(new QTimer(this)), m_StdMultiWidget(nullptr), m_ReinitAlreadyDone(false), m_IsExperimentRunning(false), m_NavigationStepTimer(mitk::USNavigationStepTimer::New()), m_ExperimentLogging(mitk::USNavigationExperimentLogging::New()), m_AblationZonesDisplacementFilter(mitk::NodeDisplacementFilter::New()), m_IconRunning(QPixmap(":/USNavigation/record.png")), m_IconNotRunning(QPixmap(":/USNavigation/record-gray.png")), m_USImageLoggingFilter(mitk::USImageLoggingFilter::New()), m_NavigationDataRecorder(mitk::NavigationDataRecorder::New()), m_SceneNumber(1), m_WarnOverlay(mitk::TextAnnotation2D::New()), m_NeedleIndex(0), m_MarkerIndex(1), m_ListenerDeviceChanged(this, &USNavigationMarkerPlacement::OnCombinedModalityPropertyChanged), ui(new Ui::USNavigationMarkerPlacement) { 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); // set prefix for experiment logging (only keys with this prefix are taken // into consideration m_ExperimentLogging->SetKeyPrefix("USNavigation::"); m_UpdateTimer->start(33); // every 33 Milliseconds = 30 Frames/Second } USNavigationMarkerPlacement::~USNavigationMarkerPlacement() { - // remove listener for ultrasound device changes if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice().IsNotNull()) { m_CombinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_ListenerDeviceChanged); } - // remove listener for ultrasound device changes if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice().IsNotNull()) { m_CombinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_ListenerDeviceChanged); } delete ui; - - } void USNavigationMarkerPlacement::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 vtkSphereSource *vtkData = vtkSphereSource::New(); vtkData->SetRadius(newSize / 2); vtkData->SetCenter(0, 0, 0); vtkData->SetPhiResolution(20); vtkData->SetThetaResolution(20); vtkData->Update(); mitk::Surface::Pointer zoneSurface = dynamic_cast(m_AblationZonesVector.at(id)->GetData()); zoneSurface->SetVtkPolyData(vtkData->GetOutput()); vtkData->Delete(); } void USNavigationMarkerPlacement::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 vtkSphereSource *vtkData = vtkSphereSource::New(); vtkData->SetRadius(size / 2); vtkData->SetCenter(0, 0, 0); vtkData->SetPhiResolution(20); vtkData->SetThetaResolution(20); vtkData->Update(); zone->SetVtkPolyData(vtkData->GetOutput()); vtkData->Delete(); // 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 USNavigationMarkerPlacement::CreateQtPartControl(QWidget *parent) { m_Parent = parent; ui->setupUi(parent); connect(ui->navigationProcessWidget, SIGNAL(SignalCombinedModalityChanged(itk::SmartPointer)), this, SLOT(OnCombinedModalityChanged(itk::SmartPointer))); connect(ui->navigationProcessWidget, SIGNAL(SignalSettingsChanged(itk::SmartPointer)), this, SLOT(OnSettingsChanged(itk::SmartPointer))); connect(ui->navigationProcessWidget, SIGNAL(SignalActiveNavigationStepChanged(int)), this, SLOT(OnActiveNavigationStepChanged(int))); connect(ui->navigationProcessWidget, SIGNAL(SignalActiveNavigationStepChangeRequested(int)), this, SLOT(OnNextNavigationStepInitialization(int))); 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())); connect(ui->navigationProcessWidget, SIGNAL(SignalIntermediateResult(const itk::SmartPointer)), this, SLOT(OnIntermediateResultProduced(const itk::SmartPointer))); ui->navigationProcessWidget->SetDataStorage(this->GetDataStorage()); // indicate that no experiment is running at start ui->runningLabel->setPixmap(m_IconNotRunning); ui->navigationProcessWidget->SetSettingsWidget(new QmitkUSNavigationCombinedSettingsWidget(m_Parent)); } void USNavigationMarkerPlacement::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.widget1", mitk::LayoutAnnotationRenderer::TopLeft); MITK_WARN << "No calibration available for the selected ultrasound image depth."; } } } void USNavigationMarkerPlacement::SetFocus() { this->ReinitOnImage(); } void USNavigationMarkerPlacement::OnTimeout() { if (!m_StdMultiWidget) { // try to get the standard multi widget if it couldn't be got before mitk::IRenderWindowPart *renderWindow = this->GetRenderWindowPart(); QmitkStdMultiWidgetEditor *multiWidgetEditor = dynamic_cast(renderWindow); // 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 = multiWidgetEditor->GetStdMultiWidget(); - if (m_StdMultiWidget) - { - m_StdMultiWidget->DisableStandardLevelWindow(); - m_StdMultiWidget->changeLayoutTo2DUpAnd3DDown(); - } + SetTwoWindowView(); } this->CreateOverlays(); } if (m_CombinedModality.IsNotNull() && !this->m_CombinedModality->GetIsFreezed()) // if the combined modality is freezed: do nothing { ui->navigationProcessWidget->UpdateNavigationProgress(); 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 USNavigationMarkerPlacement::OnEnableNavigationLayout() { MITK_INFO << "Navigation Layout"; // try to get the standard multi widget if it couldn't be got before mitk::IRenderWindowPart *renderWindow = this->GetRenderWindowPart(); QmitkStdMultiWidgetEditor *multiWidgetEditor = dynamic_cast(renderWindow); // 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 = multiWidgetEditor->GetStdMultiWidget(); - if (m_StdMultiWidget) + SetTwoWindowView(); + } +} + +void USNavigationMarkerPlacement::OnRenderWindowSelection() +{ + SetTwoWindowView(); +} + +void USNavigationMarkerPlacement::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 Support Viewing Stream")->GetData()->GetTimeGeometry());//GetNode + } + catch (...) { - m_StdMultiWidget->DisableStandardLevelWindow(); - m_StdMultiWidget->changeLayoutTo2DUpAnd3DDown(); - this->GetDataStorage()->GetNamedNode("stdmulti.widget1.plane")->SetVisibility(false); - this->GetDataStorage()->GetNamedNode("stdmulti.widget3.plane")->SetVisibility(false); + MITK_DEBUG << "No reinit possible"; } + SetTwoWindowView(); + } +} + +void USNavigationMarkerPlacement::SetTwoWindowView() +{ + if (m_StdMultiWidget) + { + m_StdMultiWidget->DisableStandardLevelWindow(); + int i, j, k; + switch (this->ui->m_RenderWindowSelection->value()) + { + case 1: + mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetCameraController()->SetViewToCaudal(); + i = 2; j = 3; //other windows + k = 1; + break; + case 2: + mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetCameraController()->SetViewToSinister(); + i = 1; j = 3; + k = 2; + break; + case 3: + mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetCameraController()->SetViewToAnterior(); + i = 2; j = 1; + k = 3; + break; + default: + return; + } + m_StdMultiWidget->changeLayoutTo2DUpAnd3DDown(k); + ////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 USNavigationMarkerPlacement::OnResetStandardLayout() { //reset render windows mitk::DataNode::Pointer widget1 = this->GetDataStorage()->GetNamedNode("stdmulti.widget1.plane"); if (widget1.IsNotNull()) { widget1->SetVisibility(true); } + mitk::DataNode::Pointer widget2 = this->GetDataStorage()->GetNamedNode("stdmulti.widget2.plane"); + if (widget2.IsNotNull()) { widget2->SetVisibility(true); } mitk::DataNode::Pointer widget3 = this->GetDataStorage()->GetNamedNode("stdmulti.widget3.plane"); if (widget3.IsNotNull()) { widget3->SetVisibility(true); } m_StdMultiWidget->changeLayoutToDefault(); } void USNavigationMarkerPlacement::OnChangeLayoutClicked() { if (ui->m_enableNavigationLayout->isChecked()) OnEnableNavigationLayout(); else OnResetStandardLayout(); } void USNavigationMarkerPlacement::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 USNavigationMarkerPlacement::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 recursivly 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); ui->navigationProcessWidget->EnableInteraction(true); // (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, m_NavigationSteps.at(0)->GetTitle().toStdString()); 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); // (re)start experiment logging and set output file name m_ExperimentLogging->Reset(); m_ExperimentLogging->SetFileName( QString(m_ExperimentResultsSubDirectory + QDir::separator() + "experiment-logging.xml").toStdString()); } } } void USNavigationMarkerPlacement::OnFinishExperiment() { this->WaitCursorOn(); MITK_INFO("USNavigationLogging") << "Experiment finished!"; MITK_INFO("USNavigationLogging") << "Position/Orientation of needle tip: " << (dynamic_cast(m_CombinedModality->GetTrackingDevice()->GetOutput(0)))->GetPosition(); MITK_INFO("USNavigationLogging") << "Position of target: " << m_TargetNodeDisplacementFilter->GetRawDisplacementNavigationData(0)->GetPosition(); MITK_INFO("USNavigationLogging") << "Total duration: " << m_NavigationStepTimer->GetTotalDuration(); ui->navigationProcessWidget->FinishCurrentNavigationStep(); m_ImageAndNavigationDataLoggingTimer->stop(); ui->runningLabel->setPixmap(m_IconNotRunning); ui->navigationProcessWidget->EnableInteraction(false); m_NavigationStepTimer->Stop(); // make sure that the navigation process will be start from beginning at the // next experiment ui->navigationProcessWidget->ResetNavigationProcess(); 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 = 0; // reset scene number for next experiment m_SceneNumber = 1; this->WaitCursorOff(); MITK_INFO("USNavigationLogging") << "Finished!"; } void USNavigationMarkerPlacement::OnCombinedModalityChanged( itk::SmartPointer combinedModality) { // remove old listener for ultrasound device changes if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice().IsNotNull()) { m_CombinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_ListenerDeviceChanged); } m_CombinedModality = combinedModality; m_ReinitAlreadyDone = false; // add a listener for ultrasound device changes if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice().IsNotNull()) { m_CombinedModality->GetUltrasoundDevice()->AddPropertyChangedListener(m_ListenerDeviceChanged); } // update navigation data recorder for using the new combined modality mitk::NavigationDataSource::Pointer navigationDataSource = combinedModality->GetNavigationDataSource(); m_NavigationDataRecorder->ConnectTo(navigationDataSource); m_NavigationDataRecorder->ResetRecording(); // update ultrasound image logging filter for using the new combined modality mitk::USDevice::Pointer ultrasoundImageSource = combinedModality->GetUltrasoundDevice(); for (unsigned int n = 0; n < ultrasoundImageSource->GetNumberOfIndexedOutputs(); ++n) { m_USImageLoggingFilter->SetInput(n, ultrasoundImageSource->GetOutput(n)); } // update ablation zone filter for using the new combined modality for (unsigned int n = 0; n < navigationDataSource->GetNumberOfIndexedOutputs(); ++n) { m_AblationZonesDisplacementFilter->SetInput(n, navigationDataSource->GetOutput(n)); } m_AblationZonesDisplacementFilter->SelectInput(m_MarkerIndex); // make sure that a reinit is done for the new images this->ReinitOnImage(); } void USNavigationMarkerPlacement::OnSettingsChanged(itk::SmartPointer settings) { std::string applicationName; if (!settings->GetStringProperty("settings.application", applicationName)) { // set default application if the string property is not available applicationName = "Marker Placement"; } // create navigation step widgets according to the selected application if (applicationName != m_CurrentApplicationName) { m_CurrentApplicationName = applicationName; QmitkUSNavigationProcessWidget::NavigationStepVector navigationSteps; if (applicationName == "Puncture") { QmitkUSNavigationStepCombinedModality* stepCombinedModality = new QmitkUSNavigationStepCombinedModality(m_Parent); QmitkUSNavigationStepTumourSelection* stepTumourSelection = new QmitkUSNavigationStepTumourSelection(m_Parent); stepTumourSelection->SetTargetSelectionOptional(true); m_TargetNodeDisplacementFilter = stepTumourSelection->GetTumourNodeDisplacementFilter(); QmitkUSNavigationStepZoneMarking* stepZoneMarking = new QmitkUSNavigationStepZoneMarking(m_Parent); QmitkUSNavigationStepPunctuationIntervention* stepIntervention = new QmitkUSNavigationStepPunctuationIntervention(m_Parent); connect(stepIntervention, SIGNAL(AddAblationZoneClicked(int)), this, SLOT(OnAddAblationZone(int))); connect(stepIntervention, SIGNAL(AblationZoneChanged(int, int)), this, SLOT(OnChangeAblationZone(int, int))); m_NavigationStepNames = std::vector(); navigationSteps.push_back(stepCombinedModality); m_NavigationStepNames.push_back("Combined Modality Initialization"); navigationSteps.push_back(stepTumourSelection); m_NavigationStepNames.push_back("Target Selection"); navigationSteps.push_back(stepZoneMarking); m_NavigationStepNames.push_back("Critical Structure Marking"); navigationSteps.push_back(stepIntervention); m_NavigationStepNames.push_back("Intervention"); } else if (applicationName == "Marker Placement") { QmitkUSNavigationStepCombinedModality *stepCombinedModality = new QmitkUSNavigationStepCombinedModality(m_Parent); QmitkUSNavigationStepTumourSelection *stepTumourSelection = new QmitkUSNavigationStepTumourSelection(m_Parent); m_TargetNodeDisplacementFilter = stepTumourSelection->GetTumourNodeDisplacementFilter(); QmitkUSNavigationStepZoneMarking *stepZoneMarking = new QmitkUSNavigationStepZoneMarking(m_Parent); QmitkUSNavigationStepPlacementPlanning *stepPlacementPlanning = new QmitkUSNavigationStepPlacementPlanning(m_Parent); QmitkUSNavigationStepMarkerIntervention *stepMarkerIntervention = new QmitkUSNavigationStepMarkerIntervention(m_Parent); m_NavigationStepNames = std::vector(); navigationSteps.push_back(stepCombinedModality); m_NavigationStepNames.push_back("Combined Modality Initialization"); navigationSteps.push_back(stepTumourSelection); m_NavigationStepNames.push_back("Target Selection"); navigationSteps.push_back(stepZoneMarking); m_NavigationStepNames.push_back("Critical Structure Marking"); navigationSteps.push_back(stepPlacementPlanning); m_NavigationStepNames.push_back("Placement Planning"); navigationSteps.push_back(stepMarkerIntervention); m_NavigationStepNames.push_back("Marker Intervention"); } // set navigation step widgets to the process widget ui->navigationProcessWidget->SetNavigationSteps(navigationSteps); for (QmitkUSNavigationProcessWidget::NavigationStepIterator it = m_NavigationSteps.begin(); it != m_NavigationSteps.end(); ++it) { delete *it; } m_NavigationSteps.clear(); m_NavigationSteps = navigationSteps; } // 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->navigationProcessWidget->ResetNavigationProcess(); ui->navigationProcessWidget->EnableInteraction(false); ui->runningLabel->setPixmap(m_IconNotRunning); } else if (!experimentMode) { if (m_IsExperimentRunning) { this->OnFinishExperiment(); } ui->navigationProcessWidget->EnableInteraction(true); } // 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 USNavigationMarkerPlacement::OnActiveNavigationStepChanged(int index) { // update navigation step timer each time the active navigation step changes m_NavigationStepTimer->SetActiveIndex(index, m_NavigationSteps.at(index)->GetTitle().toStdString()); if (static_cast(m_NavigationStepNames.size()) <= index) { MITK_INFO("USNavigationLogging") << "Someting went wrong: unknown navigation step!"; } else { MITK_INFO("USNavigationLogging") << "Navigation step finished/changed, next step: " << this->m_NavigationStepNames.at(index).toStdString() << "; duration until now: " << m_NavigationStepTimer->GetTotalDuration(); } +} - } +void USNavigationMarkerPlacement::OnNextNavigationStepInitialization(int index) +{ + MITK_DEBUG << "Next Step: " << m_NavigationSteps.at(index)->GetTitle().toStdString(); - void USNavigationMarkerPlacement::OnNextNavigationStepInitialization(int index) + if (m_NavigationSteps.at(index)->GetTitle().toStdString() == "Computer-assisted Intervention") { - - MITK_DEBUG << "Next Step: " << m_NavigationSteps.at(index)->GetTitle().toStdString(); - - if (m_NavigationSteps.at(index)->GetTitle().toStdString() == "Computer-assisted Intervention") + QmitkUSNavigationStepPunctuationIntervention* navigationStepPunctuationIntervention = static_cast(m_NavigationSteps.at(index)); + if (navigationStepPunctuationIntervention != nullptr) { - QmitkUSNavigationStepPunctuationIntervention* navigationStepPunctuationIntervention = static_cast(m_NavigationSteps.at(index)); - if (navigationStepPunctuationIntervention != nullptr) + if (m_CurrentStorage.IsNull()) { this->UpdateToolStorage(); } + if (m_CurrentStorage.IsNull() || (m_CurrentStorage->GetTool(m_NeedleIndex).IsNull())) + { + MITK_WARN << "Found null pointer when setting the tool axis, aborting"; + } + else { - if (m_CurrentStorage.IsNull()) { this->UpdateToolStorage(); } - if (m_CurrentStorage.IsNull() || (m_CurrentStorage->GetTool(m_NeedleIndex).IsNull())) - { - MITK_WARN << "Found null pointer when setting the tool axis, aborting"; - } - else - { - navigationStepPunctuationIntervention->SetNeedleMetaData(m_CurrentStorage->GetTool(m_NeedleIndex)); - MITK_DEBUG << "Needle axis vector: " << m_CurrentStorage->GetTool(m_NeedleIndex)->GetToolAxis(); - } + navigationStepPunctuationIntervention->SetNeedleMetaData(m_CurrentStorage->GetTool(m_NeedleIndex)); + MITK_DEBUG << "Needle axis vector: " << m_CurrentStorage->GetTool(m_NeedleIndex)->GetToolAxis(); } } - + } } void USNavigationMarkerPlacement::OnIntermediateResultProduced(const itk::SmartPointer resultsNode) { // intermediate results only matter during an experiment if (!m_IsExperimentRunning) { return; } this->WaitCursorOn(); // set results node to the experiment logging (for saving contents to the // file system) m_ExperimentLogging->SetResult(resultsNode); std::string resultsName; if (!resultsNode->GetName(resultsName)) { MITK_WARN << "Could not get name of current results node."; return; } // save the mitk scene std::string scenefile = QString(m_ExperimentResultsSubDirectory + QDir::separator() + QString("Scene %1 - ").arg(m_SceneNumber++, 2, 10, QChar('0')) + QString::fromStdString(resultsName).replace(":", "_") + ".mitk") .toStdString(); MITK_INFO << "Saving Scene File: " << scenefile; mitk::SceneIO::Pointer sceneIO = mitk::SceneIO::New(); mitk::NodePredicateNot::Pointer isNotHelperObject = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(true))); mitk::DataStorage::SetOfObjects::ConstPointer nodesToBeSaved = this->GetDataStorage()->GetSubset(isNotHelperObject); this->Convert2DImagesTo3D(nodesToBeSaved); sceneIO->SaveScene(nodesToBeSaved, this->GetDataStorage(), scenefile); this->WaitCursorOff(); } void USNavigationMarkerPlacement::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 *renderWindow = this->GetRenderWindowPart(); if (renderWindow != NULL && image->GetTimeGeometry()->IsValid()) { renderWindow->GetRenderingManager()->InitializeViews( image->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); renderWindow->GetRenderingManager()->RequestUpdateAll(); } this->RequestRenderWindowUpdate(); m_ReinitAlreadyDone = true; } } } void USNavigationMarkerPlacement::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 USNavigationMarkerPlacement::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 USNavigationMarkerPlacement::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 = NULL; } -} +} \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.h b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.h index 25ec7c6be6..c638743171 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.h +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.h @@ -1,199 +1,238 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef USNAVIGATIONMARKERPLACEMENT_H #define USNAVIGATIONMARKERPLACEMENT_H #include #include "IO/mitkUSNavigationLoggingBackend.h" #include "Widgets/QmitkUSNavigationProcessWidget.h" #include "mitkNavigationDataRecorder.h" #include "mitkNodeDisplacementFilter.h" #include "mitkUSImageLoggingFilter.h" #include #include #include #include namespace itk { template class SmartPointer; } namespace mitk { class USNavigationStepTimer; class USNavigationExperimentLogging; } namespace Ui { class USNavigationMarkerPlacement; } class QmitkUSAbstractNavigationStep; class QmitkUSNavigationStepPunctuationIntervention; class QmitkStdMultiWidget; class QTimer; class QSignalMapper; /** * \brief View for navigated marker placement using the combined modality. * This view utilizes the QmitkUSNavigationProcessWidget to do the navigation * process. It can be switched between widgets for marker placement and widgets * for punctuation. * * An experiment mode allows for logging results, durations and the ultrasound * images. */ class USNavigationMarkerPlacement : public QmitkAbstractView { Q_OBJECT protected slots: /** * \brief Called periodically to update the rendering. * The standard multi widget is changed to fit the navigation process once it * is available and a reinit on the ultrasound image is done for a new image * node. */ void OnTimeout(); /** * \brief Called periodically during an experiment for logging the ultrasound images. */ void OnImageAndNavigationDataLoggingTimeout(); /** * \brief Initializes anything neccessary for an experiment. * The user is asked for a directory for storing the results and the logging * is started. */ void OnStartExperiment(); /** * \brief Stops logging and saves everything to the file system. */ void OnFinishExperiment(); void OnCombinedModalityChanged(itk::SmartPointer); /** * \brief Switches the navigation step widgets if the navigation application was changed. */ void OnSettingsChanged(itk::SmartPointer); /** * \brief Updates the timer for the navigation steps durations every time the active navigation step changes. */ void OnActiveNavigationStepChanged(int); /** Initializes the next navigation step */ void OnNextNavigationStepInitialization(int); /** * \brief The data node is given to the experiment logging and scene is saved to the file system. */ void OnIntermediateResultProduced(const itk::SmartPointer); void OnAddAblationZone(int size); void OnEnableNavigationLayout(); void OnResetStandardLayout(); void OnChangeLayoutClicked(); void OnChangeAblationZone(int id, int newSize); + void OnRenderWindowSelection(); + + void OnRefreshView(); + public: static const char *DATANAME_TUMOUR; static const char *DATANAME_TARGETSURFACE; static const char *DATANAME_ZONES; static const char *DATANAME_TARGETS; static const char *DATANAME_TARGETS_PATHS; static const char *DATANAME_REACHED_TARGETS; explicit USNavigationMarkerPlacement(); ~USNavigationMarkerPlacement(); virtual void CreateQtPartControl(QWidget *parent); static const std::string VIEW_ID; void OnCombinedModalityPropertyChanged(const std::string &, const std::string &); protected: /** * \brief A reinit on the ultrasound image is performed every time the view gets the focus. */ virtual void SetFocus(); /** * \brief Helper function which performs a reinit on the ultrasound image. */ void ReinitOnImage(); + /** + * \brief Sets the multiwidget to two windows, axial on top and 3D render window on the bottom. + */ + virtual void SetTwoWindowView(); + + /** + * \brief Helper function for being able to serialize the 2d ultrasound image. + */ + void Convert2DImagesTo3D(mitk::DataStorage::SetOfObjects::ConstPointer nodes); /** * \brief Helper function for being able to serialize the 2d ultrasound image. */ void Convert2DImagesTo3D(mitk::DataStorage::SetOfObjects::ConstPointer nodes); void UpdateToolStorage(); void CreateOverlays(); + QWidget *m_Parent; QmitkUSNavigationProcessWidget::NavigationStepVector m_NavigationSteps; + QTimer *m_UpdateTimer; + QTimer *m_ImageAndNavigationDataLoggingTimer; + QmitkStdMultiWidget *m_StdMultiWidget; itk::SmartPointer m_CombinedModality; + bool m_ReinitAlreadyDone; + bool m_IsExperimentRunning; std::string m_CurrentApplicationName; + + itk::SmartPointer m_NavigationStepTimer; + itk::SmartPointer m_ExperimentLogging; + + QPixmap m_IconRunning; + QPixmap m_IconNotRunning; + QString m_ResultsDirectory; QString m_ExperimentName; QString m_ExperimentResultsSubDirectory; - std::vector m_NavigationStepNames; // stores the names of the navigation steps which are currently used (for logging purposes) + std::vector + m_NavigationStepNames; // stores the names of the navigation steps which are currently used (for logging purposes) + mitk::USNavigationLoggingBackend m_LoggingBackend; + mitk::USImageLoggingFilter::Pointer m_USImageLoggingFilter; + mitk::NavigationDataRecorder::Pointer m_NavigationDataRecorder; // records navigation data files mitk::NodeDisplacementFilter::Pointer m_TargetNodeDisplacementFilter; + mitk::NodeDisplacementFilter::Pointer m_AblationZonesDisplacementFilter; std::vector m_AblationZonesVector; + + int m_NeedleIndex; + int m_MarkerIndex; + + int m_SceneNumber; + + itk::SmartPointer m_WarnOverlay; + //To get tool storage mitk::NavigationDataSource::Pointer m_NavigationDataSource; mitk::NavigationToolStorage::Pointer m_CurrentStorage; QWidget *m_Parent; QTimer *m_UpdateTimer; QTimer *m_ImageAndNavigationDataLoggingTimer; QmitkStdMultiWidget *m_StdMultiWidget; bool m_ReinitAlreadyDone; bool m_IsExperimentRunning; itk::SmartPointer m_NavigationStepTimer; itk::SmartPointer m_ExperimentLogging; mitk::NodeDisplacementFilter::Pointer m_AblationZonesDisplacementFilter; QPixmap m_IconRunning; QPixmap m_IconNotRunning; mitk::USImageLoggingFilter::Pointer m_USImageLoggingFilter; mitk::NavigationDataRecorder::Pointer m_NavigationDataRecorder; // records navigation data files int m_SceneNumber; itk::SmartPointer m_WarnOverlay; int m_NeedleIndex; int m_MarkerIndex; private: mitk::MessageDelegate2 m_ListenerDeviceChanged; Ui::USNavigationMarkerPlacement *ui; }; #endif // USNAVIGATIONMARKERPLACEMENT_H diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.ui b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.ui index eb816e0225..a181fe0767 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.ui +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.ui @@ -1,102 +1,123 @@ USNavigationMarkerPlacement 0 0 400 146 Form 0 0 0 0 0 Qt::Horizontal - - - Enable Navigation Render Window Layout - - - true - - + + + + + Enable Navigation Render Window Layout with RenderWindow + + + true + + + + + + + 1 + + + 3 + + + + + + + Refresh view + + + + Start New Experiment false Finish Experiment 20 20 QmitkUSNavigationProcessWidget QWidget
src/internal/Widgets/QmitkUSNavigationProcessWidget.h
1
OnStartExperiment() OnFinishExperiment()
diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/UltrasoundCalibrationControls.ui b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/UltrasoundCalibrationControls.ui index 55ea3f8943..59289dd670 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/UltrasoundCalibrationControls.ui +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/UltrasoundCalibrationControls.ui @@ -1,1162 +1,1163 @@ UltrasoundCalibrationControls true 0 0 374 923 0 0 QmitkTemplate 0 0 1 0 0 - 356 - 824 + 200 + 57 Config false Start Calibration for Selected Device 0 0 356 824 Spatial Calibration 0 10 351 831 - 2 + 1 Spacing 10 150 281 41 Add Point Qt::Horizontal QSizePolicy::Expanding 40 20 false Freeze 10 10 281 131 <html><head/><body><p>1. Freeze the US-Image.</p><p>2. Mark two points in the US-Image of which you know <br/>they are exactly 30mm apart in horizontal direction.</p><p>3. Marktwo more points in the US-Image of which you <br/>know they are exactly 20mm apart vertical direction.</p><p>4. Now you can click the &quot;Calculate Spacing&quot;-Button. <br/>The spacing is calculated and applied to the US-Image.</p></body></html> Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop 10 200 281 192 20 400 261 23 Calculate Spacing Point Based 10 10 221 16 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; text-decoration: underline;">Step 1: Collect Points</span></p></body></html> 10 30 - 231 + 261 91 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Slowly move a tracking tool into the image plane of the ultrasound. As soon as it becomes visible, click &quot;freeze&quot; and mark the point on the screen. Do this with as many points as necessary, then click calibrate to perform calibration.</span></p></body></html> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Slowly move a tracking tool into the image plane of the ultrasound. As soon as it becomes visible, click &quot;freeze&quot; and mark the point on the screen by moving the Crosshair to the pont in the US image (best: click in 2D Axial view).</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Do this with as many points as necessary, then click calibrate to perform calibration.</p></body></html> true 10 120 291 31 75 true <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Tracking Status:</span></p></body></html> false 10 620 301 23 Save Calibration 10 550 291 16 Qt::Horizontal 10 200 301 225 10 450 571 16 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; text-decoration: underline;">Step 2: Calibrate (perform landmark transformation)</span></p></body></html> 10 160 301 25 Freeze Qt::Horizontal 40 20 false Add Point 10 430 301 21 Qt::Horizontal 10 510 301 23 Calibrate 10 590 584 17 Save additional logging information (MITK scene, etc.) true 10 480 584 17 Activate Scaling during Calibration Transform 10 570 291 16 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; text-decoration: underline;">Step 3: Save calibration to hard disc</span></p></body></html> 10 680 301 23 Stop Calibration Process 10 710 301 23 Restart Current Calibration 100 120 211 31 0 40 10 650 301 20 Qt::Horizontal PLUS Connection 10 10 301 241 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">Step 1: Calibrate using fCal</span></p></body></html> Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">1. Setup the Connection to PLUS</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">2. Start fCal with the EchoTrackCalibration Config file</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">3. Connect fcal to MITK, once it connected successfully you can click the &quot;Start Streaming&quot; Button below</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">4. Now follow the steps in fCal and don't forget to save the Calibration in the end</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">5. Finish fCal</p></body></html> true <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">Step 2: Get the calibration back from PLUS</span></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">1. Start a PLUS Server with the configfile you saved in the final step of fCal</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">2. Once the Server connected to MITK click the &quot;Start Streaming&quot; Button below</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">3. Now Click the &quot;Get Calibration from PLUS&quot;Button below</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">4. You can now save the calibration</p></body></html> true 10 270 301 281 false 0 90 299 23 Start Streaming false 0 140 299 23 Get Calibration from PLUS false 0 180 299 23 Save PLUS Calibration 0 220 299 23 Stop Calibration with PLUS false 0 60 291 21 0 120 281 16 false 0 30 301 23 Setup PLUS Connection false 0 10 291 21 0 0 - 356 - 824 + 100 + 30 Evaluation 0 0 311 821 1 Point Based Evaluation 10 130 301 16 Mark the visible needle tip with the crosshair 10 10 301 31 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Bring the needle into the tracking volume, so the projection can be calculated</span></p></body></html> true 10 70 291 31 Push the needle forward until it becomes visible in the Image true 10 150 291 23 Step 3: Add Target Points 10 100 291 23 Step 2: Freeze Image 10 440 291 108 When done, save results Run Next Round Prefix: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Save Results Path: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 10 180 291 247 Control QFormLayout::AllNonFixedFieldsGrow Tracking Status: # Projection Points: # Target Points: 0 Evaluation TRE: 0 Projection TRE: 0 Calibration FRE: 0 0 10 50 291 23 Step 1: Save Needle Projection Reference Device 10 10 281 16 Choose pointer: 10 30 281 50 0 50 10 90 281 366 1 0 0 179 82 Create Reference Current reference points: Add Current Pointer Tip Position Qt::Vertical 20 111 0 0 281 312 Quick Verification Start Verification Current Point: Qt::Horizontal 40 20 <none> Add current pointer tip Result: QmitkToolTrackingStatusWidget QWidget
QmitkToolTrackingStatusWidget.h
1
QmitkUSNavigationStepCombinedModality QWidget
src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.h
1
QmitkPointListWidget QWidget
QmitkPointListWidget.h
1
QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
QmitkNavigationDataSourceSelectionWidget QWidget
QmitkNavigationDataSourceSelectionWidget.h
1
OnStartCalibrationProcess() OnReset() OnStopCalibrationProcess()
diff --git a/Plugins/org.mitk.gui.qt.igtexamples/src/internal/QmitkIGTTrackingLabView.cpp b/Plugins/org.mitk.gui.qt.igtexamples/src/internal/QmitkIGTTrackingLabView.cpp index 8ed8cb6862..0c651095d4 100644 --- a/Plugins/org.mitk.gui.qt.igtexamples/src/internal/QmitkIGTTrackingLabView.cpp +++ b/Plugins/org.mitk.gui.qt.igtexamples/src/internal/QmitkIGTTrackingLabView.cpp @@ -1,734 +1,731 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkIGTTrackingLabView.h" #include #include #include #include #include #include - -#include #include #include #include #include #include -#include #include #include #include #include // Qt #include #include #include // vtk #include const std::string QmitkIGTTrackingLabView::VIEW_ID = "org.mitk.views.igttrackinglab"; QmitkIGTTrackingLabView::QmitkIGTTrackingLabView() : QmitkAbstractView() ,m_Source(nullptr) ,m_PermanentRegistrationFilter(nullptr) ,m_Visualizer(nullptr) ,m_VirtualView(nullptr) ,m_PSRecordingPointSet(nullptr) ,m_PointSetRecording(false) ,m_PermanentRegistration(false) ,m_CameraView(false) ,m_ImageFiducialsDataNode(nullptr) ,m_TrackerFiducialsDataNode(nullptr) ,m_PermanentRegistrationSourcePoints(nullptr) { } //############################################################################################### //############################################################################################### //############################## Timer method for IGT pipeline updating ######################### //############################################################################################### //############################################################################################### void QmitkIGTTrackingLabView::UpdateTimer() { if (m_PermanentRegistration && m_PermanentRegistrationFilter.IsNotNull()) { if(IsTransformDifferenceHigh(m_ObjectmarkerNavigationData, m_ObjectmarkerNavigationDataLastUpdate)) { m_ObjectmarkerNavigationDataLastUpdate->Graft(m_ObjectmarkerNavigationData); m_PermanentRegistrationFilter->Update(); } } if (m_CameraView && m_VirtualView.IsNotNull()) {m_VirtualView->Update();} if(m_PointSetRecording && m_PSRecordingPointSet.IsNotNull()) { int size = m_PSRecordingPointSet->GetSize(); mitk::NavigationData::Pointer nd = m_PointSetRecordingNavigationData; if(size > 0) { mitk::Point3D p = m_PSRecordingPointSet->GetPoint(size-1); if(p.EuclideanDistanceTo(nd->GetPosition()) > (double) m_Controls.m_PSRecordingSpinBox->value()) m_PSRecordingPointSet->InsertPoint(size, nd->GetPosition()); } else m_PSRecordingPointSet->InsertPoint(size, nd->GetPosition()); } } //############################################################################################### //############################################################################################### //############################## Slots of CONFIGURATION step #################################### //############################################################################################### //############################################################################################### void QmitkIGTTrackingLabView::OnSetupNavigation() { if(m_Source.IsNotNull()) if(m_Source->IsTracking()) return; mitk::DataStorage* ds = this->GetDataStorage(); if(ds == nullptr) { MITK_WARN << "IGTSurfaceTracker: Error. Cannot access DataStorage. Navigation not possible"; return; } //Building up the filter pipeline try { this->InitializeRegistration(); } catch(mitk::IGTException& e) { MITK_WARN << "Error while building the IGT-Pipeline: " << e.GetDescription(); this->DestroyIGTPipeline(); // destroy the pipeline if building is incomplete return; } catch(...) { MITK_WARN << "Unexpected error while building the IGT-Pipeline"; this->DestroyIGTPipeline(); return; } } void QmitkIGTTrackingLabView::OnInstrumentSelected() { if (m_Controls.m_TrackingDeviceSelectionWidget->GetSelectedNavigationDataSource().IsNotNull()) { m_InstrumentNavigationData = m_Controls.m_TrackingDeviceSelectionWidget->GetSelectedNavigationDataSource()->GetOutput(m_Controls.m_TrackingDeviceSelectionWidget->GetSelectedToolID()); } else { m_Controls.m_PointerNameLabel->setText(""); return; } if (m_InstrumentNavigationData.IsNotNull()) { m_Controls.m_PointerNameLabel->setText(m_InstrumentNavigationData->GetName()); } else { m_Controls.m_PointerNameLabel->setText(""); } } void QmitkIGTTrackingLabView::OnObjectmarkerSelected() { if (m_Controls.m_TrackingDeviceSelectionWidget->GetSelectedNavigationDataSource().IsNotNull()) { m_ObjectmarkerNavigationData = m_Controls.m_TrackingDeviceSelectionWidget->GetSelectedNavigationDataSource()->GetOutput(m_Controls.m_TrackingDeviceSelectionWidget->GetSelectedToolID()); MITK_INFO << "Objectmarker rotation: " << m_ObjectmarkerNavigationData->GetOrientation(); } else { m_Controls.m_ObjectmarkerNameLabel->setText(""); return; } if (m_ObjectmarkerNavigationData.IsNotNull()) { m_Controls.m_ObjectmarkerNameLabel->setText(m_ObjectmarkerNavigationData->GetName()); } else { m_Controls.m_ObjectmarkerNameLabel->setText(""); } } //############################################################################################### //############################################################################################### //####################### Slots of INITIAL REGISTRATION step #################################### //############################################################################################### //############################################################################################### void QmitkIGTTrackingLabView::OnInitialRegistration() { //Check for initialization if (!CheckRegistrationInitialization()) return; mitk::PointSet::Pointer imageFiducials = dynamic_cast(m_ImageFiducialsDataNode->GetData()); mitk::PointSet::Pointer trackerFiducials = dynamic_cast(m_TrackerFiducialsDataNode->GetData()); //############### conversion to vtk data types (we will use the vtk landmark based transform) ########################## //convert point sets to vtk poly data vtkSmartPointer sourcePoints = vtkSmartPointer::New(); vtkSmartPointer targetPoints = vtkSmartPointer::New(); for (int i=0; iGetSize(); i++) { double point[3] = {imageFiducials->GetPoint(i)[0],imageFiducials->GetPoint(i)[1],imageFiducials->GetPoint(i)[2]}; sourcePoints->InsertNextPoint(point); double point_targets[3] = {trackerFiducials->GetPoint(i)[0],trackerFiducials->GetPoint(i)[1],trackerFiducials->GetPoint(i)[2]}; targetPoints->InsertNextPoint(point_targets); } //########################### here, the actual transform is computed ########################## //compute transform vtkSmartPointer transform = vtkSmartPointer::New(); transform->SetSourceLandmarks(sourcePoints); transform->SetTargetLandmarks(targetPoints); transform->SetModeToRigidBody(); transform->Modified(); transform->Update(); //compute FRE of transform double FRE = mitk::StaticIGTHelperFunctions::ComputeFRE(imageFiducials, trackerFiducials, transform); m_Controls.m_RegistrationWidget->SetQualityDisplayText("FRE: " + QString::number(FRE) + " mm"); //############################################################################################# //############### conversion back to itk/mitk data types ########################## //convert from vtk to itk data types itk::Matrix rotationFloat = itk::Matrix(); itk::Vector translationFloat = itk::Vector(); itk::Matrix rotationDouble = itk::Matrix(); itk::Vector translationDouble = itk::Vector(); vtkSmartPointer m = transform->GetMatrix(); for(int k=0; k<3; k++) for(int l=0; l<3; l++) { rotationFloat[k][l] = m->GetElement(k,l); rotationDouble[k][l] = m->GetElement(k,l); } for(int k=0; k<3; k++) { translationFloat[k] = m->GetElement(k,3); translationDouble[k] = m->GetElement(k,3); } //create affine transform 3D surface mitk::AffineTransform3D::Pointer mitkTransform = mitk::AffineTransform3D::New(); mitkTransform->SetMatrix(rotationDouble); mitkTransform->SetOffset(translationDouble); //############################################################################################# //############### object is transformed ########################## //save transform m_T_ObjectReg = mitk::NavigationData::New(mitkTransform); // this is stored in a member because it is needed for permanent registration later on //transform surface if(m_Controls.m_SurfaceActive->isChecked() && m_Controls.m_ObjectComboBox->GetSelectedNode().IsNotNull()) { m_Controls.m_ObjectComboBox->GetSelectedNode()->GetData()->GetGeometry()->SetIndexToWorldTransform(mitkTransform); } //################################################################ //############### if activated: ct image is also transformed ########################## //transform ct image //todo: Erklären, dass hier AffineTransform3D verwendet wird, weil NavigationData kein Spacing unterstützt! if(m_Controls.m_ImageActive->isChecked() && m_Controls.m_ImageComboBox->GetSelectedNode().IsNotNull()) { //first we have to store the original ct image transform to compose it with the new transform later mitk::AffineTransform3D::Pointer imageTransform = m_Controls.m_ImageComboBox->GetSelectedNode()->GetData()->GetGeometry()->GetIndexToWorldTransform(); m_T_ImageGeo = mitk::AffineTransform3D::New(); // this is also stored in a member because it is needed for permanent registration later on //now the new transform of the ct image is computed m_T_ImageGeo->Compose(imageTransform); imageTransform->Compose(mitkTransform); mitk::AffineTransform3D::Pointer newImageTransform = mitk::AffineTransform3D::New(); //create new image transform... setting the composed directly leads to an error itk::Matrix rotationFloatNew = imageTransform->GetMatrix(); itk::Vector translationFloatNew = imageTransform->GetOffset(); newImageTransform->SetMatrix(rotationFloatNew); newImageTransform->SetOffset(translationFloatNew); m_Controls.m_ImageComboBox->GetSelectedNode()->GetData()->GetGeometry()->SetIndexToWorldTransform(newImageTransform); m_T_ImageReg = m_Controls.m_ImageComboBox->GetSelectedNode()->GetData()->GetGeometry()->GetIndexToWorldTransform(); } //################################################################ } void QmitkIGTTrackingLabView::OnAddRegistrationTrackingFiducial() { mitk::NavigationData::Pointer nd = m_InstrumentNavigationData; if( nd.IsNull() || !nd->IsDataValid()) { QMessageBox::warning( 0, "Invalid tracking data", "Navigation data is not available or invalid!", QMessageBox::Ok ); return; } if(m_TrackerFiducialsDataNode.IsNotNull() && m_TrackerFiducialsDataNode->GetData() != nullptr) { mitk::PointSet::Pointer ps = dynamic_cast(m_TrackerFiducialsDataNode->GetData()); ps->InsertPoint(ps->GetSize(), nd->GetPosition()); } else QMessageBox::warning(nullptr, "IGTSurfaceTracker: Error", "Can not access Tracker Fiducials. Adding fiducial not possible!"); } void QmitkIGTTrackingLabView::InitializeRegistration() { mitk::DataStorage* ds = this->GetDataStorage(); if( ds == nullptr ) return; // let the registration widget know about the slice navigation controllers // in the active render window part (crosshair updates) foreach(QmitkRenderWindow* renderWindow, this->GetRenderWindowPart()->GetQmitkRenderWindows().values()) { m_Controls.m_RegistrationWidget->AddSliceNavigationController(renderWindow->GetSliceNavigationController()); } if(m_ImageFiducialsDataNode.IsNull()) { m_ImageFiducialsDataNode = mitk::DataNode::New(); mitk::PointSet::Pointer ifPS = mitk::PointSet::New(); m_ImageFiducialsDataNode->SetData(ifPS); mitk::Color color; color.Set(1.0f, 0.0f, 0.0f); m_ImageFiducialsDataNode->SetName("Image Fiducials"); m_ImageFiducialsDataNode->SetColor(color); m_ImageFiducialsDataNode->SetBoolProperty( "updateDataOnRender", false ); ds->Add(m_ImageFiducialsDataNode); } m_Controls.m_RegistrationWidget->SetImageFiducialsNode(m_ImageFiducialsDataNode); if(m_TrackerFiducialsDataNode.IsNull()) { m_TrackerFiducialsDataNode = mitk::DataNode::New(); mitk::PointSet::Pointer tfPS = mitk::PointSet::New(); m_TrackerFiducialsDataNode->SetData(tfPS); mitk::Color color; color.Set(0.0f, 1.0f, 0.0f); m_TrackerFiducialsDataNode->SetName("Tracking Fiducials"); m_TrackerFiducialsDataNode->SetColor(color); m_TrackerFiducialsDataNode->SetBoolProperty( "updateDataOnRender", false ); ds->Add(m_TrackerFiducialsDataNode); } m_Controls.m_RegistrationWidget->SetTrackerFiducialsNode(m_TrackerFiducialsDataNode); } //############################################################################################### //############################################################################################### //####################### Slots of PERMANENT REGISTRATION step ################################## //############################################################################################### //############################################################################################### void QmitkIGTTrackingLabView::OnPermanentRegistration(bool on) { if(on) { //###################################################################### //######################## inititalization ############################# //###################################################################### //some initial checks if(!CheckRegistrationInitialization()) { m_Controls.m_UsePermanentRegistrationToggle->setChecked(false); return; } //remember initial object transform to calculate the object to marker transform later on and convert it to navigation data mitk::AffineTransform3D::Pointer transform = this->m_Controls.m_ObjectComboBox->GetSelectedNode()->GetData()->GetGeometry()->GetIndexToWorldTransform(); mitk::NavigationData::Pointer T_Object = mitk::NavigationData::New(transform,false); //TODO: catch exception during conversion? //then reset the transform because we will now start to calculate the permanent registration this->m_Controls.m_ObjectComboBox->GetSelectedNode()->GetData()->GetGeometry()->SetIdentity(); if(m_Controls.m_ImageActive->isChecked()) {this->m_Controls.m_ImageComboBox->GetSelectedNode()->GetData()->GetGeometry()->SetIndexToWorldTransform(m_T_ImageGeo);} //create the permanent registration filter m_PermanentRegistrationFilter = mitk::NavigationDataObjectVisualizationFilter::New(); //###################################################################### //first: initialize permanent registration of surface (always activated) //###################################################################### //connect filter to source m_PermanentRegistrationFilter->SetInput(0,this->m_ObjectmarkerNavigationData); //set representation object m_PermanentRegistrationFilter->SetRepresentationObject(0,this->m_Controls.m_ObjectComboBox->GetSelectedNode()->GetData()); //get the marker transform out of the navigation data mitk::NavigationData::Pointer T_Marker = m_ObjectmarkerNavigationData; //compute transform from object to marker (T_MarkerRel = T_Object * T_Marker^-1) mitk::NavigationData::Pointer T_MarkerRel = mitk::NavigationData::New(); T_MarkerRel->Compose(T_Object); T_MarkerRel->Compose(T_Marker->GetInverse()); m_T_MarkerRel = T_MarkerRel; m_PermanentRegistrationFilter->SetOffset(0,m_T_MarkerRel->GetAffineTransform3D()); //###################################################################### //second: initialize permanent registration of image (if activated) //###################################################################### if (m_Controls.m_ImageActive->isChecked() && (m_Controls.m_ImageComboBox->GetSelectedNode().IsNotNull())) { mitk::DataNode::Pointer imageNode = this->m_Controls.m_ImageComboBox->GetSelectedNode(); imageNode->AddProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New(VTK_RESLICE_LINEAR) ); m_PermanentRegistrationFilter->SetInput(1,this->m_ObjectmarkerNavigationData); m_PermanentRegistrationFilter->SetRepresentationObject(1,imageNode->GetData()); //for the image we can't use NavigationData objects as transforms because an image needs additional geometry information, e.g., spacing //thus we use mitk::AffineTransform3D objects //computer transform from image to marker (T_ImageRel = T_ImageGeo * T_MarkerRel) mitk::AffineTransform3D::Pointer T_ImageRel = mitk::AffineTransform3D::New(); T_ImageRel->SetIdentity(); T_ImageRel->Compose(m_T_ImageGeo); T_ImageRel->Compose(m_T_MarkerRel->GetAffineTransform3D()); m_PermanentRegistrationFilter->SetOffset(1,T_ImageRel); } //some general stuff m_PermanentRegistration = true; m_ObjectmarkerNavigationDataLastUpdate = mitk::NavigationData::New(); } else //if off = disable the permanent registration { //stop permanent registration m_PermanentRegistration = false; //restore old registration if(m_T_ObjectReg.IsNotNull()) {this->m_Controls.m_ObjectComboBox->GetSelectedNode()->GetData()->GetGeometry()->SetIndexToWorldTransform(m_T_ObjectReg->GetAffineTransform3D());} if(m_T_ImageReg.IsNotNull()) {this->m_Controls.m_ImageComboBox->GetSelectedNode()->GetData()->GetGeometry()->SetIndexToWorldTransform(m_T_ImageReg);} //delete filter m_PermanentRegistrationFilter = nullptr; } } //############################################################################################### //############################################################################################### //####################### Slots of POINT SET RECORDING step ##################################### //############################################################################################### //############################################################################################### void QmitkIGTTrackingLabView::OnPointSetRecording(bool record) { mitk::DataStorage* ds = this->GetDataStorage(); if(record) { if (m_Controls.m_PointSetRecordingToolSelectionWidget->GetSelectedToolID() == -1) { QMessageBox::warning(nullptr, "Error", "No tool selected for point set recording!"); m_Controls.m_PointSetRecordCheckBox->setChecked(false); return; } m_PointSetRecordingNavigationData = m_Controls.m_PointSetRecordingToolSelectionWidget->GetSelectedNavigationDataSource()->GetOutput(m_Controls.m_PointSetRecordingToolSelectionWidget->GetSelectedToolID()); //initialize point set mitk::DataNode::Pointer psRecND = ds->GetNamedNode("Recorded Points"); if(m_PSRecordingPointSet.IsNull() || psRecND.IsNull()) { m_PSRecordingPointSet = nullptr; m_PSRecordingPointSet = mitk::PointSet::New(); mitk::DataNode::Pointer dn = mitk::DataNode::New(); dn->SetName("Recorded Points"); dn->SetColor(0.,1.,0.); dn->SetData(m_PSRecordingPointSet); ds->Add(dn); } else { m_PSRecordingPointSet->Clear(); } m_PointSetRecording = true; } else { m_PointSetRecording = false; } } //############################################################################################### //############################################################################################### //####################### Slots of VIRTUAL CAMERA VIEW step ##################################### //############################################################################################### //############################################################################################### void QmitkIGTTrackingLabView::OnVirtualCamera(bool on) { if (m_Controls.m_CameraViewSelection->GetSelectedToolID() == -1) { m_Controls.m_ActivateNeedleView->setChecked(false); QMessageBox::warning(nullptr, "Error", "No tool selected for camera view!"); return; } if(on) { m_VirtualView = mitk::CameraVisualization::New(); m_VirtualView->SetInput(m_Controls.m_CameraViewSelection->GetSelectedNavigationDataSource()->GetOutput(m_Controls.m_CameraViewSelection->GetSelectedToolID())); mitk::Vector3D viewDirection; viewDirection[0] = (int)(m_Controls.m_NeedleViewX->isChecked()); viewDirection[1] = (int)(m_Controls.m_NeedleViewY->isChecked()); viewDirection[2] = (int)(m_Controls.m_NeedleViewZ->isChecked()); if (m_Controls.m_NeedleViewInvert->isChecked()) viewDirection *= -1; m_VirtualView->SetDirectionOfProjectionInToolCoordinates(viewDirection); mitk::Vector3D viewUpVector; viewUpVector[0] = (int)(m_Controls.m_NeedleUpX->isChecked()); viewUpVector[1] = (int)(m_Controls.m_NeedleUpY->isChecked()); viewUpVector[2] = (int)(m_Controls.m_NeedleUpZ->isChecked()); if (m_Controls.m_NeedleUpInvert->isChecked()) viewUpVector *= -1; m_VirtualView->SetViewUpInToolCoordinates(viewUpVector); m_VirtualView->SetRenderer(this->GetRenderWindowPart()->GetQmitkRenderWindow("3d")->GetRenderer()); //next line: better code when this plugin is migrated to mitk::abstractview //m_VirtualView->SetRenderer(mitk::BaseRenderer::GetInstance(this->GetRenderWindowPart()->GetRenderWindow("3d")->GetRenderWindow())); m_CameraView = true; //make pointer itself invisible m_Controls.m_CameraViewSelection->GetSelectedNavigationTool()->GetDataNode()->SetBoolProperty("visible",false); //disable UI elements m_Controls.m_ViewDirectionBox->setEnabled(false); m_Controls.m_ViewUpBox->setEnabled(false); } else { m_VirtualView = nullptr; m_CameraView = false; m_Controls.m_CameraViewSelection->GetSelectedNavigationTool()->GetDataNode()->SetBoolProperty("visible",true); m_Controls.m_ViewDirectionBox->setEnabled(true); m_Controls.m_ViewUpBox->setEnabled(true); } } //############################################################################################### //############################################################################################### //############################## some general UI methods, always needed ######################### //############################################################################################### //############################################################################################### QmitkIGTTrackingLabView::~QmitkIGTTrackingLabView() { if (m_Timer->isActive()) m_Timer->stop(); } void QmitkIGTTrackingLabView::CreateQtPartControl( QWidget *parent ) { // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi( parent ); this->CreateBundleWidgets(); this->CreateConnections(); } void QmitkIGTTrackingLabView::CreateBundleWidgets() { //initialize registration widget m_Controls.m_RegistrationWidget->HideStaticRegistrationRadioButton(true); m_Controls.m_RegistrationWidget->HideContinousRegistrationRadioButton(true); m_Controls.m_RegistrationWidget->HideUseICPRegistrationCheckbox(true); } void QmitkIGTTrackingLabView::CreateConnections() { //initialize timer m_Timer = new QTimer(this); //create connections connect(m_Timer, SIGNAL(timeout()), this, SLOT(UpdateTimer())); connect( m_Controls.m_UsePermanentRegistrationToggle, SIGNAL(toggled(bool)), this, SLOT(OnPermanentRegistration(bool)) ); connect( m_Controls.m_TrackingDeviceSelectionWidget, SIGNAL(NavigationDataSourceSelected(mitk::NavigationDataSource::Pointer)), this, SLOT(OnSetupNavigation()) ); connect( m_Controls.m_UseAsPointerButton, SIGNAL(clicked()), this, SLOT(OnInstrumentSelected()) ); connect( m_Controls.m_UseAsObjectmarkerButton, SIGNAL(clicked()), this, SLOT(OnObjectmarkerSelected()) ); connect( m_Controls.m_RegistrationWidget, SIGNAL(AddedTrackingFiducial()), this, SLOT(OnAddRegistrationTrackingFiducial()) ); connect( m_Controls.m_RegistrationWidget, SIGNAL(PerformFiducialRegistration()), this, SLOT(OnInitialRegistration()) ); connect( m_Controls.m_PointSetRecordCheckBox, SIGNAL(toggled(bool)), this, SLOT(OnPointSetRecording(bool)) ); connect( m_Controls.m_ActivateNeedleView, SIGNAL(toggled(bool)), this, SLOT(OnVirtualCamera(bool)) ); //start timer m_Timer->start(30); //initialize Combo Boxes m_Controls.m_ObjectComboBox->SetDataStorage(this->GetDataStorage()); m_Controls.m_ObjectComboBox->SetAutoSelectNewItems(false); m_Controls.m_ObjectComboBox->SetPredicate(mitk::NodePredicateDataType::New("Surface")); m_Controls.m_ImageComboBox->SetDataStorage(this->GetDataStorage()); m_Controls.m_ImageComboBox->SetAutoSelectNewItems(false); m_Controls.m_ImageComboBox->SetPredicate(mitk::NodePredicateDataType::New("Image")); } void QmitkIGTTrackingLabView::SetFocus() { m_Controls.m_UseAsPointerButton->setFocus(); } //############################################################################################### //############################################################################################### //####################### some additional slots and help methods ################################ //####################### for cleaner code - not that important ################################ //####################### to understand the basic functions ################################ //############################################################################################### //############################################################################################### void QmitkIGTTrackingLabView::DestroyIGTPipeline() { if(m_Source.IsNotNull()) { m_Source->StopTracking(); m_Source->Disconnect(); m_Source = nullptr; } m_PermanentRegistrationFilter = nullptr; m_Visualizer = nullptr; m_VirtualView = nullptr; } bool QmitkIGTTrackingLabView::CheckRegistrationInitialization() { // a couple of variables which we need in this method std::string warningMessage = ""; bool initializationErrorDetected = false; mitk::PointSet::Pointer imageFiducials,trackerFiducials; // check some initialization stuff if (m_ImageFiducialsDataNode.IsNull() || m_TrackerFiducialsDataNode.IsNull()) { warningMessage = "Initialization not finished!"; MITK_WARN << warningMessage; QMessageBox::warning(nullptr, "Registration not possible", warningMessage.c_str()); return false; } else { imageFiducials = dynamic_cast(m_ImageFiducialsDataNode->GetData()); trackerFiducials = dynamic_cast(m_TrackerFiducialsDataNode->GetData()); } // now, do a lot of other checks... if (m_Controls.m_SurfaceActive->isChecked() && m_Controls.m_ObjectComboBox->GetSelectedNode().IsNull()) { warningMessage = "No surface selected for registration.\nRegistration is not possible"; initializationErrorDetected = true; } else if (m_Controls.m_ImageActive->isChecked() && m_Controls.m_ImageComboBox->GetSelectedNode().IsNull()) { warningMessage = "No image selected for registration.\nRegistration is not possible"; initializationErrorDetected = true; } else if (imageFiducials.IsNull() || trackerFiducials.IsNull()) { warningMessage = "Fiducial data objects not found. \n" "Please set 3 or more fiducials in the image and with the tracking system.\n\n" "Registration is not possible"; initializationErrorDetected = true; } else if ((imageFiducials->GetSize() < 3) || (trackerFiducials->GetSize() < 3) || (imageFiducials->GetSize() != trackerFiducials->GetSize())) { warningMessage = "Not enough fiducial pairs found. At least 3 fiducial must exist for the image and the tracking system respectively."; initializationErrorDetected = true; } // finaly: if an err was detected, give a warning and an error popup, then return false if(initializationErrorDetected) { MITK_WARN << warningMessage; QMessageBox::warning(nullptr, "Registration not possible", warningMessage.c_str()); return false; } //if no error was detected simply return true else {return true;} } bool QmitkIGTTrackingLabView::IsTransformDifferenceHigh(mitk::NavigationData::Pointer transformA, mitk::NavigationData::Pointer transformB, double euclideanDistanceThreshold, double angularDifferenceThreshold) { if(transformA.IsNull() || transformA.IsNull()) {return false;} mitk::Point3D posA,posB; posA = transformA->GetPosition(); posB = transformB->GetPosition(); if(posA.EuclideanDistanceTo(posB) > euclideanDistanceThreshold) {return true;} double returnValue; mitk::Quaternion rotA,rotB; rotA = transformA->GetOrientation(); rotB = transformB->GetOrientation(); itk::Vector point; //caution 5D-Tools: Vector must lie in the YZ-plane for a correct result. point[0] = 0.0; point[1] = 0.0; point[2] = 100000.0; rotA.normalize(); rotB.normalize(); itk::Matrix rotMatrixA; for(int i=0; i<3; i++) for(int j=0; j<3; j++) rotMatrixA[i][j] = rotA.rotation_matrix_transpose().transpose()[i][j]; itk::Matrix rotMatrixB; for(int i=0; i<3; i++) for(int j=0; j<3; j++) rotMatrixB[i][j] = rotB.rotation_matrix_transpose().transpose()[i][j]; itk::Vector pt1 = rotMatrixA * point; itk::Vector pt2 = rotMatrixB * point; returnValue = (pt1[0]*pt2[0]+pt1[1]*pt2[1]+pt1[2]*pt2[2]) / ( sqrt(pow(pt1[0],2.0)+pow(pt1[1],2.0)+pow(pt1[2],2.0)) * sqrt(pow(pt2[0],2.0)+pow(pt2[1],2.0)+pow(pt2[2],2.0))); returnValue = acos(returnValue); if(returnValue*57.3 > angularDifferenceThreshold){return true;} return false; } diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibration.cpp b/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibration.cpp index 12447fc3a9..fbb63086c3 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibration.cpp +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibration.cpp @@ -1,686 +1,720 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include // Blueberry #include #include // Qmitk #include "IGTNavigationToolCalibration.h" // mitk #include #include #include #include #include #include #include // Qt #include #include //vtk #include const std::string IGTNavigationToolCalibration::VIEW_ID = "org.mitk.views.igtnavigationtoolcalibration"; IGTNavigationToolCalibration::IGTNavigationToolCalibration() -{} +{ + m_ToolTransformationWidget = new QmitkInteractiveTransformationWidget(); +} IGTNavigationToolCalibration::~IGTNavigationToolCalibration() { //The following code is required due to a bug in the point list widget. //If this is removed, MITK crashes when closing the view: m_Controls.m_RegistrationLandmarkWidget->SetPointSetNode(nullptr); m_Controls.m_CalibrationLandmarkWidget->SetPointSetNode(nullptr); + delete m_ToolTransformationWidget; } void IGTNavigationToolCalibration::SetFocus() { } void IGTNavigationToolCalibration::OnToolCalibrationMethodChanged(int index) { //if pivot calibration (3) or manual(0) is chosen only calibration pointer is needed if (index == 0 || index == 3) { if (!CheckInitialization(false)) { return; } } else{ if (!CheckInitialization()) { return; } } UpdateManualToolTipCalibrationView(); m_Controls.m_CalibrationMethodsWidget->setCurrentIndex(index); m_IndexCurrentCalibrationMethod = index; } void IGTNavigationToolCalibration::CreateQtPartControl(QWidget *parent) { - //initialize manual tool editing widget - m_ManualToolTipEditWidget = new QmitkNavigationToolCreationAdvancedWidget(parent); - m_ManualToolTipEditWidget->setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint); - m_ManualToolTipEditWidget->setWindowTitle("Edit Tool Tip Manually"); - m_ManualToolTipEditWidget->setModal(false); - m_ManualToolTipEditWidget->SetDataStorage(this->GetDataStorage()); - m_TrackingTimer = new QTimer(this); // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi(parent); connect(m_Controls.m_SetToolToCalibrate, SIGNAL(clicked()), this, SLOT(SetToolToCalibrate())); connect(m_Controls.m_SetPointer, SIGNAL(clicked()), this, SLOT(SetCalibrationPointer())); connect(m_TrackingTimer, SIGNAL(timeout()), this, SLOT(UpdateTrackingTimer())); connect(m_Controls.m_AddLandmark, SIGNAL(clicked()), this, SLOT(AddLandmark())); connect(m_Controls.m_SaveCalibratedTool, SIGNAL(clicked()), this, SLOT(SaveCalibratedTool())); connect(m_Controls.m_AddPivotPose, SIGNAL(clicked()), this, SLOT(OnAddPivotPose())); connect(m_Controls.m_ComputePivot, SIGNAL(clicked()), this, SLOT(OnComputePivot())); connect(m_Controls.m_UseComputedPivotPoint, SIGNAL(clicked()), this, SLOT(OnUseComputedPivotPoint())); connect(m_Controls.m_StartEditTooltipManually, SIGNAL(clicked()), this, SLOT(OnStartManualToolTipCalibration())); connect(m_Controls.m_GetPositions, SIGNAL(clicked()), this, SLOT(OnGetPositions())); + connect(m_Controls.m_ToolAxis_X, SIGNAL(valueChanged(double)), this, SLOT(OnToolAxisSpinboxChanged())); + connect(m_Controls.m_ToolAxis_Y, SIGNAL(valueChanged(double)), this, SLOT(OnToolAxisSpinboxChanged())); + connect(m_Controls.m_ToolAxis_Z, SIGNAL(valueChanged(double)), this, SLOT(OnToolAxisSpinboxChanged())); connect(m_Controls.m_CalibrateToolAxis, SIGNAL(clicked()), this, SLOT(OnCalibrateToolAxis())); - connect((QObject*)(m_ManualToolTipEditWidget), SIGNAL(RetrieveDataForManualToolTipManipulation()), this, SLOT(OnRetrieveDataForManualTooltipManipulation())); - connect((QObject*)(m_ManualToolTipEditWidget), SIGNAL(DialogCloseRequested()), this, SLOT(OnProcessManualTooltipEditDialogCloseRequest())); + connect((QObject*)(m_ToolTransformationWidget), SIGNAL(EditToolTipFinished(mitk::AffineTransform3D::Pointer)), this, + SLOT(OnManualEditToolTipFinished(mitk::AffineTransform3D::Pointer))); connect(m_Controls.m_CalibrationMethodComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnToolCalibrationMethodChanged(int))); connect((QObject*)(m_Controls.m_RunCalibrationButton), SIGNAL(clicked()), (QObject*) this, SLOT(OnRunSingleRefToolCalibrationClicked())); connect((QObject*)(m_Controls.m_CollectNavigationDataButton), SIGNAL(clicked()), (QObject*) this, SLOT(OnLoginSingleRefToolNavigationDataClicked())); connect((QObject*)(m_Controls.m_SetNewToolTipPosButton), SIGNAL(clicked()), (QObject*) this, SLOT(OnSetNewToolTipPosButtonClicked())); m_IDToolToCalibrate = -1; m_IDCalibrationPointer = -1; m_IndexCurrentCalibrationMethod = -1; m_OnLoginSingleRefToolNavigationDataClicked = false; m_NumberOfNavigationDataCounter = 0; m_NumberOfNavigationData = -1; //for pivot calibration m_OnAddPivotPoseClicked = false; PivotCount = 0; m_PivotPoses = std::vector(); m_CalibrationLandmarks = mitk::PointSet::New(); m_CalibrationLandmarksNode = mitk::DataNode::New(); m_CalibrationLandmarksNode->SetData(m_CalibrationLandmarks); m_Controls.m_CalibrationLandmarkWidget->SetPointSetNode(m_CalibrationLandmarksNode); m_RegistrationLandmarks = mitk::PointSet::New(); m_RegistrationLandmarksNode = mitk::DataNode::New(); m_RegistrationLandmarksNode->SetData(m_RegistrationLandmarks); m_Controls.m_RegistrationLandmarkWidget->SetPointSetNode(m_RegistrationLandmarksNode); m_ToolSurfaceInToolCoordinatesDataNode = mitk::DataNode::New(); m_ToolSurfaceInToolCoordinatesDataNode->SetName("ToolSurface(ToolCoordinates)"); m_LoggedNavigationDataDifferences = std::vector< mitk::NavigationData::Pointer >(); } void IGTNavigationToolCalibration::OnRunSingleRefToolCalibrationClicked() { if (!CheckInitialization()) { return; } mitk::NavigationData::Pointer ToolTipTransform = mitk::NavigationData::New(); if (m_Controls.m_CalibratePosition->isChecked()) { //1: Compute mean translational offset vector m_ResultOffsetVector.Fill(0); for (std::vector::iterator vecIter = m_LoggedNavigationDataOffsets.begin(); vecIter != m_LoggedNavigationDataOffsets.end(); vecIter++) { m_ResultOffsetVector[0] = m_ResultOffsetVector[0] + (*vecIter)[0]; m_ResultOffsetVector[1] = m_ResultOffsetVector[1] + (*vecIter)[1]; m_ResultOffsetVector[2] = m_ResultOffsetVector[2] + (*vecIter)[2]; } m_ResultOffsetVector[0] = m_ResultOffsetVector[0] / m_LoggedNavigationDataOffsets.size(); m_ResultOffsetVector[1] = m_ResultOffsetVector[1] / m_LoggedNavigationDataOffsets.size(); m_ResultOffsetVector[2] = m_ResultOffsetVector[2] / m_LoggedNavigationDataOffsets.size(); this->m_Controls.m_ResultOfCalibration->setText( QString("x: ") + QString(QString::number(m_ResultOffsetVector[0], 103, 3)) + QString("; y: ") + (QString::number(m_ResultOffsetVector[1], 103, 3)) + QString("; z: ") + (QString::number(m_ResultOffsetVector[2], 103, 3))); ToolTipTransform->SetPosition(m_ResultOffsetVector); } if (m_Controls.m_CalibrateOrientation->isChecked()) { //2: Compute mean orientation mitk::Quaternion meanOrientation; std::vector allOrientations = std::vector (); for (std::size_t i = 0; i < m_LoggedNavigationDataDifferences.size(); i++) { allOrientations.push_back(m_LoggedNavigationDataDifferences.at(i)->GetOrientation()); } meanOrientation = mitk::QuaternionAveraging::CalcAverage(allOrientations); this->m_Controls.m_ResultOfCalibrationOrientation->setText( QString("qx: ") + QString(QString::number(meanOrientation.x(), 103, 3)) + QString("; qy: ") + (QString::number(meanOrientation.y(), 103, 3)) + QString("; qz: ") + (QString::number(meanOrientation.z(), 103, 3)) + QString("; qr: ") + (QString::number(meanOrientation.r(), 103, 3))); ToolTipTransform->SetOrientation(meanOrientation); } MITK_INFO << "Computed calibration: "; MITK_INFO << "Translation Vector: " << ToolTipTransform->GetPosition(); MITK_INFO << "Quaternion: (" << ToolTipTransform->GetOrientation() << ")"; MITK_INFO << "Euler Angles [rad]: (" << ToolTipTransform->GetOrientation().rotation_euler_angles() << ")"; MITK_INFO << "Matrix:"; vnl_matrix_fixed rotMatrix = ToolTipTransform->GetOrientation().rotation_matrix_transpose(); MITK_INFO << rotMatrix[0][0] << " " << rotMatrix[0][1] << " " << rotMatrix[0][2] << std::endl; MITK_INFO << rotMatrix[1][0] << " " << rotMatrix[1][1] << " " << rotMatrix[1][2] << std::endl; MITK_INFO << rotMatrix[2][0] << " " << rotMatrix[2][1] << " " << rotMatrix[2][2] << std::endl; //3: write everything into the final tool tip transform and save it as member (it will be written to the tool later on) mitk::NavigationData::Pointer ToolTipInTrackingCoordinates = mitk::NavigationData::New(); ToolTipInTrackingCoordinates->Compose(ToolTipTransform); ToolTipInTrackingCoordinates->Compose(m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate)); ShowToolTipPreview(ToolTipInTrackingCoordinates); m_Controls.m_SetNewToolTipPosButton->setEnabled(true); m_ComputedToolTipTransformation = ToolTipTransform; } void IGTNavigationToolCalibration::OnLoginSingleRefToolNavigationDataClicked() { if (!CheckInitialization()) { return; } m_OnLoginSingleRefToolNavigationDataClicked = true; m_Controls.m_CollectNavigationDataButton->setEnabled(false); m_NumberOfNavigationData = m_Controls.m_NumberOfNavigationDataToCollect->value(); MITK_INFO << "Collecting " << m_NumberOfNavigationData << " NavigationData ... " << endl; } void IGTNavigationToolCalibration::LoginSingleRefToolNavigationData() { if (!CheckInitialization()) { return; } if (m_NumberOfNavigationDataCounter < m_NumberOfNavigationData) { //update label text QString labelText = "Collecting Data: " + QString::number(m_NumberOfNavigationDataCounter); m_Controls.m_CollectionStatus->setText(labelText); mitk::NavigationData::Pointer referenceTool = m_NavigationDataSourceOfCalibrationPointer->GetOutput(m_IDCalibrationPointer); mitk::NavigationData::Pointer toolToCalibrate = m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate); //compute difference: // differenceND = toolToCalibrate^-1 * referenceTool mitk::NavigationData::Pointer differenceND = mitk::NavigationData::New(); differenceND->Compose(referenceTool); differenceND->Compose(toolToCalibrate->GetInverse()); //inverse mode... if (m_Controls.m_InvertQuaternions->isChecked()) { // negate identity matrix to directly show parameters that will set up in NDI 6D Software Architect differenceND = differenceND->GetInverse(); } //save difference in member m_LoggedNavigationDataOffsets.push_back(differenceND->GetPosition()); m_LoggedNavigationDataDifferences.push_back(differenceND); m_NumberOfNavigationDataCounter++; } if (m_NumberOfNavigationDataCounter == m_NumberOfNavigationData) { m_NumberOfNavigationDataCounter = 0; m_OnLoginSingleRefToolNavigationDataClicked = false; m_Controls.m_CollectNavigationDataButton->setEnabled(true); m_Controls.m_RunCalibrationButton->setEnabled(true); MITK_INFO << "Collecting " << m_NumberOfNavigationData << " NavigationData ... Finished" << endl; QString labelText = "Collected " + QString::number(m_NumberOfNavigationData) + " data samples!"; m_Controls.m_CollectionStatus->setText(labelText); } } void IGTNavigationToolCalibration::OnSetNewToolTipPosButtonClicked() { ApplyToolTipTransform(m_ComputedToolTipTransformation); RemoveToolTipPreview(); } void IGTNavigationToolCalibration::ClearOldPivot() { mitk::NavigationData::Pointer tempND = mitk::NavigationData::New(); this->ApplyToolTipTransform(tempND); UpdateManualToolTipCalibrationView(); - m_ManualToolTipEditWidget->hide(); + //m_ManualToolTipEditWidget->hide(); //TODO this->GetDataStorage()->Remove(m_ToolSurfaceInToolCoordinatesDataNode); } void IGTNavigationToolCalibration::OnAddPivotPose() { ClearOldPivot(); //When the collect Poses Button is Clicked m_OnAddPivotPoseClicked = true; m_NumberOfNavigationData = m_Controls.m_PosesToCollect->value(); } void IGTNavigationToolCalibration::AddPivotPose() { //Save the poses to be used in computation if (PivotCount < m_NumberOfNavigationData) { mitk::NavigationData::Pointer currentPose = mitk::NavigationData::New(); currentPose->Graft(m_Controls.m_SelectionWidget->GetSelectedNavigationDataSource()->GetOutput(m_IDToolToCalibrate)); m_PivotPoses.push_back(currentPose); m_Controls.m_PoseNumber->setText(QString::number(m_PivotPoses.size())); PivotCount++; } if (PivotCount == m_NumberOfNavigationData) { m_OnAddPivotPoseClicked = false; } } void IGTNavigationToolCalibration::OnComputePivot() { mitk::PivotCalibration::Pointer myPivotCalibration = mitk::PivotCalibration::New(); for (std::size_t i = 0; i < this->m_PivotPoses.size(); i++) { myPivotCalibration->AddNavigationData(m_PivotPoses.at(i)); } QString resultString; if (myPivotCalibration->ComputePivotResult()) { mitk::NavigationData::Pointer markerTransformationTrackingCoordinates = m_PivotPoses.at(0); //Get computed pivot transfromation in tool coordinates mitk::NavigationData::Pointer ToolTipToTool = mitk::NavigationData::New(); ToolTipToTool->SetPosition(myPivotCalibration->GetResultPivotPoint()); ToolTipToTool->SetOrientation(myPivotCalibration->GetResultPivotRotation()); mitk::NavigationData::Pointer TrackerToTool = mitk::NavigationData::New(); TrackerToTool->SetOrientation(markerTransformationTrackingCoordinates->GetOrientation()); TrackerToTool->SetPosition(markerTransformationTrackingCoordinates->GetPosition()); TrackerToTool->Compose(ToolTipToTool); // Compute pivot point in relation to marker transformation for preview mitk::NavigationData::Pointer ToolTipToTracker = mitk::NavigationData::New(); ToolTipToTracker->Compose(ToolTipToTool); ToolTipToTracker->Compose(markerTransformationTrackingCoordinates); //add the preview node to the data storage ShowToolTipPreview(ToolTipToTracker); //parse result string resultString = QString("Pivot computation succeeded!\n") + QString("RMS Error: ") + QString::number(myPivotCalibration->GetResultRMSError()) + QString("\n") + QString("Pivot Point: ") + QString::number(myPivotCalibration->GetResultPivotPoint()[0]) + ";" + QString::number(myPivotCalibration->GetResultPivotPoint()[1]) + ";" + QString::number(myPivotCalibration->GetResultPivotPoint()[2]) + QString("\n") + QString("Pivot Rotation: ") + QString::number(myPivotCalibration->GetResultPivotRotation()[0]) + ";" + QString::number(myPivotCalibration->GetResultPivotRotation()[1]) + ";" + QString::number(myPivotCalibration->GetResultPivotRotation()[2]) + ";" + QString::number(myPivotCalibration->GetResultPivotRotation()[3]) + QString("\n"); //finally: save results to member variable m_ComputedToolTipTransformation = ToolTipToTool; //enable button to use the computed point with the tool m_Controls.m_UseComputedPivotPoint->setEnabled(true); } else { resultString = "Pivot computation failed!"; } MITK_INFO << resultString.toStdString().c_str(); m_Controls.m_ResultText->setText(resultString); } void IGTNavigationToolCalibration::UpdatePivotCount() { PivotCount = 0; while (!m_PivotPoses.empty()) { m_PivotPoses.pop_back(); } m_Controls.m_PoseNumber->setText(QString::number(PivotCount)); } void IGTNavigationToolCalibration::OnUseComputedPivotPoint() { RemoveToolTipPreview(); QString resultString = QString("Pivoted tool tip transformation was written to the tool ") + m_ToolToCalibrate->GetToolName().c_str(); ApplyToolTipTransform(m_ComputedToolTipTransformation, resultString.toStdString()); m_Controls.m_ResultText->setText(resultString); UpdatePivotCount(); } void IGTNavigationToolCalibration::ApplyToolTipTransform(mitk::NavigationData::Pointer ToolTipTransformInToolCoordinates, std::string message) { if (!CheckInitialization(false)) { return; } //Update tool in tool storage m_ToolToCalibrate->SetToolTipPosition(ToolTipTransformInToolCoordinates->GetPosition()); m_ToolToCalibrate->SetToolTipOrientation(ToolTipTransformInToolCoordinates->GetOrientation()); //And also update tracking device, so the transform is directly used mitk::TrackingDeviceSource::Pointer trackingDeviceSource; try { trackingDeviceSource = dynamic_cast(m_NavigationDataSourceOfToolToCalibrate.GetPointer()); mitk::TrackingTool::Pointer TrackingToolToCalibrate = trackingDeviceSource->GetTrackingDevice()->GetTool(m_IDToolToCalibrate); TrackingToolToCalibrate->SetToolTip(ToolTipTransformInToolCoordinates->GetPosition(), ToolTipTransformInToolCoordinates->GetOrientation()); } catch (std::exception& e) { MITK_ERROR << "Error while trying to set the tool tip to the running tracking device. Aborting! (" << e.what() << ")"; } MITK_INFO << message; } void IGTNavigationToolCalibration::ShowToolTipPreview(mitk::NavigationData::Pointer ToolTipInTrackingCoordinates) { mitk::DataNode::Pointer m_ToolTipPointPreview = mitk::DataNode::New(); m_ToolTipPointPreview->SetName("Modified Tool Tip Preview"); mitk::Color blue; blue.SetBlue(1); m_ToolTipPointPreview->SetColor(blue); mitk::Surface::Pointer mySphere = mitk::Surface::New(); vtkSphereSource *vtkData = vtkSphereSource::New(); vtkData->SetRadius(3.0f); vtkData->SetCenter(0.0, 0.0, 0.0); vtkData->Update(); mySphere->SetVtkPolyData(vtkData->GetOutput()); vtkData->Delete(); m_ToolTipPointPreview->SetData(mySphere); m_ToolTipPointPreview->GetData()->GetGeometry()->SetIndexToWorldTransform(ToolTipInTrackingCoordinates->GetAffineTransform3D()); this->GetDataStorage()->Add(m_ToolTipPointPreview); } void IGTNavigationToolCalibration::RemoveToolTipPreview() { this->GetDataStorage()->Remove(m_ToolTipPointPreview.GetPointer()); } void IGTNavigationToolCalibration::UpdateManualToolTipCalibrationView() { if (m_ToolToCalibrate.IsNull()) { return; } //parse human readable transformation data and display it std::stringstream translation; std::stringstream orientation; translation << m_ToolToCalibrate->GetToolTipPosition(); orientation << "Quaternion: (" << m_ToolToCalibrate->GetToolTipOrientation() << ")" << std::endl; orientation << std::endl; orientation << "Euler Angles [rad]: (" << m_ToolToCalibrate->GetToolTipOrientation().rotation_euler_angles() << ")" << std::endl; orientation << std::endl; orientation << "Matrix:" << std::endl; vnl_matrix_fixed rotMatrix = m_ToolToCalibrate->GetToolTipOrientation().rotation_matrix_transpose(); orientation << rotMatrix[0][0] << " " << rotMatrix[0][1] << " " << rotMatrix[0][2] << std::endl; orientation << rotMatrix[1][0] << " " << rotMatrix[1][1] << " " << rotMatrix[1][2] << std::endl; orientation << rotMatrix[2][0] << " " << rotMatrix[2][1] << " " << rotMatrix[2][2] << std::endl; m_Controls.m_ManualCurrentTranslation->setText(translation.str().c_str()); m_Controls.m_ManualCurrentOrientation->setPlainText(orientation.str().c_str()); } void IGTNavigationToolCalibration::OnStartManualToolTipCalibration() { if (!CheckInitialization(false)) { return; } - m_ManualToolTipEditWidget->SetToolTipSurface(false, m_ToolToCalibrate->GetDataNode()); - m_ManualToolTipEditWidget->show(); - m_ManualToolTipEditWidget->SetDefaultTooltip(m_ToolToCalibrate->GetToolTipTransform()); - m_ManualToolTipEditWidget->ReInitialize(); -} -void IGTNavigationToolCalibration::OnRetrieveDataForManualTooltipManipulation() -{ - this->GetDataStorage()->Add(m_ToolSurfaceInToolCoordinatesDataNode); - m_ManualToolTipEditWidget->SetToolTipSurface(false, m_ToolSurfaceInToolCoordinatesDataNode); + m_ToolTransformationWidget->SetToolToEdit(m_ToolToCalibrate); + m_ToolTransformationWidget->SetDefaultOffset(m_ToolToCalibrate->GetToolTipPosition()); + m_ToolTransformationWidget->SetDefaultRotation(m_ToolToCalibrate->GetToolTipOrientation()); + + m_ToolTransformationWidget->open(); } -void IGTNavigationToolCalibration::OnProcessManualTooltipEditDialogCloseRequest() +void IGTNavigationToolCalibration::OnManualEditToolTipFinished(mitk::AffineTransform3D::Pointer toolTip) { - mitk::NavigationData::Pointer tempND = mitk::NavigationData::New(m_ManualToolTipEditWidget->GetManipulatedToolTip()); - this->ApplyToolTipTransform(tempND); + //This function is called, when the toolTipEdit view is closed. + //if user pressed cancle, nullptr is returned. Do nothing. Else, set values. + if (toolTip) + { + mitk::NavigationData::Pointer tempND = mitk::NavigationData::New(toolTip);//Convert to Navigation data for simple transversion to quaternion + QString resultString = QString("Manual edited values are written to ") + m_ToolToCalibrate->GetToolName().c_str(); + ApplyToolTipTransform(tempND, resultString.toStdString()); + m_Controls.m_ResultText->setText(resultString); + } + UpdateManualToolTipCalibrationView(); - m_ManualToolTipEditWidget->hide(); - this->GetDataStorage()->Remove(m_ToolSurfaceInToolCoordinatesDataNode); } void IGTNavigationToolCalibration::OnGetPositions() { - //tool tip from tool to be calibrated - mitk::NavigationData::Pointer StartTool = mitk::NavigationData::New(); - StartTool->Graft(m_Controls.m_SelectionWidget->GetSelectedNavigationDataSource()->GetOutput(m_IDToolToCalibrate)); - double startX = StartTool->GetPosition().GetVnlVector()[0]; - double startY = StartTool->GetPosition().GetVnlVector()[1]; - double startZ = StartTool->GetPosition().GetVnlVector()[2]; - m_StartToolPosition.SetElement(0, startX); - m_StartToolPosition.SetElement(1, startY); - m_StartToolPosition.SetElement(2, startZ); - - //tool end from calibration tool - mitk::NavigationData::Pointer EndTool = mitk::NavigationData::New(); - EndTool->Graft(m_Controls.m_SelectionWidget->GetSelectedNavigationDataSource()->GetOutput(m_IDCalibrationPointer)); - double endX = EndTool->GetPosition().GetVnlVector()[0]; - double endY = EndTool->GetPosition().GetVnlVector()[1]; - double endZ = EndTool->GetPosition().GetVnlVector()[2]; - m_EndToolPosition.SetElement(0, endX); - m_EndToolPosition.SetElement(1, endY); - m_EndToolPosition.SetElement(2, endZ); - - mitk::NavigationData::Pointer trackingToToolTransform = m_Controls.m_SelectionWidget->GetSelectedNavigationDataSource()->GetOutput(m_IDToolToCalibrate)->GetInverse(); - mitk::Vector3D trackingToToolPos; - trackingToToolPos.SetElement(0, trackingToToolTransform->GetPosition()[0]); - trackingToToolPos.SetElement(1, trackingToToolTransform->GetPosition()[1]); - trackingToToolPos.SetElement(2, trackingToToolTransform->GetPosition()[2]); - - mitk::Vector3D startPosToolCoordinates = trackingToToolTransform->GetRotationMatrix() * (m_StartToolPosition)+trackingToToolPos; - mitk::Vector3D endPosToolCoordinates = trackingToToolTransform->GetRotationMatrix() * (m_EndToolPosition)+trackingToToolPos; - m_CalibratedToolAxis.SetElement(0, (-1 * endPosToolCoordinates[0] + startPosToolCoordinates[0])); - m_CalibratedToolAxis.SetElement(1, (-1 * endPosToolCoordinates[1] + startPosToolCoordinates[1])); - m_CalibratedToolAxis.SetElement(2, (-1 * endPosToolCoordinates[2] + startPosToolCoordinates[2])); - m_CalibratedToolAxis.Normalize(); + if (!CheckInitialization(true)) { return; } + + //Navigation Data from Tool which should be calibrated + if (!m_AxisCalibration_ToolToCalibrate) + m_AxisCalibration_ToolToCalibrate = mitk::NavigationData::New(); + m_AxisCalibration_ToolToCalibrate->Graft(m_Controls.m_SelectionWidget->GetSelectedNavigationDataSource()->GetOutput(m_IDToolToCalibrate)); + + //Navigation Data from calibration pointer tool + if (!m_AxisCalibration_NavDataCalibratingTool) + m_AxisCalibration_NavDataCalibratingTool = mitk::NavigationData::New(); + m_AxisCalibration_NavDataCalibratingTool->Graft(m_Controls.m_SelectionWidget->GetSelectedNavigationDataSource()->GetOutput(m_IDCalibrationPointer)); + + MITK_DEBUG << "Positions for tool axis calibration:"; + MITK_DEBUG << " ToolTip: " << m_AxisCalibration_ToolToCalibrate->GetPosition() << ","; + MITK_DEBUG << " Rotation: \n" << m_AxisCalibration_ToolToCalibrate->GetRotationMatrix(); + MITK_DEBUG << " End of the tool: " << m_AxisCalibration_NavDataCalibratingTool->GetPosition(); + + QString _label = "Position recorded: " + QString::number(m_AxisCalibration_NavDataCalibratingTool->GetPosition()[0], 'f', 1) + ", " + + QString::number(m_AxisCalibration_NavDataCalibratingTool->GetPosition()[1], 'f', 1) + ", " + + QString::number(m_AxisCalibration_NavDataCalibratingTool->GetPosition()[2], 'f', 1); + m_Controls.m_ToolAxisPositionLabel->setText(_label); } void IGTNavigationToolCalibration::OnCalibrateToolAxis() { - QString xString = QString::number(m_CalibratedToolAxis.GetElement(0),'g',3); - QString yString = QString::number(m_CalibratedToolAxis.GetElement(1), 'g', 3); - QString zString = QString::number(m_CalibratedToolAxis.GetElement(2),'g',3); + if (!m_AxisCalibration_ToolToCalibrate || !m_AxisCalibration_NavDataCalibratingTool) + { + MITK_ERROR << "Please record position first."; + return; + } + + //Calculate the tool tip + //here is an explanation, what is happening here: + /* + The axis is equal to the (tool tip) minus the (end of the tool) in tool coordinates of the tool which should be calibrated. + The tool tip in tool coordinates is zero (definition of the tip). + The end of the tool is recorded by the calibration pointer's position and is transformed using the inverse of the tool which should be calibrated. + Normalize it. + */ + m_CalibratedToolAxis = -m_AxisCalibration_ToolToCalibrate->GetInverse()->TransformPoint(m_AxisCalibration_NavDataCalibratingTool->GetPosition()).GetVectorFromOrigin(); + MITK_DEBUG << "Tool Endpoint in Tool coordinates: " << m_CalibratedToolAxis; + m_CalibratedToolAxis.Normalize(); + MITK_DEBUG << "Tool Axis: " << m_CalibratedToolAxis; + + m_ToolToCalibrate->SetToolAxis(m_CalibratedToolAxis); - QString calibratedToolAxisString = xString + ", " + yString + ", " + zString; - m_Controls.m_ToolAxis->setText(calibratedToolAxisString); - MITK_INFO << m_CalibratedToolAxis; + //Update GUI + QString calibratedToolAxisString = "Tool Axis: " + QString::number(m_CalibratedToolAxis.GetElement(0), 'f', 3) + ", " + + QString::number(m_CalibratedToolAxis.GetElement(1), 'f', 3) + ", " + QString::number(m_CalibratedToolAxis.GetElement(2), 'f', 3); + m_Controls.m_ToolAxisCalibrationLabel->setText(calibratedToolAxisString); + + //Block QT signals, we don't want to emit SpinboxChanged on the first value to overwrite the next ones + m_Controls.m_ToolAxis_X->blockSignals(true); m_Controls.m_ToolAxis_Y->blockSignals(true); m_Controls.m_ToolAxis_Z->blockSignals(true); + m_Controls.m_ToolAxis_X->setValue(m_CalibratedToolAxis[0]); + m_Controls.m_ToolAxis_Y->setValue(m_CalibratedToolAxis[1]); + m_Controls.m_ToolAxis_Z->setValue(m_CalibratedToolAxis[2]); + m_Controls.m_ToolAxis_X->blockSignals(false); m_Controls.m_ToolAxis_Y->blockSignals(false); m_Controls.m_ToolAxis_Z->blockSignals(false); +} +void IGTNavigationToolCalibration::OnToolAxisSpinboxChanged() +{ + m_CalibratedToolAxis.SetElement(0, m_Controls.m_ToolAxis_X->value()); + m_CalibratedToolAxis.SetElement(1, m_Controls.m_ToolAxis_Y->value()); + m_CalibratedToolAxis.SetElement(2, m_Controls.m_ToolAxis_Z->value()); m_ToolToCalibrate->SetToolAxis(m_CalibratedToolAxis); + MITK_INFO << "Tool axis changed to " << m_CalibratedToolAxis; } void IGTNavigationToolCalibration::SetToolToCalibrate() { m_IDToolToCalibrate = m_Controls.m_SelectionWidget->GetSelectedToolID(); - m_ToolToCalibrate = m_Controls.m_SelectionWidget->GetSelectedNavigationTool(); if (m_IDToolToCalibrate == -1) //no valid tool to calibrate { m_Controls.m_CalToolLabel->setText(""); m_Controls.m_StatusWidgetToolToCalibrate->RemoveStatusLabels(); m_TrackingTimer->stop(); } else { + m_ToolToCalibrate = m_Controls.m_SelectionWidget->GetSelectedNavigationTool(); m_NavigationDataSourceOfToolToCalibrate = m_Controls.m_SelectionWidget->GetSelectedNavigationDataSource(); m_Controls.m_CalToolLabel->setText(m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate)->GetName()); //initialize widget m_Controls.m_StatusWidgetToolToCalibrate->RemoveStatusLabels(); m_Controls.m_StatusWidgetToolToCalibrate->SetShowPositions(true); m_Controls.m_StatusWidgetToolToCalibrate->SetTextAlignment(Qt::AlignLeft); m_Controls.m_StatusWidgetToolToCalibrate->AddNavigationData(m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate)); m_Controls.m_StatusWidgetToolToCalibrate->ShowStatusLabels(); //initialize manual tool tip calibration view UpdateManualToolTipCalibrationView(); //save tool surface in tool coordinates for further editing mitk::Surface::Pointer ToolSurface = dynamic_cast(m_ToolToCalibrate->GetDataNode()->GetData())->Clone(); m_ToolSurfaceInToolCoordinatesDataNode->SetData(ToolSurface); m_ToolSurfaceInToolCoordinatesDataNode->GetData()->GetGeometry()->SetIdentity(); + + //Set the default needle axis + m_CalibratedToolAxis = m_ToolToCalibrate->GetToolAxis().GetVectorFromOrigin(); + //Block QT signals, we don't want to emit SpinboxChanged on the first value to overwrite the next ones + m_Controls.m_ToolAxis_X->blockSignals(true); m_Controls.m_ToolAxis_Y->blockSignals(true); m_Controls.m_ToolAxis_Z->blockSignals(true); + m_Controls.m_ToolAxis_X->setValue(m_CalibratedToolAxis[0]); + m_Controls.m_ToolAxis_Y->setValue(m_CalibratedToolAxis[1]); + m_Controls.m_ToolAxis_Z->setValue(m_CalibratedToolAxis[2]); + m_Controls.m_ToolAxis_X->blockSignals(false); m_Controls.m_ToolAxis_Y->blockSignals(false); m_Controls.m_ToolAxis_Z->blockSignals(false); + + UpdateManualToolTipCalibrationView(); + //start updating timer for status widgets, etc. if (!m_TrackingTimer->isActive()) m_TrackingTimer->start(100); } } void IGTNavigationToolCalibration::SetCalibrationPointer() { m_IDCalibrationPointer = m_Controls.m_SelectionWidget->GetSelectedToolID(); - m_NavigationDataSourceOfCalibrationPointer = m_Controls.m_SelectionWidget->GetSelectedNavigationDataSource(); if (m_IDCalibrationPointer == -1) { m_Controls.m_PointerLabel->setText(""); m_Controls.m_StatusWidgetCalibrationPointer->RemoveStatusLabels(); m_TrackingTimer->stop(); } else { + m_NavigationDataSourceOfCalibrationPointer = m_Controls.m_SelectionWidget->GetSelectedNavigationDataSource(); m_Controls.m_PointerLabel->setText(m_NavigationDataSourceOfCalibrationPointer->GetOutput(m_IDCalibrationPointer)->GetName()); //initialize widget m_Controls.m_StatusWidgetCalibrationPointer->RemoveStatusLabels(); m_Controls.m_StatusWidgetCalibrationPointer->SetShowPositions(true); m_Controls.m_StatusWidgetCalibrationPointer->SetTextAlignment(Qt::AlignLeft); m_Controls.m_StatusWidgetCalibrationPointer->AddNavigationData(m_NavigationDataSourceOfCalibrationPointer->GetOutput(m_IDCalibrationPointer)); m_Controls.m_StatusWidgetCalibrationPointer->ShowStatusLabels(); if (!m_TrackingTimer->isActive()) m_TrackingTimer->start(100); } } void IGTNavigationToolCalibration::UpdateOffsetCoordinates() { if (m_NavigationDataSourceOfCalibrationPointer.IsNull() || m_NavigationDataSourceOfToolToCalibrate.IsNull()) { return; } mitk::NavigationData::Pointer referenceToolND = m_NavigationDataSourceOfCalibrationPointer->GetOutput(m_IDCalibrationPointer); mitk::NavigationData::Pointer toolToCalibrateND = m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate); if (referenceToolND->IsDataValid() && toolToCalibrateND->IsDataValid()) { //computation: difference between both tools (in tool coordinates) //differenceND = toolToCalibrateND^-1 * referenceToolND mitk::NavigationData::Pointer differenceND = mitk::NavigationData::New(); differenceND->Compose(referenceToolND); differenceND->Compose(toolToCalibrateND->GetInverse()); //display this orientation in the UI m_Controls.m_OffsetCoordinates->setText( QString("x: ") + QString(QString::number(differenceND->GetPosition()[0], 103, 3)) + QString("; y: ") + (QString::number(differenceND->GetPosition()[1], 103, 3)) + QString("; z: ") + (QString::number(differenceND->GetPosition()[2], 103, 3))); m_Controls.m_OrientationOffsetCoordinates->setText( QString("qx: ") + QString(QString::number(differenceND->GetOrientation().x(), 103, 3)) + QString("; qy: ") + (QString::number(differenceND->GetOrientation().y(), 103, 3)) + QString("; qz: ") + (QString::number(differenceND->GetOrientation().z(), 103, 3)) + QString("; qr: ") + (QString::number(differenceND->GetOrientation().r(), 103, 3))); //also update preview if active if (m_ToolTipPointPreview.IsNotNull()) //NOT WORKING! TODO: fix or remove! { mitk::NavigationData::Pointer ToolTipTransform = mitk::NavigationData::New(); ToolTipTransform->SetPosition(m_ResultOffsetVector); mitk::NavigationData::Pointer ToolTipInTrackingCoordinates = mitk::NavigationData::New(); //maybe store as for better peformance... ToolTipInTrackingCoordinates->Compose(m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate)); ToolTipInTrackingCoordinates->Compose(ToolTipTransform); m_ToolTipPointPreview->GetData()->GetGeometry()->SetIndexToWorldTransform(ToolTipInTrackingCoordinates->GetAffineTransform3D()); } } } void IGTNavigationToolCalibration::UpdateTrackingTimer() { m_Controls.m_StatusWidgetToolToCalibrate->Refresh(); m_Controls.m_StatusWidgetCalibrationPointer->Refresh(); if (m_OnLoginSingleRefToolNavigationDataClicked) LoginSingleRefToolNavigationData(); if (m_OnAddPivotPoseClicked) AddPivotPose(); // 1 == Single Reference Calibration Method if (m_IndexCurrentCalibrationMethod == 1) UpdateOffsetCoordinates(); } void IGTNavigationToolCalibration::AddLandmark() { if (!CheckInitialization()) { return; } mitk::NavigationData::Pointer navDataTool = m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate); mitk::Point3D landmark = m_NavigationDataSourceOfCalibrationPointer->GetOutput(m_IDCalibrationPointer)->GetPosition(); //convert to itk transform itk::Vector translation; for (int k = 0; k < 3; k++) translation[k] = navDataTool->GetPosition()[k]; itk::Matrix rotation; for (int k = 0; k < 3; k++) for (int l = 0; l < 3; l++) rotation[k][l] = navDataTool->GetOrientation().rotation_matrix_transpose()[k][l]; rotation = rotation.GetTranspose(); itk::Vector landmarkItk; landmarkItk[0] = landmark[0]; landmarkItk[1] = landmark[1]; landmarkItk[2] = landmark[2]; //compute landmark in tool coordinates itk::Matrix rotationInverse; for (int k = 0; k < 3; k++) for (int l = 0; l < 3; l++) rotationInverse[k][l] = rotation.GetInverse()[k][l]; landmarkItk = rotationInverse * (landmarkItk - translation); //convert back and add landmark to pointset landmark[0] = landmarkItk[0]; landmark[1] = landmarkItk[1]; landmark[2] = landmarkItk[2]; m_RegistrationLandmarks->InsertPoint(m_RegistrationLandmarks->GetSize(), landmark); } void IGTNavigationToolCalibration::SaveCalibratedTool() { if (m_ToolToCalibrate.IsNotNull()) { mitk::NavigationTool::Pointer calibratedTool = m_ToolToCalibrate; calibratedTool->SetToolCalibrationLandmarks(this->m_CalibrationLandmarks); calibratedTool->SetToolRegistrationLandmarks(this->m_RegistrationLandmarks); mitk::NavigationToolWriter::Pointer myWriter = mitk::NavigationToolWriter::New(); std::string filename = QFileDialog::getSaveFileName(nullptr,tr("Save Navigation Tool"), "/", "*.IGTTool").toUtf8().data(); filename.append(".IGTTool"); if (filename == "") return; if (myWriter->DoWrite(filename, calibratedTool)) MITK_INFO << "Saved calibrated tool to file " << filename; else MITK_WARN << "Can't write tool to file " << filename; } else { MITK_ERROR << "Did not find navigation tool storage of calibrated tool, aborting!"; } } bool IGTNavigationToolCalibration::CheckInitialization(bool CalibrationPointerRequired) { if ((m_IDToolToCalibrate == -1) || ((CalibrationPointerRequired) && (m_IDCalibrationPointer == -1) ) ) { QMessageBox msgBox; msgBox.setText("Tool to calibrate and/or calibration pointer not initialized, cannot proceed!"); msgBox.exec(); return false; } else { return true; } } diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibration.h b/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibration.h index 90ddce2f52..741488fc68 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibration.h +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibration.h @@ -1,141 +1,143 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef IGTNavigationToolCalibration_h #define IGTNavigationToolCalibration_h #include #include #include -#include + +#include "QmitkInteractiveTransformationWidget.h" + #include "ui_IGTNavigationToolCalibrationControls.h" #include //QT headers #include /*! \brief IGTNavigationToolCalibration \warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. \ingroup ${plugin_target}_internal */ class IGTNavigationToolCalibration : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: IGTNavigationToolCalibration(); virtual ~IGTNavigationToolCalibration(); static const std::string VIEW_ID; virtual void CreateQtPartControl(QWidget *parent); protected slots: void OnAddPivotPose(); void OnComputePivot(); void OnUseComputedPivotPoint(); void SetToolToCalibrate(); void SetCalibrationPointer(); void UpdateTrackingTimer(); void AddLandmark(); void SaveCalibratedTool(); void OnToolCalibrationMethodChanged(int index); void OnStartManualToolTipCalibration(); - void OnRetrieveDataForManualTooltipManipulation(); - void OnProcessManualTooltipEditDialogCloseRequest(); void OnRunSingleRefToolCalibrationClicked(); void OnLoginSingleRefToolNavigationDataClicked(); void OnSetNewToolTipPosButtonClicked(); void OnGetPositions(); void OnCalibrateToolAxis(); + void OnToolAxisSpinboxChanged(); + void OnManualEditToolTipFinished(mitk::AffineTransform3D::Pointer toolTip); protected: virtual void SetFocus(); void UpdateOffsetCoordinates(); int m_IndexCurrentCalibrationMethod; Ui::IGTNavigationToolCalibrationControls m_Controls; //some general members mitk::NavigationTool::Pointer m_ToolToCalibrate; //<<< tool that will be calibrated int m_IDToolToCalibrate; //<<< id of tool that will be calibrated (of the navigation data source) mitk::NavigationDataSource::Pointer m_NavigationDataSourceOfToolToCalibrate; //<<< navigation data source of the tool that will be calibrated mitk::NavigationDataSource::Pointer m_NavigationDataSourceOfCalibrationPointer; //<<< navigation data source of the calibration pointer mitk::DataNode::Pointer m_ToolSurfaceInToolCoordinatesDataNode; //<<< holds the tool surface in tool coordinates (for preview purposes) int m_IDCalibrationPointer; //<<< id of the calibration pointer (of the corresponding navigation data source) QTimer* m_TrackingTimer; //<<< tracking timer that updates the status widgets void ApplyToolTipTransform(mitk::NavigationData::Pointer ToolTipTransformInToolCoordinates, std::string message = "Tool was updated with the calibrated tool tip!"); //<<< applys the given tool tip transform to the tool to calibrate bool CheckInitialization(bool CalibrationPointerRequired = true); //<<< checks if the tool to calibrate and (if required) the calibration pointer is initialized. Displays a warning and returns false if not. mitk::NavigationData::Pointer m_ComputedToolTipTransformation; //<<< holds the new tooltip transformation after it was computed to write it into the tool later // members and helper methods for pivot tool calibration std::vector m_PivotPoses; void AddPivotPose(); void ClearOldPivot(); void UpdatePivotCount(); bool m_OnAddPivotPoseClicked; int PivotCount; // members and helper methods for manual tool calibration void UpdateManualToolTipCalibrationView(); - QmitkNavigationToolCreationAdvancedWidget* m_ManualToolTipEditWidget; + QmitkInteractiveTransformationWidget* m_ToolTransformationWidget; // members and helper methods for single reference tool calibration void LoginSingleRefToolNavigationData(); std::vector< mitk::Point3D > m_LoggedNavigationDataOffsets; std::vector< mitk::NavigationData::Pointer > m_LoggedNavigationDataDifferences; bool m_OnLoginSingleRefToolNavigationDataClicked; int m_NumberOfNavigationData; int m_NumberOfNavigationDataCounter; mitk::Point3D m_ResultOffsetVector; // members and helper methods for tool tip preview mitk::DataNode::Pointer m_ToolTipPointPreview; //<<< Data node of the tool tip preview void ShowToolTipPreview(mitk::NavigationData::Pointer ToolTipInTrackingCoordinates); //<<< Adds a preview of the tool tip into the data storage void RemoveToolTipPreview(); //<<< Removes the preview // members for the tool landmark calibration mitk::PointSet::Pointer m_CalibrationLandmarks; mitk::DataNode::Pointer m_CalibrationLandmarksNode; mitk::PointSet::Pointer m_RegistrationLandmarks; mitk::DataNode::Pointer m_RegistrationLandmarksNode; //members and helper methods for tool axis calibration mitk::Vector3D m_CalibratedToolAxis; - mitk::Vector3D m_EndToolPosition; - mitk::Vector3D m_StartToolPosition; + mitk::NavigationData::Pointer m_AxisCalibration_ToolToCalibrate; + mitk::NavigationData::Pointer m_AxisCalibration_NavDataCalibratingTool; }; #endif // IGTNavigationToolCalibration_h diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibrationControls.ui b/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibrationControls.ui index 8b9d44b573..20f1642f61 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibrationControls.ui +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibrationControls.ui @@ -1,1077 +1,1126 @@ IGTNavigationToolCalibrationControls 0 0 - 551 + 557 958 0 0 QmitkTemplate <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Navigation Tool Calibration</span></p></body></html> Tool to calibrate 0 50 16777215 50 Calibration pointer 0 30 + tabWidget true 0 Initialization <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; text-decoration: underline;">Choose Tracking Device and Tools</span></p></body></html> Qt::Horizontal 120 0 Tool to Calibrate: Qt::Horizontal 40 20 <none> Qt::Horizontal 40 20 150 0 Use as Tool to Calibrate Qt::Horizontal 120 0 Calibration Pointer: Qt::Horizontal 40 20 <none> Qt::Horizontal 40 20 150 0 Use as Calibration Pointer Qt::Horizontal Qt::Vertical 20 586 Tool Tip Calibration 50 false Calibration Method: Qt::Horizontal 40 20 Manual Single Reference Tool Multiple Tools Reference Pivoting Qt::Horizontal 0 Current Tool Tip Translation: true true Current Tool Tip Orientation: true true Qt::Horizontal 40 20 Start Edit Tooltip 0 0 319 160 319 160 QFrame { border-image: url(:/IGTNavigationToolCalibration/Description.svg); } QFrame::Box QFrame::Plain 1 0 0 Current Offset between Tool to calibrate and Calibration pointer: Pos: 8 Qt::AlignCenter Rot: 8 Qt::AlignCenter Qt::Horizontal 0 0 Number of tracking data to collect: 0 0 10000 100 Qt::AlignCenter 0 0 1: Collect Navigation Data Qt::Horizontal Invert calibration transformation Calibrate position true Calibrate orientation true false 2: Run Calibration Qt::Horizontal 0 0 New Tool Tip Position and/or Orientation of Tool to calibrate: Pos: 8 Qt::AlignCenter Rot: 8 Qt::AlignCenter false 3: Set New Tool Tip Position and/or Tool Orientation Qt::Vertical 20 40 Number of pivot poses to collect: 10 1000 100 Number of saved poses: 0 Qt::Horizontal 40 20 Collect Pivot Poses Calibration Result: Qt::Horizontal 40 20 175 0 Compute Pivot Point Qt::Horizontal 40 20 false 0 0 175 0 Use Computed Pivot Point Qt::Vertical 20 99 Tool Landmark Calibration <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; text-decoration: underline;">Calibrate tool by marking the landmarks with the pointer</span></p></body></html> Registration Landmarks 0 170 Add Pointer Position Calibration Landmarks Qt::Vertical 20 259 Tool Axis Calibration - - - - 30 - 30 - 341 - 16 - - - - Calibrate tool axis with calibrated needle holder and already calibrated tip - - - - - - 210 - 60 - 75 - 23 - - - - Get Positions - - - - - - 30 - 60 - 171 - 21 - - - - Select when sensor is at tools end - - - - - - 30 - 100 - 101 - 23 - - - - Calibrate Tool Axis - - - - - true - - - - 160 - 100 - 241 - 21 - - - - true - - + + + + + QLayout::SetDefaultConstraint + + + + + + + + + + + + Tool axis: + + + + + + + Get Positions + + + + + + + Calibrate Tool Axis + + + + + + + + + 4 + + + -1000.000000000000000 + + + 1000.000000000000000 + + + + + + + 4 + + + -1000.000000000000000 + + + 1000.000000000000000 + + + + + + + 4 + + + -1000.000000000000000 + + + 1000.000000000000000 + + + + + + + + + + + + + + + + Calibrate the tool axis: +1. Make sure, tool tips of both tools are calibrated +2. Hold pointer at the end of the needle +3. Get Position +4. Calibrate tool axis + +Alternative: Manually edit the axis using the spinboxes. + + + + + + + + + Qt::Vertical + + + + 20 + 497 + + + + + + gridLayoutWidget_2 + label_18 + verticalSpacer_5 Qt::Horizontal 40 20 Save Calibrated Navigation Tool tabWidget label groupBox groupBox_2 - QmitkNavigationDataSourceSelectionWidget + QmitkPointListWidget QWidget -
QmitkNavigationDataSourceSelectionWidget.h
+
QmitkPointListWidget.h
1
- QmitkToolTrackingStatusWidget + QmitkNavigationDataSourceSelectionWidget QWidget -
QmitkToolTrackingStatusWidget.h
+
QmitkNavigationDataSourceSelectionWidget.h
1
- QmitkPointListWidget + QmitkToolTrackingStatusWidget QWidget -
QmitkPointListWidget.h
+
QmitkToolTrackingStatusWidget.h
1
diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTNavigationToolManagerView.cpp b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTNavigationToolManagerView.cpp index 81eaf71879..1db19eb558 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTNavigationToolManagerView.cpp +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTNavigationToolManagerView.cpp @@ -1,78 +1,78 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkMITKIGTNavigationToolManagerView.h" // MITK #include // Qt #include const std::string QmitkMITKIGTNavigationToolManagerView::VIEW_ID = "org.mitk.views.mitkigtnavigationtoolmanager"; QmitkMITKIGTNavigationToolManagerView::QmitkMITKIGTNavigationToolManagerView() : QmitkAbstractView() , m_Controls(0) { } QmitkMITKIGTNavigationToolManagerView::~QmitkMITKIGTNavigationToolManagerView() { for (auto storage : m_AllStoragesHandledByThisWidget) storage->UnRegisterMicroservice(); } void QmitkMITKIGTNavigationToolManagerView::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::QmitkMITKIGTNavigationToolManagerViewControls; m_Controls->setupUi(parent); connect((QObject*)(m_Controls->m_toolManagerWidget), SIGNAL(NewStorageAdded(mitk::NavigationToolStorage::Pointer, std::string)), this, SLOT(NewStorageByWidget(mitk::NavigationToolStorage::Pointer, std::string))); connect((QObject*)(m_Controls->m_ToolStorageListWidget), SIGNAL(NavigationToolStorageSelected(mitk::NavigationToolStorage::Pointer)), this, SLOT(ToolStorageSelected(mitk::NavigationToolStorage::Pointer))); } m_Controls->m_toolManagerWidget->Initialize(this->GetDataStorage()); } void QmitkMITKIGTNavigationToolManagerView::SetFocus() { m_Controls->m_ToolStorageListWidget->setFocus(); } void QmitkMITKIGTNavigationToolManagerView::NewStorageByWidget(mitk::NavigationToolStorage::Pointer storage, std::string storageName) { - storage->RegisterAsMicroservice(storageName); + storage->RegisterAsMicroservice(); m_AllStoragesHandledByThisWidget.push_back(storage); } void QmitkMITKIGTNavigationToolManagerView::ToolStorageSelected(mitk::NavigationToolStorage::Pointer storage) { if (storage.IsNull()) //no storage selected { //reset everything return; } this->m_Controls->m_toolManagerWidget->LoadStorage(storage); } diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp index 9f163b5936..2dfd5586ee 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp @@ -1,1244 +1,1343 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkMITKIGTTrackingToolboxView.h" // Qt #include #include #include // MITK #include #include #include #include #include #include #include #include #include +#include //for exceptions #include #include #include "mitkPluginActivator.h" const std::string QmitkMITKIGTTrackingToolboxView::VIEW_ID = "org.mitk.views.mitkigttrackingtoolbox"; QmitkMITKIGTTrackingToolboxView::QmitkMITKIGTTrackingToolboxView() : QmitkAbstractView() , m_Controls(nullptr) , m_DeviceTypeCollection(nullptr) { m_TrackingLoggingTimer = new QTimer(this); m_TrackingRenderTimer = new QTimer(this); m_TimeoutTimer = new QTimer(this); m_tracking = false; m_connected = false; m_logging = false; + m_ShowHideToolProjection = false; + m_ShowHideToolAxis = false; m_loggedFrames = 0; m_SimpleModeEnabled = false; + m_NeedleProjectionFilter = mitk::NeedleProjectionFilter::New(); //create filename for autosaving of tool storage QString loggingPathWithoutFilename = QString(mitk::LoggingBackend::GetLogFile().c_str()); if (!loggingPathWithoutFilename.isEmpty()) //if there already is a path for the MITK logging file use this one { //extract path from path+filename (if someone knows a better way to do this feel free to change it) int lengthOfFilename = QFileInfo(QString::fromStdString(mitk::LoggingBackend::GetLogFile())).fileName().size(); loggingPathWithoutFilename.resize(loggingPathWithoutFilename.size() - lengthOfFilename); m_AutoSaveFilename = loggingPathWithoutFilename + "TrackingToolboxAutoSave.IGTToolStorage"; } else //if not: use a temporary path from IOUtil { m_AutoSaveFilename = QString(mitk::IOUtil::GetTempPath().c_str()) + "TrackingToolboxAutoSave.IGTToolStorage"; } MITK_INFO("IGT Tracking Toolbox") << "Filename for auto saving of IGT ToolStorages: " << m_AutoSaveFilename.toStdString(); //! [Thread 1] //initialize worker thread m_WorkerThread = new QThread(); m_Worker = new QmitkMITKIGTTrackingToolboxViewWorker(); //! [Thread 1] ctkPluginContext* pluginContext = mitk::PluginActivator::GetContext(); if (pluginContext) { QString interfaceName = QString::fromStdString(us_service_interface_iid()); QList serviceReference = pluginContext->getServiceReferences(interfaceName); if (serviceReference.size() > 0) { m_DeviceTypeServiceReference = serviceReference.at(0); const ctkServiceReference& r = serviceReference.at(0); m_DeviceTypeCollection = pluginContext->getService(r); } else { MITK_INFO << "No Tracking Device Collection!"; } } } QmitkMITKIGTTrackingToolboxView::~QmitkMITKIGTTrackingToolboxView() { this->StoreUISettings(); m_TrackingLoggingTimer->stop(); m_TrackingRenderTimer->stop(); m_TimeoutTimer->stop(); delete m_TrackingLoggingTimer; delete m_TrackingRenderTimer; delete m_TimeoutTimer; try { //! [Thread 2] // wait for thread to finish m_WorkerThread->terminate(); m_WorkerThread->wait(); //clean up worker thread if (m_WorkerThread) { delete m_WorkerThread; } if (m_Worker) { delete m_Worker; } //! [Thread 2] //remove the tracking volume this->GetDataStorage()->Remove(m_TrackingVolumeNode); //unregister microservices if (m_toolStorage) { m_toolStorage->UnRegisterMicroservice(); } if (m_IGTLMessageProvider.IsNotNull()){ m_IGTLMessageProvider->UnRegisterMicroservice(); } } catch (std::exception& e) { MITK_WARN << "Unexpected exception during clean up of tracking toolbox view: " << e.what(); } catch (...) { MITK_WARN << "Unexpected unknown error during clean up of tracking toolbox view!"; } //store tool storage and UI settings for persistence this->AutoSaveToolStorage(); this->StoreUISettings(); m_DeviceTypeCollection = nullptr; mitk::PluginActivator::GetContext()->ungetService(m_DeviceTypeServiceReference); } void QmitkMITKIGTTrackingToolboxView::CreateQtPartControl(QWidget *parent) { // build up qt view, unless already done if (!m_Controls) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkMITKIGTTrackingToolboxViewControls; m_Controls->setupUi(parent); //create connections connect(m_Controls->m_LoadTools, SIGNAL(clicked()), this, SLOT(OnLoadTools())); connect(m_Controls->m_ConnectDisconnectButton, SIGNAL(clicked()), this, SLOT(OnConnectDisconnect())); connect(m_Controls->m_StartStopTrackingButton, SIGNAL(clicked()), this, SLOT(OnStartStopTracking())); connect(m_Controls->m_ConnectSimpleMode, SIGNAL(clicked()), this, SLOT(OnConnectDisconnect())); connect(m_Controls->m_StartTrackingSimpleMode, SIGNAL(clicked()), this, SLOT(OnStartStopTracking())); connect(m_Controls->m_FreezeUnfreezeTrackingButton, SIGNAL(clicked()), this, SLOT(OnFreezeUnfreezeTracking())); connect(m_TrackingLoggingTimer, SIGNAL(timeout()), this, SLOT(UpdateLoggingTrackingTimer())); connect(m_TrackingRenderTimer, SIGNAL(timeout()), this, SLOT(UpdateRenderTrackingTimer())); connect(m_TimeoutTimer, SIGNAL(timeout()), this, SLOT(OnTimeOut())); connect(m_Controls->m_ChooseFile, SIGNAL(clicked()), this, SLOT(OnChooseFileClicked())); connect(m_Controls->m_StartLogging, SIGNAL(clicked()), this, SLOT(StartLogging())); connect(m_Controls->m_StopLogging, SIGNAL(clicked()), this, SLOT(StopLogging())); connect(m_Controls->m_VolumeSelectionBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(OnTrackingVolumeChanged(QString))); connect(m_Controls->m_ShowTrackingVolume, SIGNAL(clicked()), this, SLOT(OnShowTrackingVolumeChanged())); connect(m_Controls->m_AutoDetectTools, SIGNAL(clicked()), this, SLOT(OnAutoDetectTools())); connect(m_Controls->m_ResetTools, SIGNAL(clicked()), this, SLOT(OnResetTools())); connect(m_Controls->m_AddSingleTool, SIGNAL(clicked()), this, SLOT(OnAddSingleTool())); connect(m_Controls->m_NavigationToolCreationWidget, SIGNAL(NavigationToolFinished()), this, SLOT(OnAddSingleToolFinished())); connect(m_Controls->m_NavigationToolCreationWidget, SIGNAL(Canceled()), this, SLOT(OnAddSingleToolCanceled())); - connect(m_Controls->m_csvFormat, SIGNAL(clicked()), this, SLOT(OnToggleFileExtension())); - connect(m_Controls->m_xmlFormat, SIGNAL(clicked()), this, SLOT(OnToggleFileExtension())); + connect(m_Controls->m_CsvFormat, SIGNAL(clicked()), this, SLOT(OnToggleFileExtension())); + connect(m_Controls->m_XmlFormat, SIGNAL(clicked()), this, SLOT(OnToggleFileExtension())); connect(m_Controls->m_UseDifferentUpdateRates, SIGNAL(clicked()), this, SLOT(OnToggleDifferentUpdateRates())); connect(m_Controls->m_RenderUpdateRate, SIGNAL(valueChanged(int)), this, SLOT(OnChangeRenderUpdateRate())); connect(m_Controls->m_DisableAllTimers, SIGNAL(stateChanged(int)), this, SLOT(EnableDisableTimerButtons(int))); connect(m_Controls->m_advancedUI, SIGNAL(clicked()), this, SLOT(OnToggleAdvancedSimpleMode())); - connect(m_Controls->m_simpleUI, SIGNAL(clicked()), this, SLOT(OnToggleAdvancedSimpleMode())); + connect(m_Controls->m_SimpleUI, SIGNAL(clicked()), this, SLOT(OnToggleAdvancedSimpleMode())); + connect(m_Controls->showHideToolProjectionCheckBox, SIGNAL(clicked()), this, SLOT(OnShowHideToolProjectionClicked())); + connect(m_Controls->showHideToolAxisCheckBox, SIGNAL(clicked()), this, SLOT(OnShowHideToolAxisClicked())); //connections for the tracking device configuration widget - connect(m_Controls->m_configurationWidget, SIGNAL(TrackingDeviceSelectionChanged()), this, SLOT(OnTrackingDeviceChanged())); + connect(m_Controls->m_ConfigurationWidget, SIGNAL(TrackingDeviceSelectionChanged()), this, SLOT(OnTrackingDeviceChanged())); //! [Thread 3] //connect worker thread connect(m_Worker, SIGNAL(AutoDetectToolsFinished(bool, QString)), this, SLOT(OnAutoDetectToolsFinished(bool, QString))); connect(m_Worker, SIGNAL(ConnectDeviceFinished(bool, QString)), this, SLOT(OnConnectFinished(bool, QString))); connect(m_Worker, SIGNAL(StartTrackingFinished(bool, QString)), this, SLOT(OnStartTrackingFinished(bool, QString))); connect(m_Worker, SIGNAL(StopTrackingFinished(bool, QString)), this, SLOT(OnStopTrackingFinished(bool, QString))); connect(m_Worker, SIGNAL(DisconnectDeviceFinished(bool, QString)), this, SLOT(OnDisconnectFinished(bool, QString))); connect(m_WorkerThread, SIGNAL(started()), m_Worker, SLOT(ThreadFunc())); - connect(m_Worker, SIGNAL(ConnectDeviceFinished(bool, QString)), m_Controls->m_configurationWidget, SLOT(OnConnected(bool))); - connect(m_Worker, SIGNAL(DisconnectDeviceFinished(bool, QString)), m_Controls->m_configurationWidget, SLOT(OnDisconnected(bool))); - connect(m_Worker, SIGNAL(StartTrackingFinished(bool, QString)), m_Controls->m_configurationWidget, SLOT(OnStartTracking(bool))); - connect(m_Worker, SIGNAL(StopTrackingFinished(bool, QString)), m_Controls->m_configurationWidget, SLOT(OnStopTracking(bool))); + connect(m_Worker, SIGNAL(ConnectDeviceFinished(bool, QString)), m_Controls->m_ConfigurationWidget, SLOT(OnConnected(bool))); + connect(m_Worker, SIGNAL(DisconnectDeviceFinished(bool, QString)), m_Controls->m_ConfigurationWidget, SLOT(OnDisconnected(bool))); + connect(m_Worker, SIGNAL(StartTrackingFinished(bool, QString)), m_Controls->m_ConfigurationWidget, SLOT(OnStartTracking(bool))); + connect(m_Worker, SIGNAL(StopTrackingFinished(bool, QString)), m_Controls->m_ConfigurationWidget, SLOT(OnStopTracking(bool))); //Add Listener, so that we know when the toolStorage changed. std::string m_Filter = "(" + us::ServiceConstants::OBJECTCLASS() + "=" + "org.mitk.services.NavigationToolStorage" + ")"; mitk::PluginActivator::GetContext()->connectServiceListener(this, "OnToolStorageChanged", QString(m_Filter.c_str())); //move the worker to the thread m_Worker->moveToThread(m_WorkerThread); //! [Thread 3] //initialize widgets m_Controls->m_TrackingToolsStatusWidget->SetShowPositions(true); m_Controls->m_TrackingToolsStatusWidget->SetTextAlignment(Qt::AlignLeft); m_Controls->m_simpleWidget->setVisible(false); //initialize tracking volume node m_TrackingVolumeNode = mitk::DataNode::New(); m_TrackingVolumeNode->SetName("TrackingVolume"); m_TrackingVolumeNode->SetBoolProperty("Backface Culling", true); mitk::Color red; red.SetRed(1); m_TrackingVolumeNode->SetColor(red); //initialize buttons m_Controls->m_AutoDetectTools->setVisible(false); //only visible if supported by tracking device m_Controls->m_StartStopTrackingButton->setEnabled(false); m_Controls->m_StartTrackingSimpleMode->setEnabled(false); m_Controls->m_FreezeUnfreezeTrackingButton->setEnabled(false); //initialize warning labels - m_Controls->m_renderWarningLabel->setVisible(false); + m_Controls->m_RenderWarningLabel->setVisible(false); m_Controls->m_TrackingFrozenLabel->setVisible(false); //Update List of available models for selected tool. std::vector Compatibles; - if ((m_Controls == nullptr) || //check all these stuff for nullptr, latterly this causes crashes from time to time - (m_Controls->m_configurationWidget == nullptr) || - (m_Controls->m_configurationWidget->GetTrackingDevice().IsNull())) + if ((m_Controls == nullptr) || //check all these stuff for NULL, latterly this causes crashes from time to time + (m_Controls->m_ConfigurationWidget == nullptr) || + (m_Controls->m_ConfigurationWidget->GetTrackingDevice().IsNull())) { MITK_ERROR << "Couldn't get current tracking device or an object is nullptr, something went wrong!"; return; } else { - Compatibles = m_DeviceTypeCollection->GetDeviceDataForLine(m_Controls->m_configurationWidget->GetTrackingDevice()->GetType()); + Compatibles = m_DeviceTypeCollection->GetDeviceDataForLine(m_Controls->m_ConfigurationWidget->GetTrackingDevice()->GetType()); } m_Controls->m_VolumeSelectionBox->clear(); for (std::size_t i = 0; i < Compatibles.size(); i++) { m_Controls->m_VolumeSelectionBox->addItem(Compatibles[i].Model.c_str()); } //initialize tool storage m_toolStorage = mitk::NavigationToolStorage::New(GetDataStorage()); m_toolStorage->SetName("TrackingToolbox Default Storage"); - m_toolStorage->RegisterAsMicroservice("no tracking device"); + m_toolStorage->RegisterAsMicroservice(); //set home directory as default path for logfile m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(QDir::homePath()) + QDir::separator() + "logfile.csv"); //tracking device may be changed already by the persistence of the //QmitkTrackingDeciveConfigurationWidget this->OnTrackingDeviceChanged(); this->LoadUISettings(); //add tracking volume node only to data storage this->GetDataStorage()->Add(m_TrackingVolumeNode); if (!m_Controls->m_ShowTrackingVolume->isChecked()) m_TrackingVolumeNode->SetOpacity(0.0); else m_TrackingVolumeNode->SetOpacity(0.25); //Update List of available models for selected tool. m_Controls->m_VolumeSelectionBox->clear(); for (std::size_t i = 0; i < Compatibles.size(); i++) { m_Controls->m_VolumeSelectionBox->addItem(Compatibles[i].Model.c_str()); } } } void QmitkMITKIGTTrackingToolboxView::SetFocus() { m_Controls->m_configurationWidget->setFocus(); } void QmitkMITKIGTTrackingToolboxView::OnLoadTools() { //read in filename QString filename = QFileDialog::getOpenFileName(nullptr, tr("Open Tool Storage"), "/", tr("Tool Storage Files (*.IGTToolStorage)")); if (filename.isNull()) return; //read tool storage from disk std::string errorMessage = ""; mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(GetDataStorage()); // try-catch block for exceptions try { this->ReplaceCurrentToolStorage(myDeserializer->Deserialize(filename.toStdString()), filename.toStdString()); } catch (mitk::IGTException) { std::string errormessage = "Error during loading the tool storage file. Please only load tool storage files created with the NavigationToolManager view."; QMessageBox::warning(nullptr, "Tool Storage Loading Error", errormessage.c_str()); return; } if (m_toolStorage->isEmpty()) { errorMessage = myDeserializer->GetErrorMessage(); MessageBox(errorMessage); return; } //update label UpdateToolStorageLabel(filename); //update tool preview m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); //save filename for persistent storage m_ToolStorageFilename = filename; } void QmitkMITKIGTTrackingToolboxView::OnResetTools() { this->ReplaceCurrentToolStorage(mitk::NavigationToolStorage::New(GetDataStorage()), "TrackingToolbox Default Storage"); m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); QString toolLabel = QString(""); - m_Controls->m_toolLabel->setText(toolLabel); + m_Controls->m_ToolLabel->setText(toolLabel); m_ToolStorageFilename = ""; } void QmitkMITKIGTTrackingToolboxView::OnStartStopTracking() { if (!m_connected) { MITK_WARN << "Can't start tracking if no device is connected. Aborting"; return; } if (m_tracking) { OnStopTracking(); } else { OnStartTracking(); } } void QmitkMITKIGTTrackingToolboxView::OnFreezeUnfreezeTracking() { if (m_Controls->m_FreezeUnfreezeTrackingButton->text() == "Freeze Tracking") { m_Worker->GetTrackingDeviceSource()->Freeze(); m_Controls->m_FreezeUnfreezeTrackingButton->setText("Unfreeze Tracking"); m_Controls->m_TrackingFrozenLabel->setVisible(true); } else if (m_Controls->m_FreezeUnfreezeTrackingButton->text() == "Unfreeze Tracking") { m_Worker->GetTrackingDeviceSource()->UnFreeze(); m_Controls->m_FreezeUnfreezeTrackingButton->setText("Freeze Tracking"); m_Controls->m_TrackingFrozenLabel->setVisible(false); } } +void QmitkMITKIGTTrackingToolboxView::OnShowHideToolProjectionClicked() +{ + if( !m_ShowHideToolProjection ) + { + //Activate and show the tool projection + mitk::DataNode::Pointer node = this->GetDataStorage()->GetNamedNode("Tool Projection"); + //If node does not exist, create the node for the Pointset + if( node.IsNull() ) + { + node = mitk::DataNode::New(); + node->SetName("Tool Projection"); + node->SetData(m_NeedleProjectionFilter->GetProjection()); + node->SetBoolProperty("show contour", true); + this->GetDataStorage()->Add(node); + } + else + { + node->SetBoolProperty("show contour", true); + } + //Enable the checkbox for displaying the (standard) tool axis + m_Controls->showHideToolAxisCheckBox->setEnabled(true); + m_ShowHideToolProjection = true; + } + else + { + //Deactivate and hide the tool projection + mitk::DataNode::Pointer node = this->GetDataStorage()->GetNamedNode("Tool Projection"); + if( !node.IsNull() ) + { + this->GetDataStorage()->Remove(node); + } + m_Controls->showHideToolAxisCheckBox->setEnabled(false); + m_ShowHideToolProjection = false; + } + if( m_NeedleProjectionFilter.IsNotNull() ) + { + m_NeedleProjectionFilter->Update(); + } + //Refresh the view and the status widget + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + m_Controls->m_TrackingToolsStatusWidget->Refresh(); +} + +void QmitkMITKIGTTrackingToolboxView::OnShowHideToolAxisClicked() +{ + if( !m_ShowHideToolAxis ) + { + //Activate and show the tool axis + m_NeedleProjectionFilter->ShowToolAxis(true); + m_ShowHideToolAxis = true; + } + else + { + //Deactivate and hide the tool axis + m_NeedleProjectionFilter->ShowToolAxis(false); + m_NeedleProjectionFilter->GetProjection()->RemovePointIfExists(2); + m_ShowHideToolAxis = false; + } + //Update the filter + if( m_NeedleProjectionFilter.IsNotNull() ) + { + m_NeedleProjectionFilter->Update(); + } + //Refresh the view and the status widget + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + m_Controls->m_TrackingToolsStatusWidget->Refresh(); +} + void QmitkMITKIGTTrackingToolboxView::OnConnectDisconnect() { if (m_connected) { OnDisconnect(); } else { OnConnect(); } } void QmitkMITKIGTTrackingToolboxView::OnConnect() { MITK_DEBUG << "Connect Clicked"; //check if everything is ready to start tracking if (this->m_toolStorage.IsNull()) { MessageBox("Error: No Tools Loaded Yet!"); return; } else if (this->m_toolStorage->GetToolCount() == 0) { MessageBox("Error: No Way To Track Without Tools!"); return; } //parse tracking device data mitk::TrackingDeviceData data = mitk::UnspecifiedTrackingTypeInformation::GetDeviceDataUnspecified(); QString qstr = m_Controls->m_VolumeSelectionBox->currentText(); if ((!qstr.isNull()) || (!qstr.isEmpty())) { std::string str = qstr.toStdString(); data = m_DeviceTypeCollection->GetDeviceDataByName(str); //Data will be set later, after device generation } //! [Thread 4] //initialize worker thread m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eConnectDevice); - m_Worker->SetTrackingDevice(this->m_Controls->m_configurationWidget->GetTrackingDevice()); + m_Worker->SetTrackingDevice(this->m_Controls->m_ConfigurationWidget->GetTrackingDevice()); m_Worker->SetInverseMode(m_Controls->m_InverseMode->isChecked()); m_Worker->SetNavigationToolStorage(this->m_toolStorage); m_Worker->SetTrackingDeviceData(data); //start worker thread m_WorkerThread->start(); //! [Thread 4] //disable buttons this->m_Controls->m_MainWidget->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::EnableDisableTimerButtons(int enable) { bool enableBool = enable; m_Controls->m_UpdateRateOptionsGroupBox->setEnabled(!enableBool); - m_Controls->m_renderWarningLabel->setVisible(enableBool); + m_Controls->m_RenderWarningLabel->setVisible(enableBool); } void QmitkMITKIGTTrackingToolboxView::OnConnectFinished(bool success, QString errorMessage) { m_WorkerThread->quit(); m_WorkerThread->wait(); //enable buttons this->m_Controls->m_MainWidget->setEnabled(true); if (!success) { MITK_WARN << errorMessage.toStdString(); MessageBox(errorMessage.toStdString()); return; } //! [Thread 6] //get data from worker thread m_TrackingDeviceData = m_Worker->GetTrackingDeviceData(); m_ToolVisualizationFilter = m_Worker->GetToolVisualizationFilter(); + if( m_ToolVisualizationFilter.IsNotNull() ) + { + //Connect the NeedleProjectionFilter to the ToolVisualizationFilter as third filter of the IGT pipeline + m_NeedleProjectionFilter->ConnectTo(m_ToolVisualizationFilter); + m_NeedleProjectionFilter->SelectInput(0); + } + //! [Thread 6] //enable/disable Buttons DisableOptionsButtons(); DisableTrackingConfigurationButtons(); m_Controls->m_TrackingControlLabel->setText("Status: connected"); m_Controls->m_ConnectDisconnectButton->setText("Disconnect"); m_Controls->m_ConnectSimpleMode->setText("Disconnect"); m_Controls->m_StartStopTrackingButton->setEnabled(true); m_Controls->m_StartTrackingSimpleMode->setEnabled(true); m_connected = true; + + //During connection, thi sourceID of the tool storage changed. However, Microservice can't be updated on a different thread. + //UpdateMicroservice is necessary to use filter to get the right storage belonging to a source. + //Don't do it before m_connected is true, as we don't want to call content of OnToolStorageChanged. + m_toolStorage->UpdateMicroservice(); } void QmitkMITKIGTTrackingToolboxView::OnDisconnect() { m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eDisconnectDevice); m_WorkerThread->start(); m_Controls->m_MainWidget->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::OnDisconnectFinished(bool success, QString errorMessage) { m_WorkerThread->quit(); m_WorkerThread->wait(); m_Controls->m_MainWidget->setEnabled(true); if (!success) { MITK_WARN << errorMessage.toStdString(); MessageBox(errorMessage.toStdString()); return; } //enable/disable Buttons m_Controls->m_StartStopTrackingButton->setEnabled(false); m_Controls->m_StartTrackingSimpleMode->setEnabled(false); EnableOptionsButtons(); EnableTrackingConfigurationButtons(); m_Controls->m_TrackingControlLabel->setText("Status: disconnected"); m_Controls->m_ConnectDisconnectButton->setText("Connect"); m_Controls->m_ConnectSimpleMode->setText("Connect"); m_Controls->m_FreezeUnfreezeTrackingButton->setText("Freeze Tracking"); m_Controls->m_TrackingFrozenLabel->setVisible(false); m_connected = false; } void QmitkMITKIGTTrackingToolboxView::OnStartTracking() { //show tracking volume this->OnTrackingVolumeChanged(m_Controls->m_VolumeSelectionBox->currentText()); //Reset the view to a defined start. Do it here and not in OnStartTrackingFinished, to give other tracking devices the chance to reset the view to a different direction. this->GlobalReinit(); m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eStartTracking); m_WorkerThread->start(); this->m_Controls->m_MainWidget->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::OnStartTrackingFinished(bool success, QString errorMessage) { //! [Thread 5] m_WorkerThread->quit(); m_WorkerThread->wait(); //! [Thread 5] this->m_Controls->m_MainWidget->setEnabled(true); if (!success) { MessageBox(errorMessage.toStdString()); MITK_WARN << errorMessage.toStdString(); return; } if (!(m_Controls->m_DisableAllTimers->isChecked())) { if (m_Controls->m_UseDifferentUpdateRates->isChecked()) { if (m_Controls->m_RenderUpdateRate->value() != 0) m_TrackingRenderTimer->start(1000 / (m_Controls->m_RenderUpdateRate->value())); m_TrackingLoggingTimer->start(1000 / (m_Controls->m_LogUpdateRate->value())); } else { m_TrackingRenderTimer->start(1000 / (m_Controls->m_UpdateRate->value())); m_TrackingLoggingTimer->start(1000 / (m_Controls->m_UpdateRate->value())); } } m_Controls->m_TrackingControlLabel->setText("Status: tracking"); //connect the tool visualization widget for (std::size_t i = 0; i < m_Worker->GetTrackingDeviceSource()->GetNumberOfOutputs(); i++) { m_Controls->m_TrackingToolsStatusWidget->AddNavigationData(m_Worker->GetTrackingDeviceSource()->GetOutput(i)); } m_Controls->m_TrackingToolsStatusWidget->ShowStatusLabels(); if (m_Controls->m_ShowToolQuaternions->isChecked()) { m_Controls->m_TrackingToolsStatusWidget->SetShowQuaternions(true); } else { m_Controls->m_TrackingToolsStatusWidget->SetShowQuaternions(false); } //if activated enable open IGT link microservice if (m_Controls->m_EnableOpenIGTLinkMicroService->isChecked()) { //create convertion filter m_IGTLConversionFilter = mitk::NavigationDataToIGTLMessageFilter::New(); m_IGTLConversionFilter->SetName("IGT Tracking Toolbox"); QString dataModeSelection = this->m_Controls->m_OpenIGTLinkDataFormat->currentText(); if (dataModeSelection == "TDATA") { m_IGTLConversionFilter->SetOperationMode(mitk::NavigationDataToIGTLMessageFilter::ModeSendTDataMsg); } else if (dataModeSelection == "TRANSFORM") { m_IGTLConversionFilter->SetOperationMode(mitk::NavigationDataToIGTLMessageFilter::ModeSendTransMsg); } else if (dataModeSelection == "QTDATA") { m_IGTLConversionFilter->SetOperationMode(mitk::NavigationDataToIGTLMessageFilter::ModeSendQTDataMsg); } else if (dataModeSelection == "POSITION") { m_IGTLConversionFilter->SetOperationMode(mitk::NavigationDataToIGTLMessageFilter::ModeSendQTransMsg); } m_IGTLConversionFilter->ConnectTo(m_ToolVisualizationFilter); m_IGTLConversionFilter->RegisterAsMicroservice(); //create server and message provider m_IGTLServer = mitk::IGTLServer::New(false); m_IGTLServer->SetName("Tracking Toolbox IGTL Server"); m_IGTLMessageProvider = mitk::IGTLMessageProvider::New(); m_IGTLMessageProvider->SetIGTLDevice(m_IGTLServer); m_IGTLMessageProvider->RegisterAsMicroservice(); } m_tracking = true; m_Controls->m_ConnectDisconnectButton->setEnabled(false); m_Controls->m_StartStopTrackingButton->setText("Stop Tracking"); m_Controls->m_StartTrackingSimpleMode->setText("Stop\nTracking"); m_Controls->m_FreezeUnfreezeTrackingButton->setEnabled(true); } void QmitkMITKIGTTrackingToolboxView::OnStopTracking() { if (!m_tracking) return; m_TrackingRenderTimer->stop(); m_TrackingLoggingTimer->stop(); m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eStopTracking); m_WorkerThread->start(); m_Controls->m_MainWidget->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::OnStopTrackingFinished(bool success, QString errorMessage) { m_WorkerThread->quit(); m_WorkerThread->wait(); m_Controls->m_MainWidget->setEnabled(true); if (!success) { MessageBox(errorMessage.toStdString()); MITK_WARN << errorMessage.toStdString(); return; } m_Controls->m_TrackingControlLabel->setText("Status: connected"); if (m_logging) StopLogging(); m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); m_tracking = false; m_Controls->m_StartStopTrackingButton->setText("Start Tracking"); m_Controls->m_StartTrackingSimpleMode->setText("Start\nTracking"); m_Controls->m_ConnectDisconnectButton->setEnabled(true); m_Controls->m_FreezeUnfreezeTrackingButton->setEnabled(false); //unregister open IGT link micro service if (m_Controls->m_EnableOpenIGTLinkMicroService->isChecked()) { m_IGTLConversionFilter->UnRegisterMicroservice(); m_IGTLMessageProvider->UnRegisterMicroservice(); } } void QmitkMITKIGTTrackingToolboxView::OnTrackingDeviceChanged() { mitk::TrackingDeviceType Type; - if (m_Controls->m_configurationWidget->GetTrackingDevice().IsNotNull()) + if (m_Controls->m_ConfigurationWidget->GetTrackingDevice().IsNotNull()) { - Type = m_Controls->m_configurationWidget->GetTrackingDevice()->GetType(); + Type = m_Controls->m_ConfigurationWidget->GetTrackingDevice()->GetType(); //enable controls because device is valid m_Controls->m_TrackingToolsGoupBox->setEnabled(true); m_Controls->m_TrackingControlsGroupBox->setEnabled(true); } else { Type = mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName(); MessageBox("Error: This tracking device is not included in this project. Please make sure that the device is installed and activated in your MITK build."); m_Controls->m_TrackingToolsGoupBox->setEnabled(false); m_Controls->m_TrackingControlsGroupBox->setEnabled(false); return; } // Code to enable/disable device specific buttons - if (m_Controls->m_configurationWidget->GetTrackingDevice()->AutoDetectToolsAvailable()) + if (m_Controls->m_ConfigurationWidget->GetTrackingDevice()->AutoDetectToolsAvailable()) { m_Controls->m_AutoDetectTools->setVisible(true); } else { m_Controls->m_AutoDetectTools->setVisible(false); } - m_Controls->m_AddSingleTool->setEnabled(this->m_Controls->m_configurationWidget->GetTrackingDevice()->AddSingleToolIsAvailable()); + m_Controls->m_AddSingleTool->setEnabled(this->m_Controls->m_ConfigurationWidget->GetTrackingDevice()->AddSingleToolIsAvailable()); // Code to select appropriate tracking volume for current type std::vector Compatibles = m_DeviceTypeCollection->GetDeviceDataForLine(Type); m_Controls->m_VolumeSelectionBox->clear(); for (std::size_t i = 0; i < Compatibles.size(); i++) { m_Controls->m_VolumeSelectionBox->addItem(Compatibles[i].Model.c_str()); } } void QmitkMITKIGTTrackingToolboxView::OnTrackingVolumeChanged(QString qstr) { if (qstr.isNull()) return; if (qstr.isEmpty()) return; mitk::TrackingVolumeGenerator::Pointer volumeGenerator = mitk::TrackingVolumeGenerator::New(); std::string str = qstr.toStdString(); mitk::TrackingDeviceData data = m_DeviceTypeCollection->GetDeviceDataByName(str); m_TrackingDeviceData = data; volumeGenerator->SetTrackingDeviceData(data); volumeGenerator->Update(); mitk::Surface::Pointer volumeSurface = volumeGenerator->GetOutput(); m_TrackingVolumeNode->SetData(volumeSurface); if (!m_Controls->m_ShowTrackingVolume->isChecked()) m_TrackingVolumeNode->SetOpacity(0.0); else m_TrackingVolumeNode->SetOpacity(0.25); GlobalReinit(); } void QmitkMITKIGTTrackingToolboxView::OnShowTrackingVolumeChanged() { if (m_Controls->m_ShowTrackingVolume->isChecked()) { OnTrackingVolumeChanged(m_Controls->m_VolumeSelectionBox->currentText()); m_TrackingVolumeNode->SetOpacity(0.25); } else { m_TrackingVolumeNode->SetOpacity(0.0); } } void QmitkMITKIGTTrackingToolboxView::OnAutoDetectTools() { - if (m_Controls->m_configurationWidget->GetTrackingDevice()->AutoDetectToolsAvailable()) + if (m_Controls->m_ConfigurationWidget->GetTrackingDevice()->AutoDetectToolsAvailable()) { DisableTrackingConfigurationButtons(); m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eAutoDetectTools); - m_Worker->SetTrackingDevice(m_Controls->m_configurationWidget->GetTrackingDevice().GetPointer()); + m_Worker->SetTrackingDevice(m_Controls->m_ConfigurationWidget->GetTrackingDevice().GetPointer()); m_Worker->SetDataStorage(this->GetDataStorage()); m_WorkerThread->start(); m_TimeoutTimer->start(7000); //disable controls until worker thread is finished this->m_Controls->m_MainWidget->setEnabled(false); } } void QmitkMITKIGTTrackingToolboxView::OnAutoDetectToolsFinished(bool success, QString errorMessage) { //Check, if the thread is running. There might have been a timeOut inbetween and this causes crashes... if (m_WorkerThread->isRunning()) { m_TimeoutTimer->stop(); m_WorkerThread->quit(); m_WorkerThread->wait(); } //enable controls again this->m_Controls->m_MainWidget->setEnabled(true); EnableTrackingConfigurationButtons(); if (!success) { MITK_WARN << errorMessage.toStdString(); MessageBox(errorMessage.toStdString()); EnableTrackingConfigurationButtons(); return; } mitk::NavigationToolStorage::Pointer autoDetectedStorage = m_Worker->GetNavigationToolStorage(); //save detected tools std::string _autoDetectText; _autoDetectText = "Autodetected "; _autoDetectText.append(this->m_TrackingDeviceData.Line); //This is the device name as string of the current TrackingDevice. _autoDetectText.append(" Storage"); this->ReplaceCurrentToolStorage(autoDetectedStorage, _autoDetectText); //auto save the new storage to hard disc (for persistence) AutoSaveToolStorage(); //update label QString toolLabel = QString("Loaded Tools: ") + QString::number(m_toolStorage->GetToolCount()) + " Tools (Auto Detected)"; - m_Controls->m_toolLabel->setText(toolLabel); + m_Controls->m_ToolLabel->setText(toolLabel); //update tool preview m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); EnableTrackingConfigurationButtons(); //print a logging message about the detected tools switch (m_toolStorage->GetToolCount()) { case 0: MITK_INFO("IGT Tracking Toolbox") << "Found no tools. Empty ToolStorage was autosaved to " << m_ToolStorageFilename.toStdString(); break; case 1: MITK_INFO("IGT Tracking Toolbox") << "Found one tool. ToolStorage was autosaved to " << m_ToolStorageFilename.toStdString(); break; default: MITK_INFO("IGT Tracking Toolbox") << "Found " << m_toolStorage->GetToolCount() << " tools. ToolStorage was autosaved to " << m_ToolStorageFilename.toStdString(); } } void QmitkMITKIGTTrackingToolboxView::MessageBox(std::string s) { QMessageBox msgBox; msgBox.setText(s.c_str()); msgBox.exec(); } void QmitkMITKIGTTrackingToolboxView::UpdateRenderTrackingTimer() { //update filter m_ToolVisualizationFilter->Update(); MITK_DEBUG << "Number of outputs ToolVisualizationFilter: " << m_ToolVisualizationFilter->GetNumberOfIndexedOutputs(); MITK_DEBUG << "Number of inputs ToolVisualizationFilter: " << m_ToolVisualizationFilter->GetNumberOfIndexedInputs(); //update tool colors to show tool status for (unsigned int i = 0; i < m_ToolVisualizationFilter->GetNumberOfIndexedOutputs(); i++) { mitk::NavigationData::Pointer currentTool = m_ToolVisualizationFilter->GetOutput(i); if (currentTool->IsDataValid()) { this->m_toolStorage->GetTool(i)->GetDataNode()->SetColor(mitk::IGTColor_VALID); } else { this->m_toolStorage->GetTool(i)->GetDataNode()->SetColor(mitk::IGTColor_WARNING); } } + //Update the NeedleProjectionFilter + if( m_NeedleProjectionFilter.IsNotNull() ) + { + m_NeedleProjectionFilter->Update(); + } + //refresh view and status widget mitk::RenderingManager::GetInstance()->RequestUpdateAll(); m_Controls->m_TrackingToolsStatusWidget->Refresh(); } void QmitkMITKIGTTrackingToolboxView::UpdateLoggingTrackingTimer() { //update logging if (m_logging) { this->m_loggingFilter->Update(); m_loggedFrames = this->m_loggingFilter->GetNumberOfRecordedSteps(); this->m_Controls->m_LoggedFramesLabel->setText("Logged Frames: " + QString::number(m_loggedFrames)); //check if logging stopped automatically if ((m_loggedFrames > 1) && (!m_loggingFilter->GetRecording())){ StopLogging(); } } //refresh status widget m_Controls->m_TrackingToolsStatusWidget->Refresh(); } void QmitkMITKIGTTrackingToolboxView::OnChooseFileClicked() { QDir currentPath = QFileInfo(m_Controls->m_LoggingFileName->text()).dir(); // if no path was selected (QDir would select current working dir then) or the // selected path does not exist -> use home directory if (currentPath == QDir() || !currentPath.exists()) { currentPath = QDir(QDir::homePath()); } QString filename = QFileDialog::getSaveFileName(nullptr, tr("Choose Logging File"), currentPath.absolutePath(), "*.*"); if (filename == "") return; this->m_Controls->m_LoggingFileName->setText(filename); this->OnToggleFileExtension(); } // bug-16470: toggle file extension after clicking on radio button void QmitkMITKIGTTrackingToolboxView::OnToggleFileExtension() { QString currentInputText = this->m_Controls->m_LoggingFileName->text(); QString currentFile = QFileInfo(currentInputText).baseName(); QDir currentPath = QFileInfo(currentInputText).dir(); if (currentFile.isEmpty()) { currentFile = "logfile"; } // Setting currentPath to default home path when currentPath is empty or it does not exist if (currentPath == QDir() || !currentPath.exists()) { currentPath = QDir::homePath(); } // check if csv radio button is clicked - if (this->m_Controls->m_csvFormat->isChecked()) + if (this->m_Controls->m_CsvFormat->isChecked()) { // you needn't add a seperator to the input text when currentpath is the rootpath if (currentPath.isRoot()) { this->m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(currentPath.absolutePath()) + currentFile + ".csv"); } else { this->m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(currentPath.absolutePath()) + QDir::separator() + currentFile + ".csv"); } } // check if xml radio button is clicked - else if (this->m_Controls->m_xmlFormat->isChecked()) + else if (this->m_Controls->m_XmlFormat->isChecked()) { // you needn't add a seperator to the input text when currentpath is the rootpath if (currentPath.isRoot()) { this->m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(currentPath.absolutePath()) + currentFile + ".xml"); } else { this->m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(currentPath.absolutePath()) + QDir::separator() + currentFile + ".xml"); } } } void QmitkMITKIGTTrackingToolboxView::OnToggleAdvancedSimpleMode() { if (m_SimpleModeEnabled) { m_Controls->m_simpleWidget->setVisible(false); m_Controls->m_MainWidget->setVisible(true); - m_Controls->m_simpleUI->setChecked(false); + m_Controls->m_SimpleUI->setChecked(false); m_SimpleModeEnabled = false; } else { m_Controls->m_simpleWidget->setVisible(true); m_Controls->m_MainWidget->setVisible(false); m_SimpleModeEnabled = true; } } void QmitkMITKIGTTrackingToolboxView::OnToggleDifferentUpdateRates() { if (m_Controls->m_UseDifferentUpdateRates->isChecked()) { if (m_Controls->m_RenderUpdateRate->value() == 0) - m_Controls->m_renderWarningLabel->setVisible(true); + m_Controls->m_RenderWarningLabel->setVisible(true); else - m_Controls->m_renderWarningLabel->setVisible(false); + m_Controls->m_RenderWarningLabel->setVisible(false); m_Controls->m_UpdateRate->setEnabled(false); m_Controls->m_OptionsUpdateRateLabel->setEnabled(false); m_Controls->m_RenderUpdateRate->setEnabled(true); m_Controls->m_OptionsRenderUpdateRateLabel->setEnabled(true); m_Controls->m_LogUpdateRate->setEnabled(true); m_Controls->m_OptionsLogUpdateRateLabel->setEnabled(true); } else { - m_Controls->m_renderWarningLabel->setVisible(false); + m_Controls->m_RenderWarningLabel->setVisible(false); m_Controls->m_UpdateRate->setEnabled(true); m_Controls->m_OptionsUpdateRateLabel->setEnabled(true); m_Controls->m_RenderUpdateRate->setEnabled(false); m_Controls->m_OptionsRenderUpdateRateLabel->setEnabled(false); m_Controls->m_LogUpdateRate->setEnabled(false); m_Controls->m_OptionsLogUpdateRateLabel->setEnabled(false); } } void QmitkMITKIGTTrackingToolboxView::OnChangeRenderUpdateRate() { if (m_Controls->m_RenderUpdateRate->value() == 0) - m_Controls->m_renderWarningLabel->setVisible(true); + m_Controls->m_RenderWarningLabel->setVisible(true); else - m_Controls->m_renderWarningLabel->setVisible(false); + m_Controls->m_RenderWarningLabel->setVisible(false); } void QmitkMITKIGTTrackingToolboxView::StartLogging() { if (m_ToolVisualizationFilter.IsNull()) { MessageBox("Cannot activate logging without a connected device. Configure and connect a tracking device first."); return; } if (!m_logging) { //initialize logging filter m_loggingFilter = mitk::NavigationDataRecorder::New(); m_loggingFilter->SetRecordOnlyValidData(m_Controls->m_SkipInvalidData->isChecked()); m_loggingFilter->ConnectTo(m_ToolVisualizationFilter); if (m_Controls->m_LoggingLimit->isChecked()){ m_loggingFilter->SetRecordCountLimit(m_Controls->m_LoggedFramesLimit->value()); } //start filter with try-catch block for exceptions try { m_loggingFilter->StartRecording(); } catch (mitk::IGTException) { std::string errormessage = "Error during start recording. Recorder already started recording?"; QMessageBox::warning(nullptr, "IGTPlayer: Error", errormessage.c_str()); m_loggingFilter->StopRecording(); return; } //update labels / logging variables this->m_Controls->m_LoggingLabel->setText("Logging ON"); this->m_Controls->m_LoggedFramesLabel->setText("Logged Frames: 0"); m_loggedFrames = 0; m_logging = true; DisableLoggingButtons(); } } void QmitkMITKIGTTrackingToolboxView::StopLogging() { if (m_logging) { //stop logging m_loggingFilter->StopRecording(); m_logging = false; //update GUI this->m_Controls->m_LoggingLabel->setText("Logging OFF"); EnableLoggingButtons(); //write the results to a file - if (m_Controls->m_csvFormat->isChecked() || m_Controls->m_xmlFormat->isChecked()) - mitk::IOUtil::Save(m_loggingFilter->GetNavigationDataSet(), this->m_Controls->m_LoggingFileName->text().toStdString()); + if (m_Controls->m_CsvFormat->isChecked()) + { + mitk::IOUtil::SaveBaseData(m_loggingFilter->GetNavigationDataSet(), this->m_Controls->m_LoggingFileName->text().toStdString()); + } + else if (m_Controls->m_XmlFormat->isChecked()) + { + mitk::IOUtil::SaveBaseData(m_loggingFilter->GetNavigationDataSet(), this->m_Controls->m_LoggingFileName->text().toStdString()); + } } } void QmitkMITKIGTTrackingToolboxView::OnAddSingleTool() { QString Identifier = "Tool#"; QString Name = "NewTool"; if (m_toolStorage.IsNotNull()) { Identifier += QString::number(m_toolStorage->GetToolCount()); Name += QString::number(m_toolStorage->GetToolCount()); } else { Identifier += "0"; Name += "0"; } m_Controls->m_NavigationToolCreationWidget->Initialize(GetDataStorage(), Identifier.toStdString(), Name.toStdString()); - m_Controls->m_NavigationToolCreationWidget->SetTrackingDeviceType(m_Controls->m_configurationWidget->GetTrackingDevice()->GetType(), false); + m_Controls->m_NavigationToolCreationWidget->SetTrackingDeviceType(m_Controls->m_ConfigurationWidget->GetTrackingDevice()->GetType(), false); m_Controls->m_TrackingToolsWidget->setCurrentIndex(1); //disable tracking volume during tool editing lastTrackingVolumeState = m_Controls->m_ShowTrackingVolume->isChecked(); if (lastTrackingVolumeState) m_Controls->m_ShowTrackingVolume->click(); GlobalReinit(); } void QmitkMITKIGTTrackingToolboxView::OnAddSingleToolFinished() { m_Controls->m_TrackingToolsWidget->setCurrentIndex(0); if (this->m_toolStorage.IsNull()) { //this shouldn't happen! MITK_WARN << "No ToolStorage available, cannot add tool, aborting!"; return; } m_toolStorage->AddTool(m_Controls->m_NavigationToolCreationWidget->GetCreatedTool()); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); - m_Controls->m_toolLabel->setText(""); + m_Controls->m_ToolLabel->setText(""); //auto save current storage for persistence MITK_INFO << "Auto saving manually added tools for persistence."; AutoSaveToolStorage(); //enable tracking volume again if (lastTrackingVolumeState) m_Controls->m_ShowTrackingVolume->click(); GlobalReinit(); } void QmitkMITKIGTTrackingToolboxView::OnAddSingleToolCanceled() { m_Controls->m_TrackingToolsWidget->setCurrentIndex(0); //enable tracking volume again if (lastTrackingVolumeState) m_Controls->m_ShowTrackingVolume->click(); GlobalReinit(); } void QmitkMITKIGTTrackingToolboxView::GlobalReinit() { // get all nodes that have not set "includeInBoundingBox" to false mitk::NodePredicateNot::Pointer pred = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("includeInBoundingBox", mitk::BoolProperty::New(false))); mitk::DataStorage::SetOfObjects::ConstPointer rs = this->GetDataStorage()->GetSubset(pred); // calculate bounding geometry of these nodes mitk::TimeGeometry::Pointer bounds = this->GetDataStorage()->ComputeBoundingGeometry3D(rs, "visible"); // initialize the views to the bounding geometry mitk::RenderingManager::GetInstance()->InitializeViews(bounds); } void QmitkMITKIGTTrackingToolboxView::DisableLoggingButtons() { m_Controls->m_StartLogging->setEnabled(false); m_Controls->m_LoggingFileName->setEnabled(false); m_Controls->m_ChooseFile->setEnabled(false); m_Controls->m_LoggingLimit->setEnabled(false); m_Controls->m_LoggedFramesLimit->setEnabled(false); - m_Controls->m_csvFormat->setEnabled(false); - m_Controls->m_xmlFormat->setEnabled(false); + m_Controls->m_CsvFormat->setEnabled(false); + m_Controls->m_XmlFormat->setEnabled(false); m_Controls->m_SkipInvalidData->setEnabled(false); m_Controls->m_StopLogging->setEnabled(true); } void QmitkMITKIGTTrackingToolboxView::EnableLoggingButtons() { m_Controls->m_StartLogging->setEnabled(true); m_Controls->m_LoggingFileName->setEnabled(true); m_Controls->m_ChooseFile->setEnabled(true); m_Controls->m_LoggingLimit->setEnabled(true); m_Controls->m_LoggedFramesLimit->setEnabled(true); - m_Controls->m_csvFormat->setEnabled(true); - m_Controls->m_xmlFormat->setEnabled(true); + m_Controls->m_CsvFormat->setEnabled(true); + m_Controls->m_XmlFormat->setEnabled(true); m_Controls->m_SkipInvalidData->setEnabled(true); m_Controls->m_StopLogging->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::DisableOptionsButtons() { m_Controls->m_ShowTrackingVolume->setEnabled(false); m_Controls->m_UseDifferentUpdateRates->setEnabled(false); m_Controls->m_UpdateRate->setEnabled(false); m_Controls->m_OptionsUpdateRateLabel->setEnabled(false); m_Controls->m_RenderUpdateRate->setEnabled(false); m_Controls->m_OptionsRenderUpdateRateLabel->setEnabled(false); m_Controls->m_LogUpdateRate->setEnabled(false); m_Controls->m_OptionsLogUpdateRateLabel->setEnabled(false); m_Controls->m_DisableAllTimers->setEnabled(false); m_Controls->m_OtherOptionsGroupBox->setEnabled(false); m_Controls->m_EnableOpenIGTLinkMicroService->setEnabled(false); m_Controls->m_OpenIGTLinkDataFormat->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::EnableOptionsButtons() { m_Controls->m_ShowTrackingVolume->setEnabled(true); m_Controls->m_UseDifferentUpdateRates->setEnabled(true); m_Controls->m_DisableAllTimers->setEnabled(true); m_Controls->m_OtherOptionsGroupBox->setEnabled(true); m_Controls->m_EnableOpenIGTLinkMicroService->setEnabled(true); m_Controls->m_OpenIGTLinkDataFormat->setEnabled(true); OnToggleDifferentUpdateRates(); } void QmitkMITKIGTTrackingToolboxView::EnableTrackingControls() { m_Controls->m_TrackingControlsGroupBox->setEnabled(true); } void QmitkMITKIGTTrackingToolboxView::DisableTrackingControls() { m_Controls->m_TrackingControlsGroupBox->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::EnableTrackingConfigurationButtons() { m_Controls->m_AutoDetectTools->setEnabled(true); - m_Controls->m_AddSingleTool->setEnabled(this->m_Controls->m_configurationWidget->GetTrackingDevice()->AddSingleToolIsAvailable()); + m_Controls->m_AddSingleTool->setEnabled(this->m_Controls->m_ConfigurationWidget->GetTrackingDevice()->AddSingleToolIsAvailable()); m_Controls->m_LoadTools->setEnabled(true); m_Controls->m_ResetTools->setEnabled(true); } void QmitkMITKIGTTrackingToolboxView::DisableTrackingConfigurationButtons() { m_Controls->m_AutoDetectTools->setEnabled(false); m_Controls->m_AddSingleTool->setEnabled(false); m_Controls->m_LoadTools->setEnabled(false); m_Controls->m_ResetTools->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::ReplaceCurrentToolStorage(mitk::NavigationToolStorage::Pointer newStorage, std::string newStorageName) { //first: get rid of the old one //don't reset if there is no tool storage. BugFix #17793 if (m_toolStorage.IsNotNull()){ m_toolStorage->UnLockStorage(); //only to be sure... m_toolStorage->UnRegisterMicroservice(); m_toolStorage = nullptr; } //now: replace by the new one m_toolStorage = newStorage; m_toolStorage->SetName(newStorageName); - m_toolStorage->RegisterAsMicroservice("no tracking device"); + m_toolStorage->RegisterAsMicroservice(); } void QmitkMITKIGTTrackingToolboxView::OnTimeOut() { MITK_WARN << "TimeOut. Quitting the thread..."; m_WorkerThread->quit(); //only if we can't quit use terminate. if (!m_WorkerThread->wait(1000)) { MITK_ERROR << "Can't quit the thread. Terminating... Might cause further problems, be careful!"; m_WorkerThread->terminate(); m_WorkerThread->wait(); } m_TimeoutTimer->stop(); } void QmitkMITKIGTTrackingToolboxView::OnToolStorageChanged(const ctkServiceEvent event) { - if ((event.getType() == ctkServiceEvent::MODIFIED)) + //don't listen to any changes during connection, toolStorage is locked anyway, so this are only changes of e.g. sourceID which are not relevant for the widget. + if (!m_connected && (event.getType() == ctkServiceEvent::MODIFIED)) { - m_Controls->m_configurationWidget->OnToolStorageChanged(); + m_Controls->m_ConfigurationWidget->OnToolStorageChanged(); } } //! [StoreUISettings] void QmitkMITKIGTTrackingToolboxView::StoreUISettings() { // persistence service does not directly work in plugins for now // -> using QSettings QSettings settings; settings.beginGroup(QString::fromStdString(VIEW_ID)); MITK_DEBUG << "Store UI settings"; // set the values of some widgets and attrbutes to the QSettings settings.setValue("ShowTrackingVolume", QVariant(m_Controls->m_ShowTrackingVolume->isChecked())); settings.setValue("toolStorageFilename", QVariant(m_ToolStorageFilename)); settings.setValue("VolumeSelectionBox", QVariant(m_Controls->m_VolumeSelectionBox->currentIndex())); settings.setValue("SimpleModeEnabled", QVariant(m_SimpleModeEnabled)); settings.setValue("OpenIGTLinkDataFormat", QVariant(m_Controls->m_OpenIGTLinkDataFormat->currentIndex())); settings.setValue("EnableOpenIGTLinkMicroService", QVariant(m_Controls->m_EnableOpenIGTLinkMicroService->isChecked())); settings.endGroup(); } //! [StoreUISettings] //! [LoadUISettings] void QmitkMITKIGTTrackingToolboxView::LoadUISettings() { // persistence service does not directly work in plugins for now -> using QSettings QSettings settings; settings.beginGroup(QString::fromStdString(VIEW_ID)); // set some widgets and attributes by the values from the QSettings m_Controls->m_ShowTrackingVolume->setChecked(settings.value("ShowTrackingVolume", true).toBool()); m_Controls->m_EnableOpenIGTLinkMicroService->setChecked(settings.value("EnableOpenIGTLinkMicroService", true).toBool()); m_Controls->m_VolumeSelectionBox->setCurrentIndex(settings.value("VolumeSelectionBox", 0).toInt()); m_Controls->m_OpenIGTLinkDataFormat->setCurrentIndex(settings.value("OpenIGTLinkDataFormat", 0).toInt()); m_ToolStorageFilename = settings.value("toolStorageFilename", QVariant("")).toString(); if (settings.value("SimpleModeEnabled", false).toBool()) { this->OnToggleAdvancedSimpleMode(); } settings.endGroup(); //! [LoadUISettings] //! [LoadToolStorage] // try to deserialize the tool storage from the given tool storage file name if (!m_ToolStorageFilename.isEmpty()) { // try-catch block for exceptions try { mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(GetDataStorage()); m_toolStorage->UnRegisterMicroservice(); m_toolStorage = myDeserializer->Deserialize(m_ToolStorageFilename.toStdString()); - m_toolStorage->RegisterAsMicroservice("no tracking device"); + m_toolStorage->RegisterAsMicroservice(); //update label UpdateToolStorageLabel(m_ToolStorageFilename); //update tool preview m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); } catch (mitk::IGTException) { MITK_WARN("QmitkMITKIGTTrackingToolBoxView") << "Error during restoring tools. Problems with file (" << m_ToolStorageFilename.toStdString() << "), please check the file?"; this->OnResetTools(); //if there where errors reset the tool storage to avoid problems later on } } //! [LoadToolStorage] } void QmitkMITKIGTTrackingToolboxView::UpdateToolStorageLabel(QString pathOfLoadedStorage) { QFileInfo myPath(pathOfLoadedStorage); //use this to seperate filename from path QString toolLabel = myPath.fileName(); if (toolLabel.size() > 45) //if the tool storage name is to long trimm the string { toolLabel.resize(40); toolLabel += "[...]"; } - m_Controls->m_toolLabel->setText(toolLabel); + m_Controls->m_ToolLabel->setText(toolLabel); } void QmitkMITKIGTTrackingToolboxView::AutoSaveToolStorage() { m_ToolStorageFilename = m_AutoSaveFilename; mitk::NavigationToolStorageSerializer::Pointer mySerializer = mitk::NavigationToolStorageSerializer::New(); mySerializer->Serialize(m_ToolStorageFilename.toStdString(), m_toolStorage); } \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.h b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.h index 905e5bead7..2ab9c33003 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.h +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.h @@ -1,242 +1,257 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkMITKIGTTrackingToolboxView_h #define QmitkMITKIGTTrackingToolboxView_h #include #include #include #include #include "ui_QmitkMITKIGTTrackingToolboxViewControls.h" //mitk headers #include #include #include #include #include #include //QT headers #include #include "QmitkMITKIGTTrackingToolboxViewWorker.h" +//Forward declaration of MITK classes +namespace mitk +{ + class NeedleProjectionFilter; +} + /*! \brief QmitkMITKIGTTrackingToolboxView This is the view of the bundle IGT Tracking Toolbox. The IGT Tracking Toolbox can be used to access tracking devices with MITK-IGT. The Tracking Toolbox can be used to log tracking data in XML or CSV format for measurement purposes. The Tracking Toolbox further allows for visualization of tools with given surfaces in combination with the NaviagtionToolManager. */ class QmitkMITKIGTTrackingToolboxView : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const std::string VIEW_ID; QmitkMITKIGTTrackingToolboxView(); virtual ~QmitkMITKIGTTrackingToolboxView(); virtual void CreateQtPartControl(QWidget *parent) override; /// /// Sets the focus to an internal widget. /// virtual void SetFocus() override; protected slots: /** @brief changes name of the filename when switching fileextension by radio button */ void OnToggleFileExtension(); /** @brief This slot is called if the user wants to load a new tool file. A new window opens where the user can choose a file. If the chosen file is corrupt or not valid the user gets an error message. If the file was loaded successfully the tools are show in the tool status widget. */ void OnLoadTools(); /** Starts tracking if tracking is stopped / stops tracking if tracking is started. */ void OnStartStopTracking(); /** Connects the device if it is disconnected / disconnects the device if it is connected. */ void OnConnectDisconnect(); /** Freezes the device if it is not frozen / unfreezes the device if it is frozen. */ void OnFreezeUnfreezeTracking(); + /** @brief Shows or hides the tool projection of the standard tool axis. */ + void OnShowHideToolProjectionClicked(); + + /** @brief Shows or hides the standard tool axis. */ + void OnShowHideToolAxisClicked(); + /** @brief This slot connects to the device. In status "connected" configuration of the device is disabled. */ void OnConnect(); /** @brief This slot disconnects from the device. */ void OnDisconnect(); /** @brief This slot tries to start tracking with the current device. If start tracking fails the user gets an error message and tracking stays off.*/ void OnStartTracking(); /** @brief This slot stops tracking. If tracking is not strated it does nothing.*/ void OnStopTracking(); /** @brief This slot is called if the user want's to choose a file name for logging. A new windows to navigate through the file system and choose a file opens.*/ void OnChooseFileClicked(); /** @brief This slot starts logging. Logging is only possible if a device is tracking. If not the logging mechanism start when the start tracking is called.*/ void StartLogging(); /** @brief This slot stops logging. If logging is not running it does nothing.*/ void StopLogging(); /** @brief This slot enables / disables UI elements depending on the tracking device after a device is changed.*/ void OnTrackingDeviceChanged(); /** @brief This slot selects the Tracking Volume appropriate for a given model */ void OnTrackingVolumeChanged(QString qstr); /** @brief Shows or hides the tracking volume according to the checkboxe's state */ void OnShowTrackingVolumeChanged(); /** @brief This slot auto detects tools of a NDI Aurora tracking device. If tools where found they will be stored internally as a tool storage. The user is also asked if he wants to save this tool storage to load it later. Only call it if a Aurora device was configured because other devices don't support auto detection.*/ void OnAutoDetectTools(); /** @brief Slot for tracking timer. The timer updates the IGT pipline and also the logging filter if logging is activated.*/ void UpdateRenderTrackingTimer(); void UpdateLoggingTrackingTimer(); /** @brief Slot for showing the rendering disabled warning label*/ void OnChangeRenderUpdateRate(); /** @brief Resets the Tracking Tools: this means all tools are removed. */ void OnResetTools(); /** @brief Opens a dialog where a new navigation tool can be created. */ void OnAddSingleTool(); /** @brief This slot is called if the user finishes the creation of a new tool. */ void OnAddSingleToolFinished(); /** @brief This slot is called if the user cancels the creation of a new tool. */ void OnAddSingleToolCanceled(); void OnTimeOut(); /** * \brief This function is called, when anything in the ToolStorage changed, e.g. AddTool or EditTool. * ServiceListener is connected in the QmitkMITKIGTTrackingToolboxView. */ void OnToolStorageChanged(const ctkServiceEvent event); protected slots: //help slots for enable/disable buttons void DisableLoggingButtons(); void EnableLoggingButtons(); void DisableOptionsButtons(); void EnableOptionsButtons(); void EnableTrackingConfigurationButtons(); void DisableTrackingConfigurationButtons(); void EnableTrackingControls(); void DisableTrackingControls(); void EnableDisableTimerButtons(int enable); void OnToggleAdvancedSimpleMode(); void OnToggleDifferentUpdateRates(); //slots for worker thread void OnAutoDetectToolsFinished(bool success, QString errorMessage); void OnConnectFinished(bool success, QString errorMessage); void OnStartTrackingFinished(bool success, QString errorMessage); void OnStopTrackingFinished(bool success, QString errorMessage); void OnDisconnectFinished(bool success, QString errorMessage); protected: Ui::QmitkMITKIGTTrackingToolboxViewControls* m_Controls; bool m_tracking; ///> bool which is true if tracking is running, false if not bool m_connected; ///> bool that is true when a tracking device is connected bool m_logging; ///> bool which is true if logging is running, false if not + bool m_ShowHideToolProjection; ///> bool, which will be true, if the tool projection is visible during tracking + bool m_ShowHideToolAxis; ///> bool, which will be true, if the tool axis is visible during tracking int m_loggedFrames; ///> stores the current number of logged frames if logging is on mitk::NavigationToolStorage::Pointer m_toolStorage; ///>stores the loaded tools mitk::DataNode::Pointer m_TrackingVolumeNode; ///>holds the data node of the tracking volume if volume is visualized bool lastTrackingVolumeState; ///>temporary holds the state of the tracking volume (activated/not activated) during some methods QString m_ToolStorageFilename; ///>stores the filename of the current tool storage QString m_AutoSaveFilename; ///>a filename for auto saving tools if no m_ToolStorageFilename was given by the user /** @brief Shows a message box with the text given as parameter. */ void MessageBox(std::string s); /** @brief reinits the view globally. */ void GlobalReinit(); //members for the filter pipeline mitk::TrackingDeviceData m_TrackingDeviceData; ///> stores the tracking device data as long as this is not handled by the tracking device configuration widget mitk::NavigationDataObjectVisualizationFilter::Pointer m_ToolVisualizationFilter; ///> holds the tool visualization filter (second filter of the IGT pipeline) mitk::NavigationDataRecorder::Pointer m_loggingFilter; ///> holds the logging filter if logging is on (third filter of the IGT pipeline) + itk::SmartPointer m_NeedleProjectionFilter; ///> Contains the needle projection filter which is used for displaying the tool projection and the tool axis during tracking (optional third filter of the IGT pipeline). The filter is updated in the method UpdateRenderTrackingTimer(). //members for open IGT link server mitk::NavigationDataToIGTLMessageFilter::Pointer m_IGTLConversionFilter; ///> Converts the navigation data as open IGT link message and makes this filter available as microservice mitk::IGTLServer::Pointer m_IGTLServer; mitk::IGTLMessageProvider::Pointer m_IGTLMessageProvider; /** @brief This timer updates the IGT pipline and also the logging filter if logging is activated.*/ QTimer* m_TrackingRenderTimer; QTimer* m_TrackingLoggingTimer; QTimer* m_TimeoutTimer; bool m_SimpleModeEnabled; ///>Stores if simple UI mode is enabled /** Replaces the current navigation tool storage which is stored in m_toolStorage. * Basically handles the microservice stuff: unregisteres the old storage, then * replaces the storage and registers the new one. */ void ReplaceCurrentToolStorage(mitk::NavigationToolStorage::Pointer newStorage, std::string newStorageName); /** * \brief Stores the properties of some QWidgets (and the tool storage file name) to QSettings. */ void StoreUISettings(); /** * \brief Loads the properties of some QWidgets (and the tool storage file name) from QSettings. */ void LoadUISettings(); /** * Help method for updating the tool label */ void UpdateToolStorageLabel(QString pathOfLoadedStorage); /** * Auto saves the current tool storage to a temporary file. This ist used for persistence. */ void AutoSaveToolStorage(); //members for worker thread QThread* m_WorkerThread; QmitkMITKIGTTrackingToolboxViewWorker* m_Worker; private: ctkServiceReference m_DeviceTypeServiceReference; mitk::TrackingDeviceTypeCollection* m_DeviceTypeCollection; }; #endif // _QMITKMITKIGTTRACKINGTOOLBOXVIEW_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewControls.ui b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewControls.ui index 46a7777220..b19715464c 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewControls.ui +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewControls.ui @@ -1,936 +1,953 @@ QmitkMITKIGTTrackingToolboxViewControls 0 0 - 370 - 723 + 680 + 1147 0 0 QmitkTemplate 0 Tracking - + 0 0 0 0 16777215 - 280 + 220 - - - + + + - + 0 0 + 6 75 true <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Tracking Tools</span></p></body></html> 0 0 ToolStorage: - + <none> Qt::Horizontal 40 20 200 - 80 + 0 Qt::Horizontal 13 49 120 0 Auto Detection 120 0 Add Single Tool 120 0 Load Tool Storage 120 0 Reset <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Tracking Control</span></p></body></html> Status: disconnected Qt::Horizontal 40 20 142 0 Connect Qt::Horizontal 40 20 142 0 Start Tracking Qt::Horizontal 40 20 <html><head/><body><p><span style=" color:#ff0000;">Tracking Frozen!</span></p></body></html> true 142 0 Freeze Tracking - - - - Qt::Vertical - - - - 20 - 40 - - - - Options Disable All Timers - + true <html><head/><body><p align="right"><span style=" color:#ff0000;">Rendering Disabled!</span></p></body></html> Qt::AutoText Update Rate Options Update Rate [per second] Qt::Horizontal 40 20 100 10 Use different Render and Log Update Rates false Render Update Rate [fps] Qt::Horizontal 40 20 false 0 100 10 false Log Update Rate [per second] Qt::Horizontal 40 20 false 1 120 10 60 Tracking Volume Options true Show Tracking Volume true Select Model: Open IGT Link Enable Open IGT Link MicroService true Select Open IGT Link Data Format: TRANSFORM QTDATA TDATA POSITION Other Options Show Tool Quaternions - + Simple UI Caution, only for backward compatibility: Inverse mode (Quaternions are stored inverse) + + + + Tool Visualization Options + + + + + + true + + + Show Tool Projection + + + + + + + false + + + Show Tool Axis + + + + + + Qt::Vertical 20 600 Logging Filename: Choose File Limit Number Of Logged Frames: Qt::Horizontal 40 20 1 9999 300 - + CSV format true - + XML format Skip invalid data Logging Status Logging OFF Logged Frames: 0 Qt::Horizontal 40 20 Start Logging Stop Logging Qt::Vertical 20 40 70 50 Connect 70 50 Start Tracking Qt::Horizontal 40 20 70 50 Advanced Mode Qt::Vertical 20 40 - QmitkTrackingDeviceConfigurationWidget + QmitkToolTrackingStatusWidget QWidget -
QmitkTrackingDeviceConfigurationWidget.h
+
QmitkToolTrackingStatusWidget.h
1
- QmitkToolTrackingStatusWidget + QmitkTrackingDeviceConfigurationWidget QWidget -
QmitkToolTrackingStatusWidget.h
+
QmitkTrackingDeviceConfigurationWidget.h
1
QmitkNavigationToolCreationWidget QWidget
QmitkNavigationToolCreationWidget.h
1
diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewWorker.cpp b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewWorker.cpp index dd9db054c4..0d1b858a06 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewWorker.cpp +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewWorker.cpp @@ -1,250 +1,250 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Qmitk #include "QmitkMITKIGTTrackingToolboxViewWorker.h" #include QmitkMITKIGTTrackingToolboxViewWorker::QmitkMITKIGTTrackingToolboxViewWorker() { } QmitkMITKIGTTrackingToolboxViewWorker::~QmitkMITKIGTTrackingToolboxViewWorker() { } void QmitkMITKIGTTrackingToolboxViewWorker::SetWorkerMethod(WorkerMethod w) { m_WorkerMethod = w; } void QmitkMITKIGTTrackingToolboxViewWorker::SetTrackingDevice(mitk::TrackingDevice::Pointer t) { m_TrackingDevice = t; } void QmitkMITKIGTTrackingToolboxViewWorker::SetDataStorage(mitk::DataStorage::Pointer d) { m_DataStorage = d; } void QmitkMITKIGTTrackingToolboxViewWorker::SetInverseMode(bool mode) { m_InverseMode = mode; } void QmitkMITKIGTTrackingToolboxViewWorker::SetTrackingDeviceData(mitk::TrackingDeviceData d) { m_TrackingDeviceData = d; } void QmitkMITKIGTTrackingToolboxViewWorker::SetNavigationToolStorage(mitk::NavigationToolStorage::Pointer n) { m_NavigationToolStorage = n; } //! [Thread 7] void QmitkMITKIGTTrackingToolboxViewWorker::ThreadFunc() { switch (m_WorkerMethod) { case eAutoDetectTools: this->AutoDetectTools(); break; case eConnectDevice: this->ConnectDevice(); break; case eStartTracking: this->StartTracking(); break; case eStopTracking: this->StopTracking(); break; case eDisconnectDevice: this->DisconnectDevice(); break; default: MITK_WARN << "Undefined worker method was set ... something went wrong!"; break; } } //! [Thread 7] void QmitkMITKIGTTrackingToolboxViewWorker::AutoDetectTools() { mitk::NavigationToolStorage::Pointer autoDetectedStorage = mitk::NavigationToolStorage::New(m_DataStorage); try { mitk::NavigationToolStorage::Pointer tempStorage = m_TrackingDevice->AutoDetectTools(); for (int i = 0; i < tempStorage->GetToolCount(); i++) { autoDetectedStorage->AddTool(tempStorage->GetTool(i)); } } catch (mitk::Exception& e) { MITK_WARN << e.GetDescription(); emit AutoDetectToolsFinished(false, e.GetDescription()); return; } m_NavigationToolStorage = nullptr; m_NavigationToolStorage = autoDetectedStorage; emit AutoDetectToolsFinished(true, ""); MITK_INFO << "AutoDetect Tools Finished."; } void QmitkMITKIGTTrackingToolboxViewWorker::ConnectDevice() { std::string message = ""; //build the IGT pipeline mitk::TrackingDevice::Pointer trackingDevice = m_TrackingDevice; trackingDevice->SetData(m_TrackingDeviceData); //set device to rotation mode transposed becaus we are working with VNL style quaternions if (m_InverseMode) { trackingDevice->SetRotationMode(mitk::TrackingDevice::RotationTransposed); } //Get Tracking Volume Data mitk::TrackingDeviceData data = m_TrackingDeviceData; //Create Navigation Data Source with the factory class mitk::TrackingDeviceSourceConfigurator::Pointer myTrackingDeviceSourceFactory = mitk::TrackingDeviceSourceConfigurator::New(m_NavigationToolStorage, trackingDevice); m_TrackingDeviceSource = myTrackingDeviceSourceFactory->CreateTrackingDeviceSource(m_ToolVisualizationFilter); if (m_TrackingDeviceSource.IsNull()) { message = std::string("Cannot connect to device: ") + myTrackingDeviceSourceFactory->GetErrorMessage(); emit ConnectDeviceFinished(false, QString(message.c_str())); return; } //set filter to rotation mode transposed becaus we are working with VNL style quaternions if (m_InverseMode) m_ToolVisualizationFilter->SetRotationMode(mitk::NavigationDataObjectVisualizationFilter::RotationTransposed); //First check if the created object is valid if (m_TrackingDeviceSource.IsNull()) { message = myTrackingDeviceSourceFactory->GetErrorMessage(); emit ConnectDeviceFinished(false, QString(message.c_str())); return; } MITK_INFO << "Connected device with " << m_TrackingDeviceSource->GetNumberOfOutputs() << " tools."; //connect to device try { m_TrackingDeviceSource->Connect(); //Microservice registration: m_TrackingDeviceSource->RegisterAsMicroservice(); - + m_NavigationToolStorage->SetSourceID(m_TrackingDeviceSource->GetMicroserviceID()); m_NavigationToolStorage->LockStorage(); } catch (...) //todo: change to mitk::IGTException { message = "Error on connecting the tracking device."; emit ConnectDeviceFinished(false, QString(message.c_str())); return; } emit ConnectDeviceFinished(true, QString(message.c_str())); } mitk::TrackingDeviceSource::Pointer QmitkMITKIGTTrackingToolboxViewWorker::GetTrackingDeviceSource() { return this->m_TrackingDeviceSource; } void QmitkMITKIGTTrackingToolboxViewWorker::StartTracking() { QString errorMessage = ""; try { m_TrackingDeviceSource->StartTracking(); } catch (...) //todo: change to mitk::IGTException { errorMessage += "Error while starting the tracking device!"; emit StartTrackingFinished(false, errorMessage); return; } //remember the original colors of the tools m_OriginalColors = std::map(); for (int i = 0; i < this->m_NavigationToolStorage->GetToolCount(); i++) { mitk::DataNode::Pointer currentToolNode = m_NavigationToolStorage->GetTool(i)->GetDataNode(); float c[3]; currentToolNode->GetColor(c); mitk::Color color; color.SetRed(c[0]); color.SetGreen(c[1]); color.SetBlue(c[2]); m_OriginalColors[currentToolNode] = color; } emit StartTrackingFinished(true, errorMessage); } void QmitkMITKIGTTrackingToolboxViewWorker::StopTracking() { //stop tracking try { m_TrackingDeviceSource->StopTracking(); } catch (mitk::Exception& e) { emit StopTrackingFinished(false, e.GetDescription()); } //restore the original colors of the tools for (int i = 0; i < this->m_NavigationToolStorage->GetToolCount(); i++) { mitk::DataNode::Pointer currentToolNode = m_NavigationToolStorage->GetTool(i)->GetDataNode(); if (m_OriginalColors.find(currentToolNode) == m_OriginalColors.end()) { MITK_WARN << "Cannot restore original color of tool " << m_NavigationToolStorage->GetTool(i)->GetToolName(); } else { currentToolNode->SetColor(m_OriginalColors[currentToolNode]); } } //emit signal emit StopTrackingFinished(true, ""); } void QmitkMITKIGTTrackingToolboxViewWorker::DisconnectDevice() { try { if (m_TrackingDeviceSource->IsTracking()) { m_TrackingDeviceSource->StopTracking(); } m_TrackingDeviceSource->Disconnect(); m_TrackingDeviceSource->UnRegisterMicroservice(); m_NavigationToolStorage->UnLockStorage(); m_TrackingDeviceSource = nullptr; } catch (mitk::Exception& e) { emit DisconnectDeviceFinished(false, e.GetDescription()); } emit DisconnectDeviceFinished(true, ""); } \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.cpp b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.cpp index 6a3b71d04d..0d9f85a552 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.cpp +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.cpp @@ -1,240 +1,240 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // 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( 0 ) { } 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(0, "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->SetTrackingTool(dummyTool.GetPointer()); currentDummyTool->SetDataNode(m_RenderingNodes.at(i)); currentDummyTool->SetIdentifier(name.str()); m_ToolStorage->AddTool(currentDummyTool); } m_Player->RegisterAsMicroservice(); m_ToolStorage->SetName("NavigationDataPlayer Tool Storage"); - m_ToolStorage->RegisterAsMicroservice(m_Player->GetMicroserviceID()); + m_ToolStorage->SetSourceID(m_Player->GetMicroserviceID()); + 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(); vtkSphereSource *vtkData = vtkSphereSource::New(); vtkData->SetRadius(5.0f); vtkData->SetCenter(0.0, 0.0, 0.0); vtkData->Update(); mySphere->SetVtkPolyData(vtkData->GetOutput()); vtkData->Delete(); node->SetData(mySphere); m_VisFilter->SetRepresentationObject(i, mySphere); // Add Node to DataStorageand to local list of Nodes GetDataStorage()->Add(node); m_RenderingNodes.push_back(node); } m_VisFilter->Update(); 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); }