Fraxinus  18.10
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.m2DFontSize = 20;
63  mProperties.m3DFontSize = 28;
64 // mProperties.mPointPos_normvp = Vector3D(0.1, 0.8, 0.0);
65  mProperties.mPointPos_normvp = Vector3D(0.05, 0.95, 0.0);
66  mProperties.mClipPlane = ptANYPLANE;
67  mProperties.mLineWidth = 2;
68  // mProperties.mDrawPlane = false;
69 }
70 
72 {
73  mConnectedTo3D = on;
74 }
75 
77 {
78  mData.clear();
79 }
80 
81 void SlicePlanesProxy::setVisible(bool visible)
82 {
83  mVisible = visible;
84  emit changed();
85 }
86 
88 {
89  return mVisible && mConnectedTo3D;
90 }
91 
93 {
94  mDrawPlane = on;
95  emit changed();
96 }
97 
99 {
100  return mDrawPlane;
101 }
102 
103 void SlicePlanesProxy::setViewportData(PLANE_TYPE type, SliceProxyPtr slice, const DoubleBoundingBox3D& vp_s)
104 {
105  if (!slice)
106  return;
107 
108  if (!mData.count(type))
109  {
110  DataType data;
111  data.mPointPos_normvp = mProperties.mPointPos_normvp;
112  data.vp_s = vp_s;
113  data.mSliceProxy = slice;
114  data.mColor = mProperties.mColor[type];
115  data.mSymbol = mProperties.mSymbol[type];
116 
117  connect(data.mSliceProxy.get(), SIGNAL(transformChanged(Transform3D)), this, SIGNAL(changed()));
118  mData[type] = data;
119  }
120 
121  mData[type].vp_s = vp_s;
122 
123  emit changed();
124 }
125 
127 {
128  SliceProxyPtr slice = SliceProxy::create(dataManager);
129  slice->initializeFromPlane(type, false, true, 1, 0.25);
130 
131  this->setViewportData(type, slice, DoubleBoundingBox3D(0, 1, 0, 1, 0, 1));
132 }
133 
135 {
136  return mData;
137 }
138 
143 
144 
146 {
147  return wrap_new(new SlicePlanes3DRep(), uid);
148 }
149 
150 SlicePlanes3DRep::SlicePlanes3DRep() :
151  RepImpl()
152 {
153 }
154 
156 {
157  if (mProxy)
158  mProxy->connectTo3D(false);
159 }
160 
166 {
167  if (on)
168  {
169  mViewportListener.reset(new ViewportListener);
170  mViewportListener->setCallback(boost::bind(&SlicePlanes3DRep::rescale, this));
171  }
172  else
173  {
174  mViewportListener.reset();
175  }
176 }
177 
179 {
180  this->changedSlot();
181  if (mViewportListener)
182  mViewportListener->startListen(view->getRenderer());
183 }
184 
186 {
187  if (mViewportListener)
188  mViewportListener->stopListen();
189  this->clearActors();
190 }
191 
192 void SlicePlanes3DRep::clearActors()
193 {
194  if (!this->getView())
195  return;
196 
197  for (DataMap::iterator i = mData.begin(); i != mData.end(); ++i)
198  {
199  this->getRenderer()->RemoveActor(i->second.mText);
200  i->second.mPoint.reset();
201  i->second.mRect.reset();
202  i->second.mAxes.reset();
203  }
204  mData.clear();
205 }
206 
207 void SlicePlanes3DRep::rescale()
208 {
209  this->changedSlot();
210 }
211 
212 void SlicePlanes3DRep::changedSlot()
213 {
214  if (!this->getView())
215  return;
216 
217  if (!mProxy->getVisible())
218  {
219  this->clearActors();
220  return;
221  }
222 
223  SlicePlanesProxy::DataMap baseData = mProxy->getData();
224 
225  for (SlicePlanesProxy::DataMap::iterator i = baseData.begin(); i != baseData.end(); ++i)
226  {
227  SlicePlanesProxy::DataType& base = i->second;
228  DataType& data = mData[i->first];
229 
230  if (!data.mText)
231  {
232  data.mText = vtkTextActor3DPtr::New();
233  data.mText->SetInput(cstring_cast(base.mSymbol));
234  data.mText->GetTextProperty()->SetColor(getColorAsVector3D(base.mColor).begin());
235  data.mText->GetTextProperty()->SetFontSize(mProxy->getProperties().m3DFontSize);
236  data.mText->GetTextProperty()->BoldOn();
237  data.mText->GetTextProperty()->SetVerticalJustificationToBottom();
238  data.mText->GetTextProperty()->SetJustificationToLeft();
239  data.mText->GetTextProperty()->ShadowOff();
240  this->getRenderer()->AddActor(data.mText);
241  }
242  if (!data.mRect)
243  {
244  data.mRect.reset(new Rect3D(this->getRenderer(), base.mColor));
245  }
246 
247  Transform3D rMs = base.mSliceProxy->get_sMr().inv();
248  Transform3D vpMnvp = createTransformNormalize(DoubleBoundingBox3D(0, 1, 0, 1, 0, 1), base.vp_s);
249  Vector3D pos_s = vpMnvp.coord(base.mPointPos_normvp);
251 
252  double scale = 1.0;
253  if (data.mText)
254  {
255  if (mViewportListener)
256  {
257  Vector3D focus = rMs.translation();
258  double size = mViewportListener->getVpnZoom(focus);
259  double planeSize = (i->second.vp_s.range()[0] + i->second.vp_s.range()[1]) / 2.0;
260  double sphereSize = std::min(0.1 / size, planeSize/5); // set to 20% of 2D plane size, but constrain upwards to 0.1/s.
261  sphereSize = sphereSize/50;
262  data.mText->GetTextProperty()->SetFontSize(mProxy->getProperties().m3DFontSize);
263 // std::cout << "set font size " << sphereSize << ", s=" << size << ", plane="<< planeSize << std::endl;
264  scale = sphereSize;
265  }
266  }
267 
268  if (data.mText)
269  {
270  Transform3D T2 = createTransformTranslate(Vector3D(0,-mProxy->getProperties().m3DFontSize,0));
271  Transform3D S = createTransformScale(Vector3D(scale,scale,scale));
272 // data.mText->SetUserMatrix((rMs * T).getVtkMatrix());
273  data.mText->SetUserMatrix((rMs * T * S * T2).getVtkMatrix());
274  }
275 
276  if (data.mPoint)
277  {
278  data.mPoint->setColor(base.mColor);
279  data.mPoint->setValue(rMs.coord(pos_s));
280  }
281  if (data.mRect)
282  {
283  data.mRect->updatePosition(base.vp_s, rMs);
284  data.mRect->setLine(mProxy->getProperties().mLineWidth != 0, mProxy->getProperties().mLineWidth);
285  data.mRect->setSurface(mProxy->getDrawPlanes());
286  }
287  if (data.mAxes)
288  {
289  data.mAxes->setPosition(rMs);
290  }
291  }
292 }
293 
295 {
296  mProxy = proxy;
297  mProxy->connectTo3D(true);
298  connect(mProxy.get(), SIGNAL(changed()), this, SLOT(changedSlot()));
299  changedSlot();
300 }
301 
305 
307 {
308  return wrap_new(new SlicePlanes3DMarkerIn2DRep(), uid);
309 }
310 
311 SlicePlanes3DMarkerIn2DRep::SlicePlanes3DMarkerIn2DRep() :
312  RepImpl()
313 {
314 }
315 
317 {
318 }
319 
321 {
322  SlicePlanesProxy::DataType baseData = mProxy->getData()[mType];
323 
324  mText.reset(new TextDisplay(baseData.mSymbol, baseData.mColor, mProxy->getProperties().m2DFontSize));
325  mText->textProperty()->BoldOn();
326  mText->textProperty()->SetVerticalJustificationToTop();
327  mText->textProperty()->SetJustificationToLeft();
328  mText->setPosition(baseData.mPointPos_normvp);
329  mText->getActor()->GetPositionCoordinate()->SetCoordinateSystemToNormalizedViewport();
330  view->getRenderer()->AddActor2D(mText->getActor());
331  this->changedSlot();
332 }
333 
335 {
336  view->getRenderer()->RemoveActor(mText->getActor());
337  mText.reset();
338 }
339 
340 void SlicePlanes3DMarkerIn2DRep::changedSlot()
341 {
342  if (mText)
343  {
344  mText->getActor()->SetVisibility(mProxy->getVisible() && mProxy->getData().count(mType));
345  // std::cout << "SlicePlanes3DMarkerIn2DRep::changedSlot() " << this << " " << mProxy.get() << " - " << mProxy->getVisible() << " " << mProxy->getData().count(mType) << std::endl;
346  }
347 
348 }
349 
351 {
352  //Logger::log("vm.log", "SlicePlanes3DMarkerIn2DRep::setProxy");
353  mType = type;
354  mProxy = proxy;
355  connect(mProxy.get(), SIGNAL(changed()), this, SLOT(changedSlot()));
356  changedSlot();
357 }
358 
359 }
void setViewportData(PLANE_TYPE type, SliceProxyPtr slice, const DoubleBoundingBox3D &vp_s)
ptCORONAL
a slice seen from the front of the patient
Definition: cxDefinitions.h:38
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:38
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:38
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:38
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
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:38
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:38
boost::shared_ptr< class SlicePlanes3DMarkerIn2DRep > SlicePlanes3DMarkerIn2DRepPtr
virtual void addRepActorsToViewRenderer(ViewPtr view)
ptSIDEPLANE
z-rotated 90* relative to anyplane (dual anyplane)
Definition: cxDefinitions.h:38
Helper for drawing a rectangle in 3D.
Namespace for all CustusX production code.