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