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