SMILX  1.01
vtkImageViewer3.cxx
1 /*=========================================================================
2  The Software is copyright (c) Commonwealth Scientific and Industrial Research Organisation (CSIRO)
3  ABN 41 687 119 230.
4  All rights reserved.
5 
6  Licensed under the CSIRO BSD 3-Clause License
7  You may not use this file except in compliance with the License.
8  You may obtain a copy of the License in the file LICENSE.md or at
9 
10  https://stash.csiro.au/projects/SMILI/repos/smili/browse/license.txt
11 
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  See the License for the specific language governing permissions and
16  limitations under the License.
17 =========================================================================*/
18 #include "vtkImageViewer3.h"
19 
20 #include <vtkCamera.h>
21 #include <vtkRenderer.h>
22 #include <vtkCommand.h>
23 #include <vtkImageData.h>
24 #include <vtkRenderWindow.h>
25 #include <vtkProperty.h>
26 #include <vtkRenderWindowInteractor.h>
27 #include <vtkRendererCollection.h>
28 #include <vtkPointPicker.h>
29 #include <vtkImageActor.h>
30 #include <vtkImageMapToWindowLevelColors.h>
31 #if(VTK_MAJOR_VERSION > 5)
32  #include "vtkStreamingDemandDrivenPipeline.h"
33  #include "vtkImageMapper3D.h"
34 #endif
35 
36 //----------------------------------------------------------------------------
37 class vtkImageViewer3Callback : public vtkCommand
38 {
39 public:
40  static vtkImageViewer3Callback *New() { return new vtkImageViewer3Callback; }
41 
42  void Execute(vtkObject *caller,
43  unsigned long event,
44  void *vtkNotUsed(callData))
45  {
46  if (this->IV->GetInput() == NULL)
47  {
48  return;
49  }
50 
51  // Reset
52 
53  if (event == vtkCommand::ResetWindowLevelEvent)
54  {
55  #if(VTK_MAJOR_VERSION > 5)
56  this->IV->GetInputAlgorithm()->UpdateInformation();
57  vtkStreamingDemandDrivenPipeline::SetUpdateExtent(
58  this->IV->GetInputInformation(),
59  vtkStreamingDemandDrivenPipeline::GetWholeExtent(
60  this->IV->GetInputInformation()));
61  this->IV->GetInputAlgorithm()->Update();
62  #else
63  this->IV->GetInput()->UpdateInformation();
64  this->IV->GetInput()->SetUpdateExtent
65  (this->IV->GetInput()->GetWholeExtent());
66  this->IV->GetInput()->Update();
67  #endif
68  double *range = this->IV->GetInput()->GetScalarRange();
69  this->IV->SetColorWindow(range[1] - range[0]);
70  this->IV->SetColorLevel(0.5 * (range[1] + range[0]));
71  this->IV->Render();
72  return;
73  }
74 
75  // Start
76 
77  if (event == vtkCommand::StartWindowLevelEvent)
78  {
79  this->InitialWindow = this->IV->GetColorWindow();
80  this->InitialLevel = this->IV->GetColorLevel();
81  return;
82  }
83 
84  // Adjust the window level here
85 
86  vtkInteractorStyleImage *isi =
87  static_cast<vtkInteractorStyleImage *>(caller);
88 
89  int *size = this->IV->GetRenderWindow()->GetSize();
90  double window = this->InitialWindow;
91  double level = this->InitialLevel;
92 
93  // Compute normalized delta
94 
95  double dx = 4.0 *
96  (isi->GetWindowLevelCurrentPosition()[0] -
97  isi->GetWindowLevelStartPosition()[0]) / size[0];
98  double dy = 4.0 *
99  (isi->GetWindowLevelStartPosition()[1] -
100  isi->GetWindowLevelCurrentPosition()[1]) / size[1];
101 
102  // Scale by current values
103 
104  if (fabs(window) > 0.01)
105  {
106  dx = dx * window;
107  }
108  else
109  {
110  dx = dx * (window < 0 ? -0.01 : 0.01);
111  }
112  if (fabs(level) > 0.01)
113  {
114  dy = dy * level;
115  }
116  else
117  {
118  dy = dy * (level < 0 ? -0.01 : 0.01);
119  }
120 
121  // Abs so that direction does not flip
122 
123  if (window < 0.0)
124  {
125  dx = -1*dx;
126  }
127  if (level < 0.0)
128  {
129  dy = -1*dy;
130  }
131 
132  // Compute new window level
133 
134  double newWindow = dx + window;
135  double newLevel;
136  newLevel = level - dy;
137 
138  // Stay away from zero and really
139 
140  if (fabs(newWindow) < 0.01)
141  {
142  newWindow = 0.01*(newWindow < 0 ? -1 : 1);
143  }
144  if (fabs(newLevel) < 0.01)
145  {
146  newLevel = 0.01*(newLevel < 0 ? -1 : 1);
147  }
148 
149  this->IV->SetColorWindow(newWindow);
150  this->IV->SetColorLevel(newLevel);
151  std::cout << "Window: " << newWindow << ", Level: " << newLevel << std::endl;
152  this->IV->Render();
153  }
154 
155  vtkImageViewer3 *IV;
156  double InitialWindow;
157  double InitialLevel;
158 };
159 
160 class vtkImageViewer3CursorCallback : public vtkCommand
161 {
162 public:
164  vtkImageViewer3CursorCallback() : vtkCommand()
165  {
166  dataPicker = vtkPointPicker::New();
167  }
168 
170  {
171  if (dataPicker)
172  dataPicker->Delete();
173  }
174 
175  void Execute(vtkObject *caller,
176  unsigned long event,
177  void *vtkNotUsed(callData))
178  {
179  if (this->IV->GetInput() == NULL)
180  {
181  return;
182  }
183 
184  //Get the interactor
185  vtkInteractorStyleImage *isi =
186  static_cast<vtkInteractorStyleImage *>(caller);
187 
188  int *size = this->IV->GetRenderWindow()->GetSize();
189 
190  if (this->IV->GetCursorEnabled())
191  {
192  if (dataPicker->Pick(isi->GetInteractor()->GetEventPosition()[0],
193  isi->GetInteractor()->GetEventPosition()[1],
194  0, // always zero.
195  isi->GetInteractor()->GetRenderWindow()->GetRenderers()->GetFirstRenderer()))
196  {
197  double picked[3];
198  dataPicker->GetMapperPosition(picked);
199  //isi->GetInteractor()->GetPicker()->GetPickPosition(picked);
200  #if(VTK_MAJOR_VERSION > 5)
201  this->IV->GetCursor()->SetCenter(picked[0], picked[1], picked[2]);
202  #else
203  this->IV->GetCursor()->SetModelBounds(this->IV->GetInput()->GetBounds());
204  this->IV->GetCursor()->SetFocalPoint(picked[0], picked[1], picked[2]);
205  #endif
206  this->IV->GetCursor()->Update();
207  this->IV->GetRenderWindow()->Modified();
208  this->IV->UpdateDisplayExtent();
209  }
210  }
211 
212  this->IV->Render();
213  }
214 
215  vtkImageViewer3 *IV;
216  vtkPointPicker *dataPicker;
217 };
218 
219 //ImageViewer
220 vtkStandardNewMacro(vtkImageViewer3);
221 
222 vtkImageViewer3::vtkImageViewer3()
223 {
224  NeurologicalView = true;
225  CursorEnabled = false;
226  cursor = NULL;
227 #if(VTK_MAJOR_VERSION < 6)
228  cursorMapper = NULL;
229 #endif
230  cursorActor = NULL;
231 }
232 
233 vtkImageViewer3::~vtkImageViewer3()
234 {
235  if (cursor)
236  {
237  cursor->Delete();
238  cursor = NULL;
239  }
240 #if(VTK_MAJOR_VERSION < 6)
241  if (cursorMapper)
242  {
243  cursorMapper->Delete();
244  cursorMapper = NULL;
245  }
246 #endif
247  if (cursorActor)
248  {
249  cursorActor->Delete();
250  cursorActor = NULL;
251  }
252 }
253 
254 void vtkImageViewer3::PrintSelf(ostream& os, vtkIndent indent)
255 {
256  this->Superclass::PrintSelf(os, indent);
257 }
258 
259 void vtkImageViewer3::UpdateOrientation()
260 {
261  vtkCamera *cam = this->Renderer ? this->Renderer->GetActiveCamera() : NULL;
262 
263  if(!cam)
264  return;
265 
266  if(!NeurologicalView)
267  {
268  switch (this->SliceOrientation)
269  {
270  case vtkImageViewer3::SLICE_ORIENTATION_XY: //Axial
271  cam->SetFocalPoint(0,0,0);
272  cam->SetPosition(0,0,1); // -1 if medical ?
273  cam->SetViewUp(0,1,0);
274  break;
275 
276  case vtkImageViewer3::SLICE_ORIENTATION_XZ: //Coronal
277  cam->SetFocalPoint(0,0,0);
278  cam->SetPosition(0,-1,0); // 1 if medical ?
279  cam->SetViewUp(0,0,1);
280  break;
281 
282  case vtkImageViewer3::SLICE_ORIENTATION_YZ: //Saggital
283  cam->SetFocalPoint(0,0,0);
284  cam->SetPosition(-1,0,0); // -1 if medical ?
285  cam->SetViewUp(0,0,1);
286  break;
287  }
288  }
289  else
290  {
291  // Set the camera position
292  std::cout << "Using Neurological (head-first) Orientation" << std::endl;
293  switch (this->SliceOrientation)
294  {
295  case vtkImageViewer3::SLICE_ORIENTATION_XY: //Axial
296  cam->SetFocalPoint(0,0,0);
297  cam->SetPosition(0,0,-1); // -1 if medical ?
298  cam->SetViewUp(0,1,0);
299  break;
300 
301  case vtkImageViewer3::SLICE_ORIENTATION_XZ: //Coronal
302  cam->SetFocalPoint(0,0,0);
303  cam->SetPosition(0,1,0); // 1 if medical ?
304  cam->SetViewUp(0,0,1);
305  break;
306 
307  case vtkImageViewer3::SLICE_ORIENTATION_YZ: //Saggital
308  cam->SetFocalPoint(0,0,0);
309  cam->SetPosition(-1,0,0); // -1 if medical ?
310  cam->SetViewUp(0,0,1);
311  break;
312  }
313  }
314 }
315 
316 //----------------------------------------------------------------------------
317 void vtkImageViewer3::InstallPipeline()
318 {
319  if (this->RenderWindow && this->Renderer)
320  {
321  this->RenderWindow->AddRenderer(this->Renderer);
322  }
323 
324  if (this->Interactor)
325  {
326  if (!this->InteractorStyle)
327  {
328  vtkInteractorStyleImage2 *scannerInteractor = vtkInteractorStyleImage2::New();
329  scannerInteractor->SetViewer(this);
330  this->InteractorStyle = scannerInteractor;
331  vtkImageViewer3Callback *cbk = vtkImageViewer3Callback::New();
332  cbk->IV = this;
333  this->InteractorStyle->AddObserver(
334  vtkCommand::WindowLevelEvent, cbk); //WindowLevel
335  this->InteractorStyle->AddObserver(
336  vtkCommand::StartWindowLevelEvent, cbk); //WindowLevel
337  this->InteractorStyle->AddObserver(
338  vtkCommand::ResetWindowLevelEvent, cbk); //WindowLevel
339  cbk->Delete();
340  vtkImageViewer3CursorCallback *cbk2 = vtkImageViewer3CursorCallback::New();
341  cbk2->IV = this;
342  this->InteractorStyle->AddObserver(
343  vtkCommand::MiddleButtonPressEvent, cbk2); //Cursor
344  }
345 
346  this->Interactor->SetInteractorStyle(this->InteractorStyle);
347  this->Interactor->SetRenderWindow(this->RenderWindow);
348  }
349 
350  if (this->Renderer && this->ImageActor)
351  {
352  this->Renderer->AddViewProp(this->ImageActor);
353  }
354 
355  if (this->ImageActor && this->WindowLevel)
356  {
357  #if(VTK_MAJOR_VERSION > 5)
358  this->ImageActor->GetMapper()->SetInputConnection(
359  this->WindowLevel->GetOutputPort());
360  #else
361  this->ImageActor->SetInput(this->WindowLevel->GetOutput());
362  #endif
363  }
364 }
365 
366 void vtkImageViewer3::SetSliceOrientation(int orientation)
367 {
368  Superclass::SetSliceOrientation(orientation);
369 #if(VTK_MAJOR_VERSION > 5)
370  if(CursorEnabled)
371  cursorActor->GetCursorAlgorithm()->SetReslicePlaneNormal(this->SliceOrientation);
372 #endif
373 }
374 
375 /*void vtkImageViewer2::SetSlice(int slice)
376 {
377  Superclass::SetSlice(slice);
378 
379 }*/
380 
381 void vtkImageViewer3::EnableCursor()
382 {
383 #if(VTK_MAJOR_VERSION > 5)
384  if (!cursor)
385  cursor = vtkResliceCursor::New();
386  cursor->SetImage(this->GetInput());
387  cursor->SetThickMode(0);
388  cursor->SetThickness(1, 1, 1);
389  if(!CursorEnabled)
390  {
391  //Set as center of image to initialise
392  /*double bounds[6];
393  this->GetInput()->GetBounds(bounds);
394  cursor->SetCenter( (bounds[1]-bounds[0])/2, (bounds[3]-bounds[2])/2, (bounds[5]-bounds[4])/2);*/
395  cursor->SetCenter(this->GetInput()->GetOrigin());
396  }
397 
398  if (!cursorActor)
399  cursorActor = vtkResliceCursorActor::New();
400  cursorActor->GetCursorAlgorithm()->SetResliceCursor(cursor);
401  cursorActor->GetCursorAlgorithm()->SetReslicePlaneNormal(this->SliceOrientation);
402 #else
403  if (!cursor)
404  cursor = vtkCursor3D::New();
405  cursor->SetModelBounds(this->GetInput()->GetBounds());
406  cursor->AllOn();
407  cursor->OutlineOff();
408 
409  if (!cursorMapper)
410  cursorMapper = vtkPolyDataMapper::New();
411  cursorMapper->SetInputConnection(cursor->GetOutputPort());
412 
413  if (!cursorActor)
414  cursorActor = vtkActor::New();
415  cursorActor->GetProperty()->SetColor(1, 0, 0);
416  cursorActor->SetMapper(cursorMapper);
417 #endif
418  cursor->Update();
419 
420  this->Renderer->AddActor(cursorActor);
421  this->Modified();
422  this->GetRenderWindow()->Modified();
423  this->UpdateDisplayExtent();
424  this->Render();
425  CursorEnabled = true;
426 }
427 
428 void vtkImageViewer3::UpdateCursor()
429 {
430  if(CursorEnabled)
431  {
432  cursor->Update();
433  #if(VTK_MAJOR_VERSION > 5)
434  cursorActor->GetCursorAlgorithm()->SetReslicePlaneNormal(this->SliceOrientation);
435  #endif
436  }
437 }
438 
439 void vtkImageViewer3::DisableCursor()
440 {
441 #if(VTK_MAJOR_VERSION > 5)
442  this->Renderer->RemoveActor(cursorActor);
443 #else
444  if (cursor)
445  cursor->AllOff();
446 #endif
447  CursorEnabled = false;
448 }
449 
450 double* vtkImageViewer3::GetCursorFocalPoint()
451 {
452 #if(VTK_MAJOR_VERSION > 5)
453  return cursor->GetCenter();
454 #else
455  return cursor->GetFocalPoint();
456 #endif
457 }
458 
459 void vtkImageViewer3::SetCursorFocalPoint(double *point)
460 {
461 #if(VTK_MAJOR_VERSION > 5)
462  cursor->SetCenter(point);
463 #else
464  cursor->SetFocalPoint(point);
465 #endif
466 }