CustusX  15.8
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 "cxVisServices.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, VisServicesPtr services):
115  ViewWrapper(services)
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(mServices->getPatientService());
134  mLandmarkRep->setGraphicsSize(settings()->value("View3D/sphereRadius").toDouble());
135  mLandmarkRep->setLabelSize(settings()->value("View3D/labelSize").toDouble());
136 
137  mPickerRep = PickerRep::New(mServices->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(mServices->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(mServices->getToolManager().get(), &TrackingService::stateChanged, this, &ViewWrapper3D::toolsAvailableSlot);
161  connect(mServices->getPatientService().get(), &PatientModelService::activeImageChanged, this, &ViewWrapper3D::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 = mServices->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 = mServices->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), mServices->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()), mServices->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 = mServices->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()), mServices->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()), mServices->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(mServices, camera3D));
539 }
540 
541 void ViewWrapper3D::centerImageActionSlot()
542 {
543  NavigationPtr nav = this->getNavigation();
544  nav->centerToDataInViewGroup(mGroupData, DataViewProperties::create3D());
545 }
546 
547 void ViewWrapper3D::centerToolActionSlot()
548 {
549  NavigationPtr nav = this->getNavigation();
550  nav->centerToTooltip();
551 }
552 
553 void ViewWrapper3D::showSlicePlanesActionSlot(bool checked)
554 {
555  if (!mSlicePlanes3DRep)
556  return;
557  mSlicePlanes3DRep->getProxy()->setVisible(checked);
558  settings()->setValue("showSlicePlanes", checked);
559 }
560 
561 void ViewWrapper3D::fillSlicePlanesActionSlot(bool checked)
562 {
563  if (!mSlicePlanes3DRep)
564  return;
565  mSlicePlanes3DRep->getProxy()->setDrawPlanes(checked);
566 }
567 
569 {
570  DataPtr data = mServices->getPatientService()->getData(uid);
571  DataViewProperties properties = mGroupData->getProperties(uid);
572 
573  if (properties.hasVolume3D())
574  this->addVolumeDataRep(data);
575  else
576  this->removeVolumeDataRep(uid);
577 
578  this->updateSlices();
579 
580  this->updateView();
581 }
582 
583 void ViewWrapper3D::addVolumeDataRep(DataPtr data)
584 {
585  if (!data)
586  return;
587  ImagePtr image = boost::dynamic_pointer_cast<Image>(data);
588  if (image)
589  {
590  mMultiVolume3DRepProducer->addImage(image);
591  }
592  else
593  {
594  if (!mDataReps.count(data->getUid()))
595  {
596  RepPtr rep = this->createDataRep3D(data);
597  if (rep)
598  {
599  mDataReps[data->getUid()] = rep;
600  mView->addRep(rep);
601  }
602  }
603  }
604 }
605 
606 void ViewWrapper3D::removeVolumeDataRep(QString uid)
607 {
608  mMultiVolume3DRepProducer->removeImage(uid);
609  if (mDataReps.count(uid))
610  {
611  mView->removeRep(mDataReps[uid]);
612  mDataReps.erase(uid);
613  }
614 }
615 
619 RepPtr ViewWrapper3D::createDataRep3D(DataPtr data)
620 {
621  if (boost::dynamic_pointer_cast<Mesh>(data))
622  {
624  rep->setMesh(boost::dynamic_pointer_cast<Mesh>(data));
625  return rep;
626  }
627  else if (boost::dynamic_pointer_cast<TrackedStream>(data))
628  {
629  TrackedStreamPtr trackedStream = boost::dynamic_pointer_cast<TrackedStream>(data);
630  return this->createTrackedStreamRep(trackedStream);
631  }
632  else
633  {
634  DataMetricRepPtr rep = this->createDataMetricRep3D(data);
635  if (rep)
636  return rep;
637  }
638 
639  return RepPtr();
640 }
641 
642 RepPtr ViewWrapper3D::createTrackedStreamRep(TrackedStreamPtr trackedStream)
643 {
644  if(!trackedStream->hasVideo())
645  {
646  connect(trackedStream.get(), &TrackedStream::streamChanged, this, &ViewWrapper3D::dataViewPropertiesChangedSlot);
647  return RepPtr();
648  }
649  else
650  disconnect(trackedStream.get(), &TrackedStream::streamChanged, this, &ViewWrapper3D::dataViewPropertiesChangedSlot);
651  if(trackedStream->is3D())
652  {
653 // std::cout << "ViewWrapper3D::createDataRep3D. Create StreamRep3D" << std::endl;
654  StreamRep3DPtr rep = StreamRep3D::New(mServices->getSpaceProvider(), mServices->getPatientService());
655  QString visualizerType = settings()->value("View3D/ImageRender3DVisualizer").toString();
656  if(visualizerType == "vtkVolumeTextureMapper3D")
657  rep->setUseVolumeTextureMapper();
658  else if(visualizerType == "vtkGPUVolumeRayCastMapper")
659  rep->setUseGPUVolumeRayCastMapper();
660  else
661  {
662  reportError(QString("No visualizer found for string=%1").arg(visualizerType));
663  return RepPtr();
664  }
665  rep->setTrackedStream(trackedStream);
666  return rep;
667  }
668  else
669  {
670  std::cout << "ViewWrapper3D::createDataRep3D. StreamRep2D not implemented yet" << std::endl;
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->getPatientService()->getActiveImage();
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->getToolManager()->getReferenceTool();
751  if (!refTool)
752  return;
753  ToolRep3DPtr refRep = RepContainer(mView->getReps()).findFirst<ToolRep3D>(refTool);
754  if (!refRep)
755  {
756  refRep = ToolRep3D::New(mServices->getSpaceProvider(), 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  if (mSlices3DRep)
771  mView->removeRep(mSlices3DRep);
772 
773  if (!mGroupData)
774  return;
775 
776  std::vector<ImagePtr> images = mGroupData->getImages(DataViewProperties::createSlice3D());
777 // std::vector<ImagePtr> images = mGroupData->get3DSliceImages();
778  if (images.empty())
779  return;
780 
781  std::vector<PLANE_TYPE> planes = mGroupData->getSliceDefinitions().get();
782  if (planes.empty())
783  return;
784 
785  mSlices3DRep = Slices3DRep::New("MultiSliceRep_" + mView->getName());
786  for (unsigned i=0; i<planes.size(); ++i)
787  mSlices3DRep->addPlane(planes[i], mServices->getPatientService());
788  mSlices3DRep->setShaderPath(DataLocations::findConfigFolder("/shaders"));
789  mSlices3DRep->setImages(images);
790  mSlices3DRep->setTool(mServices->getToolManager()->getActiveTool());
791 
792  mView->addRep(mSlices3DRep);
793 }
794 
796 {
797  return mView;
798 }
799 
800 void ViewWrapper3D::activeToolChangedSlot()
801 {
802  ToolPtr activeTool = mServices->getToolManager()->getActiveTool();
803  mPickerRep->setTool(activeTool);
804  if (mSlices3DRep)
805  mSlices3DRep->setTool(activeTool);
806 }
807 
808 void ViewWrapper3D::toolsAvailableSlot()
809 {
810  std::vector<ToolRep3DPtr> reps = RepContainer::findReps<ToolRep3D>(mView->getReps());
811 
812  TrackingService::ToolMap tools = mServices->getToolManager()->getTools();
813  TrackingService::ToolMap::iterator iter;
814  for (iter = tools.begin(); iter != tools.end(); ++iter)
815  {
816  ToolPtr tool = iter->second;
817  if (tool->hasType(Tool::TOOL_REFERENCE))
818  continue;
819 
820  ToolRep3DPtr toolRep = RepContainer(mView->getReps()).findFirst<ToolRep3D>(tool);
821 
822  std::vector<ToolRep3DPtr>::iterator oldRep = std::find(reps.begin(), reps.end(), toolRep);
823  if (oldRep!=reps.end())
824  reps.erase(oldRep);
825 
826  if (tool->hasType(Tool::TOOL_MANUAL) && !settings()->value("showManualTool").toBool())
827  {
828  if (toolRep)
829  mView->removeRep(toolRep);
830  continue;
831  }
832  // mManualTool->setVisible(settings()->value("showManualTool").toBool());
833 
834  if (!toolRep)
835  {
836  toolRep = ToolRep3D::New(mServices->getSpaceProvider(), tool->getUid() + "_rep3d_" + this->mView->getUid());
837  if (settings()->value("showToolPath").toBool())
838  toolRep->getTracer()->start();
839  }
840 
841  toolRep->setSphereRadius(settings()->value("View3D/sphereRadius").toDouble()); // use fraction of set size
842  toolRep->setSphereRadiusInNormalizedViewport(true);
843 
844  toolRep->setTool(tool);
845  toolRep->setOffsetPointVisibleAtZeroOffset(true);
846  mView->addRep(toolRep);
847  }
848 
849  // remove reps for tools no longer present
850  for (unsigned i=0; i<reps.size(); ++i)
851  {
852  mView->removeRep(reps[i]);
853  }
854 }
855 
856 void ViewWrapper3D::optionChangedSlot()
857 {
858  ViewGroupData::Options options = mGroupData->getOptions();
859 
860  this->showLandmarks(options.mShowLandmarks);
861  this->showPointPickerProbe(options.mShowPointPickerProbe);
862  mPickerRep->setGlyph(options.mPickerGlyph);
863 
864  this->updateSlices();
865 }
866 
867 void ViewWrapper3D::showLandmarks(bool on)
868 {
869  if (mLandmarkRep->isConnectedToView(mView) == on)
870  return;
871 
872  if (on)
873  {
874  mView->addRep(mLandmarkRep);
875  }
876  else
877  {
878  mView->removeRep(mLandmarkRep);
879  }
880 }
881 
882 void ViewWrapper3D::showPointPickerProbe(bool on)
883 {
884  mPickerRep->setEnabled(on);
885 }
886 
888 {
889  mSlicePlanes3DRep = SlicePlanes3DRep::New("uid");
890  mSlicePlanes3DRep->setProxy(proxy);
891  mSlicePlanes3DRep->setDynamicLabelSize(true);
892  bool show = settings()->value("showSlicePlanes").toBool();
893  mSlicePlanes3DRep->getProxy()->setVisible(show); // init with default value
894 
895  mView->addRep(mSlicePlanes3DRep);
896 }
897 
898 void ViewWrapper3D::setStereoType(int /*STEREOTYPE*/type)
899 {
900  switch (type)
901  //STEREOTYPE
902  {
903  case stFRAME_SEQUENTIAL:
904  mView->getRenderWindow()->SetStereoTypeToCrystalEyes();
905  break;
906  case stINTERLACED:
907  mView->getRenderWindow()->SetStereoTypeToInterlaced();
908  break;
909  case stDRESDEN:
910  mView->getRenderWindow()->SetStereoTypeToDresden();
911  break;
912  case stRED_BLUE:
913  mView->getRenderWindow()->SetStereoTypeToRedBlue();
914  break;
915  }
916 }
917 
918 void ViewWrapper3D::globalConfigurationFileChangedSlot(QString key)
919 {
920  if (key == "View3D/stereoType")
921  {
922  this->setStereoType(settings()->value("View3D/stereoType").toInt());
923  }
924  else if (key == "View3D/eyeAngle")
925  {
926  this->setStereoEyeAngle(settings()->value("View3D/eyeAngle").toDouble());
927  }
928 }
929 
930 void ViewWrapper3D::setStereoEyeAngle(double angle)
931 {
932  mView->getRenderer()->GetActiveCamera()->SetEyeAngle(angle);
933 }
934 
935 void ViewWrapper3D::setTranslucentRenderingToDepthPeeling(bool setDepthPeeling)
936 {
937  bool success = true;
938  if(setDepthPeeling)
939  {
940  vtkSmartPointer<vtkAppendPolyData> translucentGeometry = GenerateOverlappingBunchOfSpheres(100, 100);
941  // generate a basic Mapper and Actor
942  vtkSmartPointer<vtkPolyDataMapper> mapper =
943  vtkSmartPointer<vtkPolyDataMapper>::New();
944  mapper->SetInputConnection(translucentGeometry->GetOutputPort());
945  vtkSmartPointer<vtkActor> actor =
946  vtkSmartPointer<vtkActor>::New();
947  actor->SetMapper(mapper);
948  actor->GetProperty()->SetOpacity(0.5); // translucent !!!
949  actor->GetProperty()->SetColor(1, 0, 0);
950  actor->RotateX(-72); // put the objects in a position where it is easy to see
951  // different overlapping regions
952 
953  mView->getRenderer()->AddActor(actor); //Test add to 3D view
954 
955  /*if (!IsDepthPeelingSupported(mView->getRenderWindow(), mView->getRenderer(), true))
956  {
957  reportWarning("GPU do not support depth peeling. Rendering of translucent surfaces is not supported");
958  success = false;
959  }
960  else*/ if (!SetupEnvironmentForDepthPeeling(mView->getRenderWindow(), mView->getRenderer(), 100, 0.1))
961  {
962  reportWarning("Error setting depth peeling");
963  success = false;
964  }
965  else
966  {
967  report("Set GPU depth peeling");
968  }
969  if(!success)
970  settings()->setValue("View3D/depthPeeling", false);
971  } else
972  {
973  TurnOffDepthPeeling(mView->getRenderWindow(), mView->getRenderer());
974 // if (TurnOffDepthPeeling(mView->getRenderWindow(), mView->getRenderer()))
975 // report("Depth peeling turned off");
976  }
977 }
978 
979 //------------------------------------------------------------------------------
980 }
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 activeImageChanged(const QString &uId)
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
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)
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:90
static DataViewProperties create3D()
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="")
vtkSmartPointer< vtkAppendPolyData > GenerateOverlappingBunchOfSpheres(int theta, int phi)
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: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: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:96
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)
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
boost::shared_ptr< class GeometricRep > GeometricRepPtr
boost::shared_ptr< class Tool > ToolPtr