NorMIT-nav  2023.01.05-dev+develop.0da12
An IGT application
cxPickerRep.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 
12 
13 #include "cxPickerRep.h"
14 
15 #include "boost/bind.hpp"
16 #include <vtkActor.h>
17 #include <vtkCamera.h>
18 #include <vtkRenderer.h>
19 #include <vtkProperty.h>
20 #include <vtkImageData.h>
21 #include <vtkLineSource.h>
22 //#include <vtkDoubleArray.h>
23 #include <vtkProbeFilter.h>
24 #include <vtkSphereSource.h>
25 #include <vtkRenderWindow.h>
26 #include <vtkCallbackCommand.h>
27 #include <vtkPolyDataMapper.h>
28 //#include <vtkDataSetAttributes.h>
29 #include <vtkEventQtSlotConnect.h>
30 //#include <vtkCellPicker.h>
31 #include "cxMesh.h"
32 #include "cxPatientModelService.h"
33 #include "cxLogger.h"
34 #include "cxImage.h"
35 #include "cxView.h"
36 #include "cxTool.h"
38 #include "cxGeometricRep.h"
39 #include <vtkRenderWindowInteractor.h>
40 #include "cxLogger.h"
41 #include "vtkVolumePicker.h"
42 
43 #include "cxConfig.h"
44 #ifdef CX_BUILD_MEHDI_VTKMULTIVOLUME
45  #include "vtkMultiVolumePicker.h"
46  typedef vtkSmartPointer<class vtkMultiVolumePicker> vtkMultiVolumePickerPtr;
47 // typedef vtkSmartPointer<class vtkVolumePicker> vtkMultiVolumePickerPtr;
48 #else
49  typedef vtkSmartPointer<class vtkVolumePicker> vtkMultiVolumePickerPtr;
50 #endif
51 
52 namespace cx
53 {
54 PickerRepPtr PickerRep::New(PatientModelServicePtr dataManager, const QString& uid)
55 {
56  return wrap_new(new PickerRep(dataManager), uid);
57 }
59  RepImpl(),
60  mDataManager(dataManager),
61  mPickedPoint(), mSphereRadius(2) //, mConnections(vtkEventQtSlotConnectPtr::New())
62 {
63  mIsDragging = false;
65  mViewportListener->setCallback(boost::bind(&PickerRep::scaleSphere, this));
66 
67  this->mCallbackCommand = vtkCallbackCommandPtr::New();
68  this->mCallbackCommand->SetClientData(this);
69  this->mCallbackCommand->SetCallback(PickerRep::ProcessEvents);
70 
71  mEnabled = true;
72  mConnected = false;
73  mSnapToSurface = false;
74 }
75 
77 {
78  if (!mGraphicalPoint)
79  return;
80 
81  double size = mViewportListener->getVpnZoom(mPickedPoint);
82  double sphereSize = mSphereRadius / 100 / size;
83  mGraphicalPoint->setRadius(sphereSize);
84 }
85 
87 {
88 }
89 QString PickerRep::getType() const
90 {
91  return "PickerRep";
92 }
93 
94 void PickerRep::setSphereRadius(double radius)
95 {
96  mSphereRadius = radius;
97  if (mGraphicalPoint)
98  mGraphicalPoint->setRadius(mSphereRadius);
99 }
100 
102 {
103  if (tool == mTool)
104  return;
105 
106  if (mTool)
107  {
108  disconnect(mTool.get(), SIGNAL(toolTransformAndTimestamp(Transform3D, double)), this,
109  SLOT(setModified()));
110  }
111 
112  mTool = tool;
113 
114  if (mTool)
115  {
116  connect(mTool.get(), SIGNAL(toolTransformAndTimestamp(Transform3D, double)), this,
117  SLOT(setModified()));
118  this->setModified();
119  }
120 }
121 
123 {
124  if (!mGlyph)
125  mGlyph = glyph;
126 
127  if (!mGlyphRep)
128  {
129  mGlyphRep = GeometricRep::New("PickerGlyphRep");
130  if (this->getView())
131  {
132  this->getView()->addRep(mGlyphRep);
133  }
134  }
135 
136  mGlyphRep->setMesh(mGlyph);
137 }
138 
139 typedef vtkSmartPointer<class vtkDataSet> vtkDataSetPtr;
140 
148 void PickerRep::pickLandmark(const Vector3D& clickPosition, vtkRendererPtr renderer)
149 {
150  if (!this->mEnabled)
151  return;
152  vtkMultiVolumePickerPtr picker = vtkMultiVolumePickerPtr::New();
153  int hit = picker->Pick(clickPosition[0], clickPosition[1], 0, renderer);
154  if (!hit)
155  {
156  mIsDragging = false;
157  return;
158  }
159 
160  // search for picked data in manager, emit uid if found.
161  vtkDataSetPtr data = picker->GetDataSet();
162  if (data)
163  {
164  std::map<QString, DataPtr> allData = mDataManager->getDatas();
165  for (std::map<QString, DataPtr>::iterator iter = allData.begin(); iter != allData.end(); ++iter)
166  {
167  MeshPtr mesh = boost::dynamic_pointer_cast<Mesh>(iter->second);
168  if (mesh && mesh->getVtkPolyData() == data)
169  emit dataPicked(iter->first);
170 
171  ImagePtr image = boost::dynamic_pointer_cast<Image>(iter->second);
172  if (image && image->getBaseVtkImageData() == data)
173  emit dataPicked(iter->first);
174  }
175  }
176 
177  Vector3D pick_w(picker->GetPickPosition());
178 
179  if ( data &&
180  ((mGraphicalPoint && (data == mGraphicalPoint->getPolyData() ))
181  ||(mGlyph && (data == mGlyph->getVtkPolyData() ))
182  ||(mTool && (data == mTool->getGraphicsPolyData() )))
183  )
184  {
185  // We have clicked the picker/tool itself.
186  // Store click pos and wait for dragging.
187  mClickedPoint = pick_w;
188  mIsDragging = true;
189  mCallbackCommand->SetAbortFlag(1); // abort this event: interactor does not receive it.
190  return;
191  }
192  else
193  {
194  mIsDragging = false;
195  }
196 
197  if (hit && mSnapToSurface)
198  {
199  mPickedPoint = pick_w;
200 
201  if (mGraphicalPoint)
202  mGraphicalPoint->setValue(mPickedPoint);
204 
206  }
207 }
208 
209 void PickerRep::pickLandmarkSlot(vtkObject* renderWindowInteractor)
210 {
211  vtkRenderWindowInteractorPtr iren = vtkRenderWindowInteractor::SafeDownCast(renderWindowInteractor);
212 
213  if (iren == NULL)
214  return;
215 
216  int pickedPoint[2]; //<x,y>
217  iren->GetEventPosition(pickedPoint); //mouse positions are measured in pixels
218 
219  vtkRendererPtr renderer = this->getRenderer();
220  if (renderer == NULL)
221  return;
222 
223  Vector3D clickPoint(pickedPoint[0], pickedPoint[1], 0);
224 
225  this->pickLandmark(clickPoint, renderer);
226 }
227 
229 {
230  this->toolHasChanged();
231 }
232 
234 {
235  if (!mTool)
236  return;
237  Transform3D prMt = mTool->get_prMt();
238  Transform3D rMpr = mDataManager->get_rMpr();
239  Transform3D rMt = rMpr * prMt;
240  Vector3D p_r = rMt.coord(Vector3D(0, 0, mTool->getTooltipOffset()));
241 
242  mPickedPoint = p_r;
243  if (mGraphicalPoint)
244  mGraphicalPoint->setValue(mPickedPoint);
246 }
247 
249 {
250  mEnabled = on;
251  if (mSnapToSurface == on)
252  return;
253 
254  mSnapToSurface = on;
255 
256  if (mSnapToSurface)
257  {
258  if (mGraphicalPoint)
259  mGraphicalPoint->getActor()->SetVisibility(true);
260  }
261  else
262  {
263  if (mGraphicalPoint)
264  mGraphicalPoint->getActor()->SetVisibility(false);
265  }
266 }
267 
268 void PickerRep::ProcessEvents(vtkObject* vtkNotUsed(object), unsigned long event, void* clientdata,
269  void* vtkNotUsed(calldata))
270 {
271  PickerRep* self = reinterpret_cast<PickerRep *>(clientdata);
272 
273  //okay, let's do the right thing
274  switch (event)
275  {
276  case vtkCommand::LeftButtonPressEvent:
277  self->OnLeftButtonDown();
278  break;
279  case vtkCommand::LeftButtonReleaseEvent:
280  self->OnLeftButtonUp();
281  break;
282  case vtkCommand::MouseMoveEvent:
283  self->OnMouseMove();
284  break;
285  }
286 }
287 
292 {
293  double worldPt[4];
294  vtkRendererPtr ren = this->getRenderer();
295  ren->SetDisplayPoint(p_d.data());
296  ren->DisplayToWorld();
297  ren->GetWorldPoint(worldPt);
298  return Vector3D(worldPt)/worldPt[3];
299 }
300 
305 {
306  Vector3D p_d;
307  vtkRendererPtr ren = this->getRenderer();
308  ren->SetWorldPoint(p_w[0], p_w[1], p_w[2], 1.0);
309  ren->WorldToDisplay();
310  ren->GetDisplayPoint(p_d.data());
311  return p_d;
312 }
313 
317 {
318  vtkRenderWindowInteractorPtr interactor = this->getView()->getRenderWindow()->GetInteractor();
319 
320 // // find previous pos in world and display:
321  Vector3D p_prev_w = mClickedPoint;
322 // std::cout << " p_prev_w = \t" << p_prev_w << std::endl;
323  Vector3D p_prev_d = this->ComputeWorldToDisplay(p_prev_w);
324 // std::cout << " p_prev_d = \t" << p_prev_d << std::endl;
325 
326  // find current pos in world and display, set z-pos in d equal to previous z-pos:
327  Vector3D p_current_d(interactor->GetEventPosition()[0], interactor->GetEventPosition()[1], p_prev_d[2]);
328 // std::cout << " p_current_d = \t" << p_current_d << std::endl;
329  Vector3D p_current_w = this->ComputeDisplayToWorld(p_current_d);
330 // std::cout << " p_current_w = \t" << p_current_w << std::endl;
331 
332  // both positions are now in the camera focal plane: the diff lies in the view plane.
333 // std::cout << " diff_d = \t" << p_current_d - p_prev_d << std::endl;
334 // std::cout << " diff_w = \t" << p_current_w - p_prev_w << std::endl;
335  return p_current_w - p_prev_w;
336 }
337 
339 {
340  this->pickLandmarkSlot(this->getView()->getRenderWindow()->GetInteractor());
341 }
342 
344 {
345  if (mIsDragging)
346  {
347  mPickedPoint += this->getDisplacement();
349 
350  if (mGraphicalPoint)
351  mGraphicalPoint->setValue(mPickedPoint);
354 
355  mCallbackCommand->SetAbortFlag(1);
356  }
357 }
358 
360 {
361  if (mGlyph)
362  {
363  mGlyph->get_rMd_History()->setRegistration(createTransformTranslate(pos));
364  }
365 }
366 
367 
369 {
370  if (mIsDragging)
371  {
372  mIsDragging = false;
373  mCallbackCommand->SetAbortFlag(1); // abort this event: interactor does not receive it.
374  }
375 }
376 
378 {
379  if (!this->getView())
380  return;
381  if (mConnected)
382  return;
383 
384  vtkRenderWindowInteractorPtr i = this->getView()->getRenderWindow()->GetInteractor();
385  i->AddObserver(vtkCommand::MouseMoveEvent, this->mCallbackCommand, 1.0);
386  i->AddObserver(vtkCommand::LeftButtonPressEvent, this->mCallbackCommand, 1.0);
387  i->AddObserver(vtkCommand::LeftButtonReleaseEvent, this->mCallbackCommand, 1.0);
388 
389  mConnected = true;
390 }
391 
393 {
394  if (!this->getView())
395  return;
396  if (!mConnected)
397  return;
398 
399  // don't listen for events any more
400  this->getView()->getRenderWindow()->GetInteractor()->RemoveObserver(this->mCallbackCommand);
401 
402  mConnected = false;
403 }
404 
406 {
407  if (view == NULL)
408  {
409  reportDebug("Cannot add rep actor to a NULL view.");
410  return;
411  }
412 
413  this->connectInteractor();
414 
415  mGraphicalPoint.reset(new GraphicalPoint3D(this->getRenderer()));
416  mGraphicalPoint->setColor(QColor(Qt::blue));
417  mGraphicalPoint->setRadius(mSphereRadius);
418  mGraphicalPoint->getActor()->SetVisibility(mSnapToSurface);
419 
420  // show even if disabled
421  if (mGlyphRep)
422  {
423  this->getView()->addRep(mGlyphRep);
424  }
425 
426  mViewportListener->startListen(this->getRenderer());
427  this->scaleSphere();
428 }
429 
431 {
432  if (view == NULL)
433  return;
434 
435  this->disconnectInteractor();
436  mViewportListener->stopListen();
437  mGraphicalPoint.reset();
438 
439  if (mGlyphRep)
440  view->removeRep(mGlyphRep);
441 }
442 
444 {
445  return mPickedPoint;
446 }
447 
448 } //namespace cx
cx::PickerRep::mCallbackCommand
vtkCallbackCommandPtr mCallbackCommand
Definition: cxPickerRep.h:110
cx::PickerRep::pickLandmark
void pickLandmark(const Vector3D &clickPosition, vtkRendererPtr renderer)
When you don't use the renderwindowinteractor.
Definition: cxPickerRep.cpp:148
cx::PickerRep::disconnectInteractor
void disconnectInteractor()
Definition: cxPickerRep.cpp:392
cxLogger.h
cx::PickerRep::mSnapToSurface
bool mSnapToSurface
if set, clicking on a Data surface will pick that point
Definition: cxPickerRep.h:106
cx::PickerRep::mGlyph
MeshPtr mGlyph
Definition: cxPickerRep.h:101
cx
Namespace for all CustusX production code.
Definition: cx_dev_group_definitions.h:13
cx::ViewportListener
Listens to changes in viewport and camera matrix.
Definition: cxViewportListener.h:67
cx::PickerRep::addRepActorsToViewRenderer
virtual void addRepActorsToViewRenderer(ViewPtr view)
connects to the renderwindowinteractor
Definition: cxPickerRep.cpp:405
cx::PickerRep::ProcessEvents
static void ProcessEvents(vtkObject *object, unsigned long event, void *clientdata, void *calldata)
Definition: cxPickerRep.cpp:268
cx::RepImpl::getRenderer
vtkRendererPtr getRenderer()
Definition: cxRepImpl.cpp:88
cxImage.h
cx::reportDebug
void reportDebug(QString msg)
Definition: cxLogger.cpp:68
cx::PickerRep::mDataManager
PatientModelServicePtr mDataManager
Definition: cxPickerRep.h:111
vtkMultiVolumePickerPtr
vtkSmartPointer< class vtkVolumePicker > vtkMultiVolumePickerPtr
Definition: cxPickerRep.cpp:49
cx::PickerRep::toolHasChanged
void toolHasChanged()
Definition: cxPickerRep.cpp:233
cx::PickerRep::mTool
ToolPtr mTool
the connected tool
Definition: cxPickerRep.h:98
cx::PickerRep::mEnabled
bool mEnabled
Definition: cxPickerRep.h:96
cx::PickerRep::setEnabled
void setEnabled(bool on)
Definition: cxPickerRep.cpp:248
cx::PickerRep::getDisplacement
Vector3D getDisplacement()
Definition: cxPickerRep.cpp:316
cx::RepImpl::getView
ViewPtr getView() const
Definition: cxRepImpl.cpp:83
cxGeometricRep.h
cx::PickerRep::ComputeWorldToDisplay
Vector3D ComputeWorldToDisplay(Vector3D p_w)
Definition: cxPickerRep.cpp:304
cx::PickerRep::mSphereRadius
double mSphereRadius
Definition: cxPickerRep.h:100
cx::PickerRep::OnLeftButtonUp
void OnLeftButtonUp()
Definition: cxPickerRep.cpp:368
cx::PickerRep::mGraphicalPoint
GraphicalPoint3DPtr mGraphicalPoint
Definition: cxPickerRep.h:108
cx::PickerRep::PickerRep
PickerRep(PatientModelServicePtr dataManager)
use New instead
Definition: cxPickerRep.cpp:58
cx::PickerRep::setTool
void setTool(ToolPtr tool)
set the tool to listen to
Definition: cxPickerRep.cpp:101
cx::MeshPtr
boost::shared_ptr< class Mesh > MeshPtr
Definition: cxForwardDeclarations.h:48
cx::Transform3D
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
Definition: cxLandmarkPatientRegistrationWidget.h:33
cx::PickerRep::setGlyphCenter
void setGlyphCenter(Vector3D pos)
Definition: cxPickerRep.cpp:359
cx::PickerRep::ComputeDisplayToWorld
Vector3D ComputeDisplayToWorld(Vector3D p_d)
Definition: cxPickerRep.cpp:291
cx::PatientModelServicePtr
boost::shared_ptr< class PatientModelService > PatientModelServicePtr
Definition: cxLogicManager.h:25
cxTool.h
cxView.h
cxPatientModelService.h
cx::PickerRep::OnMouseMove
void OnMouseMove()
Definition: cxPickerRep.cpp:343
cx::ImagePtr
boost::shared_ptr< class Image > ImagePtr
Definition: cxDicomWidget.h:27
cx::PickerRep::getPosition
Vector3D getPosition() const
Definition: cxPickerRep.cpp:443
cx::PickerRep::scaleSphere
void scaleSphere()
Definition: cxPickerRep.cpp:76
cx::PickerRep::mViewportListener
ViewportListenerPtr mViewportListener
Definition: cxPickerRep.h:109
cx::PickerRep::removeRepActorsFromViewRenderer
virtual void removeRepActorsFromViewRenderer(ViewPtr view)
disconnects from the renderwindowinteractor
Definition: cxPickerRep.cpp:430
cxRegistrationTransform.h
cx::ViewPtr
boost::shared_ptr< class View > ViewPtr
Definition: cxForwardDeclarations.h:110
cx::RepImpl
Default implementation of Rep.
Definition: cxRepImpl.h:42
cx::GraphicalPoint3D
Helper for rendering a point in 3D.
Definition: cxGraphicalPrimitives.h:122
cx::PickerRep::setSphereRadius
void setSphereRadius(double radius)
Definition: cxPickerRep.cpp:94
cx::PickerRepPtr
boost::shared_ptr< class PickerRep > PickerRepPtr
Definition: cxForwardDeclarations.h:83
cx::PickerRep::pickLandmarkSlot
void pickLandmarkSlot(vtkObject *renderWindowInteractor)
When you use the renderwindowinteractor.
Definition: cxPickerRep.cpp:209
cx::RepImpl::setModified
void setModified()
Definition: cxRepImpl.cpp:112
cx::PickerRep::pointPicked
void pointPicked(Vector3D p_r)
cx::PickerRep::mClickedPoint
Vector3D mClickedPoint
Definition: cxPickerRep.h:103
vtkRenderWindowInteractorPtr
vtkSmartPointer< class vtkRenderWindowInteractor > vtkRenderWindowInteractorPtr
Definition: vtkForwardDeclarations.h:123
cx::PickerRep::dataPicked
void dataPicked(QString uid)
the rep sends out a signal when the user picks a point on it
cx::ToolPtr
boost::shared_ptr< class Tool > ToolPtr
Definition: cxVideoConnectionWidget.h:43
cx::PickerRep::mConnected
bool mConnected
Interactor connected.
Definition: cxPickerRep.h:97
cx::PickerRep::mGlyphRep
GeometricRepPtr mGlyphRep
Definition: cxPickerRep.h:102
cx::PickerRep
Picking of points in an image.
Definition: cxPickerRep.h:49
cx::GeometricRep::New
static GeometricRepPtr New(const QString &uid="")
Definition: cxGeometricRep.cpp:184
cx::PickerRep::OnLeftButtonDown
void OnLeftButtonDown()
Definition: cxPickerRep.cpp:338
cx::createTransformTranslate
Transform3D createTransformTranslate(const Vector3D &translation)
Definition: cxTransform3D.cpp:164
cxPickerRep.h
cx::PickerRep::mIsDragging
bool mIsDragging
Definition: cxPickerRep.h:104
cx::PickerRep::New
static PickerRepPtr New(PatientModelServicePtr dataManager, const QString &uid="")
for creating new instances
Definition: cxPickerRep.cpp:54
cx::RepImpl::wrap_new
static boost::shared_ptr< REP > wrap_new(REP *object, QString uid)
Definition: cxRepImpl.h:62
cx::PickerRep::getType
virtual QString getType() const
returns a string identifying this class type
Definition: cxPickerRep.cpp:89
cxMesh.h
cx::Vector3D
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:42
cx::PickerRep::onModifiedStartRender
virtual void onModifiedStartRender()
Definition: cxPickerRep.cpp:228
vtkRendererPtr
vtkSmartPointer< class vtkRenderer > vtkRendererPtr
Definition: vtkForwardDeclarations.h:122
cx::PickerRep::setGlyph
void setGlyph(MeshPtr glyph)
Definition: cxPickerRep.cpp:122
cx::vtkDataSetPtr
vtkSmartPointer< class vtkDataSet > vtkDataSetPtr
Definition: cxPickerRep.cpp:139
cx::PickerRep::~PickerRep
virtual ~PickerRep()
empty
Definition: cxPickerRep.cpp:86
cx::PickerRep::mPickedPoint
Vector3D mPickedPoint
the last point that was successfully sampled from intersection with an image
Definition: cxPickerRep.h:99
cx::PickerRep::connectInteractor
void connectInteractor()
Definition: cxPickerRep.cpp:377