34 #include <vtkAbstractVolumeMapper.h> 36 #include <vtkAssemblyNode.h> 37 #include <vtkAssemblyPath.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> 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> 58 #include "fwRenderVTK/vtk/fwVtkPicker.hpp" 64 fwVtkPicker::fwVtkPicker() : vtkPicker()
69 fwVtkPicker::~fwVtkPicker()
77 int fwVtkPicker::Pick(
double selectionX,
double selectionY,
double selectionZ,
78 vtkRenderer *renderer)
83 vtkAbstractMapper3D *mapper = NULL;
84 double p1World[4], p2World[4], p1Mapper[4], p2Mapper[4];
89 double cameraPos[4], cameraFP[4];
90 double *displayCoords, *worldCoords;
92 double ray[3], rayLength;
95 double windowLowerLeft[4], windowUpperRight[4];
96 double bounds[6], tol;
98 double hitPosition[3];
103 this->Renderer = renderer;
104 this->SelectionPoint[0] = selectionX;
105 this->SelectionPoint[1] = selectionY;
106 this->SelectionPoint[2] = selectionZ;
109 this->InvokeEvent(vtkCommand::StartPickEvent,NULL);
111 if ( renderer == NULL )
113 vtkErrorMacro(<<
"Must specify renderer!");
120 camera = renderer->GetActiveCamera();
121 camera->GetPosition(cameraPos);
123 camera->GetFocalPoint(cameraFP);
126 renderer->SetWorldPoint(cameraFP[0],cameraFP[1],cameraFP[2],cameraFP[3]);
127 renderer->WorldToDisplay();
128 displayCoords = renderer->GetDisplayPoint();
129 selectionZ = displayCoords[2];
133 renderer->SetDisplayPoint(selectionX, selectionY, selectionZ);
134 renderer->DisplayToWorld();
135 worldCoords = renderer->GetWorldPoint();
136 if ( worldCoords[3] == 0.0 )
138 vtkErrorMacro(<<
"Bad homogeneous coordinates");
141 for (i = 0; i < 3; i++)
143 this->PickPosition[i] = worldCoords[i] / worldCoords[3];
150 for (i = 0; i<3; i++)
152 ray[i] = this->PickPosition[i] - cameraPos[i];
154 for (i = 0; i<3; i++)
156 cameraDOP[i] = cameraFP[i] - cameraPos[i];
159 vtkMath::Normalize(cameraDOP);
161 if (( rayLength = vtkMath::Dot(cameraDOP,ray)) == 0.0 )
163 vtkWarningMacro(
"Cannot process points");
167 clipRange = camera->GetClippingRange();
169 if ( camera->GetParallelProjection() )
171 tF = clipRange[0] - rayLength;
172 tB = clipRange[1] - rayLength;
173 for (i = 0; i<3; i++)
175 p1World[i] = this->PickPosition[i] + tF*cameraDOP[i];
176 p2World[i] = this->PickPosition[i] + tB*cameraDOP[i];
181 tF = clipRange[0] / rayLength;
182 tB = clipRange[1] / rayLength;
183 for (i = 0; i<3; i++)
185 p1World[i] = cameraPos[i] + tF*ray[i];
186 p2World[i] = cameraPos[i] + tB*ray[i];
189 p1World[3] = p2World[3] = 1.0;
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);
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);
210 for (tol = 0.0,i = 0; i<3; i++)
212 tol += (windowUpperRight[i] - windowLowerLeft[i]) *
213 (windowUpperRight[i] - windowLowerLeft[i]);
216 tol = sqrt (tol) * this->Tolerance;
223 vtkPropCollection *props;
224 vtkProp *propCandidate;
225 if ( this->PickFromList )
227 props = this->GetPickList();
231 props = renderer->GetViewProps();
235 vtkLODProp3D *prop3D;
237 vtkImageActor *imageActor = 0;
238 vtkAssemblyPath *path;
239 vtkProperty *tempProperty;
240 this->Transform->PostMultiply();
241 vtkCollectionSimpleIterator pit;
243 for ( props->InitTraversal(pit); (prop = props->GetNextProp(pit)); )
245 for ( prop->InitPathTraversal(); (path = prop->GetNextPath()); )
249 propCandidate = path->GetLastNode()->GetViewProp();
250 if ( propCandidate->GetPickable() && propCandidate->GetVisibility() )
253 if ( (actor = vtkActor::SafeDownCast(propCandidate)) != NULL )
255 mapper = actor->GetMapper();
256 if ( actor->GetProperty()->GetOpacity() <= 0.0 )
261 else if ( (prop3D = vtkLODProp3D::SafeDownCast(propCandidate)) != NULL )
263 LODId = prop3D->GetPickLODID();
264 mapper = prop3D->GetLODMapper(LODId);
268 if ( vtkMapper::SafeDownCast(mapper) != NULL)
270 prop3D->GetLODProperty(LODId, &tempProperty);
271 if ( tempProperty->GetOpacity() <= 0.0 )
277 else if ( (volume = vtkVolume::SafeDownCast(propCandidate)) != NULL )
279 mapper = volume->GetMapper();
281 else if ( (imageActor = vtkImageActor::SafeDownCast(propCandidate)) )
294 if ( pickable && mapper != NULL )
296 vtkMatrix4x4 *lastMatrix = path->GetLastNode()->GetMatrix();
297 if (lastMatrix == NULL)
299 vtkErrorMacro (<<
"Pick: Null matrix.");
302 this->Transform->SetMatrix(lastMatrix);
303 this->Transform->Push();
304 this->Transform->Inverse();
305 this->Transform->GetScale(scale);
307 this->Transform->TransformPoint(p1World,p1Mapper);
308 this->Transform->TransformPoint(p2World,p2Mapper);
310 for (i = 0; i<3; i++)
312 ray[i] = p2Mapper[i] - p1Mapper[i];
315 this->Transform->Pop();
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) )
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 )
336 if ( !this->Prop3Ds->IsItemPresent(prop) )
338 this->Prop3Ds->AddItem(static_cast<vtkProp3D *>(prop));
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]);
348 this->Actors->AddItem(actor);
353 else if ( pickable && imageActor )
355 vtkMatrix4x4 *lastMatrix = path->GetLastNode()->GetMatrix();
356 if (lastMatrix == NULL)
358 vtkErrorMacro (<<
"Pick: Null matrix.");
361 this->Transform->SetMatrix(lastMatrix);
362 this->Transform->Push();
363 this->Transform->Inverse();
365 this->Transform->TransformPoint(p1World,p1Mapper);
366 this->Transform->TransformPoint(p2World,p2Mapper);
368 this->Transform->Pop();
372 imageActor->GetDisplayBounds(bounds);
376 for (i = 0; i < 3; i++)
378 if (bounds[2*i] == bounds[2*i+1] && p2Mapper[i] != p1Mapper[i])
381 t = (p2Mapper[i] - bounds[2*i])/(p2Mapper[i] - p1Mapper[i]);
386 if (t < VTK_DOUBLE_MAX)
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)))
404 this->Mapper = mapper;
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);
411 this->InvokeEvent(vtkCommand::PickEvent,NULL);
413 this->Prop3Ds->AddItem(imageActor);
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]);
429 this->InvokeEvent(vtkCommand::EndPickEvent,NULL);
436 int fwVtkPicker::PickPolyData(
double p1[3],
double p2[3], vtkPolyData *polydata)
439 vtkPolyDataMapper *mapper = vtkPolyDataMapper::New();
440 vtkActor *actor = vtkActor::New();
441 vtkPropCollection *props = vtkPropCollection::New();
443 mapper->SetInputData(polydata);
444 actor->SetMapper(mapper);
445 props->AddItem(actor);
447 int res = Pick( p1, p2, props );
462 int fwVtkPicker::Pick(
double p1[3],
double p2[3], vtkPropCollection *props)
466 vtkAbstractMapper3D *mapper = NULL;
467 double p1World[4], p2World[4], p1Mapper[4], p2Mapper[4];
474 double hitPosition[3];
476 double tol = this->Tolerance;
482 this->InvokeEvent(vtkCommand::StartPickEvent,NULL);
484 std::copy(p1,p1+3,p1World);
485 std::copy(p2,p2+3,p2World);
487 p1World[3] = p2World[3] = 1.0;
494 vtkProp *propCandidate;
497 vtkLODProp3D *prop3D;
499 vtkImageActor *imageActor = 0;
500 vtkAssemblyPath *path;
501 vtkProperty *tempProperty;
502 this->Transform->PostMultiply();
503 vtkCollectionSimpleIterator pit;
505 for ( props->InitTraversal(pit); (prop = props->GetNextProp(pit)); )
507 for ( prop->InitPathTraversal(); (path = prop->GetNextPath()); )
511 propCandidate = path->GetLastNode()->GetViewProp();
512 if ( propCandidate->GetPickable() && propCandidate->GetVisibility() )
515 if ( (actor = vtkActor::SafeDownCast(propCandidate)) != NULL )
517 mapper = actor->GetMapper();
518 if ( actor->GetProperty()->GetOpacity() <= 0.0 )
523 else if ( (prop3D = vtkLODProp3D::SafeDownCast(propCandidate)) != NULL )
525 LODId = prop3D->GetPickLODID();
526 mapper = prop3D->GetLODMapper(LODId);
530 if ( vtkMapper::SafeDownCast(mapper) != NULL)
532 prop3D->GetLODProperty(LODId, &tempProperty);
533 if ( tempProperty->GetOpacity() <= 0.0 )
539 else if ( (volume = vtkVolume::SafeDownCast(propCandidate)) != NULL )
541 mapper = volume->GetMapper();
543 else if ( (imageActor = vtkImageActor::SafeDownCast(propCandidate)) )
556 if ( pickable && mapper != NULL )
558 vtkMatrix4x4 *lastMatrix = path->GetLastNode()->GetMatrix();
559 if (lastMatrix == NULL)
561 vtkErrorMacro (<<
"Pick: Null matrix.");
564 this->Transform->SetMatrix(lastMatrix);
565 this->Transform->Push();
566 this->Transform->Inverse();
567 this->Transform->GetScale(scale);
569 this->Transform->TransformPoint(p1World,p1Mapper);
570 this->Transform->TransformPoint(p2World,p2Mapper);
572 for (i = 0; i<3; i++)
574 ray[i] = p2Mapper[i] - p1Mapper[i];
577 this->Transform->Pop();
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) )
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 )
598 if ( !this->Prop3Ds->IsItemPresent(prop) )
600 this->Prop3Ds->AddItem(static_cast<vtkProp3D *>(prop));
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]);
610 this->Actors->AddItem(actor);
615 else if ( pickable && imageActor )
617 vtkMatrix4x4 *lastMatrix = path->GetLastNode()->GetMatrix();
618 if (lastMatrix == NULL)
620 vtkErrorMacro (<<
"Pick: Null matrix.");
623 this->Transform->SetMatrix(lastMatrix);
624 this->Transform->Push();
625 this->Transform->Inverse();
627 this->Transform->TransformPoint(p1World,p1Mapper);
628 this->Transform->TransformPoint(p2World,p2Mapper);
630 this->Transform->Pop();
634 imageActor->GetDisplayBounds(bounds);
638 for (i = 0; i < 3; i++)
640 if (bounds[2*i] == bounds[2*i+1] && p2Mapper[i] != p1Mapper[i])
643 t = (p2Mapper[i] - bounds[2*i])/(p2Mapper[i] - p1Mapper[i]);
648 if (t < VTK_DOUBLE_MAX)
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)))
666 this->Mapper = mapper;
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);
673 this->InvokeEvent(vtkCommand::PickEvent,NULL);
675 this->Prop3Ds->AddItem(imageActor);
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]);
691 this->InvokeEvent(vtkCommand::EndPickEvent,NULL);
701 void fwVtkPicker::PrintSelf(ostream& os, vtkIndent indent)
703 os << indent <<
"fwVtkPicker: \n";
704 this->Superclass::PrintSelf(os,indent);