diff --git a/Modules/IGT/IGTFilters/mitkNavigationDataObjectVisualizationFilter.cpp b/Modules/IGT/IGTFilters/mitkNavigationDataObjectVisualizationFilter.cpp index bcba74ba68..99c9f594d3 100644 --- a/Modules/IGT/IGTFilters/mitkNavigationDataObjectVisualizationFilter.cpp +++ b/Modules/IGT/IGTFilters/mitkNavigationDataObjectVisualizationFilter.cpp @@ -1,266 +1,266 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkNavigationDataObjectVisualizationFilter.h" #include "mitkDataStorage.h" mitk::NavigationDataObjectVisualizationFilter::NavigationDataObjectVisualizationFilter() : NavigationDataToNavigationDataFilter(), m_RepresentationList(), m_TransformPosition(), m_TransformOrientation(), m_RotationMode(RotationStandard) { } mitk::NavigationDataObjectVisualizationFilter::~NavigationDataObjectVisualizationFilter() { m_RepresentationList.clear(); m_OffsetList.clear(); } const mitk::BaseData* mitk::NavigationDataObjectVisualizationFilter::GetRepresentationObject(unsigned int idx) { //if (idx >= this->GetNumberOfInputs()) // return NULL; //const NavigationData* nd = this->GetInput(idx); //if (nd == NULL) // return NULL; RepresentationPointerMap::const_iterator iter = m_RepresentationList.find(idx); if (iter != m_RepresentationList.end()) return iter->second; return NULL; } mitk::AffineTransform3D::Pointer mitk::NavigationDataObjectVisualizationFilter::GetOffset(int index) { OffsetPointerMap::const_iterator iter = m_OffsetList.find(index); if (iter != m_OffsetList.end()) return iter->second; return NULL; } void mitk::NavigationDataObjectVisualizationFilter::SetRepresentationObject(unsigned int idx, BaseData* data) { //if (idx >= this->GetNumberOfInputs()) // return false; //const NavigationData* nd = this->GetInput(idx); //if (nd == NULL || data == NULL) // return false; m_RepresentationList[idx] = RepresentationPointer(data); //std::pair returnEl; //pair for returning the result //returnEl = m_RepresentationList.insert( RepresentationPointerMap::value_type(nd, data) ); //insert the given elements //return returnEl.second; // return if insert was successful } void mitk::NavigationDataObjectVisualizationFilter::SetOffset(int index, mitk::AffineTransform3D::Pointer offset) { m_OffsetList[index] = offset; } void mitk::NavigationDataObjectVisualizationFilter::SetRotationMode(RotationMode r) { m_RotationMode = r; } void mitk::NavigationDataObjectVisualizationFilter::GenerateData() { /*get each input, lookup the associated BaseData and transfer the data*/ DataObjectPointerArray inputs = this->GetInputs(); //get all inputs for (unsigned int index=0; index < inputs.size(); index++) { //get the needed variables const mitk::NavigationData* nd = this->GetInput(index); assert(nd); mitk::NavigationData* output = this->GetOutput(index); assert(output); //check if the data is valid if (!nd->IsDataValid()) { output->SetDataValid(false); continue; } output->Graft(nd); // copy all information from input to output const mitk::BaseData* data = this->GetRepresentationObject(index); if (data == NULL) { itkWarningMacro("NavigationDataObjectVisualizationFilter: Wrong/No BaseData associated with input."); return; } //get the transform from data mitk::AffineTransform3D::Pointer affineTransform = data->GetGeometry()->GetIndexToWorldTransform(); if (affineTransform.IsNull()) { //replace with mitk standard output itkWarningMacro("NavigationDataObjectVisualizationFilter: AffineTransform IndexToWorldTransform not initialized!"); return; } //check for offset mitk::AffineTransform3D::Pointer offset = this->GetOffset(index); //store the current scaling to set it after transformation mitk::Vector3D spacing = data->GetGeometry()->GetSpacing(); //clear spacing of data to be able to set it again afterwards ScalarType scale[] = {1.0, 1.0, 1.0}; data->GetGeometry()->SetSpacing(scale); /*now bring quaternion to affineTransform by using vnl_Quaternion*/ affineTransform->SetIdentity(); if (this->GetTransformOrientation(index) == true) { mitk::NavigationData::OrientationType orientation = nd->GetOrientation(); /* because of an itk bug, the transform can not be calculated with float data type. To use it in the mitk geometry classes, it has to be transfered to mitk::ScalarType which is float */ static AffineTransform3D::MatrixType m; //convert quaternion to rotation matrix depending on the rotation mode if(m_RotationMode == RotationStandard) { //calculate the transform from the quaternions static itk::QuaternionRigidTransform::Pointer quatTransform = itk::QuaternionRigidTransform::New(); // convert mitk::ScalarType quaternion to double quaternion because of itk bug vnl_quaternion doubleQuaternion(orientation.x(), orientation.y(), orientation.z(), orientation.r()); quatTransform->SetIdentity(); quatTransform->SetRotation(doubleQuaternion); quatTransform->Modified(); mitk::TransferMatrix(quatTransform->GetMatrix(), m); } else if(m_RotationMode == RotationTransposed) { - vnl_matrix_fixed rot = orientation.rotation_matrix_transpose(); + vnl_matrix_fixed rot = orientation.rotation_matrix_transpose(); for(int i=0; i<3; i++) for (int j=0; j<3; j++) m[i][j] = rot[i][j]; } affineTransform->SetMatrix(m); } if (this->GetTransformPosition(index) == true) { ///*set the offset by convert from itkPoint to itkVector and setting offset of transform*/ mitk::Vector3D pos; pos.Set_vnl_vector(nd->GetPosition().Get_vnl_vector()); affineTransform->SetOffset(pos); } affineTransform->Modified(); //set the transform to data if(offset.IsNotNull()) //first use offset if there is one. { mitk::AffineTransform3D::Pointer overallTransform = mitk::AffineTransform3D::New(); overallTransform->SetIdentity(); overallTransform->Compose(offset); overallTransform->Compose(affineTransform); data->GetGeometry()->SetIndexToWorldTransform(overallTransform); } else { data->GetGeometry()->SetIndexToWorldTransform(affineTransform); } //set the original spacing to keep scaling of the geometrical object data->GetGeometry()->SetSpacing(spacing); data->GetGeometry()->TransferItkToVtkTransform(); // update VTK Transform for rendering too data->GetGeometry()->Modified(); data->Modified(); output->SetDataValid(true); // operation was successful, therefore data of output is valid. } } void mitk::NavigationDataObjectVisualizationFilter::SetTransformPosition( unsigned int index, bool applyTransform ) { itkDebugMacro("setting TransformPosition for index " << index << " to " << applyTransform); BooleanInputMap::const_iterator it = this->m_TransformPosition.find(index); if ((it != this->m_TransformPosition.end()) && (it->second == applyTransform)) return; this->m_TransformPosition[index] = applyTransform; this->Modified(); } bool mitk::NavigationDataObjectVisualizationFilter::GetTransformPosition( unsigned int index ) const { itkDebugMacro("returning TransformPosition for index " << index); BooleanInputMap::const_iterator it = this->m_TransformPosition.find(index); if (it != this->m_TransformPosition.end()) return it->second; else return true; // default to true } void mitk::NavigationDataObjectVisualizationFilter::TransformPositionOn( unsigned int index ) { this->SetTransformPosition(index, true); } void mitk::NavigationDataObjectVisualizationFilter::TransformPositionOff( unsigned int index ) { this->SetTransformPosition(index, false); } void mitk::NavigationDataObjectVisualizationFilter::SetTransformOrientation( unsigned int index, bool applyTransform ) { itkDebugMacro("setting TransformOrientation for index " << index << " to " << applyTransform); BooleanInputMap::const_iterator it = this->m_TransformOrientation.find(index); if ((it != this->m_TransformOrientation.end()) && (it->second == applyTransform)) return; this->m_TransformOrientation[index] = applyTransform; this->Modified(); \ } bool mitk::NavigationDataObjectVisualizationFilter::GetTransformOrientation( unsigned int index ) const { itkDebugMacro("returning TransformOrientation for index " << index); BooleanInputMap::const_iterator it = this->m_TransformOrientation.find(index); if (it != this->m_TransformOrientation.end()) return it->second; else return true; // default to true } void mitk::NavigationDataObjectVisualizationFilter::TransformOrientationOn( unsigned int index ) { this->SetTransformOrientation(index, true); } void mitk::NavigationDataObjectVisualizationFilter::TransformOrientationOff( unsigned int index ) { this->SetTransformOrientation(index, false); } 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 af866e01e5..b238b31c9e 100644 --- a/Plugins/org.mitk.gui.qt.igtexamples/src/internal/QmitkIGTTrackingLabView.cpp +++ b/Plugins/org.mitk.gui.qt.igtexamples/src/internal/QmitkIGTTrackingLabView.cpp @@ -1,898 +1,898 @@ /*=================================================================== 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 "QmitkStdMultiWidget.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Qt #include #include // vtk #include const std::string QmitkIGTTrackingLabView::VIEW_ID = "org.mitk.views.igttrackinglab"; QmitkIGTTrackingLabView::QmitkIGTTrackingLabView() : QmitkFunctionality() ,m_Source(NULL) ,m_PermanentRegistrationFilter(NULL) ,m_Visualizer(NULL) ,m_VirtualView(NULL) ,m_PSRecordingPointSet(NULL) ,m_RegistrationTrackingFiducialsName("Tracking Fiducials") ,m_RegistrationImageFiducialsName("Image Fiducials") ,m_PointSetRecordingDataNodeName("Recorded Points") ,m_PointSetRecording(false) ,m_PermanentRegistration(false) ,m_CameraView(false) ,m_ImageFiducialsDataNode(NULL) ,m_TrackerFiducialsDataNode(NULL) ,m_PermanentRegistrationSourcePoints(NULL) { //[-1;0;0] for WOLF_6D bronchoscope m_DirectionOfProjectionVector[0]=0; m_DirectionOfProjectionVector[1]=0; m_DirectionOfProjectionVector[2]=-1;} 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 ); m_ToolBox = m_Controls.m_ToolBox; this->CreateBundleWidgets( parent ); this->CreateConnections(); } void QmitkIGTTrackingLabView::CreateBundleWidgets( QWidget* parent ) { //initialize registration widget m_RegistrationWidget = m_Controls.m_RegistrationWidget; m_RegistrationWidget->HideStaticRegistrationRadioButton(true); m_RegistrationWidget->HideContinousRegistrationRadioButton(true); m_RegistrationWidget->HideUseICPRegistrationCheckbox(true); } void QmitkIGTTrackingLabView::CreateConnections() { m_Timer = new QTimer(this); connect(m_Timer, SIGNAL(timeout()), this, SLOT(UpdateTimer())); connect( m_ToolBox, SIGNAL(currentChanged(int)), this, SLOT(OnToolBoxCurrentChanged(int)) ); 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_RegistrationWidget, SIGNAL(AddedTrackingFiducial()), this, SLOT(OnAddRegistrationTrackingFiducial()) ); connect( m_RegistrationWidget, SIGNAL(PerformFiducialRegistration()), this, SLOT(OnRegisterFiducials()) ); 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::UpdateTimer() { if (m_PermanentRegistration && m_PermanentRegistrationFilter.IsNotNull()) { mitk::Transform::Pointer ObjectMarkerCurrentTransform = mitk::Transform::New(m_ObjectmarkerNavigationData); if(IsTransformDifferenceHigh(ObjectMarkerCurrentTransform, m_ObjectmarkerNavigationDataLastUpdate)) { m_ObjectmarkerNavigationDataLastUpdate = mitk::Transform::New(m_ObjectmarkerNavigationData); m_PermanentRegistrationFilter->Update(); //if(m_Controls.m_SurfaceActive->isChecked()) //{ // mitk::Transform::Pointer newTransform = mitk::Transform::New(); // newTransform->Concatenate(m_T_MarkerRel); // newTransform->Concatenate(ObjectMarkerCurrentTransform); // this->m_Controls.m_ObjectComboBox->GetSelectedNode()->GetData()->GetGeometry()->SetIndexToWorldTransform(newTransform->GetAffineTransform3D()); //} //if(m_Controls.m_ImageActive->isChecked()) //{ // mitk::AffineTransform3D::Pointer newTransform = mitk::AffineTransform3D::New(); // newTransform->SetIdentity(); // newTransform->Compose(m_T_ImageGeo); // newTransform->Compose(m_T_MarkerRel->GetAffineTransform3D()); // newTransform->Compose(ObjectMarkerCurrentTransform->GetAffineTransform3D()); // this->m_Controls.m_ImageComboBox->GetSelectedNode()->GetData()->GetGeometry()->SetIndexToWorldTransform(newTransform); //} } } 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()); } } 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() != NULL) { mitk::PointSet::Pointer ps = dynamic_cast(m_TrackerFiducialsDataNode->GetData()); ps->InsertPoint(ps->GetSize(), nd->GetPosition()); } else QMessageBox::warning(NULL, "IGTSurfaceTracker: Error", "Can not access Tracker Fiducials. Adding fiducial not possible!"); } 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()); } 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(""); } } void QmitkIGTTrackingLabView::OnSetupNavigation() { MITK_INFO << "SetupNavigationCalled"; if(m_Source.IsNotNull()) if(m_Source->IsTracking()) return; mitk::DataStorage* ds = this->GetDefaultDataStorage(); if(ds == NULL) { QMessageBox::warning(NULL, "IGTSurfaceTracker: Error", "can not access DataStorage. Navigation not possible"); return; } // Building up the filter pipeline try { this->SetupIGTPipeline(); } catch(std::exception& e) { QMessageBox::warning(NULL, QString("IGTSurfaceTracker: Error"), QString("Error while building the IGT-Pipeline: %1").arg(e.what())); this->DestroyIGTPipeline(); // destroy the pipeline if building is incomplete return; } catch(...) { QMessageBox::warning(NULL, QString("IGTSurfaceTracker: Error"), QString("Error while building the IGT-Pipeline")); this->DestroyIGTPipeline(); return; } } void QmitkIGTTrackingLabView::SetupIGTPipeline() { this->InitializeRegistration(); //initializes the registration widget } void QmitkIGTTrackingLabView::InitializeFilters() { } void QmitkIGTTrackingLabView::OnRegisterFiducials() { //Check for initialization if (!CheckRegistrationInitialization()) return; /* retrieve fiducials from data storage */ mitk::DataStorage* ds = this->GetDefaultDataStorage(); mitk::PointSet::Pointer imageFiducials = dynamic_cast(m_ImageFiducialsDataNode->GetData()); mitk::PointSet::Pointer trackerFiducials = dynamic_cast(m_TrackerFiducialsDataNode->GetData()); //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); } //compute transform vtkSmartPointer transform = vtkSmartPointer::New(); transform->SetSourceLandmarks(sourcePoints); transform->SetTargetLandmarks(targetPoints); transform->SetModeToRigidBody(); transform->Modified(); transform->Update(); //compute FRE double FRE = 0; for(unsigned int i = 0; i < imageFiducials->GetSize(); i++) { itk::Point transformed = transform->TransformPoint(imageFiducials->GetPoint(i)[0],imageFiducials->GetPoint(i)[1],imageFiducials->GetPoint(i)[2]); double cur_error_squared = transformed.SquaredEuclideanDistanceTo(trackerFiducials->GetPoint(i)); FRE += cur_error_squared; } FRE = sqrt(FRE/ (double) imageFiducials->GetSize()); m_Controls.m_RegistrationWidget->SetQualityDisplayText("FRE: " + QString::number(FRE) + " mm"); //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); } /*MITK_INFO << "MATRIX: "; for(int k=0; k<=3; k++) { MITK_INFO << m->GetElement(k,0) << " " << m->GetElement(k,1) << " " << m->GetElement(k,2) << " " << m->GetElement(k,3); }*/ //save transform m_T_ObjectReg = mitk::Transform::New(); m_T_ObjectReg->SetMatrix(m); //transform surface mitk::AffineTransform3D::Pointer newTransform = mitk::AffineTransform3D::New(); - newTransform->SetMatrix(rotationFloat); - newTransform->SetOffset(translationFloat); + newTransform->SetMatrix(rotationDouble); + newTransform->SetOffset(translationDouble); //transform surface if(m_Controls.m_SurfaceActive->isChecked() && m_Controls.m_ObjectComboBox->GetSelectedNode().IsNotNull()) { m_Controls.m_ObjectComboBox->GetSelectedNode()->GetData()->GetGeometry()->SetIndexToWorldTransform(newTransform); } //transform ct image if(m_Controls.m_ImageActive->isChecked() && m_Controls.m_ImageComboBox->GetSelectedNode().IsNotNull()) { mitk::AffineTransform3D::Pointer imageTransform = m_Controls.m_ImageComboBox->GetSelectedNode()->GetData()->GetGeometry()->GetIndexToWorldTransform(); m_T_ImageGeo = mitk::AffineTransform3D::New(); m_T_ImageGeo->Compose(imageTransform); imageTransform->Compose(newTransform); 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(); + 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::DestroyIGTPipeline() { if(m_Source.IsNotNull()) { m_Source->StopTracking(); m_Source->Disconnect(); m_Source = NULL; } m_PermanentRegistrationFilter = NULL; m_Visualizer = NULL; m_VirtualView = NULL; } void QmitkIGTTrackingLabView::InitializeRegistration() { mitk::DataStorage* ds = this->GetDefaultDataStorage(); if( ds == NULL ) return; m_RegistrationWidget->SetMultiWidget(this->GetActiveStdMultiWidget()); // passing multiwidget to pointsetwidget 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(m_RegistrationImageFiducialsName); m_ImageFiducialsDataNode->SetColor(color); m_ImageFiducialsDataNode->SetBoolProperty( "updateDataOnRender", false ); ds->Add(m_ImageFiducialsDataNode); } m_RegistrationWidget->SetMultiWidget(this->GetActiveStdMultiWidget()); 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(m_RegistrationTrackingFiducialsName); m_TrackerFiducialsDataNode->SetColor(color); m_TrackerFiducialsDataNode->SetBoolProperty( "updateDataOnRender", false ); ds->Add(m_TrackerFiducialsDataNode); } m_RegistrationWidget->SetTrackerFiducialsNode(m_TrackerFiducialsDataNode); } void QmitkIGTTrackingLabView::OnToolBoxCurrentChanged(const int index) { switch (index) { case RegistrationWidget: this->InitializeRegistration(); break; default: break; } } mitk::DataNode::Pointer QmitkIGTTrackingLabView::CreateRegistrationFiducialsNode( const std::string& label, const mitk::Color& color) { mitk::DataNode::Pointer fiducialsNode = mitk::DataNode::New(); mitk::PointSet::Pointer fiducialsPointSet = mitk::PointSet::New(); fiducialsNode->SetData(fiducialsPointSet); fiducialsNode->SetName( label ); fiducialsNode->SetColor( color ); fiducialsNode->SetBoolProperty( "updateDataOnRender", false ); return fiducialsNode; } void QmitkIGTTrackingLabView::ChangeToolRepresentation( int toolID , mitk::Surface::Pointer surface ) { mitk::DataStorage* ds = this->GetDefaultDataStorage(); if(ds == NULL) { QMessageBox::warning(NULL, "IGTSurfaceTracker: Error", "Can not access DataStorage. Changing tool representation not possible!"); return; } mitk::TrackingDevice::Pointer tracker = m_NDIConfigWidget->GetTracker(); if(tracker.IsNull()) { QMessageBox::warning(NULL, "IGTSurfaceTracker: Error", "Can not access Tracker. Changing tool representation not possible!"); return; } try { const char* name = tracker->GetTool(toolID)->GetToolName(); // get tool name by id mitk::DataNode::Pointer toolNode = ds->GetNamedNode(name); if(toolNode.IsNull()) return; toolNode->SetData(surface); // change surface representation of node toolNode->SetColor(0.45,0.70,0.85); //light blue like old 5D sensors toolNode->Modified(); m_Visualizer->SetRepresentationObject( toolID, toolNode->GetData()); // updating node with changed surface back in visualizer mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } catch(std::exception& e) { QMessageBox::warning(NULL, QString("IGTSurfaceTracker: Error"), QString("Can not change tool representation!").arg(e.what())); return; } } void QmitkIGTTrackingLabView::OnPointSetRecording(bool record) { mitk::DataStorage* ds = this->GetDefaultDataStorage(); if(record) { if (m_Controls.m_PointSetRecordingToolSelectionWidget->GetSelectedToolID() == -1) { QMessageBox::warning(NULL, "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(m_PointSetRecordingDataNodeName); if(m_PSRecordingPointSet.IsNull() || psRecND.IsNull()) { m_PSRecordingPointSet = NULL; m_PSRecordingPointSet = mitk::PointSet::New(); mitk::DataNode::Pointer dn = mitk::DataNode::New(); dn->SetName(m_PointSetRecordingDataNodeName); dn->SetColor(0.,1.,0.); dn->SetData(m_PSRecordingPointSet); ds->Add(dn); } else { m_PSRecordingPointSet->Clear(); } m_PointSetRecording = true; } else { m_PointSetRecording = false; } } /*void QmitkIGTTrackingLabView::GlobalReinit() { // request global reiinit mitk::NodePredicateNot::Pointer pred = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("includeInBoundingBox", mitk::BoolProperty::New(false))); mitk::DataStorage::SetOfObjects::ConstPointer rs = this->GetDataStorage()->GetSubset(pred); // calculate bounding geometry of these nodes mitk::TimeSlicedGeometry::Pointer bounds = this->GetDataStorage()->ComputeBoundingGeometry3D(rs, "visible"); // initialize the views to the bounding geometry mitk::RenderingManager::GetInstance()->InitializeViews(bounds); //global reinit end }*/ void QmitkIGTTrackingLabView::OnVirtualCamera(bool on) { if (m_Controls.m_CameraViewSelection->GetSelectedToolID() == -1) { m_Controls.m_ActivateNeedleView->setChecked(false); QMessageBox::warning(NULL, "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->GetActiveStdMultiWidget()->GetRenderWindow4()->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 = NULL; m_CameraView = false; m_Controls.m_CameraViewSelection->GetSelectedNavigationTool()->GetDataNode()->SetBoolProperty("visible",true); m_Controls.m_ViewDirectionBox->setEnabled(true); m_Controls.m_ViewUpBox->setEnabled(true); } } bool QmitkIGTTrackingLabView::CheckRegistrationInitialization() { mitk::DataStorage* ds = this->GetDefaultDataStorage(); mitk::PointSet::Pointer imageFiducials = dynamic_cast(m_ImageFiducialsDataNode->GetData()); mitk::PointSet::Pointer trackerFiducials = dynamic_cast(m_TrackerFiducialsDataNode->GetData()); if (m_Controls.m_SurfaceActive->isChecked() && m_Controls.m_ObjectComboBox->GetSelectedNode().IsNull()) { std::string warningMessage = "No surface selected for registration.\nRegistration is not possible"; MITK_WARN << warningMessage; QMessageBox::warning(NULL, "Registration not possible", warningMessage.c_str()); return false; } if (m_Controls.m_ImageActive->isChecked() && m_Controls.m_ImageComboBox->GetSelectedNode().IsNull()) { std::string warningMessage = "No image selected for registration.\nRegistration is not possible"; MITK_WARN << warningMessage; QMessageBox::warning(NULL, "Registration not possible", warningMessage.c_str()); return false; } if (imageFiducials.IsNull() || trackerFiducials.IsNull()) { std::string 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"; MITK_WARN << warningMessage; QMessageBox::warning(NULL, "Registration not possible", warningMessage.c_str()); return false; } unsigned int minFiducialCount = 3; // \Todo: move to view option if ((imageFiducials->GetSize() < minFiducialCount) || (trackerFiducials->GetSize() < minFiducialCount) || (imageFiducials->GetSize() != trackerFiducials->GetSize())) { QMessageBox::warning(NULL, "Registration not possible", QString("Not enough fiducial pairs found. At least %1 fiducial must " "exist for the image and the tracking system respectively.\n" "Currently, %2 fiducials exist for the image, %3 fiducials exist for the tracking system").arg(minFiducialCount).arg(imageFiducials->GetSize()).arg(trackerFiducials->GetSize())); return false; } return true; } bool QmitkIGTTrackingLabView::IsTransformDifferenceHigh(mitk::Transform::Pointer transformA, mitk::Transform::Pointer transformB) { double euclideanDistanceThreshold = .8; double angularDifferenceThreshold = .8; 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; } void QmitkIGTTrackingLabView::OnPermanentRegistration(bool on) { if(on) { if(!CheckRegistrationInitialization()) { m_Controls.m_UsePermanentRegistrationToggle->setChecked(false); return; } //remember initial object transform to calculate the object to marker transform later on mitk::AffineTransform3D::Pointer transform = this->m_Controls.m_ObjectComboBox->GetSelectedNode()->GetData()->GetGeometry()->GetIndexToWorldTransform(); vnl_matrix_fixed rotation = vnl_matrix_fixed(); rotation[0][0] = transform->GetMatrix().GetVnlMatrix()[0][0]; rotation[0][1] = transform->GetMatrix().GetVnlMatrix()[0][1]; rotation[0][2] = transform->GetMatrix().GetVnlMatrix()[0][2]; rotation[1][0] = transform->GetMatrix().GetVnlMatrix()[1][0]; rotation[1][1] = transform->GetMatrix().GetVnlMatrix()[1][1]; rotation[1][2] = transform->GetMatrix().GetVnlMatrix()[1][2]; rotation[2][0] = transform->GetMatrix().GetVnlMatrix()[2][0]; rotation[2][1] = transform->GetMatrix().GetVnlMatrix()[2][1]; rotation[2][2] = transform->GetMatrix().GetVnlMatrix()[2][2]; mitk::Point3D translation; translation[0] = transform->GetOffset()[0]; translation[1] = transform->GetOffset()[1]; translation[2] = transform->GetOffset()[2]; mitk::Transform::Pointer T_Object = mitk::Transform::New(); T_Object->SetPosition(translation); T_Object->SetRotation(rotation); //then reset the transform because we will now start to calculate the permenent 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(); //set to rotation mode transposed because we are working with VNL style quaternions m_PermanentRegistrationFilter->SetRotationMode(mitk::NavigationDataObjectVisualizationFilter::RotationTransposed); //first: 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::Transform::Pointer T_Marker = mitk::Transform::New(this->m_ObjectmarkerNavigationData); //compute transform from object to marker mitk::Transform::Pointer T_MarkerRel = mitk::Transform::New(); T_MarkerRel->Concatenate(T_Object); T_Marker->Invert(); T_MarkerRel->Concatenate(T_Marker); m_T_MarkerRel = T_MarkerRel; //TODO: remove mitk::transform from this class and use only mitk::AffineTransform3D //convert to AffineTransform3D mitk::AffineTransform3D::Pointer T_MarkerRel_conv = mitk::AffineTransform3D::New(); { - itk::Matrix rotation = itk::Matrix(); + itk::Matrix rotation = itk::Matrix(); for(int i = 0; i<3; i++)for (int j=0; j<3; j ++) rotation[i][j] = T_MarkerRel->GetVnlRotationMatrix()[i][j]; - itk::Vector translation = itk::Vector(); + itk::Vector translation = itk::Vector(); for(int i = 0; i<3; i++) translation[i] = T_MarkerRel->GetPosition()[i]; T_MarkerRel_conv->SetMatrix(rotation); T_MarkerRel_conv->SetOffset(translation); } m_PermanentRegistrationFilter->SetOffset(0,T_MarkerRel_conv); //first: image (if activated) //set interpolation mode 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()); mitk::AffineTransform3D::Pointer newTransform = mitk::AffineTransform3D::New(); newTransform->SetIdentity(); newTransform->Compose(m_T_ImageGeo); newTransform->Compose(T_MarkerRel_conv); m_PermanentRegistrationFilter->SetOffset(1,newTransform); } //some general stuff m_PermanentRegistration = true; m_ObjectmarkerNavigationDataLastUpdate = mitk::Transform::New(); } else { //stop permanent registration m_PermanentRegistration = false; //restore old registration if(m_T_ObjectReg.IsNotNull()) { //convert to AffineTransform3D //TODO: remove mitk::transform from this class and use only mitk::AffineTransform3D mitk::AffineTransform3D::Pointer m_T_ObjectReg_conv = mitk::AffineTransform3D::New(); - itk::Matrix rotation = itk::Matrix(); + itk::Matrix rotation = itk::Matrix(); for(int i = 0; i<3; i++)for (int j=0; j<3; j ++) rotation[i][j] = m_T_ObjectReg->GetVnlRotationMatrix()[i][j]; - itk::Vector translation = itk::Vector(); + itk::Vector translation = itk::Vector(); for(int i = 0; i<3; i++) translation[i] = m_T_ObjectReg->GetPosition()[i]; m_T_ObjectReg_conv->SetMatrix(rotation); m_T_ObjectReg_conv->SetOffset(translation); this->m_Controls.m_ObjectComboBox->GetSelectedNode()->GetData()->GetGeometry()->SetIndexToWorldTransform(m_T_ObjectReg_conv); } if(m_T_ImageReg.IsNotNull()) this->m_Controls.m_ImageComboBox->GetSelectedNode()->GetData()->GetGeometry()->SetIndexToWorldTransform(m_T_ImageReg); //delete filter m_PermanentRegistrationFilter = NULL; } } mitk::PointSet::Pointer QmitkIGTTrackingLabView::GetVirtualPointSetFromPosition(mitk::NavigationData::Pointer navigationData) { typedef itk::QuaternionRigidTransform QuaternionTransformType; mitk::NavigationData::PositionType pointA; mitk::NavigationData::PositionType pointB; mitk::NavigationData::PositionType pointC; //initializing three points with position(0|0|0) pointA.Fill(0); pointB.Fill(0); pointC.Fill(0); // changing position off all points in order to make them orthogonal pointA[0] = 1; pointB[1] = 1; pointC[2] = 1; QuaternionTransformType::Pointer quatTransform = QuaternionTransformType::New(); // orientation of NavigationData from parameter mitk::NavigationData::OrientationType quatIn = navigationData->GetOrientation(); // set orientation to quaternion transform vnl_quaternion const vnlQuatIn(quatIn.x(), quatIn.y(), quatIn.z(), quatIn.r()); quatTransform->SetRotation(vnlQuatIn); // transform each point pointA = quatTransform->TransformPoint(pointA); pointB = quatTransform->TransformPoint(pointB); pointC = quatTransform->TransformPoint(pointC); // add position data from NavigationData parameter to each point pointA[0] += navigationData->GetPosition()[0]; pointA[1] += navigationData->GetPosition()[1]; pointA[2] += navigationData->GetPosition()[2]; pointB[0] += navigationData->GetPosition()[0]; pointB[1] += navigationData->GetPosition()[1]; pointB[2] += navigationData->GetPosition()[2]; pointC[0] += navigationData->GetPosition()[0]; pointC[1] += navigationData->GetPosition()[1]; pointC[2] += navigationData->GetPosition()[2]; // insert points in source points pointset for the permanent registration landmark transform m_PermanentRegistrationSourcePoints->InsertPoint(0,pointA); m_PermanentRegistrationSourcePoints->InsertPoint(1,pointB); m_PermanentRegistrationSourcePoints->InsertPoint(2,pointC); return m_PermanentRegistrationSourcePoints; } diff --git a/Plugins/org.mitk.gui.qt.igtexamples/src/internal/QmitkIGTTutorialView.cpp b/Plugins/org.mitk.gui.qt.igtexamples/src/internal/QmitkIGTTutorialView.cpp index a6fac9013b..c69cbf4bf6 100644 --- a/Plugins/org.mitk.gui.qt.igtexamples/src/internal/QmitkIGTTutorialView.cpp +++ b/Plugins/org.mitk.gui.qt.igtexamples/src/internal/QmitkIGTTutorialView.cpp @@ -1,235 +1,235 @@ /*=================================================================== 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 "QmitkIGTTutorialView.h" #include "QmitkStdMultiWidget.h" #include "QmitkStdMultiWidgetEditor.h" #include "mitkNDIPassiveTool.h" #include "mitkNDITrackingDevice.h" #include "mitkVirtualTrackingDevice.h" #include "mitkStandardFileLocations.h" #include "mitkSerialCommunication.h" #include "mitkCone.h" #include #include const std::string QmitkIGTTutorialView::VIEW_ID = "org.mitk.views.igttutorial"; QmitkIGTTutorialView::QmitkIGTTutorialView() : QmitkFunctionality(), m_Controls(NULL), m_MultiWidget(NULL), m_Source(NULL), m_Visualizer(NULL), m_Timer(NULL) { } QmitkIGTTutorialView::~QmitkIGTTutorialView() { } void QmitkIGTTutorialView::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widget m_Controls = new Ui::QmitkIGTTutorialViewControls; m_Controls->setupUi(parent); this->CreateConnections(); } } void QmitkIGTTutorialView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkIGTTutorialView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkIGTTutorialView::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_StartButton), SIGNAL(clicked()),(QObject*) this, SLOT(OnStartIGT())); connect( (QObject*)(m_Controls->m_StopButton), SIGNAL(clicked()),(QObject*) this, SLOT(OnStopIGT())); } } void QmitkIGTTutorialView::Activated() { QmitkFunctionality::Activated(); } void QmitkIGTTutorialView::Deactivated() { QmitkFunctionality::Deactivated(); } void QmitkIGTTutorialView::OnStartIGT() { //This method is called when the Do IGT button is pressed. Any kind of navigation application will //start with the connection to a tracking system and as we do image guided procedures we want to show //something on the screen. In this tutorial we connect to the NDI Polaris tracking system and we will //show the movement of a tool as cone in MITK. //Check if we have a widget for visualization. Makes no sense to start otherwise. //If there is no multiwidget, create one. //if (m_MultiWidget == NULL) //{ //} if (m_MultiWidget == NULL) // if creating the multiwidget failed, stop here. { QMessageBox::warning ( NULL, "Error", "Starting the tutorial is not possible without an initialized " "rendering widget. Please load a dataset first."); return; } try { /**************** Variant 1: Use a NDI Polaris Tracking Device ****************/ ////Here we want to use the NDI Polaris tracking device. Therefore we instantiate a object of the class ////NDITrackingDevice and make some settings which are necessary for a proper connection to the device. //mitk::NDITrackingDevice::Pointer tracker = mitk::NDITrackingDevice::New(); //instantiate //tracker->SetPortNumber(mitk::SerialCommunication::COM4); //set the comport //tracker->SetBaudRate(mitk::SerialCommunication::BaudRate115200); //set the baud rate //tracker->SetType(mitk::NDIPolaris); //set the type there you can choose between Polaris and Aurora ////The tools represent the sensors of the tracking device. In this case we have one pointer tool. ////The TrackingDevice object it self fills the tool with data. So we have to add the tool to the ////TrackingDevice object. //// The Polaris system needs a ".rom" file which describes the geometry of the markers related to the tool tip. ////NDI provides an own software (NDI architect) to generate those files. //tracker->AddTool("MyInstrument", "c:\\myinstrument.rom"); /**************** End of Variant 1 ****************/ /**************** Variant 2: Emulate a Tracking Device with mitk::VirtualTrackingDevice ****************/ // For tests, it is useful to simulate a tracking device in software. This is what mitk::VirtualTrackingDevice does. // It will produce random position, orientation and error values for each tool that is added. mitk::VirtualTrackingDevice::Pointer tracker = mitk::VirtualTrackingDevice::New(); // create virtual tracker mitk::ScalarType bounds[] = {0.0, 200.0, 0.0, 200.0, 0.0, 200.0}; tracker->SetBounds(bounds); tracker->AddTool("MyInstrument"); // add a tool to tracker /**************** End of Variant 2 ****************/ //The tracking device object is used for the physical connection to the device. To use the //data inside of our tracking pipeline we need a source. This source encapsulate the tracking device //and provides objects of the type mitk::NavigationData as output. The NavigationData objects stores //position, orientation, if the data is valid or not and special error informations in a covariance //matrix. // //Typically the start of a pipeline is a TrackingDeviceSource. To work correct we have to set a //TrackingDevice object. Attention you have to set the tools before you set the whole TrackingDevice //object to the TrackingDeviceSource because the source need to know how many outputs should be //generated. m_Source = mitk::TrackingDeviceSource::New(); //We need the filter objects to stay alive, //therefore they must be members. m_Source->SetTrackingDevice(tracker); //Here we set the tracking device to the source of the pipeline. m_Source->Connect(); //Now we connect to the tracking system. //Note we do not call this on the TrackingDevice object //As we wish to visualize our tool we need to have a PolyData which shows us the movement of our tool. //Here we take a cone shaped PolyData. In MITK you have to add the PolyData as a node into the DataStorage //to show it inside of the rendering windows. After that you can change the properties of the cone //to manipulate rendering, e.g. the position and orientation as in our case. mitk::Cone::Pointer cone = mitk::Cone::New(); //instantiate a new cone - float scale[] = {10.0, 10.0, 10.0}; + double scale[] = {10.0, 10.0, 10.0}; cone->GetGeometry()->SetSpacing(scale); //scale it a little that so we can see something mitk::DataNode::Pointer node = mitk::DataNode::New(); //generate a new node to store the cone into //the DataStorage. node->SetData(cone); //The data of that node is our cone. node->SetName("My tracked object"); //The node has additional properties like a name node->SetColor(1.0, 0.0, 0.0); //or the color. Here we make it red. this->GetDefaultDataStorage()->Add(node); //After adding the Node with the cone in it to the //DataStorage, MITK will show the cone in the //render windows. //For updating the render windows we use another filter of the MITK-IGT pipeline concept. The //NavigationDataObjectVisualizationFilter needs as input a NavigationData and a //PolyData. In our case the input is the source and the PolyData our cone. //First we create a new filter for the visualization update. m_Visualizer = mitk::NavigationDataObjectVisualizationFilter::New(); m_Visualizer->SetInput(0, m_Source->GetOutput()); //Then we connect to the pipeline. m_Visualizer->SetRepresentationObject(0, cone); //After that we have to assign the cone to the input //Now this simple pipeline is ready, so we can start the tracking. Here again: We do not call the //StartTracking method from the tracker object itself. Instead we call this method from our source. m_Source->StartTracking(); //Now every call of m_Visualizer->Update() will show us the cone at the position and orientation //given from the tracking device. //We use a QTimer object to call this Update() method in a fixed interval. if (m_Timer == NULL) { m_Timer = new QTimer(this); //create a new timer } connect(m_Timer, SIGNAL(timeout()), this, SLOT(OnTimer())); //connect the timer to the method OnTimer() m_Timer->start(100); //Every 100ms the method OnTimer() is called. -> 10fps //Now have look at the OnTimer() method. } catch (std::exception& e) { // add cleanup std::cout << "Error in QmitkIGTTutorial::OnDoIGT():" << e.what() << std::endl; } } void QmitkIGTTutorialView::OnTimer() { //Here we call the Update() method from the Visualization Filter. Internally the filter checks if //new NavigationData is available. If we have a new NavigationData the cone position and orientation //will be adapted. m_Visualizer->Update(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); //update the render windows } void QmitkIGTTutorialView::OnStopIGT() { //This method is called when the Stop button is pressed. Here we disconnect the pipeline. if (m_Timer == NULL) { std::cout << "No Timer was set yet!" << std::endl; return; } //To disconnect the pipeline in a save way we first stop the timer than we disconnect the tracking device. //After that we destroy all filters with changing them to NULL. m_Timer->stop(); disconnect(m_Timer, SIGNAL(timeout()), this, SLOT(OnTimer())); m_Timer = NULL; m_Source->StopTracking(); m_Source->Disconnect(); m_Source = NULL; m_Visualizer = NULL; m_Source = NULL; this->GetDefaultDataStorage()->Remove(this->GetDefaultDataStorage()->GetNamedNode("My tracked object")); }