Medical Imaging Interaction Toolkit  2018.4.99-3e3f1a6e
Medical Imaging Interaction Toolkit
QmitkSlicesInterpolator.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
14 
16 #include "QmitkStdMultiWidget.h"
17 
19 #include "mitkColorProperty.h"
20 #include "mitkCoreObjectFactory.h"
21 #include "mitkDiffImageApplier.h"
22 #include "mitkInteractionConst.h"
24 #include "mitkOperationEvent.h"
26 #include "mitkProgressBar.h"
27 #include "mitkProperties.h"
28 #include "mitkRenderingManager.h"
29 #include "mitkSegTool2D.h"
32 #include "mitkToolManager.h"
33 #include "mitkUndoController.h"
34 #include <mitkExtractSliceFilter.h>
35 #include <mitkImageReadAccessor.h>
36 #include <mitkImageTimeSelector.h>
37 #include <mitkImageWriteAccessor.h>
38 #include <mitkPlaneProposer.h>
40 #include <mitkVtkImageOverwrite.h>
41 
42 #include <itkCommand.h>
43 
44 #include <QCheckBox>
45 #include <QCursor>
46 #include <QMenu>
47 #include <QMessageBox>
48 #include <QPushButton>
49 #include <QVBoxLayout>
50 
51 #include <vtkPolyVertex.h>
52 #include <vtkUnstructuredGrid.h>
53 
54 //#define ROUND(a) ((a)>0 ? (int)((a)+0.5) : -(int)(0.5-(a)))
55 
56 float SURFACE_COLOR_RGB[3] = {0.49f, 1.0f, 0.16f};
57 
58 const std::map<QAction *, mitk::SliceNavigationController *> QmitkSlicesInterpolator::createActionToSliceDimension()
59 {
60  std::map<QAction *, mitk::SliceNavigationController *> actionToSliceDimension;
61  foreach (mitk::SliceNavigationController *slicer, m_ControllerToDeleteObserverTag.keys())
62  {
63  actionToSliceDimension[new QAction(QString::fromStdString(slicer->GetViewDirectionAsString()), nullptr)] = slicer;
64  }
65 
66  return actionToSliceDimension;
67 }
68 
69 QmitkSlicesInterpolator::QmitkSlicesInterpolator(QWidget *parent, const char * /*name*/)
70  : QWidget(parent),
71  // ACTION_TO_SLICEDIMENSION( createActionToSliceDimension() ),
72  m_Interpolator(mitk::SegmentationInterpolationController::New()),
73  m_SurfaceInterpolator(mitk::SurfaceInterpolationController::GetInstance()),
74  m_ToolManager(nullptr),
75  m_Initialized(false),
76  m_LastSNC(nullptr),
77  m_LastSliceIndex(0),
78  m_2DInterpolationEnabled(false),
79  m_3DInterpolationEnabled(false),
80  m_FirstRun(true)
81 {
82  m_GroupBoxEnableExclusiveInterpolationMode = new QGroupBox("Interpolation", this);
83 
84  QVBoxLayout *vboxLayout = new QVBoxLayout(m_GroupBoxEnableExclusiveInterpolationMode);
85 
87  m_PointScorer = mitk::PointCloudScoringFilter::New();
88 
89  m_CmbInterpolation = new QComboBox(m_GroupBoxEnableExclusiveInterpolationMode);
90  m_CmbInterpolation->addItem("Disabled");
91  m_CmbInterpolation->addItem("2-Dimensional");
92  m_CmbInterpolation->addItem("3-Dimensional");
93  vboxLayout->addWidget(m_CmbInterpolation);
94 
95  m_BtnApply2D = new QPushButton("Confirm for single slice", m_GroupBoxEnableExclusiveInterpolationMode);
96  vboxLayout->addWidget(m_BtnApply2D);
97 
98  m_BtnApplyForAllSlices2D = new QPushButton("Confirm for all slices", m_GroupBoxEnableExclusiveInterpolationMode);
99  vboxLayout->addWidget(m_BtnApplyForAllSlices2D);
100 
101  m_BtnApply3D = new QPushButton("Confirm", m_GroupBoxEnableExclusiveInterpolationMode);
102  vboxLayout->addWidget(m_BtnApply3D);
103 
104  m_BtnSuggestPlane = new QPushButton("Suggest a plane", m_GroupBoxEnableExclusiveInterpolationMode);
105  vboxLayout->addWidget(m_BtnSuggestPlane);
106 
107  m_BtnReinit3DInterpolation = new QPushButton("Reinit Interpolation", m_GroupBoxEnableExclusiveInterpolationMode);
108  vboxLayout->addWidget(m_BtnReinit3DInterpolation);
109 
110  m_ChkShowPositionNodes = new QCheckBox("Show Position Nodes", m_GroupBoxEnableExclusiveInterpolationMode);
111  vboxLayout->addWidget(m_ChkShowPositionNodes);
112 
113  this->HideAllInterpolationControls();
114 
115  connect(m_CmbInterpolation, SIGNAL(currentIndexChanged(int)), this, SLOT(OnInterpolationMethodChanged(int)));
116  connect(m_BtnApply2D, SIGNAL(clicked()), this, SLOT(OnAcceptInterpolationClicked()));
117  connect(m_BtnApplyForAllSlices2D, SIGNAL(clicked()), this, SLOT(OnAcceptAllInterpolationsClicked()));
118  connect(m_BtnApply3D, SIGNAL(clicked()), this, SLOT(OnAccept3DInterpolationClicked()));
119 
120  connect(m_BtnSuggestPlane, SIGNAL(clicked()), this, SLOT(OnSuggestPlaneClicked()));
121 
122  connect(m_BtnReinit3DInterpolation, SIGNAL(clicked()), this, SLOT(OnReinit3DInterpolation()));
123  connect(m_ChkShowPositionNodes, SIGNAL(toggled(bool)), this, SLOT(OnShowMarkers(bool)));
124  connect(m_ChkShowPositionNodes, SIGNAL(toggled(bool)), this, SIGNAL(SignalShowMarkerNodes(bool)));
125 
126  QHBoxLayout *layout = new QHBoxLayout(this);
127  layout->addWidget(m_GroupBoxEnableExclusiveInterpolationMode);
128  this->setLayout(layout);
129 
130  itk::ReceptorMemberCommand<QmitkSlicesInterpolator>::Pointer command =
131  itk::ReceptorMemberCommand<QmitkSlicesInterpolator>::New();
132  command->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnInterpolationInfoChanged);
133  InterpolationInfoChangedObserverTag = m_Interpolator->AddObserver(itk::ModifiedEvent(), command);
134 
135  itk::ReceptorMemberCommand<QmitkSlicesInterpolator>::Pointer command2 =
136  itk::ReceptorMemberCommand<QmitkSlicesInterpolator>::New();
137  command2->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnSurfaceInterpolationInfoChanged);
138  SurfaceInterpolationInfoChangedObserverTag = m_SurfaceInterpolator->AddObserver(itk::ModifiedEvent(), command2);
139 
140  // feedback node and its visualization properties
141  m_FeedbackNode = mitk::DataNode::New();
142  mitk::CoreObjectFactory::GetInstance()->SetDefaultProperties(m_FeedbackNode);
143 
144  m_FeedbackNode->SetProperty("binary", mitk::BoolProperty::New(true));
145  m_FeedbackNode->SetProperty("outline binary", mitk::BoolProperty::New(true));
146  m_FeedbackNode->SetProperty("color", mitk::ColorProperty::New(255.0, 255.0, 0.0));
147  m_FeedbackNode->SetProperty("texture interpolation", mitk::BoolProperty::New(false));
148  m_FeedbackNode->SetProperty("layer", mitk::IntProperty::New(20));
149  m_FeedbackNode->SetProperty("levelwindow", mitk::LevelWindowProperty::New(mitk::LevelWindow(0, 1)));
150  m_FeedbackNode->SetProperty("name", mitk::StringProperty::New("Interpolation feedback"));
151  m_FeedbackNode->SetProperty("opacity", mitk::FloatProperty::New(0.8));
152  m_FeedbackNode->SetProperty("helper object", mitk::BoolProperty::New(true));
153 
154  m_InterpolatedSurfaceNode = mitk::DataNode::New();
155  m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(SURFACE_COLOR_RGB));
156  m_InterpolatedSurfaceNode->SetProperty("name", mitk::StringProperty::New("Surface Interpolation feedback"));
157  m_InterpolatedSurfaceNode->SetProperty("opacity", mitk::FloatProperty::New(0.5));
158  m_InterpolatedSurfaceNode->SetProperty("line width", mitk::FloatProperty::New(4.0f));
159  m_InterpolatedSurfaceNode->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false));
160  m_InterpolatedSurfaceNode->SetProperty("helper object", mitk::BoolProperty::New(true));
161  m_InterpolatedSurfaceNode->SetVisibility(false);
162 
163  m_3DContourNode = mitk::DataNode::New();
164  m_3DContourNode->SetProperty("color", mitk::ColorProperty::New(0.0, 0.0, 0.0));
165  m_3DContourNode->SetProperty("hidden object", mitk::BoolProperty::New(true));
166  m_3DContourNode->SetProperty("name", mitk::StringProperty::New("Drawn Contours"));
167  m_3DContourNode->SetProperty("material.representation", mitk::VtkRepresentationProperty::New(VTK_WIREFRAME));
168  m_3DContourNode->SetProperty("material.wireframeLineWidth", mitk::FloatProperty::New(2.0f));
169  m_3DContourNode->SetProperty("3DContourContainer", mitk::BoolProperty::New(true));
170  m_3DContourNode->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false));
171  m_3DContourNode->SetVisibility(
173  m_3DContourNode->SetVisibility(
175  m_3DContourNode->SetVisibility(
177  m_3DContourNode->SetVisibility(
179 
180  QWidget::setContentsMargins(0, 0, 0, 0);
181  if (QWidget::layout() != nullptr)
182  {
183  QWidget::layout()->setContentsMargins(0, 0, 0, 0);
184  }
185 
186  // For running 3D Interpolation in background
187  // create a QFuture and a QFutureWatcher
188 
189  connect(&m_Watcher, SIGNAL(started()), this, SLOT(StartUpdateInterpolationTimer()));
190  connect(&m_Watcher, SIGNAL(finished()), this, SLOT(OnSurfaceInterpolationFinished()));
191  connect(&m_Watcher, SIGNAL(finished()), this, SLOT(StopUpdateInterpolationTimer()));
192  m_Timer = new QTimer(this);
193  connect(m_Timer, SIGNAL(timeout()), this, SLOT(ChangeSurfaceColor()));
194 }
195 
197 {
198  if (m_DataStorage == storage)
199  {
200  return;
201  }
202 
203  if (m_DataStorage.IsNotNull())
204  {
205  m_DataStorage->RemoveNodeEvent.RemoveListener(
206  mitk::MessageDelegate1<QmitkSlicesInterpolator, const mitk::DataNode*>(this, &QmitkSlicesInterpolator::NodeRemoved)
207  );
208  }
209 
210  m_DataStorage = storage;
211  m_SurfaceInterpolator->SetDataStorage(storage);
212 
213  if (m_DataStorage.IsNotNull())
214  {
215  m_DataStorage->RemoveNodeEvent.AddListener(
216  mitk::MessageDelegate1<QmitkSlicesInterpolator, const mitk::DataNode*>(this, &QmitkSlicesInterpolator::NodeRemoved)
217  );
218  }
219 }
220 
222 {
223  if (m_DataStorage.IsNotNull())
224  {
225  return m_DataStorage;
226  }
227  else
228  {
229  return nullptr;
230  }
231 }
232 
234  const QList<mitk::SliceNavigationController *> &controllers)
235 {
236  Q_ASSERT(!controllers.empty());
237 
238  if (m_Initialized)
239  {
240  // remove old observers
241  Uninitialize();
242  }
243 
244  m_ToolManager = toolManager;
245 
246  if (m_ToolManager)
247  {
248  // set enabled only if a segmentation is selected
249  mitk::DataNode *node = m_ToolManager->GetWorkingData(0);
250  QWidget::setEnabled(node != nullptr);
251 
252  // react whenever the set of selected segmentation changes
253  m_ToolManager->WorkingDataChanged +=
255  m_ToolManager->ReferenceDataChanged += mitk::MessageDelegate<QmitkSlicesInterpolator>(
257 
258  // connect to the slice navigation controller. after each change, call the interpolator
259  foreach (mitk::SliceNavigationController *slicer, controllers)
260  {
261  // Has to be initialized
262  m_LastSNC = slicer;
263  m_TimeStep.insert(slicer, slicer->GetTime()->GetPos());
264 
265  itk::MemberCommand<QmitkSlicesInterpolator>::Pointer deleteCommand =
266  itk::MemberCommand<QmitkSlicesInterpolator>::New();
267  deleteCommand->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnSliceNavigationControllerDeleted);
268  m_ControllerToDeleteObserverTag.insert(slicer, slicer->AddObserver(itk::DeleteEvent(), deleteCommand));
269 
270  itk::MemberCommand<QmitkSlicesInterpolator>::Pointer timeChangedCommand =
271  itk::MemberCommand<QmitkSlicesInterpolator>::New();
272  timeChangedCommand->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnTimeChanged);
273  m_ControllerToTimeObserverTag.insert(
274  slicer, slicer->AddObserver(mitk::SliceNavigationController::TimeGeometryEvent(nullptr, 0), timeChangedCommand));
275 
276  itk::MemberCommand<QmitkSlicesInterpolator>::Pointer sliceChangedCommand =
277  itk::MemberCommand<QmitkSlicesInterpolator>::New();
278  sliceChangedCommand->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnSliceChanged);
279  m_ControllerToSliceObserverTag.insert(
280  slicer, slicer->AddObserver(mitk::SliceNavigationController::GeometrySliceEvent(nullptr, 0), sliceChangedCommand));
281  }
283  }
284 
285  m_Initialized = true;
286 }
287 
289 {
290  if (m_ToolManager.IsNotNull())
291  {
292  m_ToolManager->WorkingDataChanged -=
294  m_ToolManager->ReferenceDataChanged -= mitk::MessageDelegate<QmitkSlicesInterpolator>(
296  }
297 
298  foreach (mitk::SliceNavigationController *slicer, m_ControllerToSliceObserverTag.keys())
299  {
300  slicer->RemoveObserver(m_ControllerToDeleteObserverTag.take(slicer));
301  slicer->RemoveObserver(m_ControllerToTimeObserverTag.take(slicer));
302  slicer->RemoveObserver(m_ControllerToSliceObserverTag.take(slicer));
303  }
304 
305  ACTION_TO_SLICEDIMENSION.clear();
306 
307  m_ToolManager = nullptr;
308 
309  m_Initialized = false;
310 }
311 
313 {
314  if (m_Initialized)
315  {
316  // remove old observers
317  Uninitialize();
318  }
319 
320  WaitForFutures();
321 
322  if (m_DataStorage.IsNotNull())
323  {
324  m_DataStorage->RemoveNodeEvent.RemoveListener(
325  mitk::MessageDelegate1<QmitkSlicesInterpolator, const mitk::DataNode*>(this, &QmitkSlicesInterpolator::NodeRemoved)
326  );
327  if (m_DataStorage->Exists(m_3DContourNode))
328  m_DataStorage->Remove(m_3DContourNode);
329  if (m_DataStorage->Exists(m_InterpolatedSurfaceNode))
330  m_DataStorage->Remove(m_InterpolatedSurfaceNode);
331  }
332 
333  // remove observer
334  m_Interpolator->RemoveObserver(InterpolationInfoChangedObserverTag);
335  m_SurfaceInterpolator->RemoveObserver(SurfaceInterpolationInfoChangedObserverTag);
336 
337  delete m_Timer;
338 }
339 
344 {
345  QWidget::setEnabled(enable);
346 
347  // Set the gui elements of the different interpolation modi enabled
348  if (enable)
349  {
350  if (m_2DInterpolationEnabled)
351  {
352  this->Show2DInterpolationControls(true);
353  m_Interpolator->Activate2DInterpolation(true);
354  }
355  else if (m_3DInterpolationEnabled)
356  {
357  this->Show3DInterpolationControls(true);
358  this->Show3DInterpolationResult(true);
359  }
360  }
361  // Set all gui elements of the interpolation disabled
362  else
363  {
364  this->HideAllInterpolationControls();
365  this->Show3DInterpolationResult(false);
366  }
367 }
368 
370 {
371  OnInterpolationActivated(status);
372  m_Interpolator->Activate2DInterpolation(status);
373 }
374 
376 {
378 }
379 
381 {
382  if (status)
383  {
384  OnInterpolationActivated(!status);
386  this->Show3DInterpolationResult(false);
387  }
388 }
389 
390 void QmitkSlicesInterpolator::HideAllInterpolationControls()
391 {
392  this->Show2DInterpolationControls(false);
393  this->Show3DInterpolationControls(false);
394 }
395 
396 void QmitkSlicesInterpolator::Show2DInterpolationControls(bool show)
397 {
398  m_BtnApply2D->setVisible(show);
399  m_BtnApplyForAllSlices2D->setVisible(show);
400 }
401 
402 void QmitkSlicesInterpolator::Show3DInterpolationControls(bool show)
403 {
404  m_BtnApply3D->setVisible(show);
405  m_BtnSuggestPlane->setVisible(show);
406  m_ChkShowPositionNodes->setVisible(show);
407  m_BtnReinit3DInterpolation->setVisible(show);
408 }
409 
411 {
412  switch (index)
413  {
414  case 0: // Disabled
415  m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation");
416  this->HideAllInterpolationControls();
417  this->OnInterpolationActivated(false);
418  this->On3DInterpolationActivated(false);
419  this->Show3DInterpolationResult(false);
420  m_Interpolator->Activate2DInterpolation(false);
421  break;
422 
423  case 1: // 2D
424  m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation (Enabled)");
425  this->HideAllInterpolationControls();
426  this->Show2DInterpolationControls(true);
427  this->OnInterpolationActivated(true);
428  this->On3DInterpolationActivated(false);
429  m_Interpolator->Activate2DInterpolation(true);
430  break;
431 
432  case 2: // 3D
433  m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation (Enabled)");
434  this->HideAllInterpolationControls();
435  this->Show3DInterpolationControls(true);
436  this->OnInterpolationActivated(false);
437  this->On3DInterpolationActivated(true);
438  m_Interpolator->Activate2DInterpolation(false);
439  break;
440 
441  default:
442  MITK_ERROR << "Unknown interpolation method!";
443  m_CmbInterpolation->setCurrentIndex(0);
444  break;
445  }
446 }
447 
449 {
450  mitk::DataStorage::SetOfObjects::ConstPointer allContourMarkers =
451  m_DataStorage->GetSubset(mitk::NodePredicateProperty::New("isContourMarker", mitk::BoolProperty::New(true)));
452 
453  for (mitk::DataStorage::SetOfObjects::ConstIterator it = allContourMarkers->Begin(); it != allContourMarkers->End();
454  ++it)
455  {
456  it->Value()->SetProperty("helper object", mitk::BoolProperty::New(!state));
457  }
458 }
459 
461 {
462  if (m_ToolManager->GetWorkingData(0) != nullptr)
463  {
464  m_Segmentation = dynamic_cast<mitk::Image *>(m_ToolManager->GetWorkingData(0)->GetData());
465  m_BtnReinit3DInterpolation->setEnabled(true);
466  }
467  else
468  {
469  // If no workingdata is set, remove the interpolation feedback
470  this->GetDataStorage()->Remove(m_FeedbackNode);
471  m_FeedbackNode->SetData(nullptr);
472  this->GetDataStorage()->Remove(m_3DContourNode);
473  m_3DContourNode->SetData(nullptr);
474  this->GetDataStorage()->Remove(m_InterpolatedSurfaceNode);
475  m_InterpolatedSurfaceNode->SetData(nullptr);
476  m_BtnReinit3DInterpolation->setEnabled(false);
477  return;
478  }
479  // Updating the current selected segmentation for the 3D interpolation
481 
482  if (m_2DInterpolationEnabled)
483  {
484  OnInterpolationActivated(true); // re-initialize if needed
485  }
486  this->CheckSupportedImageDimension();
487 }
488 
490 {
491 }
492 
493 void QmitkSlicesInterpolator::OnTimeChanged(itk::Object *sender, const itk::EventObject &e)
494 {
495  // Check if we really have a GeometryTimeEvent
496  if (!dynamic_cast<const mitk::SliceNavigationController::GeometryTimeEvent *>(&e))
497  return;
498 
499  mitk::SliceNavigationController *slicer = dynamic_cast<mitk::SliceNavigationController *>(sender);
500  Q_ASSERT(slicer);
501 
502  m_TimeStep[slicer] = slicer->GetTime()->GetPos();
503 
504  m_SurfaceInterpolator->SetCurrentTimeStep(slicer->GetTime()->GetPos());
505 
506  if (m_LastSNC == slicer)
507  {
508  slicer->SendSlice(); // will trigger a new interpolation
509  }
510 }
511 
512 void QmitkSlicesInterpolator::OnSliceChanged(itk::Object *sender, const itk::EventObject &e)
513 {
514  // Check whether we really have a GeometrySliceEvent
515  if (!dynamic_cast<const mitk::SliceNavigationController::GeometrySliceEvent *>(&e))
516  return;
517 
518  mitk::SliceNavigationController *slicer = dynamic_cast<mitk::SliceNavigationController *>(sender);
519 
521  {
522  slicer->GetRenderer()->RequestUpdate();
523  }
524 }
525 
528 {
529  if (!m_2DInterpolationEnabled)
530  return false;
531 
532  try
533  {
536 
537  mitk::TimeGeometry *tsg = event.GetTimeGeometry();
538  if (tsg && m_TimeStep.contains(slicer))
539  {
540  mitk::SlicedGeometry3D *slicedGeometry =
541  dynamic_cast<mitk::SlicedGeometry3D *>(tsg->GetGeometryForTimeStep(m_TimeStep[slicer]).GetPointer());
542  if (slicedGeometry)
543  {
544  m_LastSNC = slicer;
545  mitk::PlaneGeometry *plane =
546  dynamic_cast<mitk::PlaneGeometry *>(slicedGeometry->GetPlaneGeometry(event.GetPos()));
547  if (plane)
548  Interpolate(plane, m_TimeStep[slicer], slicer);
549  return true;
550  }
551  }
552  }
553  catch (const std::bad_cast &)
554  {
555  return false; // so what
556  }
557 
558  return false;
559 }
560 
562  unsigned int timeStep,
564 {
565  if (m_ToolManager)
566  {
567  mitk::DataNode *node = m_ToolManager->GetWorkingData(0);
568  if (node)
569  {
570  m_Segmentation = dynamic_cast<mitk::Image *>(node->GetData());
571  if (m_Segmentation)
572  {
573  int clickedSliceDimension(-1);
574  int clickedSliceIndex(-1);
575 
576  // calculate real slice position, i.e. slice of the image and not slice of the TimeSlicedGeometry
577  mitk::SegTool2D::DetermineAffectedImageSlice(m_Segmentation, plane, clickedSliceDimension, clickedSliceIndex);
578 
579  mitk::Image::Pointer interpolation =
580  m_Interpolator->Interpolate(clickedSliceDimension, clickedSliceIndex, plane, timeStep);
581  m_FeedbackNode->SetData(interpolation);
582 
583  m_LastSNC = slicer;
584  m_LastSliceIndex = clickedSliceIndex;
585  }
586  }
587  }
588 }
589 
591 {
592  mitk::Surface::Pointer interpolatedSurface = m_SurfaceInterpolator->GetInterpolationResult();
593  mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0);
594 
595  if (interpolatedSurface.IsNotNull() && workingNode &&
596  workingNode->IsVisible(
598  {
599  m_BtnApply3D->setEnabled(true);
600  m_BtnSuggestPlane->setEnabled(true);
601  m_InterpolatedSurfaceNode->SetData(interpolatedSurface);
602  m_3DContourNode->SetData(m_SurfaceInterpolator->GetContoursAsSurface());
603 
604  this->Show3DInterpolationResult(true);
605 
606  if (!m_DataStorage->Exists(m_InterpolatedSurfaceNode))
607  {
608  m_DataStorage->Add(m_InterpolatedSurfaceNode);
609  }
610  if (!m_DataStorage->Exists(m_3DContourNode))
611  {
612  m_DataStorage->Add(m_3DContourNode, workingNode);
613  }
614  }
615  else if (interpolatedSurface.IsNull())
616  {
617  m_BtnApply3D->setEnabled(false);
618  m_BtnSuggestPlane->setEnabled(false);
619 
620  if (m_DataStorage->Exists(m_InterpolatedSurfaceNode))
621  {
622  this->Show3DInterpolationResult(false);
623  }
624  }
625 
626  m_BtnReinit3DInterpolation->setEnabled(true);
627 
628  foreach (mitk::SliceNavigationController *slicer, m_ControllerToTimeObserverTag.keys())
629  {
630  slicer->GetRenderer()->RequestUpdate();
631  }
632 }
633 
635 {
636  if (m_Segmentation && m_FeedbackNode->GetData())
637  {
638  // Make sure that for reslicing and overwriting the same alogrithm is used. We can specify the mode of the vtk
639  // reslicer
640  vtkSmartPointer<mitkVtkImageOverwrite> reslice = vtkSmartPointer<mitkVtkImageOverwrite>::New();
641 
642  // Set slice as input
643  mitk::Image::Pointer slice = dynamic_cast<mitk::Image *>(m_FeedbackNode->GetData());
644  reslice->SetInputSlice(slice->GetSliceData()->GetVtkImageAccessor(slice)->GetVtkImageData());
645  // set overwrite mode to true to write back to the image volume
646  reslice->SetOverwriteMode(true);
647  reslice->Modified();
648 
650  extractor->SetInput(m_Segmentation);
651  unsigned int timestep = m_LastSNC->GetTime()->GetPos();
652  extractor->SetTimeStep(timestep);
653  extractor->SetWorldGeometry(m_LastSNC->GetCurrentPlaneGeometry());
654  extractor->SetVtkOutputRequest(true);
655  extractor->SetResliceTransformByGeometry(m_Segmentation->GetTimeGeometry()->GetGeometryForTimeStep(timestep));
656 
657  extractor->Modified();
658  extractor->Update();
659 
660  // the image was modified within the pipeline, but not marked so
661  m_Segmentation->Modified();
662  m_Segmentation->GetVtkImageData()->Modified();
663 
664  m_FeedbackNode->SetData(nullptr);
666  }
667 }
668 
670 {
671  /*
672  * What exactly is done here:
673  * 1. We create an empty diff image for the current segmentation
674  * 2. All interpolated slices are written into the diff image
675  * 3. Then the diffimage is applied to the original segmentation
676  */
677  if (m_Segmentation)
678  {
679  mitk::Image::Pointer image3D = m_Segmentation;
680  unsigned int timeStep(slicer->GetTime()->GetPos());
681  if (m_Segmentation->GetDimension() == 4)
682  {
684  timeSelector->SetInput(m_Segmentation);
685  timeSelector->SetTimeNr(timeStep);
686  timeSelector->Update();
687  image3D = timeSelector->GetOutput();
688  }
689  // create a empty diff image for the undo operation
691  diffImage->Initialize(image3D);
692 
693  // Create scope for ImageWriteAccessor so that the accessor is destroyed
694  // after the image is initialized. Otherwise later image access will lead to an error
695  {
696  mitk::ImageWriteAccessor imAccess(diffImage);
697 
698  // Set all pixels to zero
699  mitk::PixelType pixelType(mitk::MakeScalarPixelType<mitk::Tool::DefaultSegmentationDataType>());
700 
701  // For legacy purpose support former pixel type of segmentations (before multilabel)
702  if (m_Segmentation->GetImageDescriptor()->GetChannelDescriptor().GetPixelType().GetComponentType() ==
703  itk::ImageIOBase::UCHAR)
704  {
705  pixelType = mitk::MakeScalarPixelType<unsigned char>();
706  }
707 
708  memset(imAccess.GetData(),
709  0,
710  (pixelType.GetBpe() >> 3) * diffImage->GetDimension(0) * diffImage->GetDimension(1) *
711  diffImage->GetDimension(2));
712  }
713 
714  // Since we need to shift the plane it must be clone so that the original plane isn't altered
715  mitk::PlaneGeometry::Pointer reslicePlane = slicer->GetCurrentPlaneGeometry()->Clone();
716 
717  int sliceDimension(-1);
718  int sliceIndex(-1);
719  mitk::SegTool2D::DetermineAffectedImageSlice(m_Segmentation, reslicePlane, sliceDimension, sliceIndex);
720 
721  unsigned int zslices = m_Segmentation->GetDimension(sliceDimension);
723 
724  mitk::Point3D origin = reslicePlane->GetOrigin();
725  unsigned int totalChangedSlices(0);
726 
727  for (unsigned int sliceIndex = 0; sliceIndex < zslices; ++sliceIndex)
728  {
729  // Transforming the current origin of the reslice plane
730  // so that it matches the one of the next slice
731  m_Segmentation->GetSlicedGeometry()->WorldToIndex(origin, origin);
732  origin[sliceDimension] = sliceIndex;
733  m_Segmentation->GetSlicedGeometry()->IndexToWorld(origin, origin);
734  reslicePlane->SetOrigin(origin);
735  // Set the slice as 'input'
736  mitk::Image::Pointer interpolation =
737  m_Interpolator->Interpolate(sliceDimension, sliceIndex, reslicePlane, timeStep);
738 
739  if (interpolation.IsNotNull()) // we don't check if interpolation is necessary/sensible - but m_Interpolator does
740  {
741  // Setting up the reslicing pipeline which allows us to write the interpolation results back into
742  // the image volume
743  vtkSmartPointer<mitkVtkImageOverwrite> reslice = vtkSmartPointer<mitkVtkImageOverwrite>::New();
744 
745  // set overwrite mode to true to write back to the image volume
746  reslice->SetInputSlice(interpolation->GetSliceData()->GetVtkImageAccessor(interpolation)->GetVtkImageData());
747  reslice->SetOverwriteMode(true);
748  reslice->Modified();
749 
751  diffslicewriter->SetInput(diffImage);
752  diffslicewriter->SetTimeStep(0);
753  diffslicewriter->SetWorldGeometry(reslicePlane);
754  diffslicewriter->SetVtkOutputRequest(true);
755  diffslicewriter->SetResliceTransformByGeometry(diffImage->GetTimeGeometry()->GetGeometryForTimeStep(0));
756 
757  diffslicewriter->Modified();
758  diffslicewriter->Update();
759  ++totalChangedSlices;
760  }
762  }
764 
765  if (totalChangedSlices > 0)
766  {
767  // store undo stack items
768  if (true)
769  {
770  // create do/undo operations
772  new mitk::ApplyDiffImageOperation(mitk::OpTEST, m_Segmentation, diffImage, timeStep);
774  new mitk::ApplyDiffImageOperation(mitk::OpTEST, m_Segmentation, diffImage, timeStep);
775  undoOp->SetFactor(-1.0);
776  std::stringstream comment;
777  comment << "Confirm all interpolations (" << totalChangedSlices << ")";
778  mitk::OperationEvent *undoStackItem =
779  new mitk::OperationEvent(mitk::DiffImageApplier::GetInstanceForUndo(), doOp, undoOp, comment.str());
783 
784  // acutally apply the changes here to the original image
786  }
787  }
788 
789  m_FeedbackNode->SetData(nullptr);
791  }
792 }
793 
795 {
796  // this redirect is for calling from outside
797 
798  if (slicer == nullptr)
800  else
801  AcceptAllInterpolations(slicer);
802 }
803 
805 {
806  QMenu orientationPopup(this);
807  std::map<QAction *, mitk::SliceNavigationController *>::const_iterator it;
808  for (it = ACTION_TO_SLICEDIMENSION.begin(); it != ACTION_TO_SLICEDIMENSION.end(); it++)
809  orientationPopup.addAction(it->first);
810 
811  connect(&orientationPopup, SIGNAL(triggered(QAction *)), this, SLOT(OnAcceptAllPopupActivated(QAction *)));
812 
813  orientationPopup.exec(QCursor::pos());
814 }
815 
817 {
818  if (m_InterpolatedSurfaceNode.IsNotNull() && m_InterpolatedSurfaceNode->GetData())
819  {
820  mitk::DataNode *segmentationNode = m_ToolManager->GetWorkingData(0);
821  mitk::Image *currSeg = dynamic_cast<mitk::Image *>(segmentationNode->GetData());
822 
824  s2iFilter->MakeOutputBinaryOn();
825  if (currSeg->GetPixelType().GetComponentType() == itk::ImageIOBase::USHORT)
826  s2iFilter->SetUShortBinaryPixelType(true);
827  s2iFilter->SetInput(dynamic_cast<mitk::Surface *>(m_InterpolatedSurfaceNode->GetData()));
828 
829  // check if ToolManager holds valid ReferenceData
830  if (m_ToolManager->GetReferenceData(0) == nullptr || m_ToolManager->GetWorkingData(0) == nullptr)
831  {
832  return;
833  }
834  s2iFilter->SetImage(dynamic_cast<mitk::Image *>(m_ToolManager->GetReferenceData(0)->GetData()));
835  s2iFilter->Update();
836 
837  mitk::Image::Pointer newSeg = s2iFilter->GetOutput();
838 
839  unsigned int timestep = m_LastSNC->GetTime()->GetPos();
840  mitk::ImageReadAccessor readAccess(newSeg, newSeg->GetVolumeData(timestep));
841  const void *cPointer = readAccess.GetData();
842 
843  if (currSeg && cPointer)
844  {
845  currSeg->SetVolume(cPointer, timestep, 0);
846  }
847  else
848  {
849  return;
850  }
851 
852  m_CmbInterpolation->setCurrentIndex(0);
855  float rgb[3];
856  segmentationNode->GetColor(rgb);
857  segSurface->SetColor(rgb);
858  segSurface->SetData(m_InterpolatedSurfaceNode->GetData());
859  std::stringstream stream;
860  stream << segmentationNode->GetName();
861  stream << "_";
862  stream << "3D-interpolation";
863  segSurface->SetName(stream.str());
864  segSurface->SetProperty("opacity", mitk::FloatProperty::New(0.7));
865  segSurface->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(true));
866  segSurface->SetProperty("3DInterpolationResult", mitk::BoolProperty::New(true));
867  segSurface->SetVisibility(false);
868  m_DataStorage->Add(segSurface, segmentationNode);
869  this->Show3DInterpolationResult(false);
870  }
871 }
872 
873 void ::QmitkSlicesInterpolator::OnSuggestPlaneClicked()
874 {
875  if (m_PlaneWatcher.isRunning())
876  m_PlaneWatcher.waitForFinished();
877  m_PlaneFuture = QtConcurrent::run(this, &QmitkSlicesInterpolator::RunPlaneSuggestion);
878  m_PlaneWatcher.setFuture(m_PlaneFuture);
879 }
880 
881 void ::QmitkSlicesInterpolator::RunPlaneSuggestion()
882 {
883  if (m_FirstRun)
885  else
887 
888  m_EdgeDetector->SetSegmentationMask(m_Segmentation);
889  m_EdgeDetector->SetInput(dynamic_cast<mitk::Image *>(m_ToolManager->GetReferenceData(0)->GetData()));
890  m_EdgeDetector->Update();
891 
893  uGrid->SetVtkUnstructuredGrid(m_EdgeDetector->GetOutput()->GetVtkUnstructuredGrid());
894 
896 
897  mitk::Surface::Pointer surface = dynamic_cast<mitk::Surface *>(m_InterpolatedSurfaceNode->GetData());
898 
899  vtkSmartPointer<vtkPolyData> vtkpoly = surface->GetVtkPolyData();
900  vtkSmartPointer<vtkPoints> vtkpoints = vtkpoly->GetPoints();
901 
902  vtkSmartPointer<vtkUnstructuredGrid> vGrid = vtkSmartPointer<vtkUnstructuredGrid>::New();
903  vtkSmartPointer<vtkPolyVertex> verts = vtkSmartPointer<vtkPolyVertex>::New();
904 
905  verts->GetPointIds()->SetNumberOfIds(vtkpoints->GetNumberOfPoints());
906  for (int i = 0; i < vtkpoints->GetNumberOfPoints(); i++)
907  {
908  verts->GetPointIds()->SetId(i, i);
909  }
910 
911  vGrid->Allocate(1);
912  vGrid->InsertNextCell(verts->GetCellType(), verts->GetPointIds());
913  vGrid->SetPoints(vtkpoints);
914 
916  interpolationGrid->SetVtkUnstructuredGrid(vGrid);
917 
918  m_PointScorer->SetInput(0, uGrid);
919  m_PointScorer->SetInput(1, interpolationGrid);
920  m_PointScorer->Update();
921 
923  scoredGrid = m_PointScorer->GetOutput();
924 
926 
929  clusterFilter->SetInput(scoredGrid);
930  clusterFilter->SetMeshing(false);
931  clusterFilter->SetMinPts(4);
932  clusterFilter->Seteps(spacing);
933  clusterFilter->Update();
934 
936 
937  // Create plane suggestion
940  mitk::PlaneProposer planeProposer;
941  std::vector<mitk::UnstructuredGrid::Pointer> grids = clusterFilter->GetAllClusters();
942 
943  planeProposer.SetUnstructuredGrids(grids);
944  mitk::SliceNavigationController::Pointer snc = br->GetSliceNavigationController();
945  planeProposer.SetSliceNavigationController(snc);
946  planeProposer.SetUseDistances(true);
947  try
948  {
949  planeProposer.CreatePlaneInfo();
950  }
951  catch (const mitk::Exception &e)
952  {
953  MITK_ERROR << e.what();
954  }
955 
957 
958  m_FirstRun = false;
959 }
960 
962 {
964  mitk::NodePredicateProperty::New("3DContourContainer", mitk::BoolProperty::New(true));
965  mitk::DataStorage::SetOfObjects::ConstPointer contourNodes =
966  m_DataStorage->GetDerivations(m_ToolManager->GetWorkingData(0), pred);
967 
968  if (contourNodes->Size() != 0)
969  {
970  m_BtnApply3D->setEnabled(true);
971  m_3DContourNode = contourNodes->at(0);
972  mitk::Surface::Pointer contours = dynamic_cast<mitk::Surface *>(m_3DContourNode->GetData());
973  if (contours)
975  m_BtnReinit3DInterpolation->setEnabled(false);
976  }
977  else
978  {
979  m_BtnApply3D->setEnabled(false);
980  QMessageBox errorInfo;
981  errorInfo.setWindowTitle("Reinitialize surface interpolation");
982  errorInfo.setIcon(QMessageBox::Information);
983  errorInfo.setText("No contours available for the selected segmentation!");
984  errorInfo.exec();
985  }
986 }
987 
989 {
990  try
991  {
992  std::map<QAction *, mitk::SliceNavigationController *>::const_iterator iter = ACTION_TO_SLICEDIMENSION.find(action);
993  if (iter != ACTION_TO_SLICEDIMENSION.end())
994  {
995  mitk::SliceNavigationController *slicer = iter->second;
996  AcceptAllInterpolations(slicer);
997  }
998  }
999  catch (...)
1000  {
1001  /* Showing message box with possible memory error */
1002  QMessageBox errorInfo;
1003  errorInfo.setWindowTitle("Interpolation Process");
1004  errorInfo.setIcon(QMessageBox::Critical);
1005  errorInfo.setText("An error occurred during interpolation. Possible cause: Not enough memory!");
1006  errorInfo.exec();
1007 
1008  // additional error message on std::cerr
1009  std::cerr << "Ill construction in " __FILE__ " l. " << __LINE__ << std::endl;
1010  }
1011 }
1012 
1014 {
1015  m_2DInterpolationEnabled = on;
1016 
1017  try
1018  {
1019  if (m_DataStorage.IsNotNull())
1020  {
1021  if (on && !m_DataStorage->Exists(m_FeedbackNode))
1022  {
1023  m_DataStorage->Add(m_FeedbackNode);
1024  }
1025  }
1026  }
1027  catch (...)
1028  {
1029  // don't care (double add/remove)
1030  }
1031 
1032  if (m_ToolManager)
1033  {
1034  mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0);
1035  mitk::DataNode *referenceNode = m_ToolManager->GetReferenceData(0);
1036  QWidget::setEnabled(workingNode != nullptr);
1037 
1038  m_BtnApply2D->setEnabled(on);
1039  m_FeedbackNode->SetVisibility(on);
1040 
1041  if (!on)
1042  {
1044  return;
1045  }
1046 
1047  if (workingNode)
1048  {
1049  mitk::Image *segmentation = dynamic_cast<mitk::Image *>(workingNode->GetData());
1050  if (segmentation)
1051  {
1052  m_Interpolator->SetSegmentationVolume(segmentation);
1053 
1054  if (referenceNode)
1055  {
1056  mitk::Image *referenceImage = dynamic_cast<mitk::Image *>(referenceNode->GetData());
1057  m_Interpolator->SetReferenceVolume(referenceImage); // may be nullptr
1058  }
1059  }
1060  }
1061  }
1062 
1064 }
1065 
1067 {
1068  m_SurfaceInterpolator->Interpolate();
1069 }
1070 
1072 {
1073  m_Timer->start(500);
1074 }
1075 
1077 {
1078  m_Timer->stop();
1079  m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(SURFACE_COLOR_RGB));
1081  mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3"))->GetRenderWindow());
1082 }
1083 
1085 {
1086  float currentColor[3];
1087  m_InterpolatedSurfaceNode->GetColor(currentColor);
1088 
1089  if (currentColor[2] == SURFACE_COLOR_RGB[2])
1090  {
1091  m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(1.0f, 1.0f, 1.0f));
1092  }
1093  else
1094  {
1095  m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(SURFACE_COLOR_RGB));
1096  }
1097  m_InterpolatedSurfaceNode->Update();
1099  mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3"))->GetRenderWindow());
1100 }
1101 
1103 {
1104  m_3DInterpolationEnabled = on;
1105 
1106  this->CheckSupportedImageDimension();
1107  try
1108  {
1109  if (m_DataStorage.IsNotNull() && m_ToolManager && m_3DInterpolationEnabled)
1110  {
1111  mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0);
1112 
1113  if (workingNode)
1114  {
1115  bool isInterpolationResult(false);
1116  workingNode->GetBoolProperty("3DInterpolationResult", isInterpolationResult);
1118  mitk::NodePredicateProperty::New("3DInterpolationResult", mitk::BoolProperty::New(true)),
1120  mitk::DataStorage::SetOfObjects::ConstPointer interpolationResults =
1121  m_DataStorage->GetDerivations(workingNode, pred);
1122 
1123  for (unsigned int i = 0; i < interpolationResults->Size(); ++i)
1124  {
1125  mitk::DataNode::Pointer currNode = interpolationResults->at(i);
1126  if (currNode.IsNotNull())
1127  m_DataStorage->Remove(currNode);
1128  }
1129 
1130  if ((workingNode->IsVisible(
1132  !isInterpolationResult && m_3DInterpolationEnabled)
1133  {
1134  int ret = QMessageBox::Yes;
1135 
1136  if (m_SurfaceInterpolator->EstimatePortionOfNeededMemory() > 0.5)
1137  {
1138  QMessageBox msgBox;
1139  msgBox.setText("Due to short handed system memory the 3D interpolation may be very slow!");
1140  msgBox.setInformativeText("Are you sure you want to activate the 3D interpolation?");
1141  msgBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
1142  ret = msgBox.exec();
1143  }
1144 
1145  if (m_Watcher.isRunning())
1146  m_Watcher.waitForFinished();
1147 
1148  if (ret == QMessageBox::Yes)
1149  {
1150  m_Future = QtConcurrent::run(this, &QmitkSlicesInterpolator::Run3DInterpolation);
1151  m_Watcher.setFuture(m_Future);
1152  }
1153  else
1154  {
1155  m_CmbInterpolation->setCurrentIndex(0);
1156  }
1157  }
1158  else if (!m_3DInterpolationEnabled)
1159  {
1160  this->Show3DInterpolationResult(false);
1161  m_BtnApply3D->setEnabled(m_3DInterpolationEnabled);
1162  m_BtnSuggestPlane->setEnabled(m_3DInterpolationEnabled);
1163  }
1164  }
1165  else
1166  {
1167  QWidget::setEnabled(false);
1168  m_ChkShowPositionNodes->setEnabled(m_3DInterpolationEnabled);
1169  }
1170  }
1171  if (!m_3DInterpolationEnabled)
1172  {
1173  this->Show3DInterpolationResult(false);
1174  m_BtnApply3D->setEnabled(m_3DInterpolationEnabled);
1175  m_BtnSuggestPlane->setEnabled(m_3DInterpolationEnabled);
1176  }
1177  }
1178  catch (...)
1179  {
1180  MITK_ERROR << "Error with 3D surface interpolation!";
1181  }
1183 }
1184 
1186 {
1187  // only to be called from the outside world
1188  // just a redirection to OnInterpolationActivated
1190 }
1191 
1193 {
1194  // only to be called from the outside world
1195  // just a redirection to OnInterpolationActivated
1197 }
1198 
1200 {
1202 }
1203 
1204 void QmitkSlicesInterpolator::OnInterpolationInfoChanged(const itk::EventObject & /*e*/)
1205 {
1206  // something (e.g. undo) changed the interpolation info, we should refresh our display
1208 }
1209 
1211 {
1212  if (m_3DInterpolationEnabled)
1213  {
1214  if (m_Watcher.isRunning())
1215  m_Watcher.waitForFinished();
1216  m_Future = QtConcurrent::run(this, &QmitkSlicesInterpolator::Run3DInterpolation);
1217  m_Watcher.setFuture(m_Future);
1218  }
1219 }
1220 
1222 {
1223  // New ContourList = hide current interpolation
1225 
1226  if (m_DataStorage.IsNotNull() && m_ToolManager && m_LastSNC)
1227  {
1228  mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0);
1229 
1230  if (workingNode)
1231  {
1232  bool isInterpolationResult(false);
1233  workingNode->GetBoolProperty("3DInterpolationResult", isInterpolationResult);
1234 
1235  if (!isInterpolationResult)
1236  {
1237  QWidget::setEnabled(true);
1238 
1239  // In case the time is not valid use 0 to access the time geometry of the working node
1240  unsigned int time_position = 0;
1241  if (m_LastSNC->GetTime() != nullptr)
1242  time_position = m_LastSNC->GetTime()->GetPos();
1243 
1244  mitk::Vector3D spacing = workingNode->GetData()->GetGeometry(time_position)->GetSpacing();
1245  double minSpacing(100);
1246  double maxSpacing(0);
1247  for (int i = 0; i < 3; i++)
1248  {
1249  if (spacing[i] < minSpacing)
1250  {
1251  minSpacing = spacing[i];
1252  }
1253  if (spacing[i] > maxSpacing)
1254  {
1255  maxSpacing = spacing[i];
1256  }
1257  }
1258 
1259  m_SurfaceInterpolator->SetMaxSpacing(maxSpacing);
1260  m_SurfaceInterpolator->SetMinSpacing(minSpacing);
1261  m_SurfaceInterpolator->SetDistanceImageVolume(50000);
1262 
1263  mitk::Image *segmentationImage = dynamic_cast<mitk::Image *>(workingNode->GetData());
1264  /*if (segmentationImage->GetDimension() == 3)
1265  {*/
1266  m_SurfaceInterpolator->SetCurrentInterpolationSession(segmentationImage);
1267  m_SurfaceInterpolator->SetCurrentTimeStep(time_position);
1268  //}
1269  /*else
1270  MITK_INFO<<"3D Interpolation is only supported for 3D images at the moment!";*/
1271 
1272  if (m_3DInterpolationEnabled)
1273  {
1274  if (m_Watcher.isRunning())
1275  m_Watcher.waitForFinished();
1276  m_Future = QtConcurrent::run(this, &QmitkSlicesInterpolator::Run3DInterpolation);
1277  m_Watcher.setFuture(m_Future);
1278  }
1279  }
1280  }
1281  else
1282  {
1283  QWidget::setEnabled(false);
1284  }
1285  }
1286 }
1287 
1289 {
1290  if (m_InterpolatedSurfaceNode.IsNotNull())
1291  m_InterpolatedSurfaceNode->SetVisibility(status);
1292 
1293  if (m_3DContourNode.IsNotNull())
1294  m_3DContourNode->SetVisibility(
1296 
1298 }
1299 
1300 void QmitkSlicesInterpolator::CheckSupportedImageDimension()
1301 {
1302  if (m_ToolManager->GetWorkingData(0))
1303  m_Segmentation = dynamic_cast<mitk::Image *>(m_ToolManager->GetWorkingData(0)->GetData());
1304 
1305  /*if (m_3DInterpolationEnabled && m_Segmentation && m_Segmentation->GetDimension() != 3)
1306  {
1307  QMessageBox info;
1308  info.setWindowTitle("3D Interpolation Process");
1309  info.setIcon(QMessageBox::Information);
1310  info.setText("3D Interpolation is only supported for 3D images at the moment!");
1311  info.exec();
1312  m_CmbInterpolation->setCurrentIndex(0);
1313  }*/
1314 }
1315 
1317  const itk::EventObject & /*e*/)
1318 {
1319  // Don't know how to avoid const_cast here?!
1321  dynamic_cast<mitk::SliceNavigationController *>(const_cast<itk::Object *>(sender));
1322  if (slicer)
1323  {
1324  m_ControllerToTimeObserverTag.remove(slicer);
1325  m_ControllerToSliceObserverTag.remove(slicer);
1326  m_ControllerToDeleteObserverTag.remove(slicer);
1327  }
1328 }
1329 
1330 void QmitkSlicesInterpolator::WaitForFutures()
1331 {
1332  if (m_Watcher.isRunning())
1333  {
1334  m_Watcher.waitForFinished();
1335  }
1336 
1337  if (m_PlaneWatcher.isRunning())
1338  {
1339  m_PlaneWatcher.waitForFinished();
1340  }
1341 }
1342 
1343 void QmitkSlicesInterpolator::NodeRemoved(const mitk::DataNode* node)
1344 {
1345  if ((m_ToolManager && m_ToolManager->GetWorkingData(0) == node) ||
1346  node == m_3DContourNode ||
1347  node == m_FeedbackNode ||
1348  node == m_InterpolatedSurfaceNode)
1349  {
1350  WaitForFutures();
1351  }
1352 }
QmitkSlicesInterpolator(QWidget *parent=nullptr, const char *name=nullptr)
void Progress(unsigned int steps=1)
Sets the current amount of progress to current progress + steps.
void ReinitializeInterpolation(mitk::Surface::Pointer contours)
Reinitializes the interpolation using the provided contour data.
Operation, that holds information about some image difference.
Class for storing surfaces (vtkPolyData).
Definition: mitkSurface.h:28
void OnAcceptAllPopupActivated(QAction *action)
void IndexToWorld(const mitk::Vector3D &vec_units, mitk::Vector3D &vec_mm) const
Convert (continuous or discrete) index coordinates of a vector vec_units to world coordinates (in mm)...
Data management class that handles &#39;was created by&#39; relations.
static Pointer New()
const std::map< QAction *, mitk::SliceNavigationController * > createActionToSliceDimension()
void OnInterpolationMethodChanged(int index)
static BaseRenderer * GetInstance(vtkRenderWindow *renWin)
static vtkRenderWindow * GetRenderWindowByName(const std::string &name)
static Pointer New()
const mitk::PixelType GetPixelType(int n=0) const
Returns the PixelType of channel n.
Definition: mitkImage.cpp:101
float SURFACE_COLOR_RGB[3]
#define MITK_ERROR
Definition: mitkLogMacros.h:20
void Initialize(mitk::ToolManager *toolManager, const QList< mitk::SliceNavigationController *> &controllers)
static Pointer New()
void OnSliceChanged(itk::Object *sender, const itk::EventObject &)
void OnInterpolationInfoChanged(const itk::EventObject &)
DataCollection - Class to facilitate loading/accessing structured data.
static Pointer New()
virtual vtkImageData * GetVtkImageData(int t=0, int n=0)
Get a volume at a specific time t of channel n as a vtkImageData.
Definition: mitkImage.cpp:217
Pointer Clone() const
void * GetData()
Gives full data access.
Constants for most interaction classes, due to the generic StateMachines.
bool GetBoolProperty(const char *propertyKey, bool &boolValue, const mitk::BaseRenderer *renderer=nullptr) const
Convenience access method for bool properties (instances of BoolProperty)
static ProgressBar * GetInstance()
static method to get the GUI dependent ProgressBar-instance so the methods for steps to do and progre...
Controls the selection of the slice the associated BaseRenderer will display.
virtual mitk::PlaneGeometry * GetPlaneGeometry(int s) const
Returns the PlaneGeometry of the slice (s).
void SignalShowMarkerNodes(bool)
vcl_size_t GetBpe() const
Get the number of bits per element (of an element)
virtual bool SetVolume(const void *data, int t=0, int n=0)
Set data as volume at time t in channel n. It is in the responsibility of the caller to ensure that t...
Definition: mitkImage.cpp:669
static Pointer New()
void AcceptAllInterpolations(mitk::SliceNavigationController *slicer)
The LevelWindow class Class to store level/window values.
static Pointer New()
int GetComponentType() const
Get the component type (the scalar (!) type). Each element may contain m_NumberOfComponents (more tha...
const mitk::TimeGeometry * GetTimeGeometry() const
Return the TimeGeometry of the data as const pointer.
Definition: mitkBaseData.h:61
virtual void SendSlice()
Send the currently selected slice to the connected observers (renderers)
void SetUseDistances(bool)
If true, the three clusters with the biggest mean distances are used for plane proposal Required the ...
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
void FinishInterpolation(mitk::SliceNavigationController *slicer=nullptr)
mitk::DataStorage * GetDataStorage()
bool IsVisible(const mitk::BaseRenderer *renderer, const char *propertyKey="visible", bool defaultIsOn=true) const
Convenience access method for visibility properties (instances of BoolProperty). Return value is the ...
Definition: mitkDataNode.h:462
static DiffImageApplier * GetInstanceForUndo()
unsigned int GetDimension() const
Get dimension of the image.
Definition: mitkImage.cpp:106
bool GetColor(float rgb[3], const mitk::BaseRenderer *renderer=nullptr, const char *propertyKey="color") const
Convenience access method for color properties (instances of ColorProperty)
static Pointer New()
An object of this class represents an exception of MITK. Please don&#39;t instantiate exceptions manually...
Definition: mitkException.h:45
static RenderingManager * GetInstance()
void CreatePlaneInfo()
Creates the actual plane proposal.
Image class for storing images.
Definition: mitkImage.h:72
const mitk::PlaneGeometry * GetCurrentPlaneGeometry()
Returns the currently selected Plane in the current BaseGeometry (if existent).
SlicedGeometry3D * GetSlicedGeometry(unsigned int t=0) const
Convenience access method for the geometry, which is of type SlicedGeometry3D (or a sub-class of it)...
bool TranslateAndInterpolateChangedSlice(const itk::EventObject &e, mitk::SliceNavigationController *slicer)
std::map< QAction *, mitk::SliceNavigationController * > ACTION_TO_SLICEDIMENSION
void OnTimeChanged(itk::Object *sender, const itk::EventObject &)
static Pointer New()
static Pointer New(const char *_arg)
void SetSliceNavigationController(itk::SmartPointer< mitk::SliceNavigationController > &snc)
void WorldToIndex(const mitk::Point3D &pt_mm, mitk::Point3D &pt_units) const
Convert world coordinates (in mm) of a point to (continuous!) index coordinates.
Describes the geometry of a data object consisting of slices.
void ExecuteOperation(Operation *operation) override
static Pointer New()
static Pointer New(const char *_arg)
virtual void Remove(const DataNode *node)=0
Removes node from the DataStorage.
void RequestUpdate(vtkRenderWindow *renderWindow)
void SetDataStorage(mitk::DataStorage::Pointer storage)
void AddStepsToDo(unsigned int steps)
Adds steps to totalSteps.
The PlaneProposer creates a new plane based on an input point cloud.
static Pointer New()
const mitk::Vector3D GetSpacing() const
Get the spacing (size of a pixel).
void OnSurfaceInterpolationInfoChanged(const itk::EventObject &)
static SurfaceInterpolationController * GetInstance()
virtual BaseGeometry::Pointer GetGeometryForTimeStep(TimeStepType timeStep) const =0
Returns the geometry which corresponds to the given time step.
virtual bool SetOperationEvent(UndoStackItem *stackItem)=0
static UndoModel * GetCurrentUndoModel()
gives access to the currently used UndoModel Introduced to access special functions of more specific ...
mitk::Stepper * GetTime()
Get the Stepper through the time.
virtual unsigned int GetPos() const
ImageWriteAccessor class to get locked write-access for a particular image part.
Describes a two-dimensional, rectangular plane.
static void IncCurrObjectEventId()
Increases the current ObjectEventId For example if a button click generates operations the ObjectEven...
void Show3DInterpolationResult(bool)
Set the visibility of the 3d interpolation.
ImageDescriptor::Pointer GetImageDescriptor() const
Definition: mitkImage.h:528
BaseRenderer * GetRenderer() const
Gets the BaseRenderer associated with this SNC (if any). While the BaseRenderer is not directly used ...
ImageReadAccessor class to get locked read access for a particular image part.
mitk::BaseGeometry * GetGeometry(int t=0) const
Return the geometry, which is a TimeGeometry, of the data as non-const pointer.
Definition: mitkBaseData.h:138
void Interpolate(mitk::PlaneGeometry *plane, unsigned int timeStep, mitk::SliceNavigationController *slicer)
static void IncCurrGroupEventId()
Increases the current GroupEventId For example if a button click generates operations the GroupEventI...
static Pointer New()
void OnSliceNavigationControllerDeleted(const itk::Object *sender, const itk::EventObject &)
void RequestUpdateAll(RequestType type=REQUEST_UPDATE_ALL)
Represents a pair of operations: undo and the according redo.
const void * GetData() const
Gives const access to the data.
void SetUnstructuredGrids(std::vector< itk::SmartPointer< mitk::UnstructuredGrid >> &grids)
Class for nodes of the DataTree.
Definition: mitkDataNode.h:57
static Pointer New()
Class for defining the data type of pixels.
Definition: mitkPixelType.h:51
bool GetName(std::string &nodeName, const mitk::BaseRenderer *renderer=nullptr, const char *propertyKey="name") const
Convenience access method for accessing the name of an object (instance of StringProperty with proper...
Definition: mitkDataNode.h:369
Manages and coordinates instances of mitk::Tool.
static bool DetermineAffectedImageSlice(const Image *image, const PlaneGeometry *plane, int &affectedDimension, int &affectedSlice)
Calculates for a given Image and PlaneGeometry, which slice of the image (in index corrdinates) is me...