Fraxinus  17.12
An IGT application
cxViewWrapper2D.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) 2008-2014, SINTEF Department of Medical Technology
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice,
11  this list of conditions and the following disclaimer.
12 
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 3. Neither the name of the copyright holder nor the names of its contributors
18  may be used to endorse or promote products derived from this software
19  without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =========================================================================*/
32 
33 /*
34  * cxViewWrapper2D.cpp
35  *
36  * \date Mar 24, 2010
37  * \author christiana
38  */
39 
40 
41 #include "cxViewWrapper2D.h"
42 #include <vector>
43 #include <vtkCamera.h>
44 #include <vtkRenderer.h>
45 #include <vtkRenderWindow.h>
46 
47 #include <QAction>
48 #include <QActionGroup>
49 #include <QMenu>
50 #include <QMouseEvent>
51 #include <QWheelEvent>
52 
53 #include "cxUtilHelpers.h"
54 #include "cxView.h"
55 #include "cxSliceProxy.h"
56 #include "cxSlicerRepSW.h"
57 #include "cxToolRep2D.h"
60 #include "cxDisplayTextRep.h"
61 
62 #include "cxManualTool.h"
63 #include "cxTrackingService.h"
64 #include "cxViewGroup.h"
65 #include "cxDefinitionStrings.h"
66 #include "cxSlicePlanes3DRep.h"
67 #include "cxDefinitionStrings.h"
68 #include "cxSliceComputer.h"
69 #include "cxGeometricRep2D.h"
70 #include "cxDataLocations.h"
71 #include "cxSettings.h"
72 #include "cxGLHelpers.h"
73 #include "cxData.h"
74 #include "cxMesh.h"
75 #include "cxImage.h"
76 #include "cxTrackedStream.h"
77 #include "cxPointMetricRep2D.h"
78 
79 #include "cxViewFollower.h"
80 #include "cxVisServices.h"
81 #include "cx2DZoomHandler.h"
82 #include "cxNavigation.h"
83 #include "cxDataRepContainer.h"
84 #include "vtkRenderWindowInteractor.h"
85 #include "cxPatientModelService.h"
86 #include "cxLogger.h"
87 #include "cxViewService.h"
89 
90 #include "cxTexture3DSlicerRep.h"
91 
92 namespace cx
93 {
94 
96  ViewWrapper(backend),
97  mOrientationActionGroup(new QActionGroup(view.get()))
98 {
99  qRegisterMetaType<Vector3D>("Vector3D");
100  mView = view;
101  this->connectContextMenu(mView);
102 
103  // disable vtk interactor: this wrapper IS an interactor
104  mView->getRenderWindow()->GetInteractor()->Disable();
105  mView->getRenderer()->GetActiveCamera()->SetParallelProjection(true);
106  double clipDepth = 1.0; // 1mm depth, i.e. all 3D props rendered outside this range is not shown.
107  double length = clipDepth*10;
108  mView->getRenderer()->GetActiveCamera()->SetPosition(0,0,length);
109  mView->getRenderer()->GetActiveCamera()->SetClippingRange(length-clipDepth, length+0.1);
110 
111  // slice proxy
112  mSliceProxy = SliceProxy::create(mServices->patient());
113 
114  mDataRepContainer.reset(new DataRepContainer());
115  mDataRepContainer->setSliceProxy(mSliceProxy);
116  mDataRepContainer->setView(mView);
117 
118  mViewFollower = ViewFollower::create(mServices->patient());
119  mViewFollower->setSliceProxy(mSliceProxy);
120 
121  addReps();
122 
123  mZoom2D.reset(new Zoom2DHandler());
124  connect(mZoom2D.get(), SIGNAL(zoomChanged()), this, SLOT(viewportChanged()));
125 
126  connect(mServices->tracking().get(), SIGNAL(activeToolChanged(const QString&)), this, SLOT(activeToolChangedSlot()));
127  connect(mView.get(), SIGNAL(resized(QSize)), this, SLOT(viewportChanged()));
128  connect(mView.get(), SIGNAL(shown()), this, SLOT(showSlot()));
129  connect(mView.get(), SIGNAL(mousePress(int, int, Qt::MouseButtons)), this, SLOT(mousePressSlot(int, int, Qt::MouseButtons)));
130  connect(mView.get(), SIGNAL(mouseMove(int, int, Qt::MouseButtons)), this, SLOT(mouseMoveSlot(int, int, Qt::MouseButtons)));
131  connect(mView.get(), SIGNAL(mouseWheel(int, int, int, int, Qt::MouseButtons)), this, SLOT(mouseWheelSlot(int, int, int, int, Qt::MouseButtons)));
132 
134 
135  this->activeToolChangedSlot();
136  this->updateView();
137 }
138 
140 {
141  if (mView)
142  mView->removeReps();
143 }
144 
145 void ViewWrapper2D::changeZoom(double delta)
146 {
147  if (similar(delta, 1.0))
148  return;
149 
150  double zoom = mZoom2D->getFactor();
151 // CX_LOG_CHANNEL_DEBUG("CA") << "changing zoom from " << zoom << " by " << delta;
152  zoom *= delta;
153 // CX_LOG_CHANNEL_DEBUG("CA") << " new zoom:" << zoom;
154  mZoom2D->setFactor(zoom);
155 // CX_LOG_CHANNEL_DEBUG("CA") << " got zoom:" << mZoom2D->getFactor();
156 }
157 
159 {
160  if(!this->isAnyplane())
161  return;
162 
163  Transform3D sMr = mSliceProxy->get_sMr();
164  Transform3D vpMs = mView->get_vpMs();
165 
166  Vector3D p_s = vpMs.inv().coord(click_vp);
167  Vector3D p_r = sMr.inv().coord(p_s);
168 
169  emit pointSampled(p_r);
170 }
171 
172 void ViewWrapper2D::appendToContextMenu(QMenu& contextMenu)
173 {
174  contextMenu.addSeparator();
175  mZoom2D->addActionsToMenu(&contextMenu);
176 
177  contextMenu.addSeparator();
178  QAction* showManualTool = new QAction("Show Manual Tool 2D", &contextMenu);
179  showManualTool->setCheckable(true);
180  showManualTool->setChecked(settings()->value("View2D/showManualTool").toBool());
181  connect(showManualTool, SIGNAL(triggered(bool)), this, SLOT(showManualToolSlot(bool)));
182  contextMenu.addAction(showManualTool);
183 }
184 
186 {
188 
189  mZoom2D->setGroupData(group);
190  connect(group.get(), SIGNAL(optionsChanged()), this, SLOT(optionChangedSlot()));
191  this->optionChangedSlot();
192 }
193 
194 void ViewWrapper2D::optionChangedSlot()
195 {
196  ViewGroupData::Options options = mGroupData->getOptions();
197 
198  if (mPickerGlyphRep)
199  {
200  mPickerGlyphRep->setMesh(options.mPickerGlyph);
201  }
202 }
203 
204 void ViewWrapper2D::addReps()
205 {
206  // annotation rep
207  mOrientationAnnotationRep = OrientationAnnotationSmartRep::New();
208  mView->addRep(mOrientationAnnotationRep);
209 
210  this->ViewWrapper::addReps();
211 
212  // tool rep
213  mToolRep2D = ToolRep2D::New(mServices->spaceProvider(), "Tool2D_" + mView->getName());
214  mToolRep2D->setSliceProxy(mSliceProxy);
215  mToolRep2D->setUseCrosshair(true);
216  this->toggleShowManualTool();
217 
218  mPickerGlyphRep = GeometricRep2D::New("PickerGlyphRep_" + mView->getName());
219  mPickerGlyphRep->setSliceProxy(mSliceProxy);
220  if (mGroupData)
221  {
222  mPickerGlyphRep->setMesh(mGroupData->getOptions().mPickerGlyph);
223  }
224  mView->addRep(mPickerGlyphRep);
225 }
226 
228 {
230 
231  if (key == "View2D/useGPU2DRendering")
232  {
233  this->updateView();
234  }
235  if (key == "View2D/useLinearInterpolationIn2DRendering")
236  {
237  this->updateView();
238  }
239  if (key == "Navigation/anyplaneViewOffset")
240  {
241  this->updateView();
242  }
243  if (key == "View2D/showManualTool")
244  {
245  this->toggleShowManualTool();
246  }
247 }
248 
249 void ViewWrapper2D::toggleShowManualTool()
250 {
251  if (settings()->value("View2D/showManualTool").toBool())
252  mView->addRep(mToolRep2D);
253  else
254  mView->removeRep(mToolRep2D);
255 }
256 
257 void ViewWrapper2D::removeAndResetSliceRep()
258 {
259  if (mSliceRep)
260  {
261  mView->removeRep(mSliceRep);
262  mSliceRep.reset();
263  }
264 }
265 
266 void ViewWrapper2D::removeAndResetMultiSliceRep()
267 {
268  if (mMultiSliceRep)
269  {
270  mView->removeRep(mMultiSliceRep);
271  mMultiSliceRep.reset();
272  }
273 }
274 
275 bool ViewWrapper2D::createAndAddMultiSliceRep()
276 {
278  {
279  CX_LOG_WARNING() << "ViewWrapper2D::createAndAddMultiSliceRep(): Got no mSharedOpenGLContext";
280  return false;
281  }
282  if (mMultiSliceRep)
283  return true;
284 
286  mMultiSliceRep->setShaderPath(DataLocations::findConfigFolder("/shaders"));
287  mMultiSliceRep->setSliceProxy(mSliceProxy);
288  mMultiSliceRep->setRenderWindow(mView->getRenderWindow());
289 
290  mView->addRep(mMultiSliceRep);
291 
292  return true;
293 }
294 
300 void ViewWrapper2D::recreateMultiSlicer()
301 {
302  this->removeAndResetSliceRep();
303 
304  if (!this->useGPU2DRendering())
305  {
306  this->removeAndResetMultiSliceRep();
307  return;
308  }
309 
310  if(!this->createAndAddMultiSliceRep())
311  {
312  return;
313  }
314 
315  if (mGroupData)
316  mMultiSliceRep->setImages(this->getImagesToView());
317  else
318  mMultiSliceRep->setImages(std::vector<ImagePtr>());
319 
320  this->viewportChanged();
321 }
322 
323 std::vector<ImagePtr> ViewWrapper2D::getImagesToView()
324 {
325  std::vector<ImagePtr> images = mGroupData->getImagesAndChangingImagesFromTrackedStreams(DataViewProperties::createSlice2D());
326 
327  if(this->isAnyplane())
328  {
329  std::vector<TrackedStreamPtr> streams = mGroupData->getTracked2DStreams(DataViewProperties::createSlice2D());
330  for(int i = 0; i < streams.size(); ++i)
331  images.push_back(streams[i]->getChangingImage());
332  }
333  return images;
334 }
335 
336 bool ViewWrapper2D::isAnyplane()
337 {
338  PLANE_TYPE plane = mSliceProxy->getComputer().getPlaneType();
339  return plane == ptANYPLANE;
340 }
341 
345 void ViewWrapper2D::viewportChanged()
346 {
347  if (!mView->getRenderer()->IsActiveCameraCreated())
348  return;
349 
350  mView->setZoomFactor(mZoom2D->getFactor());
351 
352  double viewHeight = mView->getViewport_s().range()[1];
353  mView->getRenderer()->GetActiveCamera()->SetParallelScale(viewHeight / 2);
354 
355  // Heuristic guess for a good clip depth. The point is to show 3D data clipped in 2D
356  // with a suitable thickness projected onto the plane.
357  double clipDepth = 2.0; // i.e. all 3D props rendered outside this range is not shown.
358  double length = clipDepth*10;
359  clipDepth = viewHeight/120 + 1.5;
360  mView->getRenderer()->GetActiveCamera()->SetPosition(0,0,length);
361  mView->getRenderer()->GetActiveCamera()->SetClippingRange(length-clipDepth, length+0.1);
362 
363  mSliceProxy->setToolViewportHeight(viewHeight);
364  double anyplaneViewOffset = settings()->value("Navigation/anyplaneViewOffset").toDouble();
365  mSliceProxy->initializeFromPlane(mSliceProxy->getComputer().getPlaneType(), false, true, viewHeight, anyplaneViewOffset);
366 
367  DoubleBoundingBox3D BB_vp = getViewport();
368  Transform3D vpMs = mView->get_vpMs();
369  DoubleBoundingBox3D BB_s = transform(vpMs.inv(), BB_vp);
370  PLANE_TYPE plane = mSliceProxy->getComputer().getPlaneType();
371 
372  mToolRep2D->setViewportData(vpMs, BB_vp);
373  if (mSlicePlanes3DMarker)
374  {
375  mSlicePlanes3DMarker->getProxy()->setViewportData(plane, mSliceProxy, BB_s);
376  }
377 }
378 
379 void ViewWrapper2D::applyViewFollower()
380 {
381  if (!mGroupData)
382  return;
383  QString roiUid = mGroupData->getOptions().mCameraStyle.mAutoZoomROI;
384  mViewFollower->setAutoZoomROI(roiUid);
385  mViewFollower->setView(this->getViewport_s());
386  SliceAutoViewportCalculator::ReturnType result = mViewFollower->calculate();
387 
388 // CX_LOG_CHANNEL_DEBUG("CA") << "roi=" << roiUid;
389 // CX_LOG_CHANNEL_DEBUG("CA") << this << " autozoom zoom=" << result.zoom << ", center=" << result.center_shift_s;
390  this->changeZoom(result.zoom);
391  Vector3D newcenter_r = mViewFollower->findCenter_r_fromShift_s(result.center_shift_s);
392  mServices->patient()->setCenter(newcenter_r);
393 }
394 
397 DoubleBoundingBox3D ViewWrapper2D::getViewport() const
398 {
399  QSize size = mView->size();
400  Vector3D p0_d(0, 0, 0);
401  Vector3D p1_d(size.width(), size.height(), 0);
402  DoubleBoundingBox3D BB_vp(p0_d, p1_d);
403  return BB_vp;
404 }
405 
406 void ViewWrapper2D::showSlot()
407 {
408  activeToolChangedSlot();
409  viewportChanged();
410 }
411 
412 void ViewWrapper2D::initializePlane(PLANE_TYPE plane)
413 {
414  double viewHeight = mView->getViewport_s().range()[1];
415  mSliceProxy->initializeFromPlane(plane, false, true, viewHeight, 0.25);
416  mOrientationAnnotationRep->setSliceProxy(mSliceProxy);
417 }
418 
421 ORIENTATION_TYPE ViewWrapper2D::getOrientationType() const
422 {
423  return mSliceProxy->getComputer().getOrientationType();
424 }
425 
427 {
428  return mView;
429 }
430 
433 void ViewWrapper2D::imageAdded(ImagePtr image)
434 {
435  this->updateView();
436 
437  // removed this side effect: unwanted when loading a patient, might also be unwanted to change scene when adding/removing via gui?
438  //Navigation().centerToView(mViewGroup->getImages());
439 }
440 
442 {
443  if (!mGroupData)
444  return ImagePtr();
445 
446  std::vector<ImagePtr> images = mGroupData->getImagesAndChangingImagesFromTrackedStreams(DataViewProperties::createSlice2D(), true);
447  ImagePtr image;
448  if (!images.empty())
449  image = images.back(); // always show last in vector
450 
451  return image;
452 }
453 
454 bool ViewWrapper2D::useGPU2DRendering()
455 {
456  return settings()->value("View2D/useGPU2DRendering").toBool();
457 }
458 
459 void ViewWrapper2D::createAndAddSliceRep()
460 {
461  if (!mSliceRep)
462  {
463  mSliceRep = SliceRepSW::New("SliceRep_" + mView->getName());
464  mSliceRep->setSliceProxy(mSliceProxy);
465  mView->addRep(mSliceRep);
466  }
467 }
468 
470 {
471  QString text;
472  if (this->useGPU2DRendering())
473  {
474  text = this->getAllDataNames(DataViewProperties::createSlice2D()).join("\n");
475  }
476  else //software rendering
477  {
478  ImagePtr image = this->getImageToDisplay();
479  if (!image)
480  return "";
481  // list all meshes and one image.
482  QStringList textList;
483  std::vector<MeshPtr> mesh = mGroupData->getMeshes(DataViewProperties::createSlice2D());
484  for (unsigned i = 0; i < mesh.size(); ++i)
485  textList << qstring_cast(mesh[i]->getName());
486  if (image)
487  textList << image->getName();
488  text = textList.join("\n");
489  }
490  return text;
491 }
492 
494 {
495  return qstring_cast(mSliceProxy->getComputer().getPlaneType());
496 }
497 
498 void ViewWrapper2D::updateItemsFromViewGroup()
499 {
500  if (!mGroupData)
501  return;
502 
503  ImagePtr image = this->getImageToDisplay();
504 
505  if (image)
506  {
507  Vector3D c = image->get_rMd().coord(image->boundingBox().center());
508  mSliceProxy->setDefaultCenter(c);
509 
510  if (this->useGPU2DRendering())
511  {
512  this->recreateMultiSlicer();
513  }
514  else //software rendering
515  {
516  this->removeAndResetMultiSliceRep();
517  this->createAndAddSliceRep();
518 
519  mSliceRep->setImage(image);
520  }
521  }
522  else //no images to display in the view
523  {
524  this->removeAndResetSliceRep();
525  this->removeAndResetMultiSliceRep();
526  }
527 }
528 
530 {
531  if (!this->getView())
532  return;
533  this->updateItemsFromViewGroup();
534 
535  this->ViewWrapper::updateView();
536 
537  //UPDATE ORIENTATION ANNOTATION
538  mOrientationAnnotationRep->setVisible(settings()->value("View/showOrientationAnnotation").value<bool>());
539 
540  //UPDATE DATA METRIC ANNOTATION
541  mDataRepContainer->updateSettings();
542 
543  if (mToolRep2D)
544  {
545  bool isOblique = mSliceProxy->getComputer().getOrientationType() == otOBLIQUE;
546  bool useCrosshair = settings()->value("View2D/showToolCrosshair", true).toBool();
547  mToolRep2D->setUseCrosshair(!isOblique && useCrosshair);
548  mToolRep2D->setCrosshairColor(settings()->value("View2D/toolCrossHairColor").value<QColor>());
549  mToolRep2D->setTooltipLineColor(settings()->value("View2D/toolColor").value<QColor>());
550  mToolRep2D->setTooltipPointColor(settings()->value("View/toolTipPointColor").value<QColor>());
551  mToolRep2D->setToolOffsetPointColor(settings()->value("View/toolOffsetPointColor").value<QColor>());
552  mToolRep2D->setToolOffsetLineColor(settings()->value("View/toolOffsetLineColor").value<QColor>());
553  }
554 
555  this->applyViewFollower();
556 }
557 
558 DoubleBoundingBox3D ViewWrapper2D::getViewport_s() const
559 {
560  DoubleBoundingBox3D BB_vp = getViewport();
561  Transform3D vpMs = mView->get_vpMs();
562  DoubleBoundingBox3D BB_s = transform(vpMs.inv(), BB_vp);
563  return BB_s;
564 }
565 
567 {
568  DataPtr data = mServices->patient()->getData(uid);
569  DataViewProperties properties = mGroupData->getProperties(uid);
570 
571  if (properties.hasSlice2D())
572  this->dataAdded(data);
573  else
574  this->dataRemoved(uid);
575 }
576 
577 void ViewWrapper2D::dataAdded(DataPtr data)
578 {
579  if (boost::dynamic_pointer_cast<Image>(data))
580  {
581  this->imageAdded(boost::dynamic_pointer_cast<Image>(data));
582  }
583  else
584  {
585  mDataRepContainer->addData(data);
586  }
587  this->updateView();
588 }
589 
590 void ViewWrapper2D::dataRemoved(const QString& uid)
591 {
592  mDataRepContainer->removeData(uid);
593  this->updateView();
594 }
595 
596 void ViewWrapper2D::activeToolChangedSlot()
597 {
598  ToolPtr activeTool = mServices->tracking()->getActiveTool();
599  mSliceProxy->setTool(activeTool);
600 }
601 
606 void ViewWrapper2D::mousePressSlot(int x, int y, Qt::MouseButtons buttons)
607 {
608  if (buttons & Qt::LeftButton)
609  {
610  Vector3D clickPos_vp = qvp2vp(QPoint(x,y));
611  moveManualTool(clickPos_vp, Vector3D(0,0,0));
612  samplePoint(clickPos_vp);
613  }
614 }
615 
620 void ViewWrapper2D::mouseMoveSlot(int x, int y, Qt::MouseButtons buttons)
621 {
622  if (buttons & Qt::LeftButton)
623  {
624  Vector3D clickPos_vp = qvp2vp(QPoint(x,y));
625  moveManualTool(clickPos_vp, clickPos_vp - mLastClickPos_vp);
626  }
627 }
628 
629 void ViewWrapper2D::moveManualTool(Vector3D vp, Vector3D delta_vp)
630 {
631  if (this->getOrientationType() == otORTHOGONAL)
632  setAxisPos(vp);
633  else
634  {
635  this->shiftAxisPos(delta_vp); // signal the maual tool that something is happening (important for playback tool)
636  mLastClickPos_vp = vp;
637  }
638 }
639 
643 void ViewWrapper2D::mouseWheelSlot(int x, int y, int delta, int orientation, Qt::MouseButtons buttons)
644 {
645  // scale zoom in log space
646  double val = log10(mZoom2D->getFactor());
647  val += delta / 120.0 / 20.0; // 120 is normal scroll resolution, x is zoom resolution
648  double newZoom = pow(10.0, val);
649 
650  mZoom2D->setFactor(newZoom);
651 
652  Navigation(mServices).centerToTooltip(); // side effect: center on tool
653 }
654 
658 Vector3D ViewWrapper2D::qvp2vp(QPoint pos_qvp)
659 {
660  QSize size = mView->size();
661  Vector3D pos_vp(pos_qvp.x(), size.height()-1 - pos_qvp.y(), 0.0); // convert from left-handed qt space to vtk space display/viewport
662  return pos_vp;
663 }
664 
668 void ViewWrapper2D::shiftAxisPos(Vector3D delta_vp)
669 {
670  delta_vp = -delta_vp;
671  ToolPtr tool = mServices->tracking()->getManualTool();
672 
673  Transform3D sMr = mSliceProxy->get_sMr();
674  Transform3D rMpr = mServices->patient()->get_rMpr();
675  Transform3D prMt = tool->get_prMt();
676  Transform3D vpMs = mView->get_vpMs();
677  Vector3D delta_s = vpMs.inv().vector(delta_vp);
678 
679  Vector3D delta_pr = (rMpr.inv() * sMr.inv()).vector(delta_s);
680 
681  // MD is the actual tool movement in patient space, matrix form
682  Transform3D MD = createTransformTranslate(delta_pr);
683  // set new tool position to old modified by MD:
684  tool->set_prMt(MD * prMt);
685 }
686 
690 void ViewWrapper2D::setAxisPos(Vector3D click_vp)
691 {
692  ToolPtr tool = mServices->tracking()->getManualTool();
693 
694  Transform3D sMr = mSliceProxy->get_sMr();
695  Transform3D rMpr = mServices->patient()->get_rMpr();
696  Transform3D prMt = tool->get_prMt();
697 
698  // find tool position in s
699  Vector3D tool_t(0, 0, tool->getTooltipOffset());
700  Vector3D tool_s = (sMr * rMpr * prMt).coord(tool_t);
701 
702  // find click position in s.
703  Transform3D vpMs = mView->get_vpMs();
704  Vector3D click_s = vpMs.inv().coord(click_vp);
705 
706  // compute the new tool position in slice space as a synthesis of the plane part of click and the z part of original.
707  Vector3D cross_s(click_s[0], click_s[1], tool_s[2]);
708  // compute the position change and transform to patient.
709  Vector3D delta_s = cross_s - tool_s;
710  Vector3D delta_pr = (rMpr.inv() * sMr.inv()).vector(delta_s);
711 
712  // MD is the actual tool movement in patient space, matrix form
713  Transform3D MD = createTransformTranslate(delta_pr);
714  // set new tool position to old modified by MD:
715  tool->set_prMt(MD * prMt);
716 }
717 
719 {
720  mSlicePlanes3DMarker = SlicePlanes3DMarkerIn2DRep::New("uid");
721  PLANE_TYPE plane = mSliceProxy->getComputer().getPlaneType();
722  mSlicePlanes3DMarker->setProxy(plane, proxy);
723 
724 // DoubleBoundingBox3D BB_vp = getViewport();
725 // Transform3D vpMs = mView->get_vpMs();
726 // mSlicePlanes3DMarker->getProxy()->setViewportData(plane, mSliceProxy, transform(vpMs.inv(), BB_vp));
727  mSlicePlanes3DMarker->getProxy()->setViewportData(plane, mSliceProxy, this->getViewport_s());
728 
729  mView->addRep(mSlicePlanes3DMarker);
730 }
731 
733 {
734  this->updateView();
735 }
736 
737 void ViewWrapper2D::showManualToolSlot(bool visible)
738 {
739  settings()->setValue("View2D/showManualTool", visible);
740 }
741 
742 //------------------------------------------------------------------------------
743 }
QString qstring_cast(const T &val)
DoubleBoundingBox3D transform(const Transform3D &m, const DoubleBoundingBox3D &bb)
boost::shared_ptr< class ViewGroupData > ViewGroupDataPtr
Definition: cxViewGroup.h:50
static SliceProxyPtr create(PatientModelServicePtr dataManager)
boost::shared_ptr< class SlicePlanesProxy > SlicePlanesProxyPtr
virtual void videoSourcesChangedSlot()
virtual QString getViewDescription()
otOBLIQUE
orient planes relative to the tool space
Definition: cxDefinitions.h:50
boost::shared_ptr< class VisServices > VisServicesPtr
Definition: cxMainWindow.h:61
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
virtual ViewPtr getView()
boost::shared_ptr< class Image > ImagePtr
Definition: cxDicomWidget.h:48
Superclass for ViewWrappers.
SharedOpenGLContextPtr mSharedOpenGLContext
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Definition: cxSettings.cpp:87
boost::shared_ptr< class View > ViewPtr
virtual QString getDataDescription()
virtual void setViewGroup(ViewGroupDataPtr group)
static DataViewProperties createSlice2D()
static SlicePlanes3DMarkerIn2DRepPtr New(const QString &uid="")
static OrientationAnnotationSmartRepPtr New(const QString &uid="")
void setValue(const QString &key, const QVariant &value)
Definition: cxSettings.cpp:79
virtual void setViewGroup(ViewGroupDataPtr group)
boost::shared_ptr< class Data > DataPtr
virtual void updateView()
static QString findConfigFolder(QString pathRelativeToConfigRoot, QString alternativeAbsolutePath="")
void settingsChangedSlot(QString key)
void centerToTooltip()
otORTHOGONAL
orient planes relative to the image/reference space.
Definition: cxDefinitions.h:50
ViewGroupDataPtr mGroupData
static Texture3DSlicerRepPtr New(SharedOpenGLContextPtr context, const QString &uid="")
static SliceRepSWPtr New(const QString &uid="")
Transform3D createTransformTranslate(const Vector3D &translation)
virtual void dataViewPropertiesChangedSlot(QString uid)
virtual void initializePlane(PLANE_TYPE plane)
virtual void settingsChangedSlot(QString key)
Settings * settings()
Shortcut for accessing the settings instance.
Definition: cxSettings.cpp:42
Representation of a floating-point bounding box in 3D. The data are stored as {xmin,xmax,ymin,ymax,zmin,zmax}, in order to simplify communication with vtk.
virtual void setSlicePlanesProxy(SlicePlanesProxyPtr proxy)
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:63
static GeometricRep2DPtr New(const QString &uid="")
virtual void addReps()
VisServicesPtr mServices
void samplePoint(Vector3D click_vp)
QStringList getAllDataNames(DataViewProperties properties) const
bool similar(const CameraInfo &lhs, const CameraInfo &rhs, double tol)
#define CX_LOG_WARNING
Definition: cxLogger.h:119
RealScalar length() const
virtual void updateView()
static ToolRep2DPtr New(SpaceProviderPtr spaceProvider, const QString &uid="")
Definition: cxToolRep2D.cpp:87
ImagePtr getImageToDisplay()
ptANYPLANE
a plane aligned with the tool base plane
Definition: cxDefinitions.h:56
void connectContextMenu(ViewPtr view)
static ViewFollowerPtr create(PatientModelServicePtr dataManager)
ViewWrapper2D(ViewPtr view, VisServicesPtr backend)
void pointSampled(Vector3D p_r)
Namespace for all CustusX production code.
boost::shared_ptr< class Tool > ToolPtr