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