Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
QmitkSurfaceBasedInterpolatorWidget.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 
15 #include "mitkColorProperty.h"
16 #include "mitkInteractionConst.h"
17 #include "mitkOperationEvent.h"
18 #include "mitkProgressBar.h"
19 #include "mitkProperties.h"
20 #include "mitkRenderingManager.h"
21 #include "mitkSegTool2D.h"
24 #include "mitkUndoController.h"
27 
28 #include "QmitkStdMultiWidget.h"
29 
30 #include <itkCommand.h>
31 #include <vtkProperty.h>
32 
33 #include <QMessageBox>
34 
36  : QWidget(parent),
37  m_SurfaceBasedInterpolatorController(mitk::SurfaceBasedInterpolationController::GetInstance()),
38  m_ToolManager(nullptr),
39  m_Activated(false),
40  m_DataStorage(nullptr)
41 {
42  m_Controls.setupUi(this);
43 
45  Q_ASSERT(m_ToolManager);
46 
49 
50  connect(m_Controls.m_btStart, SIGNAL(toggled(bool)), this, SLOT(OnToggleWidgetActivation(bool)));
51  connect(m_Controls.m_btAccept, SIGNAL(clicked()), this, SLOT(OnAcceptInterpolationClicked()));
52  connect(m_Controls.m_cbShowPositionNodes, SIGNAL(toggled(bool)), this, SLOT(OnShowMarkers(bool)));
53 
54  itk::ReceptorMemberCommand<QmitkSurfaceBasedInterpolatorWidget>::Pointer command =
55  itk::ReceptorMemberCommand<QmitkSurfaceBasedInterpolatorWidget>::New();
57  m_SurfaceInterpolationInfoChangedObserverTag =
58  m_SurfaceBasedInterpolatorController->AddObserver(itk::ModifiedEvent(), command);
59 
60  m_InterpolatedSurfaceNode = mitk::DataNode::New();
61  m_InterpolatedSurfaceNode->SetName("Surface Interpolation feedback");
62  m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(255.0, 255.0, 0.0));
63  m_InterpolatedSurfaceNode->SetProperty("opacity", mitk::FloatProperty::New(0.5));
64  m_InterpolatedSurfaceNode->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false));
65  m_InterpolatedSurfaceNode->SetProperty("helper object", mitk::BoolProperty::New(true));
66  m_InterpolatedSurfaceNode->SetVisibility(false);
67 
68  m_3DContourNode = mitk::DataNode::New();
69  m_3DContourNode->SetName("Drawn Contours");
70  m_3DContourNode->SetProperty("color", mitk::ColorProperty::New(0.0, 0.0, 0.0));
71  m_3DContourNode->SetProperty("helper object", mitk::BoolProperty::New(true));
72  m_3DContourNode->SetProperty("material.representation", mitk::VtkRepresentationProperty::New(VTK_WIREFRAME));
73  m_3DContourNode->SetProperty("material.wireframeLineWidth", mitk::FloatProperty::New(2.0f));
74  m_3DContourNode->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false));
75  m_3DContourNode->SetVisibility(
77  m_3DContourNode->SetVisibility(
79  m_3DContourNode->SetVisibility(
81  m_3DContourNode->SetVisibility(
83 
84  connect(&m_Watcher, SIGNAL(started()), this, SLOT(StartUpdateInterpolationTimer()));
85  connect(&m_Watcher, SIGNAL(finished()), this, SLOT(OnSurfaceInterpolationFinished()));
86  connect(&m_Watcher, SIGNAL(finished()), this, SLOT(StopUpdateInterpolationTimer()));
87 
88  m_Timer = new QTimer(this);
89  connect(m_Timer, SIGNAL(timeout()), this, SLOT(ChangeSurfaceColor()));
90 
91  m_Controls.m_btAccept->setEnabled(false);
92  m_Controls.m_cbShowPositionNodes->setEnabled(false);
93 
94  this->setEnabled(false);
95 }
96 
98 {
99  m_DataStorage = &storage;
100 }
101 
103 {
106 
107  if (m_DataStorage->Exists(m_3DContourNode))
108  m_DataStorage->Remove(m_3DContourNode);
109 
110  if (m_DataStorage->Exists(m_InterpolatedSurfaceNode))
111  m_DataStorage->Remove(m_InterpolatedSurfaceNode);
112 
113  // remove observer
114  m_SurfaceBasedInterpolatorController->RemoveObserver(m_SurfaceInterpolationInfoChangedObserverTag);
115 
116  delete m_Timer;
117 }
118 
120 {
121  if (m_InterpolatedSurfaceNode.IsNotNull())
122  m_InterpolatedSurfaceNode->SetVisibility(status);
123 
124  if (m_3DContourNode.IsNotNull())
125  m_3DContourNode->SetVisibility(
127 
129 }
130 
132 {
133  mitk::Surface::Pointer interpolatedSurface = m_SurfaceBasedInterpolatorController->GetInterpolationResult();
134 
135  if (interpolatedSurface.IsNotNull())
136  {
137  m_InterpolatedSurfaceNode->SetData(interpolatedSurface);
138  m_3DContourNode->SetData(m_SurfaceBasedInterpolatorController->GetContoursAsSurface());
139  this->ShowInterpolationResult(true);
140  }
141  else
142  {
143  m_InterpolatedSurfaceNode->SetData(nullptr);
144  m_3DContourNode->SetData(nullptr);
145  this->ShowInterpolationResult(false);
146  }
147 }
148 
150 {
151  mitk::DataStorage::SetOfObjects::ConstPointer allContourMarkers =
152  m_DataStorage->GetSubset(mitk::NodePredicateProperty::New("isContourMarker", mitk::BoolProperty::New(true)));
153 
154  for (mitk::DataStorage::SetOfObjects::ConstIterator it = allContourMarkers->Begin(); it != allContourMarkers->End();
155  ++it)
156  {
157  it->Value()->SetProperty("helper object", mitk::BoolProperty::New(!state));
158  }
159 
160  mitk::SegTool2D::Pointer manualSegmentationTool;
161 
162  unsigned int numberOfExistingTools = m_ToolManager->GetTools().size();
163 
164  for (unsigned int i = 0; i < numberOfExistingTools; i++)
165  {
166  manualSegmentationTool = dynamic_cast<mitk::SegTool2D *>(m_ToolManager->GetToolById(i));
167 
168  if (manualSegmentationTool)
169  {
170  manualSegmentationTool->SetShowMarkerNodes(state);
171  }
172  }
173 }
174 
176 {
177  m_Timer->start(500);
178 }
179 
181 {
182  m_Timer->stop();
183  m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(255.0, 255.0, 0.0));
185  mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3"))->GetRenderWindow());
186 }
187 
189 {
190  float currentColor[3];
191  m_InterpolatedSurfaceNode->GetColor(currentColor);
192 
193  float yellow[3] = {255.0, 255.0, 0.0};
194 
195  if (currentColor[2] == yellow[2])
196  {
197  m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(255.0, 255.0, 255.0));
198  }
199  else
200  {
201  m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(yellow));
202  }
203  m_InterpolatedSurfaceNode->Update();
205  mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3"))->GetRenderWindow());
206 }
207 
209 {
210  mitk::DataNode *workingNode = this->m_ToolManager->GetWorkingData(0);
211  if (!workingNode)
212  {
213  this->setEnabled(false);
214  return;
215  }
216 
217  mitk::LabelSetImage *workingImage = dynamic_cast<mitk::LabelSetImage *>(workingNode->GetData());
218  // TODO adapt tool manager so that this check is done there, e.g. convenience function
219  // Q_ASSERT(workingImage);
220  if (!workingImage)
221  {
222  this->setEnabled(false);
223  return;
224  }
225 
226  if (workingImage->GetDimension() > 4 || workingImage->GetDimension() < 3)
227  {
228  this->setEnabled(false);
229  return;
230  }
231 
232  m_WorkingImage = workingImage;
233 
234  this->setEnabled(true);
235 }
236 
238 {
239  m_SurfaceBasedInterpolatorController->Interpolate();
240 }
241 
243 {
244  Q_ASSERT(m_ToolManager);
245 
246  mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0);
247  if (!workingNode)
248  return;
249 
250  m_Controls.m_btAccept->setEnabled(enabled);
251  m_Controls.m_cbShowPositionNodes->setEnabled(enabled);
252 
253  if (enabled)
254  m_Controls.m_btStart->setText("Stop");
255  else
256  m_Controls.m_btStart->setText("Start");
257 
258  for (unsigned int i = 0; i < m_ToolManager->GetTools().size(); i++)
259  {
260  mitk::SegTool2D *tool = dynamic_cast<mitk::SegTool2D *>(m_ToolManager->GetToolById(i));
261  if (tool)
262  tool->SetEnable3DInterpolation(enabled);
263  }
264 
265  if (enabled)
266  {
267  if (!m_DataStorage->Exists(m_InterpolatedSurfaceNode))
268  {
269  m_DataStorage->Add(m_InterpolatedSurfaceNode);
270  }
271 
272  if (!m_DataStorage->Exists(m_3DContourNode))
273  {
274  m_DataStorage->Add(m_3DContourNode);
275  }
276 
277  mitk::Vector3D spacing = m_WorkingImage->GetGeometry(0)->GetSpacing();
278  double minSpacing(100);
279  double maxSpacing(0);
280  for (int i = 0; i < 3; i++)
281  {
282  if (spacing[i] < minSpacing)
283  {
284  minSpacing = spacing[i];
285  }
286  else if (spacing[i] > maxSpacing)
287  {
288  maxSpacing = spacing[i];
289  }
290  }
291 
292  m_SurfaceBasedInterpolatorController->SetWorkingImage(m_WorkingImage);
293  m_SurfaceBasedInterpolatorController->SetActiveLabel(m_WorkingImage->GetActiveLabel()->GetValue());
294  m_SurfaceBasedInterpolatorController->SetMaxSpacing(maxSpacing);
295  m_SurfaceBasedInterpolatorController->SetMinSpacing(minSpacing);
296  m_SurfaceBasedInterpolatorController->SetDistanceImageVolume(50000);
297 
298  int ret = QMessageBox::Yes;
299 
300  if (m_SurfaceBasedInterpolatorController->EstimatePortionOfNeededMemory() > 0.5)
301  {
302  QMessageBox msgBox;
303  msgBox.setText("Due to short handed system memory the 3D interpolation may be very slow!");
304  msgBox.setInformativeText("Are you sure you want to activate the 3D interpolation?");
305  msgBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
306  ret = msgBox.exec();
307  }
308 
309  if (m_Watcher.isRunning())
310  m_Watcher.waitForFinished();
311 
312  if (ret == QMessageBox::Yes)
313  {
314  m_Future = QtConcurrent::run(this, &QmitkSurfaceBasedInterpolatorWidget::OnRunInterpolation);
315  m_Watcher.setFuture(m_Future);
316  }
317  }
318  else
319  {
320  if (m_DataStorage->Exists(m_InterpolatedSurfaceNode))
321  {
322  m_DataStorage->Remove(m_InterpolatedSurfaceNode);
323  }
324  if (m_DataStorage->Exists(m_3DContourNode))
325  {
326  m_DataStorage->Remove(m_3DContourNode);
327  }
328 
330  }
331 
332  m_Activated = enabled;
333 
335 }
336 
338 {
339  if (m_InterpolatedSurfaceNode.IsNotNull() && m_InterpolatedSurfaceNode->GetData())
340  {
341  // m_WorkingImage->SurfaceStamp(dynamic_cast<mitk::Surface*>(m_InterpolatedSurfaceNode->GetData()), false);
342  this->ShowInterpolationResult(false);
343  }
344 }
345 
347 {
348  if (m_Activated)
349  {
350  if (m_Watcher.isRunning())
351  m_Watcher.waitForFinished();
352 
353  m_Future = QtConcurrent::run(this, &QmitkSurfaceBasedInterpolatorWidget::OnRunInterpolation);
354  m_Watcher.setFuture(m_Future);
355  }
356 }
Ui::QmitkSurfaceBasedInterpolatorWidgetGUIControls m_Controls
Data management class that handles &#39;was created by&#39; relations.
void ShowInterpolationResult(bool)
Set the visibility of the interpolation.
static BaseRenderer * GetInstance(vtkRenderWindow *renWin)
static vtkRenderWindow * GetRenderWindowByName(const std::string &name)
Message WorkingDataChanged
static Pointer New()
Tool * GetToolById(int id)
DataCollection - Class to facilitate loading/accessing structured data.
virtual mitk::ToolManager * GetToolManager()
Returns ToolManager object.
Constants for most interaction classes, due to the generic StateMachines.
void OnToggleWidgetActivation(bool)
Reaction to "Start/Stop" button click.
void OnSurfaceInterpolationInfoChanged(const itk::EventObject &)
void SetEnable3DInterpolation(bool)
Enables or disables the 3D interpolation after writing back the 2D segmentation result, and defaults to true.
static Pointer New()
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
unsigned int GetDimension() const
Get dimension of the image.
Definition: mitkImage.cpp:106
mitk::DataStorage::Pointer m_DataStorage
static Pointer New()
static RenderingManager * GetInstance()
QmitkSurfaceBasedInterpolatorWidget(QWidget *parent=nullptr, const char *name=nullptr)
static Pointer New(const char *_arg)
static Pointer New()
void RequestUpdate(vtkRenderWindow *renderWindow)
const ToolVectorTypeConst GetTools()
Gives you a list of all tools. This is const on purpose.
Abstract base class for segmentation tools.
Definition: mitkSegTool2D.h:54
static UndoModel * GetCurrentUndoModel()
gives access to the currently used UndoModel Introduced to access special functions of more specific ...
LabelSetImage class for handling labels and layers in a segmentation session.
virtual void Clear()=0
clears undo and Redolist
void RequestUpdateAll(RequestType type=REQUEST_UPDATE_ALL)
Class for nodes of the DataTree.
Definition: mitkDataNode.h:57
DataVectorType GetWorkingData()
static mitk::ToolManagerProvider * GetInstance()
Returns an instance of ToolManagerProvider service.