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