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