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