CustusX  2023.01.05-dev+develop.0da12
An IGT application
cxCustomMetricRep.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) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 
12 #include "cxCustomMetricRep.h"
13 
14 #include <boost/shared_ptr.hpp>
15 #include <vtkRenderer.h>
16 #include <vtkCamera.h>
17 #include <vtkImageActor.h>
18 #include <vtkSelectVisiblePoints.h>
19 #include "cxTypeConversions.h"
20 #include "cxCustomMetric.h"
21 #include "cxLogger.h"
22 #include "cxBoundingBox3D.h"
23 #include "cxGeometricRep.h"
24 #include "cxMesh.h"
25 #include "cxImage.h"
26 #include "cxImage2DRep3D.h"
27 #include "cxGraphicalPrimitives.h"
28 
29 
30 namespace cx
31 {
32 
34 {
35  return wrap_new(new CustomMetricRep(), uid);
36 }
37 
38 CustomMetricRep::CustomMetricRep()
39 {
40 }
41 
43 {
45  mMeshGeometry.clear();
46  for(int i = 0; i < mImageGeometryProxy.size(); ++i)
47  {
48  this->getRenderer()->RemoveActor(mImageGeometryProxy[i]->getActor());
49  }
50  mImageGeometryProxy.clear();
51 }
52 
53 CustomMetricPtr CustomMetricRep::getCustomMetric()
54 {
55  return boost::dynamic_pointer_cast<CustomMetric>(mMetric);
56 }
57 
59 {
60  if (!mMetric)
61  return;
62 
63  this->updateModel();
64  this->drawText();
65 }
66 
68 {
69  this->hideDistanceMetrics();
70 }
71 
72 void CustomMetricRep::updateModel()
73 {
74  this->clear();
75  CustomMetricPtr custom = this->getCustomMetric();
76 
77  if (!this->getView() || !custom)
78  return;
79 
80  DataPtr model = custom->getModel();
81 
82  if(custom->modelIsImage())
83  this->updateImageModel(model);
84  else
85  this->updateMeshModel(model);
86  this->createDistanceMarkers();
87 }
88 
89 void CustomMetricRep::updateImageModel(DataPtr model)
90 {
91  ImagePtr imageModel = boost::dynamic_pointer_cast<Image>(model);
92 
93  if(!imageModel && !imageModel->is2D())
94  return;
95 
96  CustomMetricPtr custom = this->getCustomMetric();
97  std::vector<Transform3D> pos = custom->calculateOrientations();
98 
99  mImageGeometryProxy.resize(pos.size());
100 
101  for(unsigned i = 0; i < mImageGeometryProxy.size(); ++i)
102  {
103  if(!mImageGeometryProxy[i])
104  mImageGeometryProxy[i] = cx::Image2DProxy::New();
105 
106  mImageGeometryProxy[i]->setImage(imageModel);
107  this->getRenderer()->AddActor(mImageGeometryProxy[i]->getActor());
108 
109  mImageGeometryProxy[i]->setTransformOffset(pos[i]);
110  }
111 }
112 
113 void CustomMetricRep::updateMeshModel(DataPtr model)
114 {
115  MeshPtr meshModel = boost::dynamic_pointer_cast<Mesh>(model);
116 
117  CustomMetricPtr custom = this->getCustomMetric();
118  std::vector<Transform3D> pos = custom->calculateOrientations();
119 
120  mMeshGeometry.resize(pos.size());
121 
122  for (unsigned i=0; i<mMeshGeometry.size(); ++i)
123  {
124  if (!mMeshGeometry[i])
125  {
126  mMeshGeometry[i].reset(new GraphicalGeometric);
127  mMeshGeometry[i]->setRenderer(this->getRenderer());
128  }
129 
130  mMeshGeometry[i]->setMesh(meshModel);
131 
132  mMeshGeometry[i]->setTransformOffset(pos[i]);
133 
134  custom->updateTexture(meshModel, pos[i]);
135  }
136 
137 }
138 
139 void CustomMetricRep::createDistanceMarkers()
140 {
141  mDistanceText.clear();
142  CustomMetricPtr custom = this->getCustomMetric();
143  if(!custom->getModel() || !custom->getShowDistanceMarkers())
144  return;
145  std::vector<Transform3D> pos = custom->calculateOrientations();
146 
147  if(pos.size() < 2)
148  return;
149 
150  DoubleBoundingBox3D bounds = custom->getModel()->boundingBox();
151 
152 
153  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
154  points->SetNumberOfPoints(pos.size());
155 
156  mDistanceText.resize(pos.size());
157  Vector3D pos_0 = custom->getZeroPosition();
158  for(unsigned i = 0; i < mDistanceText.size(); ++i)
159  {
160  Vector3D pos_i = pos[i].coord(Vector3D(0,0,0));
161  double distance = (pos_i - pos_0).length();
162  Vector3D textpos = bounds.center();
163  textpos[2] = bounds.bottomLeft()[2];
164  mDistanceText[i] = this->createDistanceText(pos[i].coord(textpos), distance);
165 
166  Vector3D point = pos[i].coord(textpos);
167  vtkIdType pointId = i;
168  points->SetPoint(pointId, point.data());
169  }
170 }
171 
172 CaptionText3DPtr CustomMetricRep::createDistanceText(Vector3D pos, double distance)
173 {
175  text->setColor(mMetric->getColor());
176  text->setText(QString("%1").arg(distance));
177 
178  text->setPosition(pos);
179  text->placeAboveCenter();
180  text->setSize(mLabelSize / 100);
181 
182  return text;
183 }
184 
185 //Hide the distance metrics if outside the view port, obscured by other structures, or of too far from the camera
186 void CustomMetricRep::hideDistanceMetrics()
187 {
188  if(mDistanceText.empty())
189  return;
190  static vtkSmartPointer<vtkSelectVisiblePoints> visPts = vtkSmartPointer<vtkSelectVisiblePoints>::New();
191  visPts->SetRenderer(this->getRenderer());
192  float * zbuffer = visPts->Initialize(true);
193 
194  for(unsigned i = 0; i < mDistanceText.size(); ++i)
195  {
196  Vector3D pos = mDistanceText[i]->getPosition();
197  bool visible = visPts->IsPointOccluded(pos.data(), zbuffer);
198  bool closeToCamera = this->isCloseToCamera(pos);
199  mDistanceText[i]->setVisibility(visible && closeToCamera);
200  }
201  delete zbuffer;
202 }
203 
204 bool CustomMetricRep::isCloseToCamera(Vector3D pos)
205 {
206  double distanceThreshold = this->getCustomMetric()->getDistanceMarkerVisibility();
207  Vector3D cameraPos(this->getRenderer()->GetActiveCamera()->GetPosition());
208  Vector3D diff = cameraPos - pos;
209  double distance = diff.norm();
210  if(distance < distanceThreshold)
211  return true;
212  return false;
213 }
214 
215 }
ViewPtr getView() const
Definition: cxRepImpl.cpp:83
vtkRendererPtr getRenderer()
Definition: cxRepImpl.cpp:88
A mesh data set.
Definition: cxMesh.h:45
virtual void onModifiedStartRender()
virtual void onEveryRender()
Display one Mesh in 3D.
boost::shared_ptr< class Image > ImagePtr
Definition: cxDicomWidget.h:27
Vector3D bottomLeft() const
virtual void clear()
static boost::shared_ptr< REP > wrap_new(REP *object, QString uid)
Definition: cxRepImpl.h:62
boost::shared_ptr< class Data > DataPtr
A volumetric data set.
Definition: cxImage.h:45
Data class that represents a custom.
boost::shared_ptr< class CustomMetricRep > CustomMetricRepPtr
Helper for rendering 3D text that faces the camera and has a constant viewed size, always on top.
Representation of a floating-point bounding box in 3D. The data are stored as {xmin,xmax,ymin,ymax,zmin,zmax}, in order to simplify communication with vtk.
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:42
Vector3D center() const
RealScalar length() const
boost::shared_ptr< class Mesh > MeshPtr
DataMetricPtr mMetric
boost::shared_ptr< CaptionText3D > CaptionText3DPtr
static Image2DProxyPtr New()
boost::shared_ptr< class CustomMetric > CustomMetricPtr
static CustomMetricRepPtr New(const QString &uid="")
Namespace for all CustusX production code.