GOFIGURE2  0.9.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
vtkViewImage2DCommand.cxx
Go to the documentation of this file.
1 /*========================================================================
2  Copyright (c) INRIA - ASCLEPIOS Project (http://www-sop.inria.fr/asclepios).
3  All rights reserved.
4 
5  Redistribution and use in source and binary forms, with or without
6  modification, are permitted provided that the following conditions are met:
7 
8  * Redistributions of source code must retain the above copyright notice,
9  this list of conditions and the following disclaimer.
10 
11  * Redistributions in binary form must reproduce the above copyright notice,
12  this list of conditions and the following disclaimer in the documentation
13  and/or other materials provided with the distribution.
14 
15  * Neither the name of INRIA or ASCLEPIOS, nor the names of any contributors
16  may be used to endorse or promote products derived from this software
17  without specific prior written permission.
18 
19  * Modified source versions must be plainly marked as such, and must not be
20  misrepresented as being the original software.
21 
22  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
23  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
26  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  =========================================================================*/
33 
34 /*=========================================================================
35  Modifications were made by the GoFigure Dev. Team.
36  while at Megason Lab, Systems biology, Harvard Medical school, 2009-11
37 
38  Copyright (c) 2009-11, President and Fellows of Harvard College.
39  All rights reserved.
40 
41  Redistribution and use in source and binary forms, with or without
42  modification, are permitted provided that the following conditions are met:
43 
44  Redistributions of source code must retain the above copyright notice,
45  this list of conditions and the following disclaimer.
46  Redistributions in binary form must reproduce the above copyright notice,
47  this list of conditions and the following disclaimer in the documentation
48  and/or other materials provided with the distribution.
49  Neither the name of the President and Fellows of Harvard College
50  nor the names of its contributors may be used to endorse or promote
51  products derived from this software without specific prior written
52  permission.
53 
54  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
55  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
56  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
57  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
58  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
59  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
60  OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
61  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
62  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
63  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
64  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
65 
66  =========================================================================*/
67 
68 #ifdef _MSC_VER
69 # pragma warning (disable : 4018)
70 #endif
71 
72 #include <vtkAbstractPropPicker.h>
73 #include <vtkAssemblyPath.h>
74 #include <vtkCellPicker.h>
75 #include <vtkRenderer.h>
76 #include <vtkRenderWindow.h>
77 #include <vtkRenderWindowInteractor.h>
78 #include <vtkImageData.h>
79 #include <vtkCornerAnnotation.h>
80 #include <vtkCamera.h>
81 #include <vtkMath.h>
82 
83 #include "vtkViewImage2D.h"
85 
86 #include "vtkViewImage2DCommand.h"
88 
89 #include <string>
90 #include <sstream>
91 
92 //----------------------------------------------------------------------------
94 {
95 }
96 
97 //----------------------------------------------------------------------------
98 void
99 vtkViewImage2DCommand::Execute( vtkObject *caller,
100  unsigned long event,
101  void *vtkNotUsed(callData) )
102 {
104  static_cast< vtkInteractorStyleImage2D * >( caller );
105 
106  if ( !isi || !this->Viewer || !this->Viewer->GetInput() )
107  {
108  return;
109  }
110 
111  // Reset
112  if ( event == vtkCommand::ResetWindowLevelEvent )
113  {
114  this->Viewer->ResetWindowLevel();
115  this->Viewer->Render();
116  return;
117  }
118  // Reset
120  {
121  this->Viewer->Reset();
122  this->Viewer->Render();
123  return;
124  }
125 
126  // Start
127  if ( event == vtkCommand::StartWindowLevelEvent )
128  {
129  //no since it is min an max now...!
130  this->InitialWindow = this->Viewer->GetLevel() - this->Viewer->GetWindow();
131  this->InitialLevel = this->Viewer->GetLevel() - this->InitialWindow/2;
132  return;
133  }
134 
135  // Adjust the window level here
136  if ( event == vtkCommand::WindowLevelEvent )
137  {
138  this->Windowing(isi);
139  return;
140  }
141 
143  {
144  //std::cout << "Mesh pick single" << std::endl;
145  }
146 
147  if ( event == vtkCommand::KeyPressEvent )
148  {
149  vtkRenderWindowInteractor *rwi =
150  this->Viewer->GetRenderWindow()->GetInteractor();
151  if ( rwi->GetKeyCode() == 't' )
152  {
153  this->Viewer->SetViewOrientation (
154  ( this->Viewer->GetViewOrientation() + 1 ) % 3);
155  this->Viewer->Render();
156  }
157  else if ( rwi->GetKeyCode() == 'i' )
158  {
159  this->Viewer->SetInterpolate ( ( this->Viewer->GetInterpolate() + 1 ) % 2 );
160  this->Viewer->Render();
161  }
162  return;
163  }
164 
166  {
167  int step = isi->GetSliceStep();
168  this->Viewer->SetSlice (this->Viewer->GetSlice() + step);
170  }
171 
172  if ( event == vtkViewImage2DCommand::ZoomEvent )
173  {
174  this->Zooming();
175  }
176 
177  if ( event == vtkViewImage2DCommand::PanEvent )
178  {
179  this->Panning();
180  }
181 
182  // Move
183  // Position Value requested
184  if ( event == vtkViewImage2DCommand::InteractionEvent )
185  {
187  }
188 
189  // Position requested
191  {
192  double *position = this->Viewer->GetWorldCoordinatesFromDisplayPosition (
193  isi->GetRequestedPosition () );
194  this->Viewer->SetWorldCoordinates(position);
195  this->Viewer->Render();
196  }
197 }
198 //----------------------------------------------------------------------------
199 
200 //----------------------------------------------------------------------------
201 void
203 {
204  // don't do the window level if the image has more than 1 channel
205  if ( this->Viewer->GetIsColor() )
206  {
207  return;
208  }
209 
210  int * size = this->Viewer->GetRenderWindow()->GetSize();
211 
212  double window = this->InitialWindow;
213  double level = this->InitialLevel;
214 
215  // Compute normalized delta
216  double dx = 4.0
217  * ( isi->GetWindowLevelCurrentPosition()[0]
218  - isi->GetWindowLevelStartPosition()[0] ) / size[0];
219  double dy = 4.0
220  * ( isi->GetWindowLevelStartPosition()[1]
221  - isi->GetWindowLevelCurrentPosition()[1] ) / size[1];
222 
223  // Scale by current values
224  if ( fabs(window) > 0.01 ) { dy = dy * window; }
225  else
226  {
227  dy = dy * ( window < 0 ? -0.01 : 0.01 );
228  }
229  if ( fabs(level) > 0.01 ) { dx = dx * level; }
230  else
231  {
232  dx = dx * ( level < 0 ? -0.01 : 0.01 );
233  }
234 
235  // Abs so that direction does not flip
236  if ( window < 0.0 ) { dy = -1 * dy; }
237  if ( level < 0.0 ) { dx = -1 * dx; }
238 
239  // Compute new window level
240  double newWindow = window - dy;
241  double newLevel = level + dx;
242 
243  // Stay away from zero and really
244  if ( fabs(newWindow) < 0.01 ) { newWindow = 0.01 * ( newWindow < 0 ? -1 : 1 ); }
245  if ( fabs(newLevel) < 0.01 ) { newLevel = 0.01 * ( newLevel < 0 ? -1 : 1 ); }
246 
247  // compute new window
248  double min = 0.0;
249  if(newLevel - newWindow /2 > 0)
250  min = newLevel - newWindow /2;
251 
252  double max = this->Viewer->GetInput()->GetScalarRange()[1];
253  if(newLevel + newWindow /2 < this->Viewer->GetInput()->GetScalarRange()[1])
254  max = newLevel + newWindow /2;
255 
256  // can happen if we move too fast
257  if(min > max - 2)
258  return;
259 
260  this->Viewer->SetWindow(min);
261  this->Viewer->SetLevel(max);
262 }
263 //----------------------------------------------------------------------------
264 
265 //----------------------------------------------------------------------------
267 {
268  vtkRenderWindowInteractor *rwi =
269  this->Viewer->GetRenderWindow()->GetInteractor();
270 
271  double *pos = this->Viewer->GetWorldCoordinatesFromDisplayPosition (
272  rwi->GetLastEventPosition () );
273 
274  int *idx = this->Viewer->GetImageCoordinatesFromWorldCoordinates(pos);
275 
276  int dims[3];
277 
278  this->Viewer->GetInput()->GetDimensions(dims);
279 
280  double spacing[3];
281  this->Viewer->GetInput()->GetSpacing(spacing);
282 
283  std::ostringstream os;
286  os << "Size: " << "[ " << dims[0] << " x " << dims[1] << " x " << dims[2]
287  << " ]" << std::endl;
288  os << "Pixel Size: " << "[ " << spacing[0] << " x "
289  << spacing[1] << " x " << spacing[2] << " ] um" << std::endl;
290  os << "Slice: " << this->Viewer->GetSlice() << " / "
291  << this->Viewer->GetSliceMax() - this->Viewer->GetSliceMin() << std::endl;
292  this->Viewer->GetCornerAnnotation()->SetText ( 2, os.str().c_str() );
293 
294  std::ostringstream os2;
295  os2 << "Location: " << "[ " << pos[0] << " ; " << pos[1] << " ; "
296  << pos[2] << " ] um" << std::endl;
297 
298  os2 << "Index: " << "[ " << idx[0] << " ; " << idx[1] << " ; "
299  << idx[2] << " ]" << std::endl;
300 
301  if ( !this->Viewer->GetIsColor() )
302  {
303  os2 << "Value : " << this->Viewer->GetValueAtPosition (pos);
304  }
305  // one display value for single channel images
306  /*
307  * \todo Nicolas- show channel value if we look at a multi channel image
308  */
309  /*else
310  {
311  os2 << "Value : [";
312  for ( int i = 0; i < 3; i++ )
313  {
314  os2 << this->Viewer->GetValueAtPosition (pos, i) << ", ";
315  }
316  os2 << "]";
317  }*/
318 
319 
320  this->Viewer->GetCornerAnnotation()->SetText ( 3, os2.str().c_str() );
321  this->Viewer->Render();
322 
323  // GetImageCoordinatesFromWorldCoordinates gives a pointer
324  // to allocated but not managed memory : have to cleanup :
325  delete[] idx;
326 }
327 //----------------------------------------------------------------------------
328 
329 //----------------------------------------------------------------------------
331 {
332  vtkRenderWindowInteractor *rwi =
333  this->Viewer->GetRenderWindow()->GetInteractor();
334 
335  rwi->FindPokedRenderer(rwi->GetEventPosition()[0],
336  rwi->GetEventPosition()[1]);
337 
338  vtkRenderer *ren = this->Viewer->GetRenderer();
339 
340  int *size = ren->GetSize();
341  int dy = rwi->GetEventPosition()[1] - rwi->GetLastEventPosition()[1];
342 
343  double factor = 10. * static_cast< double >( dy ) / static_cast< double >( size[1] );
344 
345  double z = pow(static_cast< double >( 1.1 ), factor);
346 
347  this->Viewer->SetZoom(z);
348 
349  double parallel_scale =
350  this->Viewer->GetRenderer()->GetActiveCamera()->GetParallelScale();
351 
352  if(parallel_scale == factor)
353  { std::cout << "are equal" << std::endl;}
354 
355  double t = parallel_scale / z;
356 
357  this->Viewer->GetRenderer()->GetActiveCamera()->SetParallelScale(t);
358 
359  // ???
360  if ( this->Viewer->GetInteractorStyle()->GetInteractor()->GetLightFollowCamera() )
361  {
362  this->Viewer->GetRenderer()->UpdateLightsGeometryToFollowCamera();
363  }
364 // item->Render();
365 
366 }
367 //----------------------------------------------------------------------------
368 
369 //----------------------------------------------------------------------------
370 void
372 {
373  vtkRenderWindowInteractor *rwi =
374  this->Viewer->GetRenderWindow()->GetInteractor();
375 
376  double ViewFocus[4], focalDepth, ViewPoint[3];
377  double NewPickPoint[4], OldPickPoint[4], MotionVector[3];
378 
379  // Calculate the focal depth since we'll be using it a lot
380  vtkRenderer *ren = this->Viewer->GetRenderer();
381  vtkCamera * camera = ren->GetActiveCamera();
382 
383  camera->GetFocalPoint(ViewFocus);
384  vtkInteractorObserver::ComputeWorldToDisplay(ren,
385  ViewFocus[0], ViewFocus[1], ViewFocus[2], ViewFocus);
386 
387  focalDepth = ViewFocus[2];
388 
389  vtkInteractorObserver::ComputeDisplayToWorld(ren,
390  rwi->GetEventPosition()[0],
391  rwi->GetEventPosition()[1],
392  focalDepth,
393  NewPickPoint);
394 
395  vtkInteractorObserver::ComputeDisplayToWorld(ren,
396  rwi->GetLastEventPosition()[0],
397  rwi->GetLastEventPosition()[1],
398  focalDepth,
399  OldPickPoint);
400 
401  // Camera motion is reversed
402  MotionVector[0] = OldPickPoint[0] - NewPickPoint[0];
403  MotionVector[1] = OldPickPoint[1] - NewPickPoint[1];
404  MotionVector[2] = OldPickPoint[2] - NewPickPoint[2];
405 
406  // Get the current focal point and position
407 
408  camera->GetFocalPoint(ViewFocus);
409  camera->GetPosition(ViewPoint);
410  camera->SetFocalPoint(MotionVector[0] + ViewFocus[0],
411  MotionVector[1] + ViewFocus[1],
412  MotionVector[2] + ViewFocus[2]);
413  camera->SetPosition(MotionVector[0] + ViewPoint[0],
414  MotionVector[1] + ViewPoint[1],
415  MotionVector[2] + ViewPoint[2]);
416 
417  this->Viewer->SetCameraMotionVector(MotionVector);
418 }
virtual double * GetWorldCoordinatesFromDisplayPosition(int xy[2])
Useful method that transform a display position into a world corrdinate point.
void PrintInformation()
Method to be called when an event is caught to update information in 2D view such as position...
virtual void SetViewOrientation(int orientation)
void SetLevel(double iLevel)
void SetWindow(double iWindow)
virtual double GetValueAtPosition(double worldcoordinates[3], int component=0)
Get the pixel value at a given world coordinate point in space, return zero if out of bounds...
void Zooming()
Method to be called if an event is caught in "Zooming Mode".
Define the interactor behavior withing a vtkImage2D. 4 modes (Default, Zoom, Pan and Pick) ...
virtual void ResetWindowLevel(void)
Reset the window level.
void Windowing(vtkInteractorStyleImage2D *isi)
Method to be called if an event is caught in "Windowing Mode".
virtual int * GetImageCoordinatesFromWorldCoordinates(double position[3])
Convert a world coordinate point into an image indices coordinate point.
double GetLevel()
virtual void SetWorldCoordinates(double pos[3])
The world is not always what we think it is ... Use this method to move the viewer slice such that th...
virtual void Reset(void)
Reset position - zoom - window/level to default.
virtual void SetSlice(int s)
Set/Get the current slice to display (depending on the orientation this can be in X...
virtual void Execute(vtkObject *caller, unsigned long event, void *vtkNotUsed(callData))
virtual int GetInterpolate()
Get whether or not the interpolation between pixels should be activated. It is Off by default...
virtual void Render(void)
virtual vtkRenderWindowInteractor * GetInteractor()
void Panning()
Method to be called if an event is caught in "Panning Mode".
virtual void SetInterpolate(const int &val)
Set whether or not the interpolation between pixels should be activated. It is Off by default...
double GetWindow()