CustusX  2023.01.05-dev+develop.0da12
An IGT application
cxSlicePlanes3DRep.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 
13 #include "cxSlicePlanes3DRep.h"
14 
15 #include <boost/bind.hpp>
16 #include <vtkRenderer.h>
17 #include <vtkMatrix4x4.h>
18 #include <vtkActor2D.h>
19 #include <vtkTextProperty.h>
20 #include <vtkTextActor3D.h>
21 
22 #include "cxView.h"
23 #include "cxSliceProxy.h"
24 #include "cxVtkHelperClasses.h"
25 #include "cxTypeConversions.h"
26 
27 namespace cx
28 {
29 
31 {
32  mConnectedTo3D = false;
33  mVisible = true;
34  mDrawPlane = false;
35 
36  QColor color1 = QColor::fromRgbF(0, 1, 1);
37  QColor color2 = QColor::fromRgbF(0, 0.6, 1);
38  QColor color3 = QColor::fromRgbF(0.5, 0.5, 1);
39  QColor color4 = QColor::fromRgbF(0.75, 0.75, 1);
40 
41  mProperties.mColor[ptAXIAL] = color1;
42  mProperties.mSymbol[ptAXIAL] = "A";
43 
44  mProperties.mColor[ptCORONAL] = color2;
45  mProperties.mSymbol[ptCORONAL] = "C";
46 
47  mProperties.mColor[ptSAGITTAL] = color3;
48  mProperties.mSymbol[ptSAGITTAL] = "S";
49 
50  mProperties.mColor[ptANYPLANE] = color1;
51  mProperties.mSymbol[ptANYPLANE] = "O";
52 
53  mProperties.mColor[ptSIDEPLANE] = color2;
54  mProperties.mSymbol[ptSIDEPLANE] = "|";
55 
56  mProperties.mColor[ptRADIALPLANE] = color3;
57  mProperties.mSymbol[ptRADIALPLANE] = "X";
58 
59  mProperties.mColor[ptTOOLSIDEPLANE] = color4;
60  mProperties.mSymbol[ptTOOLSIDEPLANE] = "T";
61 
62  mProperties.mColor[ptINVERSEANYPLANE] = color4;
63  mProperties.mSymbol[ptINVERSEANYPLANE] = "IO";
64 
65 
66  mProperties.m2DFontSize = 20;
67  mProperties.m3DFontSize = 28;
68 // mProperties.mPointPos_normvp = Vector3D(0.1, 0.8, 0.0);
69  mProperties.mPointPos_normvp = Vector3D(0.05, 0.95, 0.0);
70  mProperties.mClipPlane = ptANYPLANE;
71  mProperties.mLineWidth = 2;
72  // mProperties.mDrawPlane = false;
73 }
74 
76 {
77  mConnectedTo3D = on;
78 }
79 
81 {
82  mData.clear();
83 }
84 
85 void SlicePlanesProxy::setVisible(bool visible)
86 {
87  mVisible = visible;
88  emit changed();
89 }
90 
92 {
93  return mVisible && mConnectedTo3D;
94 }
95 
97 {
98  mDrawPlane = on;
99  emit changed();
100 }
101 
103 {
104  return mDrawPlane;
105 }
106 
107 void SlicePlanesProxy::setViewportData(PLANE_TYPE type, SliceProxyPtr slice, const DoubleBoundingBox3D& vp_s)
108 {
109  if (!slice)
110  return;
111 
112  if (!mData.count(type))
113  {
114  DataType data;
115  data.mPointPos_normvp = mProperties.mPointPos_normvp;
116  data.vp_s = vp_s;
117  data.mSliceProxy = slice;
118  data.mColor = mProperties.mColor[type];
119  data.mSymbol = mProperties.mSymbol[type];
120 
121  connect(data.mSliceProxy.get(), SIGNAL(transformChanged(Transform3D)), this, SIGNAL(changed()));
122  mData[type] = data;
123  }
124 
125  mData[type].vp_s = vp_s;
126 
127  emit changed();
128 }
129 
131 {
132  SliceProxyPtr slice = SliceProxy::create(dataManager);
133  slice->initializeFromPlane(type, false, true, 1, 0.25);
134 
135  this->setViewportData(type, slice, DoubleBoundingBox3D(0, 1, 0, 1, 0, 1));
136 }
137 
139 {
140  return mData;
141 }
142 
147 
148 
150 {
151  return wrap_new(new SlicePlanes3DRep(), uid);
152 }
153 
154 SlicePlanes3DRep::SlicePlanes3DRep() :
155  RepImpl()
156 {
157 }
158 
160 {
161  if (mProxy)
162  mProxy->connectTo3D(false);
163 }
164 
170 {
171  if (on)
172  {
173  mViewportListener.reset(new ViewportListener);
174  mViewportListener->setCallback(boost::bind(&SlicePlanes3DRep::rescale, this));
175  }
176  else
177  {
178  mViewportListener.reset();
179  }
180 }
181 
183 {
184  this->changedSlot();
185  if (mViewportListener)
186  mViewportListener->startListen(view->getRenderer());
187 }
188 
190 {
191  if (mViewportListener)
192  mViewportListener->stopListen();
193  this->clearActors();
194 }
195 
196 void SlicePlanes3DRep::clearActors()
197 {
198  if (!this->getView())
199  return;
200 
201  for (DataMap::iterator i = mData.begin(); i != mData.end(); ++i)
202  {
203  this->getRenderer()->RemoveActor(i->second.mText);
204  i->second.mPoint.reset();
205  i->second.mRect.reset();
206  i->second.mAxes.reset();
207  }
208  mData.clear();
209 }
210 
211 void SlicePlanes3DRep::rescale()
212 {
213  this->changedSlot();
214 }
215 
216 void SlicePlanes3DRep::changedSlot()
217 {
218  if (!this->getView())
219  return;
220 
221  if (!mProxy->getVisible())
222  {
223  this->clearActors();
224  return;
225  }
226 
227  SlicePlanesProxy::DataMap baseData = mProxy->getData();
228 
229  for (SlicePlanesProxy::DataMap::iterator i = baseData.begin(); i != baseData.end(); ++i)
230  {
231  SlicePlanesProxy::DataType& base = i->second;
232  DataType& data = mData[i->first];
233 
234  if (!data.mText)
235  {
236  data.mText = vtkTextActor3DPtr::New();
237  data.mText->SetInput(cstring_cast(base.mSymbol));
238  data.mText->GetTextProperty()->SetColor(getColorAsVector3D(base.mColor).begin());
239  data.mText->GetTextProperty()->SetFontSize(mProxy->getProperties().m3DFontSize);
240  data.mText->GetTextProperty()->BoldOn();
241  data.mText->GetTextProperty()->SetVerticalJustificationToBottom();
242  data.mText->GetTextProperty()->SetJustificationToLeft();
243  data.mText->GetTextProperty()->ShadowOff();
244  this->getRenderer()->AddActor(data.mText);
245  }
246  if (!data.mRect)
247  {
248  data.mRect.reset(new Rect3D(this->getRenderer(), base.mColor));
249  }
250 
251  Transform3D rMs = base.mSliceProxy->get_sMr().inv();
252  Transform3D vpMnvp = createTransformNormalize(DoubleBoundingBox3D(0, 1, 0, 1, 0, 1), base.vp_s);
253  Vector3D pos_s = vpMnvp.coord(base.mPointPos_normvp);
255 
256  double scale = 1.0;
257  if (data.mText)
258  {
259  if (mViewportListener)
260  {
261  Vector3D focus = rMs.translation();
262  double size = mViewportListener->getVpnZoom(focus);
263  double planeSize = (i->second.vp_s.range()[0] + i->second.vp_s.range()[1]) / 2.0;
264  double sphereSize = std::min(0.1 / size, planeSize/5); // set to 20% of 2D plane size, but constrain upwards to 0.1/s.
265  sphereSize = sphereSize/50;
266  data.mText->GetTextProperty()->SetFontSize(mProxy->getProperties().m3DFontSize);
267 // std::cout << "set font size " << sphereSize << ", s=" << size << ", plane="<< planeSize << std::endl;
268  scale = sphereSize;
269  }
270  }
271 
272  if (data.mText)
273  {
274  Transform3D T2 = createTransformTranslate(Vector3D(0,-mProxy->getProperties().m3DFontSize,0));
275  Transform3D S = createTransformScale(Vector3D(scale,scale,scale));
276 // data.mText->SetUserMatrix((rMs * T).getVtkMatrix());
277  data.mText->SetUserMatrix((rMs * T * S * T2).getVtkMatrix());
278  }
279 
280  if (data.mPoint)
281  {
282  data.mPoint->setColor(base.mColor);
283  data.mPoint->setValue(rMs.coord(pos_s));
284  }
285  if (data.mRect)
286  {
287  data.mRect->updatePosition(base.vp_s, rMs);
288  data.mRect->setLine(mProxy->getProperties().mLineWidth != 0, mProxy->getProperties().mLineWidth);
289  data.mRect->setSurface(mProxy->getDrawPlanes());
290  }
291  if (data.mAxes)
292  {
293  data.mAxes->setPosition(rMs);
294  }
295  }
296 }
297 
299 {
300  mProxy = proxy;
301  mProxy->connectTo3D(true);
302  connect(mProxy.get(), SIGNAL(changed()), this, SLOT(changedSlot()));
303  changedSlot();
304 }
305 
309 
311 {
312  return wrap_new(new SlicePlanes3DMarkerIn2DRep(), uid);
313 }
314 
315 SlicePlanes3DMarkerIn2DRep::SlicePlanes3DMarkerIn2DRep() :
316  RepImpl()
317 {
318 }
319 
321 {
322 }
323 
325 {
326  SlicePlanesProxy::DataType baseData = mProxy->getData()[mType];
327 
328  mText.reset(new TextDisplay(baseData.mSymbol, baseData.mColor, mProxy->getProperties().m2DFontSize));
329  mText->textProperty()->BoldOn();
330  mText->textProperty()->SetVerticalJustificationToTop();
331  mText->textProperty()->SetJustificationToLeft();
332  mText->setPosition(baseData.mPointPos_normvp);
333  mText->getActor()->GetPositionCoordinate()->SetCoordinateSystemToNormalizedViewport();
334  view->getRenderer()->AddActor2D(mText->getActor());
335  this->changedSlot();
336 }
337 
339 {
340  view->getRenderer()->RemoveActor(mText->getActor());
341  mText.reset();
342 }
343 
344 void SlicePlanes3DMarkerIn2DRep::changedSlot()
345 {
346  if (mText)
347  {
348  mText->getActor()->SetVisibility(mProxy->getVisible() && mProxy->getData().count(mType));
349  // std::cout << "SlicePlanes3DMarkerIn2DRep::changedSlot() " << this << " " << mProxy.get() << " - " << mProxy->getVisible() << " " << mProxy->getData().count(mType) << std::endl;
350  }
351 
352 }
353 
355 {
356  //Logger::log("vm.log", "SlicePlanes3DMarkerIn2DRep::setProxy");
357  mType = type;
358  mProxy = proxy;
359  connect(mProxy.get(), SIGNAL(changed()), this, SLOT(changedSlot()));
360  changedSlot();
361 }
362 
363 }
void setViewportData(PLANE_TYPE type, SliceProxyPtr slice, const DoubleBoundingBox3D &vp_s)
ptCORONAL
a slice seen from the front of the patient
Definition: cxDefinitions.h:39
static SliceProxyPtr create(PatientModelServicePtr dataManager)
Vector3D getColorAsVector3D(QColor color)
boost::shared_ptr< class SlicePlanesProxy > SlicePlanesProxyPtr
PLANE_TYPE mClipPlane
what plane to use for 3D clipping
Transform3D createTransformScale(const Vector3D &scale_)
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
boost::shared_ptr< class SliceProxy > SliceProxyPtr
std::map< PLANE_TYPE, DataType > DataMap
static SlicePlanes3DRepPtr New(const QString &uid="")
Vector3D mPointPos_normvp
position of symbol in normalized space <0..1, 0..1>
int mLineWidth
draw wireframe lines. 0 means no line
cstring_cast_Placeholder cstring_cast(const T &val)
Display a set of planes in 3D.
virtual void removeRepActorsFromViewRenderer(ViewPtr view)
void setVisible(bool visible)
ptAXIAL
a slice seen from the top of the patient
Definition: cxDefinitions.h:39
boost::shared_ptr< class View > ViewPtr
static SlicePlanes3DMarkerIn2DRepPtr New(const QString &uid="")
Transform3D createTransformNormalize(const DoubleBoundingBox3D &in, const DoubleBoundingBox3D &out)
Listens to changes in viewport and camera matrix.
ptSAGITTAL
a slice seen from the side of the patient
Definition: cxDefinitions.h:39
vtkMatrix4x4Ptr getVtkMatrix(const Eigen::Affine3d *self)
void setProxy(SlicePlanesProxyPtr proxy)
Display annotations for the SlicePlanesProxy planes in 2D.
void addSimpleSlicePlane(PLANE_TYPE type, PatientModelServicePtr dataManager)
std::map< PLANE_TYPE, QString > mSymbol
normalized RGB
std::map< PLANE_TYPE, QColor > mColor
ptTOOLSIDEPLANE
z-rotated 90* relative to anyplane like side plane, but always kept oriented like the plane defined b...
Definition: cxDefinitions.h:39
Helper for drawing text in 2D.
boost::shared_ptr< class PatientModelService > PatientModelServicePtr
Transform3D createTransformTranslate(const Vector3D &translation)
Default implementation of Rep.
Definition: cxRepImpl.h:42
ptINVERSEANYPLANE
a plane aligned with the tool base plane, inverse of tool direction
Definition: cxDefinitions.h:39
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.
void setProxy(PLANE_TYPE type, SlicePlanesProxyPtr proxy)
boost::shared_ptr< class SlicePlanes3DRep > SlicePlanes3DRepPtr
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:42
ptRADIALPLANE
y-rotated 90* relative to anyplane (bird&#39;s view)
Definition: cxDefinitions.h:39
virtual void removeRepActorsFromViewRenderer(ViewPtr view)
virtual void addRepActorsToViewRenderer(ViewPtr view)
void setDynamicLabelSize(bool on)
ptANYPLANE
a plane aligned with the tool base plane
Definition: cxDefinitions.h:39
boost::shared_ptr< class SlicePlanes3DMarkerIn2DRep > SlicePlanes3DMarkerIn2DRepPtr
virtual void addRepActorsToViewRenderer(ViewPtr view)
ptSIDEPLANE
z-rotated 90* relative to anyplane (dual anyplane)
Definition: cxDefinitions.h:39
Helper for drawing a rectangle in 3D.
Namespace for all CustusX production code.