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