fw4spl
fwVtkPicker.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2015.
3  * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
4  * published by the Free Software Foundation.
5  * ****** END LICENSE BLOCK ****** */
6 
7 /*=========================================================================
8  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
9  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
10  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
11  Patched version of vtkPicker,
12  see http://www.vtk.org/doc/release/5.4/html/a00996.html
13  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
14  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
15  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
16  =========================================================================*/
17 
18 /*=========================================================================
19 
20  Program: Visualization Toolkit
21  Module: $RCSfile: fwVtkPicker.cxx,v $
22 
23  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
24  All rights reserved.
25  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
26 
27  This software is distributed WITHOUT ANY WARRANTY; without even
28  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
29  PURPOSE. See the above copyright notice for more information.
30 
31  =========================================================================*/
32 
33 
34 #include <vtkAbstractVolumeMapper.h>
35 #include <vtkActor.h>
36 #include <vtkAssemblyNode.h>
37 #include <vtkAssemblyPath.h>
38 #include <vtkBox.h>
39 #include <vtkCamera.h>
40 #include <vtkCommand.h>
41 #include <vtkImageActor.h>
42 #include <vtkImageData.h>
43 #include <vtkLODProp3D.h>
44 #include <vtkMapper.h>
45 #include <vtkMath.h>
46 #include <vtkObjectFactory.h>
47 #include <vtkPoints.h>
48 #include <vtkPolyDataMapper.h>
49 #include <vtkProp3DCollection.h>
50 #include <vtkPropCollection.h>
51 #include <vtkProperty.h>
52 #include <vtkRenderWindow.h>
53 #include <vtkRenderer.h>
54 #include <vtkTransform.h>
55 #include <vtkVertex.h>
56 #include <vtkVolume.h>
57 
58 #include "fwRenderVTK/vtk/fwVtkPicker.hpp"
59 
60 vtkStandardNewMacro(fwVtkPicker);
61 
62 // Construct object with initial tolerance of 1/40th of window. There are no
63 // pick methods and picking is performed from the renderer's actors.
64 fwVtkPicker::fwVtkPicker() : vtkPicker()
65 {
66 
67 }
68 
69 fwVtkPicker::~fwVtkPicker()
70 {
71 }
72 
73 
74 // Perform pick operation with selection point provided. Normally the
75 // first two values for the selection point are x-y pixel coordinate, and
76 // the third value is =0. Return non-zero if something was successfully picked.
77 int fwVtkPicker::Pick(double selectionX, double selectionY, double selectionZ,
78  vtkRenderer *renderer)
79 {
80  int i;
81  vtkProp *prop;
82  vtkCamera *camera;
83  vtkAbstractMapper3D *mapper = NULL;
84  double p1World[4], p2World[4], p1Mapper[4], p2Mapper[4];
85  int picked = 0;
86  int *winSize;
87  double x, y, t;
88  double *viewport;
89  double cameraPos[4], cameraFP[4];
90  double *displayCoords, *worldCoords;
91  double *clipRange;
92  double ray[3], rayLength;
93  int pickable;
94  int LODId;
95  double windowLowerLeft[4], windowUpperRight[4];
96  double bounds[6], tol;
97  double tF, tB;
98  double hitPosition[3];
99  double cameraDOP[3];
100 
101  // Initialize picking process
102  this->Initialize();
103  this->Renderer = renderer;
104  this->SelectionPoint[0] = selectionX;
105  this->SelectionPoint[1] = selectionY;
106  this->SelectionPoint[2] = selectionZ;
107 
108  // Invoke start pick method if defined
109  this->InvokeEvent(vtkCommand::StartPickEvent,NULL);
110 
111  if ( renderer == NULL )
112  {
113  vtkErrorMacro(<<"Must specify renderer!");
114  return 0;
115  }
116 
117  // Get camera focal point and position. Convert to display (screen)
118  // coordinates. We need a depth value for z-buffer.
119  //
120  camera = renderer->GetActiveCamera();
121  camera->GetPosition(cameraPos);
122  cameraPos[3] = 1.0;
123  camera->GetFocalPoint(cameraFP);
124  cameraFP[3] = 1.0;
125 
126  renderer->SetWorldPoint(cameraFP[0],cameraFP[1],cameraFP[2],cameraFP[3]);
127  renderer->WorldToDisplay();
128  displayCoords = renderer->GetDisplayPoint();
129  selectionZ = displayCoords[2];
130 
131  // Convert the selection point into world coordinates.
132  //
133  renderer->SetDisplayPoint(selectionX, selectionY, selectionZ);
134  renderer->DisplayToWorld();
135  worldCoords = renderer->GetWorldPoint();
136  if ( worldCoords[3] == 0.0 )
137  {
138  vtkErrorMacro(<<"Bad homogeneous coordinates");
139  return 0;
140  }
141  for (i = 0; i < 3; i++)
142  {
143  this->PickPosition[i] = worldCoords[i] / worldCoords[3];
144  }
145 
146  // Compute the ray endpoints. The ray is along the line running from
147  // the camera position to the selection point, starting where this line
148  // intersects the front clipping plane, and terminating where this
149  // line intersects the back clipping plane.
150  for (i = 0; i<3; i++)
151  {
152  ray[i] = this->PickPosition[i] - cameraPos[i];
153  }
154  for (i = 0; i<3; i++)
155  {
156  cameraDOP[i] = cameraFP[i] - cameraPos[i];
157  }
158 
159  vtkMath::Normalize(cameraDOP);
160 
161  if (( rayLength = vtkMath::Dot(cameraDOP,ray)) == 0.0 )
162  {
163  vtkWarningMacro("Cannot process points");
164  return 0;
165  }
166 
167  clipRange = camera->GetClippingRange();
168 
169  if ( camera->GetParallelProjection() )
170  {
171  tF = clipRange[0] - rayLength;
172  tB = clipRange[1] - rayLength;
173  for (i = 0; i<3; i++)
174  {
175  p1World[i] = this->PickPosition[i] + tF*cameraDOP[i];
176  p2World[i] = this->PickPosition[i] + tB*cameraDOP[i];
177  }
178  }
179  else
180  {
181  tF = clipRange[0] / rayLength;
182  tB = clipRange[1] / rayLength;
183  for (i = 0; i<3; i++)
184  {
185  p1World[i] = cameraPos[i] + tF*ray[i];
186  p2World[i] = cameraPos[i] + tB*ray[i];
187  }
188  }
189  p1World[3] = p2World[3] = 1.0;
190 
191  // Compute the tolerance in world coordinates. Do this by
192  // determining the world coordinates of the diagonal points of the
193  // window, computing the width of the window in world coordinates, and
194  // multiplying by the tolerance.
195  //
196  viewport = renderer->GetViewport();
197  winSize = renderer->GetRenderWindow()->GetSize();
198  x = winSize[0] * viewport[0];
199  y = winSize[1] * viewport[1];
200  renderer->SetDisplayPoint(x, y, selectionZ);
201  renderer->DisplayToWorld();
202  renderer->GetWorldPoint(windowLowerLeft);
203 
204  x = winSize[0] * viewport[2];
205  y = winSize[1] * viewport[3];
206  renderer->SetDisplayPoint(x, y, selectionZ);
207  renderer->DisplayToWorld();
208  renderer->GetWorldPoint(windowUpperRight);
209 
210  for (tol = 0.0,i = 0; i<3; i++)
211  {
212  tol += (windowUpperRight[i] - windowLowerLeft[i]) *
213  (windowUpperRight[i] - windowLowerLeft[i]);
214  }
215 
216  tol = sqrt (tol) * this->Tolerance;
217 
218  // Loop over all props. Transform ray (defined from position of
219  // camera to selection point) into coordinates of mapper (not
220  // transformed to actors coordinates! Reduces overall computation!!!).
221  // Note that only vtkProp3D's can be picked by fwVtkPicker.
222  //
223  vtkPropCollection *props;
224  vtkProp *propCandidate;
225  if ( this->PickFromList )
226  {
227  props = this->GetPickList();
228  }
229  else
230  {
231  props = renderer->GetViewProps();
232  }
233 
234  vtkActor *actor;
235  vtkLODProp3D *prop3D;
236  vtkVolume *volume;
237  vtkImageActor *imageActor = 0;
238  vtkAssemblyPath *path;
239  vtkProperty *tempProperty;
240  this->Transform->PostMultiply();
241  vtkCollectionSimpleIterator pit;
242  double scale[3];
243  for ( props->InitTraversal(pit); (prop = props->GetNextProp(pit)); )
244  {
245  for ( prop->InitPathTraversal(); (path = prop->GetNextPath()); )
246  {
247  pickable = 0;
248  actor = NULL;
249  propCandidate = path->GetLastNode()->GetViewProp();
250  if ( propCandidate->GetPickable() && propCandidate->GetVisibility() )
251  {
252  pickable = 1;
253  if ( (actor = vtkActor::SafeDownCast(propCandidate)) != NULL )
254  {
255  mapper = actor->GetMapper();
256  if ( actor->GetProperty()->GetOpacity() <= 0.0 )
257  {
258  pickable = 0;
259  }
260  }
261  else if ( (prop3D = vtkLODProp3D::SafeDownCast(propCandidate)) != NULL )
262  {
263  LODId = prop3D->GetPickLODID();
264  mapper = prop3D->GetLODMapper(LODId);
265 
266  // if the mapper is a vtkMapper (as opposed to a vtkVolumeMapper),
267  // then check the transparency to see if the object is pickable
268  if ( vtkMapper::SafeDownCast(mapper) != NULL)
269  {
270  prop3D->GetLODProperty(LODId, &tempProperty);
271  if ( tempProperty->GetOpacity() <= 0.0 )
272  {
273  pickable = 0;
274  }
275  }
276  }
277  else if ( (volume = vtkVolume::SafeDownCast(propCandidate)) != NULL )
278  {
279  mapper = volume->GetMapper();
280  }
281  else if ( (imageActor = vtkImageActor::SafeDownCast(propCandidate)) )
282  {
283  mapper = 0;
284  }
285  else
286  {
287  pickable = 0; //only vtkProp3D's (actors and volumes) can be picked
288  }
289  }
290 
291  // If actor can be picked, get its composite matrix, invert it, and
292  // use the inverted matrix to transform the ray points into mapper
293  // coordinates.
294  if ( pickable && mapper != NULL )
295  {
296  vtkMatrix4x4 *lastMatrix = path->GetLastNode()->GetMatrix();
297  if (lastMatrix == NULL)
298  {
299  vtkErrorMacro (<< "Pick: Null matrix.");
300  return 0;
301  }
302  this->Transform->SetMatrix(lastMatrix);
303  this->Transform->Push();
304  this->Transform->Inverse();
305  this->Transform->GetScale(scale); //need to scale the tolerance
306 
307  this->Transform->TransformPoint(p1World,p1Mapper);
308  this->Transform->TransformPoint(p2World,p2Mapper);
309 
310  for (i = 0; i<3; i++)
311  {
312  ray[i] = p2Mapper[i] - p1Mapper[i];
313  }
314 
315  this->Transform->Pop();
316 
317  // Have the ray endpoints in mapper space, now need to compare this
318  // with the mapper bounds to see whether intersection is possible.
319  //
320  // Get the bounding box of the modeller. Note that the tolerance is
321  // added to the bounding box to make sure things on the edge of the
322  // bounding box are picked correctly.
323  mapper->GetBounds(bounds);
324  bounds[0] -= tol; bounds[1] += tol;
325  bounds[2] -= tol; bounds[3] += tol;
326  bounds[4] -= tol; bounds[5] += tol;
327  if ( vtkBox::IntersectBox(bounds, p1Mapper,
328  ray, hitPosition, t) )
329  {
330  t = this->IntersectWithLine(p1Mapper, p2Mapper,
331  tol*0.333*(scale[0]+scale[1]+scale[2]), path,
332  static_cast<vtkProp3D *>(propCandidate), mapper);
333  if ( t < VTK_DOUBLE_MAX )
334  {
335  picked = 1;
336  if ( !this->Prop3Ds->IsItemPresent(prop) )
337  {
338  this->Prop3Ds->AddItem(static_cast<vtkProp3D *>(prop));
339  }
340  this->PickedPositions->InsertNextPoint
341  ((1.0 - t)*p1World[0] + t*p2World[0],
342  (1.0 - t)*p1World[1] + t*p2World[1],
343  (1.0 - t)*p1World[2] + t*p2World[2]);
344 
345  // backwards compatibility: also add to this->Actors
346  if (actor)
347  {
348  this->Actors->AddItem(actor);
349  }
350  }
351  }
352  }
353  else if ( pickable && imageActor )
354  { // special case for imageActor, which has no mapper
355  vtkMatrix4x4 *lastMatrix = path->GetLastNode()->GetMatrix();
356  if (lastMatrix == NULL)
357  {
358  vtkErrorMacro (<< "Pick: Null matrix.");
359  return 0;
360  }
361  this->Transform->SetMatrix(lastMatrix);
362  this->Transform->Push();
363  this->Transform->Inverse();
364 
365  this->Transform->TransformPoint(p1World,p1Mapper);
366  this->Transform->TransformPoint(p2World,p2Mapper);
367 
368  this->Transform->Pop();
369 
370  // Have the ray endpoints in data space, now need to compare this
371  // with the displayed image bounds.
372  imageActor->GetDisplayBounds(bounds);
373 
374  t = VTK_DOUBLE_MAX;
375 
376  for (i = 0; i < 3; i++)
377  {
378  if (bounds[2*i] == bounds[2*i+1] && p2Mapper[i] != p1Mapper[i])
379  {
380 // t = (p2World[i] - bounds[2*i])/(p2Mapper[i] - p1Mapper[i]);
381  t = (p2Mapper[i] - bounds[2*i])/(p2Mapper[i] - p1Mapper[i]);
382  break;
383  }
384  }
385 
386  if (t < VTK_DOUBLE_MAX)
387  {
388 // hitPosition[0] = (1.0 - t)*p1Mapper[0] + t*p2Mapper[0];
389 // hitPosition[1] = (1.0 - t)*p1Mapper[1] + t*p2Mapper[1];
390 // hitPosition[2] = (1.0 - t)*p1Mapper[2] + t*p2Mapper[2];
391  hitPosition[0] = t*p1Mapper[0] + (1.0 - t)*p2Mapper[0];
392  hitPosition[1] = t*p1Mapper[1] + (1.0 - t)*p2Mapper[1];
393  hitPosition[2] = t*p1Mapper[2] + (1.0 - t)*p2Mapper[2];
394  if ((bounds[0] == bounds[1] || (hitPosition[0] >= bounds[0]-tol &&
395  hitPosition[0] <= bounds[1]+tol)) &&
396  (bounds[2] == bounds[3] || (hitPosition[1] >= bounds[2]-tol &&
397  hitPosition[1] <= bounds[3]+tol)) &&
398  (bounds[4] == bounds[5] || (hitPosition[2] >= bounds[4]-tol &&
399  hitPosition[2] <= bounds[5]+tol)))
400  {
401  picked = 1;
402 
403  // the following code is handled in MarkPicked for other Prop3Ds
404  this->Mapper = mapper; // mapper is null
405  this->DataSet = imageActor->GetInput();
406  this->MapperPosition[0] = hitPosition[0];
407  this->MapperPosition[1] = hitPosition[1];
408  this->MapperPosition[2] = hitPosition[2];
409  this->Transform->TransformPoint(hitPosition,this->PickPosition);
410  imageActor->Pick();
411  this->InvokeEvent(vtkCommand::PickEvent,NULL);
412 
413  this->Prop3Ds->AddItem(imageActor);
414 // this->PickedPositions->InsertNextPoint
415 // ((1.0 - t)*p1World[0] + t*p2World[0],
416 // (1.0 - t)*p1World[1] + t*p2World[1],
417 // (1.0 - t)*p1World[2] + t*p2World[2]);
418  this->PickedPositions->InsertNextPoint
419  (t*p1World[0] + (1.0 - t)*p2World[0],
420  t*p1World[1] + (1.0 - t)*p2World[1],
421  t*p1World[2] + (1.0 - t)*p2World[2]);
422  }
423  }
424  }//if visible and pickable not transparent and has mapper
425  }//for all parts
426  }//for all actors
427 
428  // Invoke end pick method if defined
429  this->InvokeEvent(vtkCommand::EndPickEvent,NULL);
430 
431  return picked;
432 }
433 
434 
435 
436 int fwVtkPicker::PickPolyData( double p1[3], double p2[3], vtkPolyData *polydata)
437 {
438 
439  vtkPolyDataMapper *mapper = vtkPolyDataMapper::New();
440  vtkActor *actor = vtkActor::New();
441  vtkPropCollection *props = vtkPropCollection::New();
442 
443  mapper->SetInputData(polydata);
444  actor->SetMapper(mapper);
445  props->AddItem(actor);
446 
447  int res = Pick( p1, p2, props );
448 
449  props->Delete();
450  mapper->Delete();
451  actor->Delete();
452 
453  return res;
454 }
455 
456 
457 
458 
459 // Perform pick operation with selection point provided. Normally the
460 // first two values for the selection point are x-y pixel coordinate, and
461 // the third value is =0. Return non-zero if something was successfully picked.
462 int fwVtkPicker::Pick( double p1[3], double p2[3], vtkPropCollection *props)
463 {
464  int i;
465  vtkProp *prop;
466  vtkAbstractMapper3D *mapper = NULL;
467  double p1World[4], p2World[4], p1Mapper[4], p2Mapper[4];
468  int picked = 0;
469  double t;
470  double ray[3];
471  int pickable;
472  int LODId;
473  double bounds[6];
474  double hitPosition[3];
475 
476  double tol = this->Tolerance;
477 
478  // Initialize picking process
479  this->Initialize();
480 
481  // Invoke start pick method if defined
482  this->InvokeEvent(vtkCommand::StartPickEvent,NULL);
483 
484  std::copy(p1,p1+3,p1World);
485  std::copy(p2,p2+3,p2World);
486 
487  p1World[3] = p2World[3] = 1.0;
488 
489  // Loop over all props. Transform ray (defined from position of
490  // camera to selection point) into coordinates of mapper (not
491  // transformed to actors coordinates! Reduces overall computation!!!).
492  // Note that only vtkProp3D's can be picked by fwVtkPicker.
493  //
494  vtkProp *propCandidate;
495 
496  vtkActor *actor;
497  vtkLODProp3D *prop3D;
498  vtkVolume *volume;
499  vtkImageActor *imageActor = 0;
500  vtkAssemblyPath *path;
501  vtkProperty *tempProperty;
502  this->Transform->PostMultiply();
503  vtkCollectionSimpleIterator pit;
504  double scale[3];
505  for ( props->InitTraversal(pit); (prop = props->GetNextProp(pit)); )
506  {
507  for ( prop->InitPathTraversal(); (path = prop->GetNextPath()); )
508  {
509  pickable = 0;
510  actor = NULL;
511  propCandidate = path->GetLastNode()->GetViewProp();
512  if ( propCandidate->GetPickable() && propCandidate->GetVisibility() )
513  {
514  pickable = 1;
515  if ( (actor = vtkActor::SafeDownCast(propCandidate)) != NULL )
516  {
517  mapper = actor->GetMapper();
518  if ( actor->GetProperty()->GetOpacity() <= 0.0 )
519  {
520  pickable = 0;
521  }
522  }
523  else if ( (prop3D = vtkLODProp3D::SafeDownCast(propCandidate)) != NULL )
524  {
525  LODId = prop3D->GetPickLODID();
526  mapper = prop3D->GetLODMapper(LODId);
527 
528  // if the mapper is a vtkMapper (as opposed to a vtkVolumeMapper),
529  // then check the transparency to see if the object is pickable
530  if ( vtkMapper::SafeDownCast(mapper) != NULL)
531  {
532  prop3D->GetLODProperty(LODId, &tempProperty);
533  if ( tempProperty->GetOpacity() <= 0.0 )
534  {
535  pickable = 0;
536  }
537  }
538  }
539  else if ( (volume = vtkVolume::SafeDownCast(propCandidate)) != NULL )
540  {
541  mapper = volume->GetMapper();
542  }
543  else if ( (imageActor = vtkImageActor::SafeDownCast(propCandidate)) )
544  {
545  mapper = 0;
546  }
547  else
548  {
549  pickable = 0; //only vtkProp3D's (actors and volumes) can be picked
550  }
551  }
552 
553  // If actor can be picked, get its composite matrix, invert it, and
554  // use the inverted matrix to transform the ray points into mapper
555  // coordinates.
556  if ( pickable && mapper != NULL )
557  {
558  vtkMatrix4x4 *lastMatrix = path->GetLastNode()->GetMatrix();
559  if (lastMatrix == NULL)
560  {
561  vtkErrorMacro (<< "Pick: Null matrix.");
562  return 0;
563  }
564  this->Transform->SetMatrix(lastMatrix);
565  this->Transform->Push();
566  this->Transform->Inverse();
567  this->Transform->GetScale(scale); //need to scale the tolerance
568 
569  this->Transform->TransformPoint(p1World,p1Mapper);
570  this->Transform->TransformPoint(p2World,p2Mapper);
571 
572  for (i = 0; i<3; i++)
573  {
574  ray[i] = p2Mapper[i] - p1Mapper[i];
575  }
576 
577  this->Transform->Pop();
578 
579  // Have the ray endpoints in mapper space, now need to compare this
580  // with the mapper bounds to see whether intersection is possible.
581  //
582  // Get the bounding box of the modeller. Note that the tolerance is
583  // added to the bounding box to make sure things on the edge of the
584  // bounding box are picked correctly.
585  mapper->GetBounds(bounds);
586  bounds[0] -= tol; bounds[1] += tol;
587  bounds[2] -= tol; bounds[3] += tol;
588  bounds[4] -= tol; bounds[5] += tol;
589  if ( vtkBox::IntersectBox(bounds, p1Mapper,
590  ray, hitPosition, t) )
591  {
592  t = this->IntersectWithLine(p1Mapper, p2Mapper,
593  tol*0.333*(scale[0]+scale[1]+scale[2]), path,
594  static_cast<vtkProp3D *>(propCandidate), mapper);
595  if ( t < VTK_DOUBLE_MAX )
596  {
597  picked = 1;
598  if ( !this->Prop3Ds->IsItemPresent(prop) )
599  {
600  this->Prop3Ds->AddItem(static_cast<vtkProp3D *>(prop));
601  }
602  this->PickedPositions->InsertNextPoint
603  ((1.0 - t)*p1World[0] + t*p2World[0],
604  (1.0 - t)*p1World[1] + t*p2World[1],
605  (1.0 - t)*p1World[2] + t*p2World[2]);
606 
607  // backwards compatibility: also add to this->Actors
608  if (actor)
609  {
610  this->Actors->AddItem(actor);
611  }
612  }
613  }
614  }
615  else if ( pickable && imageActor )
616  { // special case for imageActor, which has no mapper
617  vtkMatrix4x4 *lastMatrix = path->GetLastNode()->GetMatrix();
618  if (lastMatrix == NULL)
619  {
620  vtkErrorMacro (<< "Pick: Null matrix.");
621  return 0;
622  }
623  this->Transform->SetMatrix(lastMatrix);
624  this->Transform->Push();
625  this->Transform->Inverse();
626 
627  this->Transform->TransformPoint(p1World,p1Mapper);
628  this->Transform->TransformPoint(p2World,p2Mapper);
629 
630  this->Transform->Pop();
631 
632  // Have the ray endpoints in data space, now need to compare this
633  // with the displayed image bounds.
634  imageActor->GetDisplayBounds(bounds);
635 
636  t = VTK_DOUBLE_MAX;
637 
638  for (i = 0; i < 3; i++)
639  {
640  if (bounds[2*i] == bounds[2*i+1] && p2Mapper[i] != p1Mapper[i])
641  {
642 // t = (p2World[i] - bounds[2*i])/(p2Mapper[i] - p1Mapper[i]);
643  t = (p2Mapper[i] - bounds[2*i])/(p2Mapper[i] - p1Mapper[i]);
644  break;
645  }
646  }
647 
648  if (t < VTK_DOUBLE_MAX)
649  {
650 // hitPosition[0] = (1.0 - t)*p1Mapper[0] + t*p2Mapper[0];
651 // hitPosition[1] = (1.0 - t)*p1Mapper[1] + t*p2Mapper[1];
652 // hitPosition[2] = (1.0 - t)*p1Mapper[2] + t*p2Mapper[2];
653  hitPosition[0] = t*p1Mapper[0] + (1.0 - t)*p2Mapper[0];
654  hitPosition[1] = t*p1Mapper[1] + (1.0 - t)*p2Mapper[1];
655  hitPosition[2] = t*p1Mapper[2] + (1.0 - t)*p2Mapper[2];
656  if ((bounds[0] == bounds[1] || (hitPosition[0] >= bounds[0]-tol &&
657  hitPosition[0] <= bounds[1]+tol)) &&
658  (bounds[2] == bounds[3] || (hitPosition[1] >= bounds[2]-tol &&
659  hitPosition[1] <= bounds[3]+tol)) &&
660  (bounds[4] == bounds[5] || (hitPosition[2] >= bounds[4]-tol &&
661  hitPosition[2] <= bounds[5]+tol)))
662  {
663  picked = 1;
664 
665  // the following code is handled in MarkPicked for other Prop3Ds
666  this->Mapper = mapper; // mapper is null
667  this->DataSet = imageActor->GetInput();
668  this->MapperPosition[0] = hitPosition[0];
669  this->MapperPosition[1] = hitPosition[1];
670  this->MapperPosition[2] = hitPosition[2];
671  this->Transform->TransformPoint(hitPosition,this->PickPosition);
672  imageActor->Pick();
673  this->InvokeEvent(vtkCommand::PickEvent,NULL);
674 
675  this->Prop3Ds->AddItem(imageActor);
676 // this->PickedPositions->InsertNextPoint
677 // ((1.0 - t)*p1World[0] + t*p2World[0],
678 // (1.0 - t)*p1World[1] + t*p2World[1],
679 // (1.0 - t)*p1World[2] + t*p2World[2]);
680  this->PickedPositions->InsertNextPoint
681  (t*p1World[0] + (1.0 - t)*p2World[0],
682  t*p1World[1] + (1.0 - t)*p2World[1],
683  t*p1World[2] + (1.0 - t)*p2World[2]);
684  }
685  }
686  }//if visible and pickable not transparent and has mapper
687  }//for all parts
688  }//for all actors
689 
690  // Invoke end pick method if defined
691  this->InvokeEvent(vtkCommand::EndPickEvent,NULL);
692 
693  return picked;
694 }
695 
696 
697 
698 
699 
700 
701 void fwVtkPicker::PrintSelf(ostream& os, vtkIndent indent)
702 {
703  os << indent << "fwVtkPicker: \n";
704  this->Superclass::PrintSelf(os,indent);
705 }
706