NorMIT-nav  18.04
An IGT application
cxViewWrapper3D.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 #include "cxViewWrapper3D.h"
13 
14 #include <vector>
15 
16 #include "boost/bind.hpp"
17 #include "boost/function.hpp"
18 
19 #include <QAction>
20 #include <QMenu>
21 
22 #include <vtkRenderWindow.h>
23 #include <vtkRenderer.h>
24 #include <vtkImageData.h>
25 
26 #include "cxView.h"
27 #include "cxSliceProxy.h"
28 #include "cxSlicerRepSW.h"
29 #include "cxToolRep2D.h"
30 #include "cxDisplayTextRep.h"
31 #include "cxLogger.h"
32 #include "cxSlicePlanes3DRep.h"
33 #include "cxMesh.h"
34 #include "cxPickerRep.h"
35 #include "cxGeometricRep.h"
36 #include "cxToolRep3D.h"
37 #include "cxTypeConversions.h"
38 #include "cxVideoSource.h"
39 #include "cxVideoRep.h"
40 #include "cxToolTracer.h"
42 #include "cxSettings.h"
43 #include "cxTrackingService.h"
44 #include "cxRepManager.h"
45 #include "cxCameraControl.h"
46 #include "cxLandmarkRep.h"
47 #include "cxPointMetricRep.h"
48 #include "cxDistanceMetricRep.h"
50 #include "cxAngleMetricRep.h"
51 #include "cxPlaneMetricRep.h"
52 #include "cxFrameMetricRep.h"
53 #include "cxToolMetricRep.h"
54 #include "cxDataMetricRep.h"
55 #include "cxDataLocations.h"
56 #include "cxEnumConverter.h"
57 #include "cxManualTool.h"
58 #include "cxImage2DRep3D.h"
59 
60 #include "cxPatientModelService.h"
61 #include "cxRepContainer.h"
62 
63 
64 #include "cxData.h"
65 #include "cxAxesRep.h"
66 #include "cxViewGroup.h"
67 
68 #include "cxAngleMetric.h"
69 #include "cxDistanceMetric.h"
70 #include "cxPointMetric.h"
71 #include "cxSphereMetric.h"
72 #include "cxShapedMetric.h"
73 #include "cxCustomMetric.h"
74 #include "cxSphereMetricRep.h"
75 #include "cxDonutMetricRep.h"
76 #include "cxCustomMetricRep.h"
77 
78 #include "cxDepthPeeling.h"
79 #include "cxAxisConnector.h"
81 #include "cxMetricNamesRep.h"
82 #include "cxVisServices.h"
83 #include "cxNavigation.h"
84 
85 #include "cxTrackedStream.h"
86 #include "cxStreamRep3D.h"
87 #include "cxStream2DRep3D.h"
88 #include "cxActiveData.h"
89 
90 #include "cxSlices3DRep.h"
91 
92 namespace cx
93 {
94 
95 ViewWrapper3D::ViewWrapper3D(int startIndex, ViewPtr view, VisServicesPtr services):
96  ViewWrapper(services)
97 {
98  view->getRenderer()->GetActiveCamera()->SetClippingRange(0.1, 2000);
99  if (!view->getRenderWindow()->GetStereoCapableWindow())
100  view->getRenderWindow()->StereoCapableWindowOn(); // Just set all 3D views 3D capable
101 
102  mShowAxes = false;
103  mView = view;
104  this->connectContextMenu(mView);
105  QString index = QString::number(startIndex);
106  QColor background = settings()->value("backgroundColor").value<QColor>();
107  mView->setBackgroundColor(background);
108 
109  view->getRenderer()->GetActiveCamera()->SetParallelProjection(false);
110 // connect(settings(), SIGNAL(valueChangedFor(QString)), this, SLOT(settingsChangedSlot(QString)));
111 
112  this->initializeMultiVolume3DRepProducer();
113 
114  mLandmarkRep = LandmarkRep::New(mServices->patient());
115  mLandmarkRep->setGraphicsSize(settings()->value("View3D/sphereRadius").toDouble());
116  mLandmarkRep->setLabelSize(settings()->value("View3D/labelSize").toDouble());
117 
118  mPickerRep = PickerRep::New(mServices->patient());
119 
120  connect(mPickerRep.get(), SIGNAL(pointPicked(Vector3D)), this, SLOT(pickerRepPointPickedSlot(Vector3D)));
121 // connect(mPickerRep.get(), SIGNAL(dataPicked(QString)), this, SLOT(pickerRepDataPickedSlot(QString)));
122  mPickerRep->setSphereRadius(settings()->value("View3D/sphereRadius").toDouble());
123  mPickerRep->setEnabled(false);
124  mView->addRep(mPickerRep);
125  connect(mServices->tracking().get(), SIGNAL(activeToolChanged(const QString&)), this, SLOT(activeToolChangedSlot()));
126  this->activeToolChangedSlot();
127 
128  this->ViewWrapper::addReps();
129 
130  //data name text rep
131  this->updateMetricNamesRep();
132 
133  connect(mServices->tracking().get(), &TrackingService::stateChanged, this, &ViewWrapper3D::toolsAvailableSlot);
134  connect(mServices->patient()->getActiveData().get(), &ActiveData::activeImageChanged, this, &ViewWrapper3D::activeImageChangedSlot);
135  this->toolsAvailableSlot();
136 
138  this->settingsChangedSlot("View3D/annotationModel");
139  this->settingsChangedSlot("View3D/annotationModelSize");
140  mView->addRep(mAnnotationMarker);
141 
142 //Stereo
143 // mView->getRenderWindow()->StereoCapableWindowOn(); // Moved to cxView3D
144 // connect(settings(), SIGNAL(valueChangedFor(QString)), this, SLOT(globalConfigurationFileChangedSlot(QString)));
145  //Init 3D stereo from settings
146  this->setStereoType(settings()->value("View3D/stereoType").toInt());
147  this->setStereoEyeAngle(settings()->value("View3D/eyeAngle").toDouble());
148 
149  //Only try to set depth peeling if View3D/depthPeeling == true
150  if(settings()->value("View3D/depthPeeling").toBool())
151  this->setTranslucentRenderingToDepthPeeling(settings()->value("View3D/depthPeeling").toBool());
152 
153  this->updateView();
154 }
155 
157 {
158  if (mView)
159  {
160  mView->removeReps();
161  mMultiVolume3DRepProducer->removeRepsFromView();
162  }
163 }
164 
165 void ViewWrapper3D::initializeMultiVolume3DRepProducer()
166 {
167  if (!mView)
168  reportError("Missing View in initializeMultiVolume3DRepProducer");
169 
170  if (!mMultiVolume3DRepProducer)
171  {
172  mMultiVolume3DRepProducer.reset(new MultiVolume3DRepProducer());
173  connect(mMultiVolume3DRepProducer.get(), SIGNAL(imagesChanged()), this, SLOT(updateView()));
174  mMultiVolume3DRepProducer->setView(mView);
175  }
176 
177  mMultiVolume3DRepProducer->setMaxRenderSize(settings()->value("View3D/maxRenderSize").toInt());
178  mMultiVolume3DRepProducer->setVisualizerType(settings()->value("View3D/ImageRender3DVisualizer").toString());
179 }
180 
182 {
184 
185  if (key == "View3D/stereoType")
186  {
187  this->setStereoType(settings()->value("View3D/stereoType").toInt());
188  }
189  if (key == "View3D/eyeAngle")
190  {
191  this->setStereoEyeAngle(settings()->value("View3D/eyeAngle").toDouble());
192  }
193  if (key == "backgroundColor")
194  {
195  QColor background = settings()->value("backgroundColor").value<QColor>();
196  mView->setBackgroundColor(background);
197  }
198  if (( key=="View3D/ImageRender3DVisualizer" )||( key=="View3D/maxRenderSize" ))
199  {
200  this->initializeMultiVolume3DRepProducer();
201  }
202  if ((key == "View/showDataText")
203  || (key == "View/showOrientationAnnotation"))
204  {
205  this->updateView();
206  }
207  if ((key == "View3D/annotationModelSize" )||( key == "View3D/annotationModel"))
208  {
209  QString annotationFile = settings()->value("View3D/annotationModel").toString();
210  mAnnotationMarker->setMarkerFilename(DataLocations::findConfigFilePath(annotationFile, "/models"));
211  mAnnotationMarker->setSize(settings()->value("View3D/annotationModelSize").toDouble());
212  }
213  if (key == "View3D/showManualTool")
214  {
215  this->toolsAvailableSlot();
216  }
217  if ((key == "View3D/sphereRadius" )
218  ||( key == "View3D/labelSize" )
219  ||( key == "View/showLabels")
220  ||( key == "View/showMetricNamesInCorner"))
221  {
222  for (RepMap::iterator iter = mDataReps.begin(); iter != mDataReps.end(); ++iter)
223  {
224  this->readDataRepSettings(iter->second);
225  }
226 
227  this->updateMetricNamesRep();
228 
229  this->toolsAvailableSlot();
230  mLandmarkRep->setGraphicsSize(settings()->value("View3D/sphereRadius").toDouble());
231  mLandmarkRep->setLabelSize(settings()->value("View3D/labelSize").toDouble());
232  }
233  if (key == "View3D/depthPeeling")
234  this->setTranslucentRenderingToDepthPeeling(settings()->value("View3D/depthPeeling").toBool());
235 }
236 
237 void ViewWrapper3D::updateMetricNamesRep()
238 {
239  bool enabled = settings()->value("View/showMetricNamesInCorner").value<bool>();
240 
241  if (enabled)
242  {
243  if (!mMetricNames)
244  {
245  mMetricNames = MetricNamesRep::New();
246  mView->addRep(mMetricNames);
247  }
248 
249  if (mGroupData)
250  mMetricNames->setData(mGroupData->getData());
251  }
252  else
253  {
254  mView->removeRep(mMetricNames);
255  mMetricNames.reset();
256  }
257 }
258 
259 void ViewWrapper3D::pickerRepPointPickedSlot(Vector3D p_r)
260 {
261  NavigationPtr nav = this->getNavigation();
262  nav->centerToPosition(p_r, Navigation::v2D);
263 }
264 
265 void ViewWrapper3D::pickerRepDataPickedSlot(QString uid)
266 {
267  //std::cout << "picked: " << uid << std::endl;
268 }
269 
270 void ViewWrapper3D::appendToContextMenu(QMenu& contextMenu)
271 {
272  QAction* slicePlanesAction = NULL;
273  QAction* fillSlicePlanesAction = NULL;
274  if (mSlicePlanes3DRep)
275  {
276  slicePlanesAction = new QAction("Show Slice Planes", &contextMenu);
277  slicePlanesAction->setCheckable(true);
278  slicePlanesAction->setChecked(mSlicePlanes3DRep->getProxy()->getVisible());
279  connect(slicePlanesAction, SIGNAL(triggered(bool)), this, SLOT(showSlicePlanesActionSlot(bool)));
280 
281  fillSlicePlanesAction = new QAction("Fill Slice Planes", &contextMenu);
282  fillSlicePlanesAction->setCheckable(true);
283  fillSlicePlanesAction->setEnabled(mSlicePlanes3DRep->getProxy()->getVisible());
284  fillSlicePlanesAction->setChecked(mSlicePlanes3DRep->getProxy()->getDrawPlanes());
285  connect(fillSlicePlanesAction, SIGNAL(triggered(bool)), this, SLOT(fillSlicePlanesActionSlot(bool)));
286  }
287 
288  QAction* resetCameraAction = new QAction("Reset Camera (r)", &contextMenu);
289  connect(resetCameraAction, SIGNAL(triggered()), this, SLOT(resetCameraActionSlot()));
290 
291  QAction* centerImageAction = new QAction("Center to image", &contextMenu);
292  connect(centerImageAction, SIGNAL(triggered()), this, SLOT(centerImageActionSlot()));
293 
294  QAction* centerToolAction = new QAction("Center to tool", &contextMenu);
295  connect(centerToolAction, SIGNAL(triggered()), this, SLOT(centerToolActionSlot()));
296 
297  QAction* showAxesAction = new QAction("Show Coordinate Axes", &contextMenu);
298  showAxesAction->setCheckable(true);
299  showAxesAction->setChecked(mShowAxes);
300  connect(showAxesAction, SIGNAL(triggered(bool)), this, SLOT(showAxesActionSlot(bool)));
301 
302  QAction* showManualTool = new QAction("Show Manual Tool 3D", &contextMenu);
303  showManualTool->setCheckable(true);
304  showManualTool->setChecked(settings()->value("View3D/showManualTool").toBool());
305  connect(showManualTool, SIGNAL(triggered(bool)), this, SLOT(showManualToolSlot(bool)));
306 
307  QAction* showOrientation = new QAction("Show Orientation", &contextMenu);
308  showOrientation->setCheckable(true);
309  showOrientation->setChecked(mAnnotationMarker->getVisible());
310  connect(showOrientation, SIGNAL(triggered(bool)), this, SLOT(showOrientationSlot(bool)));
311 
312  QAction* showToolPath = new QAction("Show Tool Path", &contextMenu);
313  showToolPath->setCheckable(true);
314  showToolPath->setChecked(settings()->value("showToolPath").toBool());
315  connect(showToolPath, SIGNAL(triggered(bool)), this, SLOT(showToolPathSlot(bool)));
316 
317  QMenu* show3DSlicesMenu = new QMenu("Show 3D slices");
318  mShow3DSlicesInteractor->addDataActionsOfType<Image>(show3DSlicesMenu);
319 
320  QMenu* showSlicesMenu = new QMenu("Slice Type", &contextMenu);
321  this->createSlicesActions(showSlicesMenu);
322 
323  QAction* showRefTool = new QAction("Show Reference Tool", &contextMenu);
324  showRefTool->setDisabled(true);
325  showRefTool->setCheckable(true);
326  ToolPtr refTool = mServices->tracking()->getReferenceTool();
327  if (refTool)
328  {
329  showRefTool->setText("Show " + refTool->getName());
330  showRefTool->setEnabled(true);
331  showRefTool->setChecked(RepContainer(mView->getReps()).findFirst<ToolRep3D>(refTool) ? true : false);
332  connect(showRefTool, SIGNAL(toggled(bool)), this, SLOT(showRefToolSlot(bool)));
333  }
334 
335  contextMenu.addSeparator();
336  contextMenu.addMenu(show3DSlicesMenu);
337  contextMenu.addMenu(showSlicesMenu);
338  contextMenu.addSeparator();
339  contextMenu.addAction(resetCameraAction);
340  contextMenu.addAction(centerImageAction);
341  contextMenu.addAction(centerToolAction);
342  contextMenu.addAction(showAxesAction);
343  contextMenu.addAction(showOrientation);
344  contextMenu.addSeparator();
345  contextMenu.addAction(showManualTool);
346  contextMenu.addAction(showRefTool);
347  if (showToolPath)
348  contextMenu.addAction(showToolPath);
349  contextMenu.addSeparator();
350  if (slicePlanesAction)
351  contextMenu.addAction(slicePlanesAction);
352  if (fillSlicePlanesAction)
353  contextMenu.addAction(fillSlicePlanesAction);
354 }
355 
356 void ViewWrapper3D::createSlicesActions(QWidget* parent)
357 {
358  this->createSlicesAction(PlaneTypeCollection(ptAXIAL, ptCORONAL, ptSAGITTAL), parent);
359  this->createSlicesAction(PlaneTypeCollection(ptAXIAL), parent);
360  this->createSlicesAction(PlaneTypeCollection(ptCORONAL), parent);
361  this->createSlicesAction(PlaneTypeCollection(ptSAGITTAL), parent);
362  this->createSlicesAction(PlaneTypeCollection(ptANYPLANE), parent);
363  this->createSlicesAction(PlaneTypeCollection(ptRADIALPLANE), parent);
364  this->createSlicesAction(PlaneTypeCollection(ptSIDEPLANE), parent);
365  this->createSlicesAction(PlaneTypeCollection(ptTOOLSIDEPLANE), parent);
366 }
367 
368 QAction* ViewWrapper3D::createSlicesAction(PlaneTypeCollection planes, QWidget* parent)
369 {
370  QString title = planes.toString();
371  QString active = mGroupData->getSliceDefinitions().toString();
372 
373  QAction* action = new QAction(title, parent);
374  connect(action, SIGNAL(triggered()), this, SLOT(showSlices()));
375  action->setData(title);
376  action->setCheckable(true);
377  action->setChecked(active == title);
378 
379  parent->addAction(action);
380  return action;
381 }
382 
383 void ViewWrapper3D::showSlices()
384 {
385  QAction* action = dynamic_cast<QAction*>(sender());
386  if (!action)
387  return;
388 
389  PlaneTypeCollection planes = PlaneTypeCollection::fromString(action->data().toString());
390 
391  if (!action->isChecked())
392  mGroupData->setSliceDefinitions(PlaneTypeCollection());
393  else
394  mGroupData->setSliceDefinitions(planes);
395 }
396 
398 {
400 
401  connect(group.get(), &ViewGroupData::initialized, this, &ViewWrapper3D::resetCameraActionSlot);
402  connect(group.get(), &ViewGroupData::optionsChanged, this, &ViewWrapper3D::optionChangedSlot);
403  mView->getRenderer()->SetActiveCamera(mGroupData->getCamera3D()->getCamera());
404 
405  // Set eye angle after camera change. Maybe create a cameraChangedSlot instead
406  this->setStereoEyeAngle(settings()->value("View3D/eyeAngle").toDouble());
407  this->optionChangedSlot();
408 
409 }
410 
411 void ViewWrapper3D::showToolPathSlot(bool checked)
412 {
413  ToolPtr tool = mServices->tracking()->getActiveTool();
414  ToolRep3DPtr activeRep3D = RepContainer(mView->getReps()).findFirst<ToolRep3D>(tool);
415  if (activeRep3D)
416  {
417  if(checked)
418  {
419  activeRep3D->getTracer()->start();
420  }
421  else if(!checked)
422  {
423  activeRep3D->getTracer()->stop();
424  activeRep3D->getTracer()->clear();
425  }
426  }
427 
428  settings()->setValue("showToolPath", checked);
429 }
430 
431 void ViewWrapper3D::showAxesActionSlot(bool checked)
432 {
433  if (mShowAxes == checked)
434  return;
435 
436  mShowAxes = checked;
437 
438  // clear all
439  for (unsigned i=0; i<mAxis.size(); ++i)
440  mView->removeRep(mAxis[i]->mRep);
441  mAxis.clear();
442 
443  // show all
444  if (mShowAxes)
445  {
446  AxisConnectorPtr axis;
447 
448  // reference space
449  axis.reset(new AxisConnector(CoordinateSystem(csREF), mServices->spaceProvider()));
450  axis->mRep->setAxisLength(0.12);
451  axis->mRep->setShowAxesLabels(true);
452  axis->mRep->setCaption("ref", Vector3D(1, 0, 0));
453  axis->mRep->setFontSize(0.03);
454  mAxis.push_back(axis);
455 
456  // data spaces
457  std::vector<DataPtr> data = mGroupData->getData();
458  for (unsigned i = 0; i < data.size(); ++i)
459  {
460  axis.reset(new AxisConnector(CoordinateSystem(csDATA, data[i]->getUid()), mServices->spaceProvider()));
461  axis->mRep->setAxisLength(0.08);
462  axis->mRep->setShowAxesLabels(false);
463  axis->mRep->setCaption(data[i]->getName(), Vector3D(1, 0, 0));
464  axis->mRep->setFontSize(0.03);
465  mAxis.push_back(axis);
466  }
467 
468  // tool spaces
469  TrackingService::ToolMap tools = mServices->tracking()->getTools();
470  TrackingService::ToolMap::iterator iter;
471  for (iter = tools.begin(); iter != tools.end(); ++iter)
472  {
473  ToolPtr tool = iter->second;
474 
475  axis.reset(new AxisConnector(CoordinateSystem(csTOOL, tool->getUid()), mServices->spaceProvider()));
476  axis->mRep->setAxisLength(0.08);
477  axis->mRep->setShowAxesLabels(false);
478  axis->mRep->setCaption("t", Vector3D(0.7, 1, 0.7));
479  axis->mRep->setFontSize(0.03);
480  axis->connectTo(tool);
481  SpaceListenerPtr mToolListener = axis->mListener;
482 
483  mAxis.push_back(axis);
484 
485  axis.reset(new AxisConnector(CoordinateSystem(csSENSOR, tool->getUid()), mServices->spaceProvider()));
486  axis->mRep->setAxisLength(0.05);
487  axis->mRep->setShowAxesLabels(false);
488  axis->mRep->setCaption("s", Vector3D(1, 1, 0));
489  axis->mRep->setFontSize(0.03);
490  axis->connectTo(tool);
491  axis->mergeWith(mToolListener);
492  mAxis.push_back(axis);
493  }
494 
495  for (unsigned i=0; i<mAxis.size(); ++i)
496  mView->addRep(mAxis[i]->mRep);
497  }
498 }
499 
500 void ViewWrapper3D::showManualToolSlot(bool visible)
501 {
502  settings()->setValue("View3D/showManualTool", visible);
503 }
504 
505 void ViewWrapper3D::showOrientationSlot(bool visible)
506 {
507  settings()->setValue("View/showOrientationAnnotation", visible);
508  this->updateView();
509 }
510 
511 void ViewWrapper3D::resetCameraActionSlot()
512 {
513  mView->getRenderer()->ResetCamera();
514  //Update eye angle after camera is reset
515  this->setStereoEyeAngle(settings()->value("View3D/eyeAngle").toDouble());
516 }
517 
518 NavigationPtr ViewWrapper3D::getNavigation()
519 {
520  CameraControlPtr camera3D(new CameraControl());
521  camera3D->setView(mView);
522 
523  return NavigationPtr(new Navigation(mServices, camera3D));
524 }
525 
526 void ViewWrapper3D::centerImageActionSlot()
527 {
528  NavigationPtr nav = this->getNavigation();
529  nav->centerToDataInViewGroup(mGroupData, DataViewProperties::create3D());
530 }
531 
532 void ViewWrapper3D::centerToolActionSlot()
533 {
534  NavigationPtr nav = this->getNavigation();
535  nav->centerToTooltip();
536 }
537 
538 void ViewWrapper3D::showSlicePlanesActionSlot(bool checked)
539 {
540  if (!mSlicePlanes3DRep)
541  return;
542  mSlicePlanes3DRep->getProxy()->setVisible(checked);
543  settings()->setValue("showSlicePlanes", checked);
544 }
545 
546 void ViewWrapper3D::fillSlicePlanesActionSlot(bool checked)
547 {
548  if (!mSlicePlanes3DRep)
549  return;
550  mSlicePlanes3DRep->getProxy()->setDrawPlanes(checked);
551 }
552 
554 {
555  DataPtr data = mServices->patient()->getData(uid);
556  DataViewProperties properties = mGroupData->getProperties(uid);
557 
558  if (properties.hasVolume3D())
559  this->addVolumeDataRep(data);
560  else
561  this->removeVolumeDataRep(uid);
562 
563  this->updateSlices();
564 
565  this->updateView();
566 }
567 
568 void ViewWrapper3D::addVolumeDataRep(DataPtr data)
569 {
570  if (!data)
571  return;
572  ImagePtr image = boost::dynamic_pointer_cast<Image>(data);
573  if (image)
574  {
575  mMultiVolume3DRepProducer->addImage(image);
576  }
577  else
578  {
579  if (!mDataReps.count(data->getUid()))
580  {
581  RepPtr rep = this->createDataRep3D(data);
582  if (rep)
583  {
584  mDataReps[data->getUid()] = rep;
585  mView->addRep(rep);
586  }
587  }
588  }
589 }
590 
591 void ViewWrapper3D::removeVolumeDataRep(QString uid)
592 {
593  mMultiVolume3DRepProducer->removeImage(uid);
594  if (mDataReps.count(uid))
595  {
596  mView->removeRep(mDataReps[uid]);
597  mDataReps.erase(uid);
598  }
599 }
600 
604 RepPtr ViewWrapper3D::createDataRep3D(DataPtr data)
605 {
606  if (boost::dynamic_pointer_cast<Mesh>(data))
607  {
609  rep->setMesh(boost::dynamic_pointer_cast<Mesh>(data));
610  return rep;
611  }
612  else if (boost::dynamic_pointer_cast<TrackedStream>(data))
613  {
614  TrackedStreamPtr trackedStream = boost::dynamic_pointer_cast<TrackedStream>(data);
615  return this->createTrackedStreamRep(trackedStream);
616  }
617  else
618  {
619  DataMetricRepPtr rep = this->createDataMetricRep3D(data);
620  if (rep)
621  return rep;
622  }
623 
624  return RepPtr();
625 }
626 
627 RepPtr ViewWrapper3D::createTrackedStreamRep(TrackedStreamPtr trackedStream)
628 {
629  if(!trackedStream->hasVideo())
630  {
631  connect(trackedStream.get(), &TrackedStream::streamChanged, this, &ViewWrapper3D::dataViewPropertiesChangedSlot);
632  return RepPtr();
633  }
634  else
635  disconnect(trackedStream.get(), &TrackedStream::streamChanged, this, &ViewWrapper3D::dataViewPropertiesChangedSlot);
636  if(trackedStream->is3D())
637  {
638  StreamRep3DPtr rep = StreamRep3D::New(mServices->spaceProvider(), mServices->patient());
639  rep->setTrackedStream(trackedStream);
640  return rep;
641  }
642  else if (trackedStream->is2D())
643  {
644  Stream2DRep3DPtr rep = Stream2DRep3D::New(mServices->spaceProvider());
645  rep->setTrackedStream(trackedStream);
646  return rep;
647  }
648  else
649  {
650  reportWarning("ViewWrapper3D::createDataRep3D. TrackedStream is not 2D or 3D");
651  return RepPtr();
652  }
653 }
654 
655 DataMetricRepPtr ViewWrapper3D::createDataMetricRep3D(DataPtr data)
656 {
657  DataMetricRepPtr rep;
658 
659  if (boost::dynamic_pointer_cast<PointMetric>(data))
660  rep = PointMetricRep::New();
661  else if (boost::dynamic_pointer_cast<FrameMetric>(data))
662  rep = FrameMetricRep::New();
663  else if (boost::dynamic_pointer_cast<ToolMetric>(data))
664  rep = ToolMetricRep::New();
665  else if (boost::dynamic_pointer_cast<DistanceMetric>(data))
666  rep = DistanceMetricRep::New();
667  else if (boost::dynamic_pointer_cast<AngleMetric>(data))
668  rep = AngleMetricRep::New();
669  else if (boost::dynamic_pointer_cast<PlaneMetric>(data))
670  rep = PlaneMetricRep::New();
671  else if (boost::dynamic_pointer_cast<DonutMetric>(data))
672  rep = DonutMetricRep::New();
673  else if (boost::dynamic_pointer_cast<CustomMetric>(data))
674  rep = CustomMetricRep::New();
675  else if (boost::dynamic_pointer_cast<SphereMetric>(data))
676  rep = SphereMetricRep::New();
677  else if (boost::dynamic_pointer_cast<RegionOfInterestMetric>(data))
679 
680  if (rep)
681  {
682  this->readDataRepSettings(rep);
683  rep->setDataMetric(boost::dynamic_pointer_cast<DataMetric>(data));
684  }
685  return rep;
686 }
687 
691 void ViewWrapper3D::readDataRepSettings(RepPtr rep)
692 {
693  DataMetricRepPtr val = boost::dynamic_pointer_cast<DataMetricRep>(rep);
694  if (!val)
695  return;
696 
697  val->setGraphicsSize(settings()->value("View3D/sphereRadius").toDouble());
698  val->setShowLabel(settings()->value("View/showLabels").toBool());
699  val->setLabelSize(settings()->value("View3D/labelSize").toDouble());
700  val->setShowAnnotation(!settings()->value("View/showMetricNamesInCorner").toBool());
701 }
702 
704 {
705  return this->getAllDataNames(DataViewProperties::create3D()).join("\n");
706 }
707 
709 {
710  return "3D";
711 }
712 
713 void ViewWrapper3D::updateView()
714 {
715  this->ViewWrapper::updateView();
716 
717  if (!this->getView())
718  return;
719 
720  this->updateMetricNamesRep();
721 
722  mAnnotationMarker->setVisible(settings()->value("View/showOrientationAnnotation").value<bool>());
723 
724  ToolRep3DPtr manualToolRep = RepContainer(mView->getReps()).findManualToolRep<ToolRep3D>();
725  if (manualToolRep)
726  {
727  manualToolRep->setTooltipPointColor(settings()->value("View/toolTipPointColor").value<QColor>());
728  manualToolRep->setToolOffsetPointColor(settings()->value("View/toolOffsetPointColor").value<QColor>());
729  manualToolRep->setToolOffsetLineColor(settings()->value("View/toolOffsetLineColor").value<QColor>());
730  }
731 }
732 
733 void ViewWrapper3D::activeImageChangedSlot(QString uid)
734 {
735  if(!mGroupData)
736  return;
737  ImagePtr image = mServices->patient()->getData<Image>(uid);
738 
739  // only show landmarks belonging to image visible in this view:
740  std::vector<ImagePtr> images = mGroupData->getImages(DataViewProperties::create3D());
741  if (!std::count(images.begin(), images.end(), image))
742  image.reset();
743 }
744 
745 void ViewWrapper3D::showRefToolSlot(bool checked)
746 {
747  ToolPtr refTool = mServices->tracking()->getReferenceTool();
748  if (!refTool)
749  return;
750  ToolRep3DPtr refRep = RepContainer(mView->getReps()).findFirst<ToolRep3D>(refTool);
751  if (!refRep)
752  {
753  refRep = ToolRep3D::New(mServices->spaceProvider(), refTool->getUid() + "_rep3d_" + this->mView->getUid());
754  refRep->setTool(refTool);
755  }
756 
757  if (checked) //should show
758  mView->addRep(refRep);
759  else
760  //should not show
761  mView->removeRep(refRep);
762 }
763 
764 
765 void ViewWrapper3D::updateSlices()
766 {
767  if (mSlices3DRep)
768  mView->removeRep(mSlices3DRep);
769 
770  if (!mGroupData)
771  return;
772 
773  std::vector<ImagePtr> images = mGroupData->getImages(DataViewProperties::createSlice3D());
774 // std::vector<ImagePtr> images = mGroupData->get3DSliceImages();
775  if (images.empty())
776  return;
777 
778  std::vector<PLANE_TYPE> planes = mGroupData->getSliceDefinitions().get();
779  if (planes.empty())
780  return;
781  mSlices3DRep = Slices3DRep::New(mSharedOpenGLContext, "MultiSliceRep_" + mView->getName());
782  for (unsigned i=0; i<planes.size(); ++i)
783  mSlices3DRep->addPlane(planes[i], mServices->patient());
784  mSlices3DRep->setShaderPath(DataLocations::findConfigFolder("/shaders"));
785  mSlices3DRep->setImages(images);
786  mSlices3DRep->setTool(mServices->tracking()->getActiveTool());
787  mView->addRep(mSlices3DRep);
788 }
789 
791 {
792  return mView;
793 }
794 
795 void ViewWrapper3D::activeToolChangedSlot()
796 {
797  ToolPtr activeTool = mServices->tracking()->getActiveTool();
798  mPickerRep->setTool(activeTool);
799  if (mSlices3DRep)
800  mSlices3DRep->setTool(activeTool);
801 }
802 
803 void ViewWrapper3D::toolsAvailableSlot()
804 {
805  std::vector<ToolRep3DPtr> reps = RepContainer::findReps<ToolRep3D>(mView->getReps());
806 
807  TrackingService::ToolMap tools = mServices->tracking()->getTools();
808  TrackingService::ToolMap::iterator iter;
809  for (iter = tools.begin(); iter != tools.end(); ++iter)
810  {
811  ToolPtr tool = iter->second;
812  if (tool->hasType(Tool::TOOL_REFERENCE))
813  continue;
814 
815  ToolRep3DPtr toolRep = RepContainer(mView->getReps()).findFirst<ToolRep3D>(tool);
816 
817  std::vector<ToolRep3DPtr>::iterator oldRep = std::find(reps.begin(), reps.end(), toolRep);
818  if (oldRep!=reps.end())
819  reps.erase(oldRep);
820 
821  if (tool->hasType(Tool::TOOL_MANUAL) && !settings()->value("View3D/showManualTool").toBool())
822  {
823  if (toolRep)
824  mView->removeRep(toolRep);
825  continue;
826  }
827 
828  if (!toolRep)
829  {
830  toolRep = ToolRep3D::New(mServices->spaceProvider(), tool->getUid() + "_rep3d_" + this->mView->getUid());
831  if (settings()->value("showToolPath").toBool())
832  toolRep->getTracer()->start();
833  }
834 
835  toolRep->setSphereRadius(settings()->value("View3D/sphereRadius").toDouble()); // use fraction of set size
836  toolRep->setSphereRadiusInNormalizedViewport(true);
837 
838  toolRep->setTool(tool);
839  toolRep->setOffsetPointVisibleAtZeroOffset(true);
840  mView->addRep(toolRep);
841  }
842 
843  // remove reps for tools no longer present
844  for (unsigned i=0; i<reps.size(); ++i)
845  {
846  mView->removeRep(reps[i]);
847  }
848 }
849 
850 void ViewWrapper3D::optionChangedSlot()
851 {
852  ViewGroupData::Options options = mGroupData->getOptions();
853 
854  this->showLandmarks(options.mShowLandmarks);
855  this->showPointPickerProbe(options.mShowPointPickerProbe);
856  mPickerRep->setGlyph(options.mPickerGlyph);
857 
858  this->updateSlices();
859 }
860 
861 void ViewWrapper3D::showLandmarks(bool on)
862 {
863  if (mLandmarkRep->isConnectedToView(mView) == on)
864  return;
865 
866  if (on)
867  {
868  mView->addRep(mLandmarkRep);
869  }
870  else
871  {
872  mView->removeRep(mLandmarkRep);
873  }
874 }
875 
876 void ViewWrapper3D::showPointPickerProbe(bool on)
877 {
878  mPickerRep->setEnabled(on);
879 }
880 
882 {
883  mSlicePlanes3DRep = SlicePlanes3DRep::New("uid");
884  mSlicePlanes3DRep->setProxy(proxy);
885  mSlicePlanes3DRep->setDynamicLabelSize(true);
886  bool show = settings()->value("showSlicePlanes").toBool();
887  mSlicePlanes3DRep->getProxy()->setVisible(show); // init with default value
888 
889  mView->addRep(mSlicePlanes3DRep);
890 }
891 
892 void ViewWrapper3D::setStereoType(int /*STEREOTYPE*/type)
893 {
894  switch (type)
895  //STEREOTYPE
896  {
897  case stFRAME_SEQUENTIAL:
898  mView->getRenderWindow()->SetStereoTypeToCrystalEyes();
899  break;
900  case stINTERLACED:
901  mView->getRenderWindow()->SetStereoTypeToInterlaced();
902  break;
903  case stDRESDEN:
904  mView->getRenderWindow()->SetStereoTypeToDresden();
905  break;
906  case stRED_BLUE:
907  mView->getRenderWindow()->SetStereoTypeToRedBlue();
908  break;
909  }
910 }
911 
912 void ViewWrapper3D::setStereoEyeAngle(double angle)
913 {
914  mView->getRenderer()->GetActiveCamera()->SetEyeAngle(angle);
915 }
916 
917 void ViewWrapper3D::setTranslucentRenderingToDepthPeeling(bool setDepthPeeling)
918 {
919  if(setDepthPeeling)
920  {
921  bool isDPSupported = true;
922 
923  //IsDepthPeelingSupported function don't seem to work on OSX (error messages or seg. fault)
924 #ifndef __APPLE__
925  if (!IsDepthPeelingSupported(mView->getRenderWindow(), mView->getRenderer(), true))
926  {
927  reportWarning("GPU do not support depth peeling. Rendering of translucent surfaces is not supported");
928  isDPSupported = false;
929  }
930 #endif
931 
932  if (isDPSupported && SetupEnvironmentForDepthPeeling(mView->getRenderWindow(), mView->getRenderer(), 100, 0.1))
933  {
934  report("Set GPU depth peeling");
935  }
936  else
937  {
938  reportWarning("Error setting depth peeling. The GPU or operating system might not support it.");
939  settings()->setValue("View3D/depthPeeling", false);
940  }
941  }
942  else
943  {
944  TurnOffDepthPeeling(mView->getRenderWindow(), mView->getRenderer());
945  }
946 }
947 
948 //------------------------------------------------------------------------------
949 }
bool SetupEnvironmentForDepthPeeling(vtkSmartPointer< vtkRenderWindow > renderWindow, vtkSmartPointer< vtkRenderer > renderer, int maxNoOfPeels, double occlusionRatio)
virtual QString getDataDescription()
static DataViewProperties createSlice3D()
static LandmarkRepPtr New(PatientModelServicePtr dataManager, const QString &uid="")
virtual void dataViewPropertiesChangedSlot(QString uid)
boost::shared_ptr< class ViewGroupData > ViewGroupDataPtr
Definition: cxViewGroup.h:29
ptCORONAL
a slice seen from the front of the patient
Definition: cxDefinitions.h:38
void reportError(QString msg)
Definition: cxLogger.cpp:71
static DonutMetricRepPtr New(const QString &uid="")
static RepManager * getInstance()
get the only instance of this class
boost::shared_ptr< class SlicePlanesProxy > SlicePlanesProxyPtr
boost::shared_ptr< class Stream2DRep3D > Stream2DRep3DPtr
boost::shared_ptr< class CameraControl > CameraControlPtr
boost::shared_ptr< class TrackedStream > TrackedStreamPtr
boost::shared_ptr< class VisServices > VisServicesPtr
Definition: cxMainWindow.h:40
virtual ViewPtr getView()
std::string toString(T const &value)
converts any type to a string
Definition: catch.hpp:755
csSENSOR
a tools sensor space (s)
Definition: cxDefinitions.h:88
void setStereoType(int type)
static SlicePlanes3DRepPtr New(const QString &uid="")
boost::shared_ptr< class Image > ImagePtr
Definition: cxDicomWidget.h:27
Superclass for ViewWrappers.
Definition: cxViewWrapper.h:89
boost::shared_ptr< REP > getCachedRep(QString uid="")
Definition: cxRepManager.h:72
SharedOpenGLContextPtr mSharedOpenGLContext
virtual void setSlicePlanesProxy(SlicePlanesProxyPtr proxy)
csREF
the data reference space (r) using LPS (left-posterior-superior) coordinates.
Definition: cxDefinitions.h:88
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Definition: cxSettings.cpp:66
static PlaneMetricRepPtr New(const QString &uid="")
boost::shared_ptr< class StreamRep3D > StreamRep3DPtr
ptAXIAL
a slice seen from the top of the patient
Definition: cxDefinitions.h:38
Base class for all Data Metric reps.
static AngleMetricRepPtr New(const QString &uid="")
boost::shared_ptr< class DataMetricRep > DataMetricRepPtr
Class for display of an orientation annotation cube in 3D.
virtual void settingsChangedSlot(QString key)
A data set for video streams (2D/3D).
boost::shared_ptr< class View > ViewPtr
stFRAME_SEQUENTIAL
csDATA
a datas space (d)
Definition: cxDefinitions.h:88
static ToolMetricRepPtr New(const QString &uid="")
Reference tool.
Definition: cxTool.h:84
static DataViewProperties create3D()
static Stream2DRep3DPtr New(SpaceProviderPtr spaceProvider, const QString &uid="")
void setValue(const QString &key, const QVariant &value)
Definition: cxSettings.cpp:58
virtual void setViewGroup(ViewGroupDataPtr group)
boost::shared_ptr< class Data > DataPtr
stINTERLACED
static MetricNamesRepPtr New(const QString &uid="")
static QString findConfigFolder(QString pathRelativeToConfigRoot, QString alternativeAbsolutePath="")
void streamChanged(QString uid)
void settingsChangedSlot(QString key)
ptSAGITTAL
a slice seen from the side of the patient
Definition: cxDefinitions.h:38
static PlaneTypeCollection fromString(QString input, PlaneTypeCollection defVal=PlaneTypeCollection())
void reportWarning(QString msg)
Definition: cxLogger.cpp:70
static FrameMetricRepPtr New(const QString &uid="")
ptTOOLSIDEPLANE
z-rotated 90* relative to anyplane like side plane, but always kept oriented like the plane defined b...
Definition: cxDefinitions.h:38
ViewGroupDataPtr mGroupData
A volumetric data set.
Definition: cxImage.h:45
Identification of a Coordinate system.
static QString findConfigFilePath(QString fileName, QString pathRelativeToConfigRoot, QString alternativeAbsolutePath="")
virtual QString getViewDescription()
Representation of a mouse/keyboard-controlled virtual tool.
Definition: cxTool.h:85
static GeometricRepPtr New(const QString &uid="")
virtual void setViewGroup(ViewGroupDataPtr group)
Settings * settings()
Shortcut for accessing the settings instance.
Definition: cxSettings.cpp:21
static Slices3DRepPtr New(SharedOpenGLContextPtr context, const QString &uid)
static RegionOfInterestMetricRepPtr New(const QString &uid="")
std::map< QString, ToolPtr > ToolMap
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:42
boost::shared_ptr< class AxisConnector > AxisConnectorPtr
ptRADIALPLANE
y-rotated 90* relative to anyplane (bird&#39;s view)
Definition: cxDefinitions.h:38
bool hasVolume3D() const
bool TurnOffDepthPeeling(vtkSmartPointer< vtkRenderWindow > renderWindow, vtkSmartPointer< vtkRenderer > renderer)
Turn off depth peeling.
virtual void addReps()
void report(QString msg)
Definition: cxLogger.cpp:69
VisServicesPtr mServices
QStringList getAllDataNames(DataViewProperties properties) const
static PointMetricRepPtr New(const QString &uid="")
boost::shared_ptr< class SpaceListener > SpaceListenerPtr
stDRESDEN
virtual void updateView()
static StreamRep3DPtr New(SpaceProviderPtr spaceProvider, PatientModelServicePtr patientModelService, const QString &uid="")
static PickerRepPtr New(PatientModelServicePtr dataManager, const QString &uid="")
for creating new instances
Definition: cxPickerRep.cpp:54
DataViewPropertiesInteractorPtr mShow3DSlicesInteractor
static ToolRep3DPtr New(SpaceProviderPtr spaceProvider, const QString &uid="")
Definition: cxToolRep3D.cpp:74
boost::shared_ptr< class ToolRep3D > ToolRep3DPtr
ptANYPLANE
a plane aligned with the tool base plane
Definition: cxDefinitions.h:38
ViewWrapper3D(int startIndex, ViewPtr view, VisServicesPtr services)
boost::shared_ptr< class Navigation > NavigationPtr
bool IsDepthPeelingSupported(vtkSmartPointer< vtkRenderWindow > renderWindow, vtkSmartPointer< vtkRenderer > renderer, bool doItOffScreen)
void connectContextMenu(ViewPtr view)
csTOOL
a tools rspace (t)
Definition: cxDefinitions.h:88
boost::shared_ptr< class Rep > RepPtr
Definition: cxRepManager.h:24
static DistanceMetricRepPtr New(const QString &uid="")
static SphereMetricRepPtr New(const QString &uid="")
void setGraphicsSize(double size)
ptSIDEPLANE
z-rotated 90* relative to anyplane (dual anyplane)
Definition: cxDefinitions.h:38
static CustomMetricRepPtr New(const QString &uid="")
void activeImageChanged(const QString &uId)
boost::shared_ptr< class GeometricRep > GeometricRepPtr
Namespace for all CustusX production code.
boost::shared_ptr< class Tool > ToolPtr