MITK-IGT
IGT Extension of MITK
Loading...
Searching...
No Matches
USNavigation.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
13// Blueberry
14#include <berryISelectionService.h>
15#include <berryIWorkbenchWindow.h>
16
17// Qmitk
18#include "USNavigation.h"
19#include <QFileDialog>
20
21//MITK
22#include <mitkBaseRenderer.h>
23#include <mitkIRenderingManager.h>
24#include <QmitkRenderWindow.h>
25#include <mitkDataStorage.h>
26
27// VTK
28#include <vtkSphereSource.h>
29
30// Qt
31#include <QMessageBox>
32#include <QBoxLayout>
33#include <QShortcut>
34
35const std::string USNavigation::VIEW_ID = "org.mitk.views.usnavigation";
36
38{
39 // m_Controls.buttonPerformImageProcessing->setFocus();
40}
41
43: m_ImageAlreadySetToNode(false)
44{
45}
46
47void USNavigation::CreateQtPartControl( QWidget *parent )
48{
49 m_Timer = new QTimer(this);
50 m_RangeMeterTimer = new QTimer(this);
51 // create GUI widgets from the Qt Designer's .ui file
52 m_Controls.setupUi( parent );
53
54 m_Controls.m_ZonesWidget->SetDataStorage(this->GetDataStorage());
55
56 // Timer
57 connect( m_Timer, SIGNAL(timeout()), this, SLOT(Update()));
58 connect( m_RangeMeterTimer, SIGNAL(timeout()), this, SLOT(UpdateMeters()));
59
60 connect( m_Controls.m_BtnSelectDevices, SIGNAL(clicked()), this, SLOT(OnSelectDevices()) );
61 connect( m_Controls.m_CombinedModalitySelectionWidget, SIGNAL(SignalReadyForNextStep()),
62 this, SLOT(OnDeviceSelected()) );
63 connect( m_Controls.m_CombinedModalitySelectionWidget, SIGNAL(SignalNoLongerReadyForNextStep()),
64 this, SLOT(OnDeviceDeselected()) );
65
66 connect( m_Controls.m_TabWidget, SIGNAL(currentChanged ( int )), this, SLOT(OnTabSwitch( int )) );
67
68 // Zones
69 connect( m_Controls.m_BtnFreeze, SIGNAL(clicked()), this, SLOT(OnFreeze()) );
70 connect( m_Controls.m_ZonesWidget, SIGNAL(ZoneAdded()), this, SLOT(OnZoneAdded()) );
71 // Navigation
72 connect( m_Controls.m_BtnStartIntervention, SIGNAL(clicked ()), this, SLOT(OnStartIntervention()) );
73 connect( m_Controls.m_BtnReset, SIGNAL(clicked ()), this, SLOT(OnReset()) );
74 connect( m_Controls.m_BtnNeedleView, SIGNAL(clicked ()), this, SLOT(OnNeedleViewToogle()) );
75
76 m_Freeze = false;
78
79 m_Controls.m_TabWidget->setTabEnabled(1, false);
80 m_Controls.m_TabWidget->setTabEnabled(2, false);
81 m_ZoneFilter = mitk::NodeDisplacementFilter::New();
82 m_NeedleProjectionFilter = mitk::NeedleProjectionFilter::New();
83 m_SmoothingFilter = mitk::NavigationDataSmoothingFilter::New();
84 m_CameraVis = mitk::CameraVisualization::New();
85 m_RangeMeterStyle = "QProgressBar:horizontal {\nborder: 1px solid gray;\nborder-radius: 3px;\nbackground: white;\npadding: 1px;\ntext-align: center;\n}\nQProgressBar::chunk:horizontal {\nbackground: qlineargradient(x1: 0, y1: 0.5, x2: 1, y2: 0.5, stop: 0 #StartColor#, stop: 0.8 #StartColor#, stop: 1 #StopColor#);\n}";
86 QBoxLayout * layout = new QBoxLayout(QBoxLayout::Down, m_Controls.m_RangeBox);
87 // Pedal Support for Needle View
88 QShortcut *shortcut = new QShortcut(QKeySequence(Qt::Key_PageDown), parent);
89 QObject::connect(shortcut, SIGNAL(activated()), m_Controls.m_BtnNeedleView, SLOT(animateClick()) );
90
91 m_Controls.m_CombinedModalitySelectionWidget->OnActivateStep();
92}
93
95{
96 m_Controls.m_BtnSelectDevices->setEnabled(true);
97}
98
100{
101 m_Controls.m_BtnSelectDevices->setEnabled(false);
102 m_Controls.m_TabWidget->setCurrentIndex(0);
103 m_Controls.m_TabWidget->setTabEnabled(1, false);
104 m_Controls.m_TabWidget->setTabEnabled(2, false);
105}
106
108 m_USDevice = m_Controls.m_CombinedModalitySelectionWidget->GetSelectedCombinedModality();
109 if (m_USDevice.IsNull())
110 {
111 MITK_WARN << "No device selected.";
112 return;
113 }
114
115 QApplication::setOverrideCursor(Qt::WaitCursor);
116 // make sure that the combined modality is in connected state before using it
117 if ( m_USDevice->GetDeviceState() < mitk::USDevice::State_Connected ) { m_USDevice->Connect(); }
118 if ( m_USDevice->GetDeviceState() < mitk::USDevice::State_Activated ) { m_USDevice->Activate(); }
119 QApplication::restoreOverrideCursor();
120
121 m_Tracker = m_USDevice->GetNavigationDataSource();
122
123 // Build Pipeline
124 m_ZoneFilter->SetInput(0, m_Tracker->GetOutput(0));
125 m_ZoneFilter->SetInput(1, m_Tracker->GetOutput(1));
126 m_ZoneFilter->SelectInput(1);
127 m_NeedleProjectionFilter->SetInput(0, m_ZoneFilter->GetOutput(0));
128 m_NeedleProjectionFilter->SetInput(1, m_ZoneFilter->GetOutput(1));
129 m_NeedleProjectionFilter->SelectInput(0);
130 m_NeedleProjectionFilter->SetTargetPlane(m_USDevice->GetCalibration());
131
132 // Setting up the Camera Visualization Filter
133
134 mitk::BaseRenderer* renderer = mitk::BaseRenderer::GetInstance(this->GetRenderWindowPart(mitk::WorkbenchUtil::OPEN)->GetQmitkRenderWindow("3d")->GetRenderWindow());
135
136 m_CameraVis->SetInput(0, m_NeedleProjectionFilter->GetOutput(0));
137 m_CameraVis->SetRenderer( renderer );
138 m_CameraVis->SetFocalLength(40);
139
140 mitk::Vector3D direction;
141 direction[0] = 0;
142 direction[1] = 0;
143 direction[2] = 1;
144 m_CameraVis->SetDirectionOfProjectionInToolCoordinates(direction);
145 direction[0] = -1;
146 direction[1] = 0;
147 direction[2] = 0;
148 m_CameraVis->SetViewUpInToolCoordinates(direction);
149
150 // Create Node for Needle Projection
151 mitk::DataNode::Pointer node = this->GetDataStorage()->GetNamedNode("Needle Path");
152 if ( node.IsNull() )
153 {
154 node = mitk::DataNode::New();
155 node->SetName("Needle Path");
156 node->SetData(m_NeedleProjectionFilter->GetProjection());
157 node->SetBoolProperty("show contour", true);
158 this->GetDataStorage()->Add(node);
159 node->SetFloatProperty("opacity", 0.80f );
160 }
161
162 m_Timer->start(15);
163
164 // Create Node for US Stream
165 m_USStream = mitk::DataNode::New();
166 m_USStream->SetName("US Image Stream");
167 m_USStream->SetFloatProperty("opacity", 0.80f );
168 this->GetDataStorage()->Add(m_USStream);
169
170 // Switch active tab to next page
171 m_Controls.m_TabWidget->setTabEnabled(1, true);
172 m_Controls.m_TabWidget->setTabEnabled(2, true);
173 m_Controls.m_TabWidget->setCurrentIndex(1);
174}
175
177{
178 if (m_Freeze) return;
179
180 // Update NeedleVisFilter only if the view is desired
182 m_NeedleProjectionFilter->Update();
183 else
184 m_CameraVis->Update();
185 //only Update USImage every other time
186 m_UpdateImage ++;
187 if (m_UpdateImage)
188 {
189 m_USDevice->Modified();
190 m_USDevice->Update();
191 mitk::Image::Pointer image = m_USDevice->GetOutput();
192 if ( ! m_ImageAlreadySetToNode && image.IsNotNull() && image->IsInitialized() )
193 {
194 m_USStream->SetData(image);
196
197 // make a reinit on the ultrasound image
198 mitk::IRenderWindowPart* renderWindow = this->GetRenderWindowPart();
199 if ( renderWindow != nullptr && image->GetTimeGeometry()->IsValid() )
200 {
201 renderWindow->GetRenderingManager()->InitializeViews(image->GetTimeGeometry());
202 }
203 }
204 this->RequestRenderWindowUpdate();
205 }
206}
207
209
211{
212 // make sure that the data nodes in m_Zones are exactly the same as
213 // the zone nodes of the zone node widget
214 m_Zones.clear();
215 mitk::DataStorage::SetOfObjects::ConstPointer zoneNodes = m_Controls.m_ZonesWidget->GetZoneNodes();
216 for (mitk::DataStorage::SetOfObjects::ConstIterator it = zoneNodes->Begin();
217 it != zoneNodes->End(); ++it)
218 {
219 m_Zones.push_back(it->Value());
220 }
221
222 QLayout * layout = m_Controls.m_RangeBox->layout();
223 for (int i = 0; i < m_Zones.size(); i++)
224 {
225 QProgressBar * meter = CreateRangeMeter(i);
226 layout->addWidget(meter);
227 m_RangeMeters.push_back(meter);
228 }
229 m_RangeMeterTimer->start(100);
230}
231
233{
234 mitk::DataNode::Pointer zone = m_Zones.at(i);
235
236 float zoneColor[3];
237 bool success = m_Zones.at(i)->GetColor(zoneColor);
238 QString zoneColorString = "#555555";
239 if (success)
240 {
241 QString zoneColorString = QString("#%1%2%3").arg(static_cast<unsigned int>(zoneColor[0]*255), 2, 16, QChar('0'))
242 .arg(static_cast<unsigned int>(zoneColor[1]*255), 2, 16, QChar('0')).arg(static_cast<unsigned int>(zoneColor[2]*255), 2, 16, QChar('0'));
243 }
244
245 QProgressBar* meter = new QProgressBar();
246 meter->setMinimum(0);
247 meter->setMaximum(100);
248 meter->setValue(0);
249 QString zoneName = zone->GetName().c_str();
250 meter->setFormat(zoneName + ": No Data");
251 QString style = m_RangeMeterStyle;
252 style = style.replace("#StartColor#", zoneColorString);
253 style = style.replace("#StopColor#", zoneColorString);
254 meter->setStyleSheet(style);
255 meter->setVisible(true);
256 return meter;
257}
258
260{
261 // Get NeedlePosition
262 mitk::NavigationData::Pointer needle = this->m_Tracker->GetOutput(0);
263 if (! needle->IsDataValid()) return;
264 mitk::Point3D needlePosition = needle->GetPosition();
265 // Update each meter
266 for (int i = 0; i < m_Zones.size(); i++)
267 {
268 mitk::Point3D zoneOrigin = m_Zones.at(i)->GetData()->GetGeometry()->GetOrigin();
269 // calculate absolute distance
270 mitk::ScalarType distance = sqrt( pow(zoneOrigin[0] - needlePosition[0], 2) + pow(zoneOrigin[1] - needlePosition[1], 2) + pow(zoneOrigin[2] - needlePosition[2], 2) );
271 // Subtract zone size
272 float zoneSize;
273 m_Zones.at(i)->GetFloatProperty("zone.size", zoneSize);
274 distance = distance - zoneSize;
275
276 // Prepare new Style
277 float zoneColor[3];
278 m_Zones.at(i)->GetColor(zoneColor);
279 QString zoneColorString = QString("#%1%2%3").arg(static_cast<unsigned int>(zoneColor[0]*255), 2, 16, QChar('0'))
280 .arg(static_cast<unsigned int>(zoneColor[1]*255), 2, 16, QChar('0')).arg(static_cast<unsigned int>(zoneColor[2]*255), 2, 16, QChar('0'));
281 QString style = m_RangeMeterStyle;
282 QString text = m_Zones.at(i)->GetName().c_str();
283 int value = 0;
284 // There Are now four possible Outcomes
285 // 1) Needle is inside zone (bad news)
286 if (distance < 0)
287 {
288 style = style.replace("#StartColor#", "red");
289 style = style.replace("#StopColor#", "red");
290 text = text + ": VIOLATED";
291 value = 100;
292 } // 2) Needle is close to Zone
293 else if (distance < WARNRANGE)
294 {
295 style = style.replace("#StartColor#", zoneColorString);
296 style = style.replace("#StopColor#", "red");
297 text = text + ": " + QString::number(distance) + " mm";
298 value = 100 - 100 * ((float) distance / (float )MAXRANGE);
299 } // 3) Needle is away from zone
300 else if (distance < MAXRANGE)
301 {
302 style = style.replace("#StartColor#", zoneColorString);
303 style = style.replace("#StopColor#", zoneColorString);
304 text = text + ": " + QString::number(distance) + " mm";
305 value = 100 - 100 * ((float) distance / (float )MAXRANGE);
306 } // 4) Needle is far away from zone
307 else
308 {
309 style = style.replace("#StartColor#", zoneColorString);
310 style = style.replace("#StopColor#", zoneColorString);
311 text = text + ": " + QString::number(distance) + " mm";
312 value = 0;
313 }
314
315 QProgressBar * meter = this->m_RangeMeters.at(i);
316 meter->setStyleSheet(style);
317 meter->setFormat(text);
318 meter->setValue(value);
319 }
320}
321
323
325{
326 this->ResetRangeMeters();
327
328 m_Controls.m_TabWidget->setCurrentIndex(2);
329 this->SetupProximityView();
330}
331
333{
334 // Swap Freeze State
335 m_Freeze = ! m_Freeze;
336
337 if ( m_Freeze )
338 {
339 m_Controls.m_ZonesWidget->OnStartAddingZone();
340 }
341 else
342 {
343 m_Controls.m_ZonesWidget->OnAbortAddingZone();
344 }
345}
346
348{
349 // Reset Zones
350 m_ZoneFilter->ResetNodes();
351 m_Zones.clear();
352 m_Controls.m_ZonesWidget->OnResetZones();
353
354 this->ResetRangeMeters();
355
356 m_RangeMeters.clear();
357 m_RangeMeterTimer->stop();
358}
359
361{
362 m_IsNeedleViewActive = m_Controls.m_BtnNeedleView->isChecked();
363
364 mitk::DataNode::Pointer node = this->GetDataStorage()->GetNamedNode("Needle Path");
365 if ( node.IsNotNull() )
366 node->SetVisibility( ! m_IsNeedleViewActive );
367}
368
370{
371 if ( m_Freeze )
372 {
373 m_Controls.m_BtnFreeze->setChecked(false);
374 m_Freeze = false;
375 }
376
377 mitk::DataStorage::SetOfObjects::ConstPointer zoneNodes = m_Controls.m_ZonesWidget->GetZoneNodes();
378 for (mitk::DataStorage::SetOfObjects::ConstIterator it = zoneNodes->Begin();
379 it != zoneNodes->End(); ++it)
380 {
381 // add all zones to zone filter which aren't added until now
382 if ( find(m_Zones.begin(), m_Zones.end(), it->Value()) == m_Zones.end() )
383 {
384 m_Zones.push_back(it->Value());
385 m_ZoneFilter->AddNode(it->Value());
386 }
387 }
388}
389
391{
392 m_RangeMeters.clear();
393
394 QLayout* layout = m_Controls.m_RangeBox->layout();
395 QLayoutItem *item;
396 while((item = layout->takeAt(0))) {
397 if (item->widget()) {
398 delete item->widget();
399 }
400 delete item;
401 }
402}
QTimer * m_RangeMeterTimer
void OnNeedleViewToggle()
mitk::NeedleProjectionFilter::Pointer m_NeedleProjectionFilter
Creates a Pointset that projects the needle's path.
mitk::NavigationDataSmoothingFilter::Pointer m_SmoothingFilter
mitk::CameraVisualization::Pointer m_CameraVis
bool m_ImageAlreadySetToNode
mitk::NodeDisplacementFilter::Pointer m_ZoneFilter
void OnSelectDevices()
Triggered, when the user has clicked "select Devices".
mitk::DataNode::Pointer m_USStream
void OnDeviceDeselected()
static const int MAXRANGE
QProgressBar * CreateRangeMeter(int i)
virtual void SetFocus()
QString m_RangeMeterStyle
mitk::USCombinedModality::Pointer m_USDevice
The CombinedModality used for imaging.
mitk::NavigationDataSource::Pointer m_Tracker
NavigationDataSource used for tracking data.
QTimer * m_Timer
std::vector< mitk::DataNode::Pointer > m_Zones
void SetupProximityView()
Sets up the RangeMeter Section of the Navigation by creating and initializing all necessary Progress ...
void ResetRangeMeters()
static const std::string VIEW_ID
bool m_IsNeedleViewActive
virtual void CreateQtPartControl(QWidget *parent)
Ui::USNavigationControls m_Controls
void OnDeviceSelected()
Triggered, when the user selects a device from either the list of USDevices or Tracking Devices.
std::vector< QProgressBar * > m_RangeMeters
static const int WARNRANGE
void OnStartIntervention()
Triggered, when the user has clicked "Load Calibration".