CustusX  16.5
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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) 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 
34 #include "cxSlicePlanes3DRep.h"
35 
36 #include <boost/bind.hpp>
37 #include <vtkRenderer.h>
38 #include <vtkMatrix4x4.h>
39 #include <vtkActor2D.h>
40 #include <vtkTextProperty.h>
41 #include <vtkTextActor3D.h>
42 
43 #include "cxView.h"
44 #include "cxSliceProxy.h"
45 #include "cxVtkHelperClasses.h"
46 #include "cxTypeConversions.h"
47 
48 namespace cx
49 {
50 
52 {
53  mConnectedTo3D = false;
54  mVisible = true;
55  mDrawPlane = false;
56 
57  QColor color1 = QColor::fromRgbF(0, 1, 1);
58  QColor color2 = QColor::fromRgbF(0, 0.6, 1);
59  QColor color3 = QColor::fromRgbF(0.5, 0.5, 1);
60 
61  mProperties.mColor[ptAXIAL] = color1;
62  mProperties.mSymbol[ptAXIAL] = "A";
63 
64  mProperties.mColor[ptCORONAL] = color2;
65  mProperties.mSymbol[ptCORONAL] = "C";
66 
67  mProperties.mColor[ptSAGITTAL] = color3;
68  mProperties.mSymbol[ptSAGITTAL] = "S";
69 
70  mProperties.mColor[ptANYPLANE] = color1;
71  mProperties.mSymbol[ptANYPLANE] = "O";
72 
73  mProperties.mColor[ptSIDEPLANE] = color2;
74  mProperties.mSymbol[ptSIDEPLANE] = "|";
75 
76  mProperties.mColor[ptRADIALPLANE] = color3;
77  mProperties.mSymbol[ptRADIALPLANE] = "X";
78 
79  mProperties.m2DFontSize = 20;
80  mProperties.m3DFontSize = 28;
81 // mProperties.mPointPos_normvp = Vector3D(0.1, 0.8, 0.0);
82  mProperties.mPointPos_normvp = Vector3D(0.05, 0.95, 0.0);
83  mProperties.mClipPlane = ptANYPLANE;
84  mProperties.mLineWidth = 2;
85  // mProperties.mDrawPlane = false;
86 }
87 
89 {
90  mConnectedTo3D = on;
91 }
92 
94 {
95  mData.clear();
96 }
97 
98 void SlicePlanesProxy::setVisible(bool visible)
99 {
100  mVisible = visible;
101  emit changed();
102 }
103 
105 {
106  return mVisible && mConnectedTo3D;
107 }
108 
110 {
111  mDrawPlane = on;
112  emit changed();
113 }
114 
116 {
117  return mDrawPlane;
118 }
119 
120 void SlicePlanesProxy::setViewportData(PLANE_TYPE type, SliceProxyPtr slice, const DoubleBoundingBox3D& vp_s)
121 {
122  if (!slice)
123  return;
124 
125  if (!mData.count(type))
126  {
127  DataType data;
128  data.mPointPos_normvp = mProperties.mPointPos_normvp;
129  data.vp_s = vp_s;
130  data.mSliceProxy = slice;
131  data.mColor = mProperties.mColor[type];
132  data.mSymbol = mProperties.mSymbol[type];
133 
134  connect(data.mSliceProxy.get(), SIGNAL(transformChanged(Transform3D)), this, SIGNAL(changed()));
135  mData[type] = data;
136  }
137 
138  mData[type].vp_s = vp_s;
139 
140  emit changed();
141 }
142 
144 {
145  SliceProxyPtr slice = SliceProxy::create(dataManager);
146  slice->initializeFromPlane(type, false, Vector3D(0, 0, 1), true, 1, 0.25);
147 
148  this->setViewportData(type, slice, DoubleBoundingBox3D(0, 1, 0, 1, 0, 1));
149 }
150 
152 {
153  return mData;
154 }
155 
160 
161 
163 {
164  return wrap_new(new SlicePlanes3DRep(), uid);
165 }
166 
167 SlicePlanes3DRep::SlicePlanes3DRep() :
168  RepImpl()
169 {
170 }
171 
173 {
174  if (mProxy)
175  mProxy->connectTo3D(false);
176 }
177 
183 {
184  if (on)
185  {
186  mViewportListener.reset(new ViewportListener);
187  mViewportListener->setCallback(boost::bind(&SlicePlanes3DRep::rescale, this));
188  }
189  else
190  {
191  mViewportListener.reset();
192  }
193 }
194 
196 {
197  this->changedSlot();
198  if (mViewportListener)
199  mViewportListener->startListen(view->getRenderer());
200 }
201 
203 {
204  if (mViewportListener)
205  mViewportListener->stopListen();
206  this->clearActors();
207 }
208 
209 void SlicePlanes3DRep::clearActors()
210 {
211  if (!this->getView())
212  return;
213 
214  for (DataMap::iterator i = mData.begin(); i != mData.end(); ++i)
215  {
216  this->getRenderer()->RemoveActor(i->second.mText);
217  i->second.mPoint.reset();
218  i->second.mRect.reset();
219  i->second.mAxes.reset();
220  }
221  mData.clear();
222 }
223 
224 void SlicePlanes3DRep::rescale()
225 {
226  this->changedSlot();
227 }
228 
229 void SlicePlanes3DRep::changedSlot()
230 {
231  if (!this->getView())
232  return;
233 
234  if (!mProxy->getVisible())
235  {
236  this->clearActors();
237  return;
238  }
239 
240  SlicePlanesProxy::DataMap baseData = mProxy->getData();
241 
242  for (SlicePlanesProxy::DataMap::iterator i = baseData.begin(); i != baseData.end(); ++i)
243  {
244  SlicePlanesProxy::DataType& base = i->second;
245  DataType& data = mData[i->first];
246 
247  if (!data.mText)
248  {
249  data.mText = vtkTextActor3DPtr::New();
250  data.mText->SetInput(cstring_cast(base.mSymbol));
251  data.mText->GetTextProperty()->SetColor(getColorAsVector3D(base.mColor).begin());
252  data.mText->GetTextProperty()->SetFontSize(mProxy->getProperties().m3DFontSize);
253  data.mText->GetTextProperty()->BoldOn();
254  data.mText->GetTextProperty()->SetVerticalJustificationToBottom();
255  data.mText->GetTextProperty()->SetJustificationToLeft();
256  data.mText->GetTextProperty()->ShadowOff();
257  this->getRenderer()->AddActor(data.mText);
258  }
259  if (!data.mRect)
260  {
261  data.mRect.reset(new Rect3D(this->getRenderer(), base.mColor));
262  }
263 
264  Transform3D rMs = base.mSliceProxy->get_sMr().inv();
265  Transform3D vpMnvp = createTransformNormalize(DoubleBoundingBox3D(0, 1, 0, 1, 0, 1), base.vp_s);
266  Vector3D pos_s = vpMnvp.coord(base.mPointPos_normvp);
268 
269  double scale = 1.0;
270  if (data.mText)
271  {
272  if (mViewportListener)
273  {
274  double size = mViewportListener->getVpnZoom();
275  double planeSize = (i->second.vp_s.range()[0] + i->second.vp_s.range()[1]) / 2.0;
276  double sphereSize = std::min(0.1 / size, planeSize/5); // set to 20% of 2D plane size, but constrain upwards to 0.1/s.
277  sphereSize = sphereSize/50;
278  data.mText->GetTextProperty()->SetFontSize(mProxy->getProperties().m3DFontSize);
279 // std::cout << "set font size " << sphereSize << ", s=" << size << ", plane="<< planeSize << std::endl;
280  scale = sphereSize;
281  }
282  }
283 
284  if (data.mText)
285  {
286  Transform3D T2 = createTransformTranslate(Vector3D(0,-mProxy->getProperties().m3DFontSize,0));
287  Transform3D S = createTransformScale(Vector3D(scale,scale,scale));
288 // data.mText->SetUserMatrix((rMs * T).getVtkMatrix());
289  data.mText->SetUserMatrix((rMs * T * S * T2).getVtkMatrix());
290  }
291 
292  if (data.mPoint)
293  {
294  data.mPoint->setColor(base.mColor);
295  data.mPoint->setValue(rMs.coord(pos_s));
296  }
297  if (data.mRect)
298  {
299  data.mRect->updatePosition(base.vp_s, rMs);
300  data.mRect->setLine(mProxy->getProperties().mLineWidth != 0, mProxy->getProperties().mLineWidth);
301  data.mRect->setSurface(mProxy->getDrawPlanes());
302  }
303  if (data.mAxes)
304  {
305  data.mAxes->setPosition(rMs);
306  }
307  }
308 }
309 
311 {
312  mProxy = proxy;
313  mProxy->connectTo3D(true);
314  connect(mProxy.get(), SIGNAL(changed()), this, SLOT(changedSlot()));
315  changedSlot();
316 }
317 
321 
323 {
324  return wrap_new(new SlicePlanes3DMarkerIn2DRep(), uid);
325 }
326 
327 SlicePlanes3DMarkerIn2DRep::SlicePlanes3DMarkerIn2DRep() :
328  RepImpl()
329 {
330 }
331 
333 {
334 }
335 
337 {
338  SlicePlanesProxy::DataType baseData = mProxy->getData()[mType];
339 
340  mText.reset(new TextDisplay(baseData.mSymbol, baseData.mColor, mProxy->getProperties().m2DFontSize));
341  mText->textProperty()->BoldOn();
342  mText->textProperty()->SetVerticalJustificationToTop();
343  mText->textProperty()->SetJustificationToLeft();
344  mText->setPosition(baseData.mPointPos_normvp);
345  mText->getActor()->GetPositionCoordinate()->SetCoordinateSystemToNormalizedViewport();
346  view->getRenderer()->AddActor2D(mText->getActor());
347  this->changedSlot();
348 }
349 
351 {
352  view->getRenderer()->RemoveActor(mText->getActor());
353  mText.reset();
354 }
355 
356 void SlicePlanes3DMarkerIn2DRep::changedSlot()
357 {
358  if (mText)
359  {
360  mText->getActor()->SetVisibility(mProxy->getVisible() && mProxy->getData().count(mType));
361  // std::cout << "SlicePlanes3DMarkerIn2DRep::changedSlot() " << this << " " << mProxy.get() << " - " << mProxy->getVisible() << " " << mProxy->getData().count(mType) << std::endl;
362  }
363 
364 }
365 
367 {
368  //Logger::log("vm.log", "SlicePlanes3DMarkerIn2DRep::setProxy");
369  mType = type;
370  mProxy = proxy;
371  connect(mProxy.get(), SIGNAL(changed()), this, SLOT(changedSlot()));
372  changedSlot();
373 }
374 
375 }
ViewPtr getView() const
Definition: cxRepImpl.cpp:104
void setViewportData(PLANE_TYPE type, SliceProxyPtr slice, const DoubleBoundingBox3D &vp_s)
vtkRendererPtr getRenderer()
Definition: cxRepImpl.cpp:109
ptCORONAL
a slice seen from the front of the patient
Definition: cxDefinitions.h:56
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
static boost::shared_ptr< REP > wrap_new(REP *object, QString uid)
Definition: cxRepImpl.h:83
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:56
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:56
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
Helper for drawing text in 2D.
boost::shared_ptr< class PatientModelService > PatientModelServicePtr
Transform3D createTransformTranslate(const Vector3D &translation)
Default implementation of Rep.
Definition: cxRepImpl.h:63
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:63
ptRADIALPLANE
y-rotated 90* relative to anyplane (bird's view)
Definition: cxDefinitions.h:56
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:56
boost::shared_ptr< class SlicePlanes3DMarkerIn2DRep > SlicePlanes3DMarkerIn2DRepPtr
virtual void addRepActorsToViewRenderer(ViewPtr view)
ptSIDEPLANE
z-rotated 90* relative to anyplane (dual anyplane)
Definition: cxDefinitions.h:56