MITK-IGT
IGT Extension of MITK
Loading...
Searching...
No Matches
QmitkUSNavigationStepPlacementPlanning.cpp
Go to the documentation of this file.
1/*============================================================================
2
3The Medical Imaging Interaction Toolkit (MITK)
4
5Copyright (c) German Cancer Research Center (DKFZ)
6All rights reserved.
7
8Use of this source code is governed by a 3-clause BSD license that can be
9found in the LICENSE file.
10
11============================================================================*/
12
14#include "ui_QmitkUSNavigationStepPlacementPlanning.h"
15
20#include "usModuleRegistry.h"
21
24
26
27#include "mitkLookupTableProperty.h"
28#include "mitkSurface.h"
29#include <mitkBaseGeometry.h>
30
31#include "mitkLayoutAnnotationRenderer.h"
32#include "mitkTextAnnotation3D.h"
33
34#include "vtkFloatArray.h"
35#include "vtkLookupTable.h"
36#include "vtkPointData.h"
37#include "vtkPolyData.h"
38#include "vtkSmartPointer.h"
39
40#include "vtkLineSource.h"
41#include <vtkSphereSource.h>
42
43#include "vtkCenterOfMass.h"
44#include "vtkLinearTransform.h"
45#include "vtkPoints.h"
46#include "vtkTransformPolyDataFilter.h"
47#include "vtkUnstructuredGrid.h"
48
49#include "vtkMath.h"
50
53 m_NumberOfTargets(0),
54 m_CurrentTargetIndex(0),
55 m_BodyMarkerValid(false),
56 m_PointMarkInteractor(mitk::USPointMarkInteractor::New()),
57 m_TargetUpdateFilter(mitk::USNavigationTargetUpdateFilter::New()),
58 m_NodeDisplacementFilter(mitk::NodeDisplacementFilter::New()),
59 m_NeedleProjectionFilter(mitk::NeedleProjectionFilter::New()),
60 m_TargetIntersectionFilter(mitk::USNavigationTargetIntersectionFilter::New()),
61 m_PlacementQualityCalculator(mitk::USTargetPlacementQualityCalculator::New()),
62 m_ReferenceSensorIndex(1),
63 m_NeedleSensorIndex(0),
64 m_ListenerTargetCoordinatesChanged(this, &QmitkUSNavigationStepPlacementPlanning::UpdateTargetCoordinates),
66{
67 ui->setupUi(this);
68
69 connect(ui->freezeImageButton, SIGNAL(SignalFreezed(bool)), this, SLOT(OnFreeze(bool)));
70
71 m_TargetUpdateFilter->SetScalarArrayIdentifier("USNavigation::PlanningPlacement");
72
74}
75
80
82{
83 // create node for needle projection
84 mitk::DataNode::Pointer node =
86 node->SetData(m_NeedleProjectionFilter->GetProjection());
87 node->SetBoolProperty("show contour", true);
88
89 // make sure that the targets node exist in the data storage
94
95 // listen to event of point mark interactor
96 m_PointMarkInteractor->CoordinatesChangedEvent.AddListener(m_ListenerTargetCoordinatesChanged);
97
98 return true;
99}
100
102{
103 // remove listener to event of point mark interactor
104 m_PointMarkInteractor->CoordinatesChangedEvent.RemoveListener(m_ListenerTargetCoordinatesChanged);
105
107 m_TargetUpdateFilter->Reset();
108 m_NodeDisplacementFilter->ResetNodes();
109
110 // remove the planned target nodes from the data storage
111 mitk::DataStorage::Pointer dataStorage = this->GetDataStorage();
112 for (QVector<itk::SmartPointer<mitk::DataNode>>::iterator it = m_PlannedTargetNodes.begin();
113 it != m_PlannedTargetNodes.end();
114 ++it)
115 {
116 dataStorage->Remove(*it);
117 }
118 m_PlannedTargetNodes.clear();
119
120 // remove the planned target path nodes from the data storage
121 for (QVector<itk::SmartPointer<mitk::DataNode>>::iterator it = m_PlannedNeedlePaths.begin();
122 it != m_PlannedNeedlePaths.end();
123 ++it)
124 {
125 dataStorage->Remove(*it);
126 }
127 m_PlannedNeedlePaths.clear();
128
129 // remove the targets node from the data storage
130 mitk::DataNode::Pointer targetsNode = this->GetNamedDerivedNode(QmitkUSNavigationMarkerPlacement::DATANAME_TARGETS,
132 if (targetsNode.IsNotNull())
133 {
134 dataStorage->Remove(targetsNode);
135 }
136
137 // remove the target paths node from the data storage
138 mitk::DataNode::Pointer targetPathsNode = this->GetNamedDerivedNode(
140 if (targetPathsNode.IsNotNull())
141 {
142 dataStorage->Remove(targetPathsNode);
143 }
144
145 // make sure that the image is no longer freezed after stopping
146 ui->freezeImageButton->Unfreeze();
147
148 return true;
149}
150
152{
153 this->OnStopStep();
154 this->OnStartStep();
155
156 return true;
157}
158
160{
161 // create scalars showing the planned positions on the target surface
162 if (!m_PlannedTargetNodes.isEmpty())
163 {
164 mitk::USNavigationTargetUpdateFilter::Pointer planningSurfaceFilter = mitk::USNavigationTargetUpdateFilter::New();
165 planningSurfaceFilter->SetOptimalAngle(0);
166 planningSurfaceFilter->SetScalarArrayIdentifier("USNavigation::PlanningScalars");
167 planningSurfaceFilter->SetUseMaximumScore(true);
168 planningSurfaceFilter->SetTargetStructure(m_TargetNode);
169
170 unsigned int n = 0;
171 for (QVector<itk::SmartPointer<mitk::DataNode>>::iterator it = m_PlannedTargetNodes.begin();
172 it != m_PlannedTargetNodes.end();
173 ++it)
174 {
175 bool isSurfaceEmpty;
176 if (((*it)->GetBoolProperty("surface_empty", isSurfaceEmpty)) && isSurfaceEmpty)
177 {
178 // remove node from data storage if it is not fully planned
179 this->GetDataStorage()->Remove(*it);
180 }
181 else
182 {
183 // set origin to filter for coloring target surface (good
184 // positions are positions near to the origin)
185 planningSurfaceFilter->SetControlNode(n, *it);
186 }
187
188 n++;
189 }
190 }
191
192 // make sure that the image is no longer freezed after finishing
193 ui->freezeImageButton->Unfreeze();
194
195 return true;
196}
197
199{
201
204
205 if (m_PlannedTargetNodes.empty())
206 {
208 }
209 else
210 {
212 }
213
216 m_TargetNode->SetBoolProperty("visible", true);
217
218 // set lookup table of tumour node
219 m_TargetNode->SetProperty("LookupTable", m_TargetColorLookupTableProperty);
220
221 m_TargetUpdateFilter->SetTargetStructure(m_TargetNode);
222
223 for (QVector<itk::SmartPointer<mitk::DataNode>>::iterator it = m_PlannedTargetNodes.begin();
224 it != m_PlannedTargetNodes.end();
225 ++it)
226 {
227 (*it)->SetBoolProperty("visible", true);
228 }
229
231
232 // m_TargetUpdateFilter->UpdateTargetScores();
233
234 return true;
235}
236
238{
239 ui->freezeImageButton->Unfreeze();
240
241 return true;
242}
243
245{
246 this->UpdateTargetColors();
247
248 // get navigation data source and make sure that it is not null
249 mitk::NavigationDataSource::Pointer navigationDataSource = this->GetCombinedModality()->GetNavigationDataSource();
250 if (navigationDataSource.IsNull())
251 {
252 MITK_ERROR("QmitkUSAbstractNavigationStep")
253 ("QmitkUSNavigationStepPunctuationIntervention") << "Navigation Data Source of Combined Modality must not be null.";
254 mitkThrow() << "Navigation Data Source of Combined Modality must not be null.";
255 }
256
257 navigationDataSource->Update();
258 this->UpdateBodyMarkerStatus(navigationDataSource->GetOutput(m_ReferenceSensorIndex));
259
260 ui->freezeImageButton->setEnabled(m_BodyMarkerValid);
261
262 mitk::PointSet::Pointer needleProjectionPointSet = m_NeedleProjectionFilter->GetProjection();
263 if (needleProjectionPointSet->GetSize() == 2)
264 {
265 m_TargetIntersectionFilter->SetTargetSurface(dynamic_cast<mitk::Surface *>(m_TargetNode->GetData()));
266 m_TargetIntersectionFilter->SetLine(needleProjectionPointSet);
267 m_TargetIntersectionFilter->CalculateIntersection();
268 if (m_TargetIntersectionFilter->GetIsIntersecting())
269 {
270 // only enable button if body marker is in the tracking volume, too
271 ui->placeTargetButton->setEnabled(m_BodyMarkerValid);
272 ui->placeTargetButton->setToolTip("");
273
274 if (m_PlannedTargetNodes.size() == m_NumberOfTargets - 1)
275 {
276 mitk::PointSet::Pointer targetPointSet = mitk::PointSet::New();
277
278 mitk::PointSet::PointIdentifier n = 0;
279 for (QVector<itk::SmartPointer<mitk::DataNode>>::iterator it = m_PlannedTargetNodes.begin();
280 it != m_PlannedTargetNodes.end();
281 ++it)
282 {
283 targetPointSet->InsertPoint(n++, (*it)->GetData()->GetGeometry()->GetOrigin());
284 }
285 targetPointSet->InsertPoint(n, m_TargetIntersectionFilter->GetIntersectionPoint());
286
287 this->CalculatePlanningQuality(dynamic_cast<mitk::Surface *>(m_TargetNode->GetData()), targetPointSet);
288 }
289 }
290 else
291 {
292 ui->placeTargetButton->setEnabled(false);
293 ui->placeTargetButton->setToolTip(
294 "Target cannot be placed as the needle path is not intersecting the target surface.");
295
296 // no not show planning quality if not all nodes are planned for now
297 // and there is no needle path intersection
299 {
300 ui->angleDifferenceValue->setText("");
301 ui->centersOfMassValue->setText("");
302 }
303 }
304 }
305}
306
308{
309 int numberOfTargets;
310 if (settingsNode->GetIntProperty("settings.number-of-targets", numberOfTargets))
311 {
312 m_NumberOfTargets = numberOfTargets;
313 m_TargetUpdateFilter->SetNumberOfTargets(numberOfTargets);
314
315 m_PlacementQualityCalculator->SetOptimalAngle(m_TargetUpdateFilter->GetOptimalAngle());
316 }
317
318 std::string referenceSensorName;
319 if (settingsNode->GetStringProperty("settings.reference-name-selected", referenceSensorName))
320 {
321 m_ReferenceSensorName = referenceSensorName;
322 }
323
324 std::string needleSensorName;
325 if (settingsNode->GetStringProperty("settings.needle-name-selected", needleSensorName))
326 {
327 m_NeedleSensorName = needleSensorName;
328 }
329
330 this->UpdateSensorsNames();
331}
332
334{
335 return "Placement Planning";
336}
337
339{
340 FilterVector filterVector;
341 filterVector.push_back(m_NodeDisplacementFilter.GetPointer());
342 filterVector.push_back(m_NeedleProjectionFilter.GetPointer());
343 return filterVector;
344}
345
347{
348 mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality = this->GetCombinedModality(false);
349 if (combinedModality.IsNotNull())
350 {
351 mitk::AffineTransform3D::Pointer calibration = combinedModality->GetCalibration();
352 if (calibration.IsNotNull())
353 {
354 m_NeedleProjectionFilter->SetTargetPlane(calibration);
355 }
356 }
357
358 ui->freezeImageButton->SetCombinedModality(combinedModality, m_ReferenceSensorIndex);
359
360 this->UpdateSensorsNames();
361}
362
364{
365 if (freeze)
366 this->GetCombinedModality()->SetIsFreezed(true);
367 if (freeze)
368 {
369 // load state machine and event config for data interactor
370 m_PointMarkInteractor->LoadStateMachine("USPointMarkInteractions.xml", us::ModuleRegistry::GetModule("MitkUS"));
371 m_PointMarkInteractor->SetEventConfig("globalConfig.xml");
372
374
376 }
377 else
378 {
379 m_PointMarkInteractor->SetDataNode(nullptr);
380 }
381
382 if (!freeze)
383 this->GetCombinedModality()->SetIsFreezed(false);
384}
385
387{
389
390 mitk::DataNode::Pointer currentNode = m_PlannedTargetNodes.at(m_CurrentTargetIndex);
391
392 currentNode->SetData(this->CreateSphere(5));
393 currentNode->SetBoolProperty("surface_empty", false);
394
395 mitk::PointSet::Pointer needleProjection = m_NeedleProjectionFilter->GetProjection();
396
397 m_TargetIntersectionFilter->SetTargetSurface(dynamic_cast<mitk::Surface *>(m_TargetNode->GetData()));
398 m_TargetIntersectionFilter->SetLine(m_NeedleProjectionFilter->GetProjection());
399 m_TargetIntersectionFilter->CalculateIntersection();
400 mitk::Point3D intersectionPoint = m_TargetIntersectionFilter->GetIntersectionPoint();
401
402 currentNode->GetData()->GetGeometry()->SetOrigin(intersectionPoint);
403 m_TargetUpdateFilter->SetControlNode(m_CurrentTargetIndex, currentNode);
404
405 mitk::PointSet::Pointer plannedPath = mitk::PointSet::New();
406 m_PlannedNeedlePaths.at(m_CurrentTargetIndex)->SetData(plannedPath);
407 plannedPath->SetPoint(0, needleProjection->GetPoint(0));
408 plannedPath->SetPoint(1, intersectionPoint);
409
411 {
412 this->OnGoToNextTarget();
413 }
414 else
415 {
417 }
418
420
421 MITK_INFO("QmitkUSAbstractNavigationStep")
422 ("QmitkUSNavigationStepPlacementPlanning") << "Target " << m_CurrentTargetIndex + 1 << " planned at position "
423 << intersectionPoint << ".";
424}
425
427{
428 if (m_CurrentTargetIndex < 1)
429 {
430 mitkThrow() << "Cannot go to previous target as current target is first target.";
431 }
432
434
436}
437
444
446{
448 {
449 MITK_WARN << "Cannot remove current target as there aren't as much planned target nodes.";
450 return;
451 }
452
458
459 for (int n = 0; n < m_PlannedTargetNodes.size(); ++n)
460 {
461 // set name of the target node according to its new index
462 m_PlannedTargetNodes.at(n)->SetName(
463 QString("Target %1").arg(n + 1, m_NumberOfTargets / 10 + 1, 10, QLatin1Char('0')).toStdString());
464
465 m_PlannedNeedlePaths.at(n)->SetName(
466 QString("Target Path %1").arg(n + 1, m_NumberOfTargets / 10 + 1, 10, QLatin1Char('0')).toStdString());
467 }
468
469 m_TargetUpdateFilter->RemovePositionOfTarget(m_CurrentTargetIndex);
470
472
474
475 MITK_INFO("QmitkUSAbstractNavigationStep")
476 ("QmitkUSNavigationStepPlacementPlanning") << "Planned target " << m_CurrentTargetIndex + 1 << " removed.";
477}
478
480{
481 mitk::DataStorage::Pointer dataStorage = this->GetDataStorage();
482
484 {
485 QString targetNumber =
486 QString("%1").arg(m_PlannedTargetNodes.size() + 1, m_NumberOfTargets / 10 + 1, 10, QLatin1Char('0'));
487
488 mitk::DataNode::Pointer targetNode = this->GetNamedDerivedNodeAndCreate(
489 (QString("Target ") + targetNumber).toStdString().c_str(), QmitkUSNavigationMarkerPlacement::DATANAME_TARGETS);
490 targetNode->SetOpacity(0.5);
491 targetNode->SetBoolProperty("surface_empty", true);
492 targetNode->SetData(mitk::Surface::New());
493
494 m_PlannedTargetNodes.push_back(targetNode);
495
496 mitk::DataNode::Pointer targetPathNode =
497 this->GetNamedDerivedNodeAndCreate((QString("Target Path ") + targetNumber).toStdString().c_str(),
499 targetPathNode->SetOpacity(0.5);
500 targetPathNode->SetColor(1, 1, 1);
501 targetPathNode->SetColor(1, 1, 1, nullptr, "contourcolor");
502 targetPathNode->SetBoolProperty("show contour", true);
503 m_PlannedNeedlePaths.push_back(targetPathNode);
504
505 mitk::Surface::Pointer pathSurface = mitk::Surface::New();
506 targetPathNode->SetData(pathSurface);
507 }
508}
509
511{
512 bool surfaceEmpty;
513 if (dataNode->GetBoolProperty("surface_empty", surfaceEmpty) && surfaceEmpty)
514 {
515 mitk::Point3D origin = dataNode->GetData()->GetGeometry()->GetOrigin();
516 dataNode->SetData(this->CreateSphere(5));
517 dataNode->SetBoolProperty("surface_empty", false);
518 dataNode->GetData()->GetGeometry()->SetOrigin(origin);
519 }
520
522
523 mitk::BaseData *baseData = dataNode->GetData();
524 if (!baseData)
525 {
526 mitkThrow() << "Data of the data node must not be null.";
527 }
528
529 mitk::BaseGeometry::Pointer geometry = baseData->GetGeometry();
530 if (geometry.IsNull())
531 {
532 mitkThrow() << "Geometry of the data node must not be null.";
533 }
534
535 m_TargetUpdateFilter->SetControlNode(m_CurrentTargetIndex, dataNode);
536
537 MITK_INFO("QmitkUSAbstractNavigationStep")
538 ("QmitkUSNavigationStepPlacementPlanning") << "Target " << m_CurrentTargetIndex + 1 << " planned at position "
539 << geometry->GetOrigin() << ".";
540
541 if (ui->freezeImageButton->isChecked())
542 {
543 ui->freezeImageButton->Unfreeze();
544
546 {
547 this->OnGoToNextTarget();
548 }
549 }
550
552}
553
555{
556 if (m_TargetNode.IsNull())
557 {
558 return;
559 }
560
561 m_TargetNode->SetColor(1, 1, 1);
562
563 mitk::BaseData *targetNodeData = m_TargetNode->GetData();
564 if (targetNodeData == nullptr)
565 {
566 return;
567 }
568
569 mitk::Surface::Pointer targetNodeSurface = dynamic_cast<mitk::Surface *>(targetNodeData);
570 vtkSmartPointer<vtkPolyData> targetNodeSurfaceVtk = targetNodeSurface->GetVtkPolyData();
571
572 vtkFloatArray *targetScoreScalars = dynamic_cast<vtkFloatArray *>(
573 targetNodeSurface->GetVtkPolyData()->GetPointData()->GetScalars("USNavigation::PlanningPlacement"));
574
575 if (!targetScoreScalars)
576 {
577 return;
578 }
579
580 unsigned int numberOfTupels = targetScoreScalars->GetNumberOfTuples();
581
583 colors->SetNumberOfComponents(1);
584 colors->SetNumberOfTuples(numberOfTupels);
585 colors->SetName("Colors");
586
587 double markerScore;
588
589 for (unsigned int n = 0; n < numberOfTupels; n++)
590 {
591 targetScoreScalars->GetTuple(n, &markerScore);
592 colors->SetTuple(n, &markerScore);
593 }
594
595 if (numberOfTupels > 0)
596 {
597 targetNodeSurfaceVtk->GetPointData()->SetScalars(colors);
598 targetNodeSurfaceVtk->GetPointData()->Update();
599 }
600}
601
603{
604 ui->previousButton->setEnabled(m_CurrentTargetIndex > 0);
605 ui->nextButton->setEnabled(m_CurrentTargetIndex + 1 < m_PlannedTargetNodes.size());
606 ui->removeButton->setEnabled(m_PlannedTargetNodes.size() > 0);
607
608 ui->currentTargetLabel->setText(
609 QString("Planning Target %1 of %2").arg(m_CurrentTargetIndex + 1).arg(m_NumberOfTargets));
610
611 ui->removeButton->setEnabled(m_CurrentTargetIndex < m_PlannedTargetNodes.size());
612
614}
615
617{
619 lookupTable->SetHueRange(0.0, 0.27);
620 lookupTable->SetSaturationRange(1.0, 1.0);
621 lookupTable->SetValueRange(1.0, 1.0);
622 lookupTable->SetTableRange(0.0, 1.0);
623 lookupTable->Build();
624
625 mitk::LookupTable::Pointer lut = mitk::LookupTable::New();
626 lut->SetVtkLookupTable(lookupTable);
627
628 m_TargetColorLookupTableProperty = mitk::LookupTableProperty::New(lut);
629}
630
632{
633 m_NodeDisplacementFilter->ResetNodes();
634 for (QVector<itk::SmartPointer<mitk::DataNode>>::iterator it = m_PlannedTargetNodes.begin();
635 it != m_PlannedTargetNodes.end();
636 ++it)
637 {
638 if (it->IsNotNull() && (*it)->GetData() != nullptr)
639 {
640 m_NodeDisplacementFilter->AddNode(*it);
641 }
642 }
643 for (QVector<itk::SmartPointer<mitk::DataNode>>::iterator it = m_PlannedNeedlePaths.begin();
644 it != m_PlannedNeedlePaths.end();
645 ++it)
646 {
647 if (it->IsNotNull() && (*it)->GetData() != nullptr)
648 {
649 m_NodeDisplacementFilter->AddNode(*it);
650 }
651 }
652}
653
655{
657 {
658 ui->angleDifferenceLabel->setEnabled(false);
659 ui->centersOfMassLabel->setEnabled(false);
660 ui->allTargetsPlannedLabel->setEnabled(false);
661 ui->angleDifferenceValue->setText("");
662 ui->centersOfMassValue->setText("");
663 return;
664 }
665
666 ui->angleDifferenceLabel->setEnabled(true);
667 ui->centersOfMassLabel->setEnabled(true);
668 ui->allTargetsPlannedLabel->setEnabled(true);
669
670 mitk::PointSet::Pointer targetPointSet = mitk::PointSet::New();
671
672 mitk::PointSet::PointIdentifier n = 0;
673 for (QVector<itk::SmartPointer<mitk::DataNode>>::iterator it = m_PlannedTargetNodes.begin();
674 it != m_PlannedTargetNodes.end();
675 ++it)
676 {
677 targetPointSet->InsertPoint(n++, (*it)->GetData()->GetGeometry()->GetOrigin());
678 }
679
680 mitk::DataNode::Pointer planningQualityResult =
681 this->CalculatePlanningQuality(dynamic_cast<mitk::Surface *>(m_TargetNode->GetData()), targetPointSet);
682 emit SignalIntermediateResult(planningQualityResult);
683}
684
686 mitk::Surface::Pointer targetSurface, mitk::PointSet::Pointer targetPoints)
687{
688 if (targetSurface.IsNull())
689 {
690 mitkThrow() << "Target surface must not be null.";
691 }
692
693 m_PlacementQualityCalculator->SetTargetSurface(targetSurface);
694 m_PlacementQualityCalculator->SetTargetPoints(targetPoints);
696
697 mitk::DataNode::Pointer planningQualityResult = mitk::DataNode::New();
698 planningQualityResult->SetName("PlanningQuality");
699
700 double centersOfMassDistance = m_PlacementQualityCalculator->GetCentersOfMassDistance();
701 ui->centersOfMassValue->setText(QString::number(centersOfMassDistance, 103, 2) + " mm");
702 planningQualityResult->SetFloatProperty("USNavigation::CentersOfMassDistance", centersOfMassDistance);
703
704 if (m_PlannedTargetNodes.size() > 1)
705 {
706 double meanAnglesDifference = m_PlacementQualityCalculator->GetMeanAngleDifference();
707 ui->angleDifferenceValue->setText(QString::number(meanAnglesDifference, 103, 2) + QString::fromLatin1(" °"));
708
709 planningQualityResult->SetFloatProperty("USNavigation::MeanAngleDifference", meanAnglesDifference);
710 planningQualityResult->SetProperty(
711 "USNavigation::AngleDifferences",
712 mitk::GenericProperty<mitk::VnlVector>::New(m_PlacementQualityCalculator->GetAngleDifferences()));
713 }
714 else
715 {
716 ui->angleDifferenceValue->setText("not valid for one point");
717 }
718
719 return planningQualityResult;
720}
721
723{
724 mitk::Surface::Pointer surface = mitk::Surface::New();
725
726 // create a vtk sphere with fixed radius
728 vtkSphere->SetRadius(5);
729 vtkSphere->SetCenter(0, 0, 0);
730 vtkSphere->Update();
731 surface->SetVtkPolyData(vtkSphere->GetOutput());
732
733 return surface;
734}
735
736void QmitkUSNavigationStepPlacementPlanning::UpdateBodyMarkerStatus(mitk::NavigationData::Pointer bodyMarker)
737{
738 if (bodyMarker.IsNull())
739 {
740 MITK_ERROR("QmitkUSAbstractNavigationStep")
741 ("QmitkUSNavigationStepPunctuationIntervention")
742 << "Current Navigation Data for body marker of Combined Modality must not be null.";
743 mitkThrow() << "Current Navigation Data for body marker of Combined Modality must not be null.";
744 }
745
746 m_BodyMarkerValid = bodyMarker->IsDataValid();
747
748 // update body marker status label
750 {
751 ui->bodyMarkerTrackingStatusLabel->setStyleSheet(
752 "background-color: #8bff8b; margin-right: 1em; margin-left: 1em; border: 1px solid grey");
753 ui->bodyMarkerTrackingStatusLabel->setText("Body marker is inside the tracking volume.");
754 }
755 else
756 {
757 ui->bodyMarkerTrackingStatusLabel->setStyleSheet(
758 "background-color: #ff7878; margin-right: 1em; margin-left: 1em; border: 1px solid grey");
759 ui->bodyMarkerTrackingStatusLabel->setText("Body marker is not inside the tracking volume.");
760 }
761}
762
764{
765 mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality = this->GetCombinedModality(false);
766 if (combinedModality.IsNull())
767 {
768 return;
769 }
770
771 mitk::NavigationDataSource::Pointer navigationDataSource = combinedModality->GetNavigationDataSource();
772 if (navigationDataSource.IsNull())
773 {
774 return;
775 }
776
777 if (!m_NeedleSensorName.empty())
778 {
779 try
780 {
781 m_NeedleSensorIndex = navigationDataSource->GetOutputIndex(m_NeedleSensorName);
782 }
783 catch (const std::exception &e)
784 {
785 MITK_WARN("QmitkUSAbstractNavigationStep")
786 ("QmitkUSNavigationStepPlacementPlanning") << "Cannot get index for needle sensor name: " << e.what();
787 }
788 }
790 {
792 }
793
794 if (!m_ReferenceSensorName.empty())
795 {
796 try
797 {
798 m_ReferenceSensorIndex = navigationDataSource->GetOutputIndex(m_ReferenceSensorName);
799 }
800 catch (const std::exception &e)
801 {
802 MITK_WARN("QmitkUSAbstractNavigationStep")
803 ("QmitkUSNavigationStepPlacementPlanning") << "Cannot get index for reference sensor name: " << e.what();
804 }
805 }
807 {
809 }
810
811 ui->freezeImageButton->SetCombinedModality(combinedModality, m_ReferenceSensorIndex);
812}
Abstract base class for navigation step widgets.
itk::SmartPointer< mitk::DataStorage > GetDataStorage(bool throwNull=true)
Returns the data storage set for the navigation step.
NavigationStepState GetNavigationStepState()
Get the current state of the navigation step.
void SignalReadyForNextStep()
Signals that all necessary actions where done. The user can proceed with the next stept after this wa...
itk::SmartPointer< mitk::DataNode > GetNamedDerivedNodeAndCreate(const char *name, const char *sourceName)
Returns node with the given name and the given source node (parent) from the data storage....
itk::SmartPointer< mitk::AbstractUltrasoundTrackerDevice > GetCombinedModality(bool throwNull=true)
Returns the combined modality set for the navigation step.
std::vector< itk::SmartPointer< mitk::NavigationDataToNavigationDataFilter > > FilterVector
void SignalIntermediateResult(const itk::SmartPointer< mitk::DataNode >)
Signals that an intermediate result was produced. The properties of the given data node must contain ...
itk::SmartPointer< mitk::DataNode > GetNamedDerivedNode(const char *name, const char *sourceName)
Returns node with the given name and the given source node (parent) from the data storage.
Navigation step for planning the positions for implanting markers.
bool OnRestartStep() override
Called when restarting a navigation step. This method may be implemented by a concrete subclass to ha...
void OnSetCombinedModality() override
Called every time SetCombinedModality() was called. This method may be implemented by a concrete subc...
void OnFreeze(bool freezed)
Freezes or unfreezes the combined modality. In freeze state an interactor is activated in the render ...
void OnUpdate() override
Called periodically while a navigation step is active. This method has to be implemented by a concret...
void OnRemoveCurrentTargetClicked()
The currently active target is removed from the data storage.
FilterVector GetFilter() override
Getter for navigation data filters of the navigation step. This method may be implemented by a concre...
bool OnStartStep() override
Called when the navigation step gets started. This method has to be implemented by a concrete subclas...
bool OnActivateStep() override
Called when the navigation step gets activated. This method has to be implemented by a concrete subcl...
itk::SmartPointer< mitk::USTargetPlacementQualityCalculator > m_PlacementQualityCalculator
itk::SmartPointer< mitk::USNavigationTargetUpdateFilter > m_TargetUpdateFilter
bool OnFinishStep() override
Called when all necessary actions for the step where done. This method has to be implemented by a con...
void OnPlaceTargetButtonClicked()
Plan target position at the intersection between needle path and target surface.
itk::SmartPointer< mitk::LookupTableProperty > m_TargetColorLookupTableProperty
void OnGoToPreviousTarget()
Selects the previous target as active target.
itk::SmartPointer< mitk::USPointMarkInteractor > m_PointMarkInteractor
void OnSettingsChanged(const itk::SmartPointer< mitk::DataNode > settingsNode) override
Called every time the settings for the navigation process where changed. This method may be implement...
bool OnDeactivateStep() override
Called when the navigation step gets deactivated (-> state started). This method may be implemented b...
itk::SmartPointer< mitk::NodeDisplacementFilter > m_NodeDisplacementFilter
QVector< itk::SmartPointer< mitk::DataNode > > m_PlannedNeedlePaths
itk::SmartPointer< mitk::Surface > CreateSphere(float radius)
QString GetTitle() override
Getter for the title of the navigation step. This title should be human readable and can be used to d...
bool OnStopStep() override
Callen when the navigation step gets stopped. This method may be implemented by a concrete subclass t...
itk::SmartPointer< mitk::NeedleProjectionFilter > m_NeedleProjectionFilter
itk::SmartPointer< mitk::USNavigationTargetIntersectionFilter > m_TargetIntersectionFilter
QVector< itk::SmartPointer< mitk::DataNode > > m_PlannedTargetNodes
void UpdateBodyMarkerStatus(mitk::NavigationData::Pointer bodyMarker)
void OnGoToNextTarget()
Selects the next target as active target.
IGT Exceptions.