Fraxinus  17.12-rc2
An IGT application
cxToolRep2D.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 
35 #include "cxToolRep2D.h"
36 
37 #include <vtkRenderer.h>
38 #include <vtkActor2D.h>
39 #include <vtkTextProperty.h>
40 #include <vtkPolyDataMapper.h>
41 #include <vtkPolyData.h>
42 #include <vtkMatrix4x4.h>
43 #include <vtkProperty2D.h>
44 #include "cxSliceProxy.h"
45 #include "cxTool.h"
46 #include "cxView.h"
47 
48 #include "cxTypeConversions.h"
49 #include "cxProbeSector.h"
50 #include "cxSpaceProvider.h"
51 #include "cxSettings.h"
52 
53 namespace cx
54 {
55 
56 ToolRep2D::ToolRep2D(SpaceProviderPtr spaceProvider) :
57  RepImpl(),
58  mSpaceProvider(spaceProvider),
59  m_vpMs(Transform3D::Identity()),
60  mBB_vp(0, 1, 0, 1, 0, 1),
61  mTooltipPointColor(0.96, 0.87, 0.17),
62  mOffsetPointColor(0.96, 0.87, 0.17),
63 // mTooltipLineColor(1, 0, 0),
64  mTooltipLineColor(0.25, 0.87, 0.16),
65  mOffsetLineColor(1.0, 0.8, 0.0),
66  mStipplePattern(0xffff)
67 {
68  mTooltipLineColor = settings()->value("View2D/toolColor").value<QColor>();
69  mTooltipPointColor = settings()->value("View/toolTipPointColor").value<QColor>();
70  mOffsetPointColor = settings()->value("View/toolOffsetPointColor").value<QColor>();
71  mOffsetLineColor = settings()->value("View/toolOffsetLineColor").value<QColor>();
72 
73  mUseOffset = true;
74  mUseCrosshair = false;
75  mUseToolLine = true;
76  mUseOffsetText = false;
77  mMergeOffsetAndToolLine = false;
78  mProbeSector.reset(new ProbeSector());
79  mProbeSectorPolyDataMapper = vtkPolyDataMapperPtr::New();
80  mProbeSectorActor = vtkActorPtr::New();
81 }
82 
84 {
85 }
86 
87 ToolRep2DPtr ToolRep2D::New(SpaceProviderPtr spaceProvider, const QString& uid)
88 {
89  return wrap_new(new ToolRep2D(spaceProvider), uid);
90 }
91 
92 QString ToolRep2D::getType() const
93 {
94  return "vm::ToolRep2D";
95 }
96 
97 double ToolRep2D::getOffset()
98 {
99  if (mSlicer->getTool() && showOffset())
100  return mSlicer->getTool()->getTooltipOffset();
101  return 0.0;
102 }
103 
108 {
109  if (similar(m_vpMs, vpMs) && similar(mBB_vp, vp))
110  return;
111 
112  m_vpMs = vpMs;
113  mBB_vp = vp;
114 
115  crossHairResized();
116  this->setModified();
117 }
118 
122 {
123  if (mSlicer)
124  {
125  disconnect(mSlicer.get(), SIGNAL(transformChanged(Transform3D)), this, SLOT(sliceTransformChangedSlot(Transform3D)));
126  disconnect(mSlicer.get(), SIGNAL(toolTransformAndTimestamp(Transform3D,double)), this, SLOT(toolTransformAndTimestampSlot(Transform3D,double)));
127  disconnect(mSlicer.get(), SIGNAL(toolVisible(bool)), this, SLOT(toolVisibleSlot(bool)));
128  }
129 
130  mSlicer = slicer;
131 
132  connect(mSlicer.get(), SIGNAL(transformChanged(Transform3D)), this, SLOT(sliceTransformChangedSlot(Transform3D)));
133  connect(mSlicer.get(), SIGNAL(toolTransformAndTimestamp(Transform3D,double)), this, SLOT(toolTransformAndTimestampSlot(Transform3D,double)));
134  connect(mSlicer.get(), SIGNAL(toolVisible(bool)), this, SLOT(toolVisibleSlot(bool)));
135 }
136 
140 {
141  if (mUseCrosshair==on)
142  return;
143  mUseCrosshair = on;
144  setVisibility();
145 }
146 
147 void ToolRep2D::setCrosshairColor(const QColor& color)
148 {
149  if(cursor)
150  setColorAndOpacity(cursor->getActor()->GetProperty(), color);
151 }
152 
153 void ToolRep2D::setTooltipLineColor(const QColor& color)
154 {
155  if(tool2Back)
156  setColorAndOpacity(tool2Back->getActor()->GetProperty(), color);
157 }
158 
159 void ToolRep2D::setTooltipPointColor(const QColor& color)
160 {
161  if(toolPoint)
162  setColorAndOpacity(toolPoint->getActor()->GetProperty(), color);
163 }
164 
165 void ToolRep2D::setToolOffsetPointColor(const QColor& color)
166 {
167  if(centerPoint)
168  setColorAndOpacity(centerPoint->getActor()->GetProperty(), color);
169 }
170 
171 void ToolRep2D::setToolOffsetLineColor(const QColor& color)
172 {
173  if(center2Tool)
174  setColorAndOpacity(center2Tool->getActor()->GetProperty(), color);
175 }
176 
178 {
179  createCrossHair(view->getRenderer() );
180  createToolLine(view->getRenderer(), Vector3D(0,0,0));
181  createOffsetText(view->getRenderer(), Vector3D(0,0,0));
182  view->getRenderer()->AddActor(mProbeSectorActor);
183  setVisibility();
184  this->setModified();
185 }
186 
188 {
189  cursor.reset();
190  center2Tool.reset();
191  tool2Back.reset();
192  centerPoint.reset();
193  toolPoint.reset();
194  distanceText.reset();
195  view->getRenderer()->RemoveActor(mProbeSectorActor);
196 }
197 
198 void ToolRep2D::sliceTransformChangedSlot(Transform3D sMr)
199 {
200  this->setModified();
201 }
202 
203 void ToolRep2D::toolTransformAndTimestampSlot(Transform3D prMt, double timestamp)
204 {
205  this->setModified();
206 }
207 
208 void ToolRep2D::toolVisibleSlot(bool visible)
209 {
210  setVisibility();
211  this->setModified();
212 }
213 
215 {
216  this->update();
217 }
218 
219 void ToolRep2D::update()
220 {
221  if (!mSlicer->getTool())
222  return;
223 
224  Transform3D prMt = Transform3D::Identity();
225  if (mSlicer->getTool())
226  {
227  prMt = mSlicer->getTool()->get_prMt();
228  }
229  Transform3D rMpr = mSpaceProvider->get_rMpr();
230  Transform3D sMr = mSlicer->get_sMr();
231  Transform3D sMt = sMr*rMpr*prMt;
232  Transform3D vpMt = m_vpMs*sMt;
233 
234  // only show probe if aligned with the slice plane:
235  double dotted = dot(Vector3D(0,0,1),sMt.vector(Vector3D(1,0,0)));
236  bool aligned = similar(fabs(dotted), 1.0, 0.1);
237  if (this->showProbe() && aligned)
238  {
240 
241  mProbeSector->setData(mSlicer->getTool()->getProbe()->getProbeDefinition());
242  Transform3D tMu = mProbeSector->get_tMu();
243  mProbeSectorPolyDataMapper->SetInputData(mProbeSector->getSectorLinesOnly());
244  if (mProbeSectorPolyDataMapper->GetInput())
245  {
246  mProbeSectorActor->SetMapper(mProbeSectorPolyDataMapper);
247  }
248  mProbeSectorActor->SetUserMatrix((T*sMt*tMu).getVtkMatrix());
249  mProbeSectorActor->SetVisibility(mSlicer->getTool()->getVisible());
250  }
251  else
252  {
253  mProbeSectorActor->SetVisibility(false);
254  }
255 
256  Vector3D cross = vpMt.coord(getOffset() * Vector3D(0,0,1)); // zero position plus offset along z
257  Vector3D tooltip = vpMt.coord(Vector3D(0,0,0)); // the zero position
258  Vector3D toolback = vpMt.coord(Vector3D(0,0,-1000)); // a point 1m backwards in z
259 
260  if (cursor)
261  {
262  cursor->update(cross, mBB_vp);
263  }
264  updateOffsetText();
265  updateToolLine(cross, tooltip, toolback);
266 }
267 
269 {
270  return mSlicer->getTool() && mSlicer->getTool()->hasType(Tool::TOOL_US_PROBE);
271 }
273 {
274  return mSlicer->getTool() && mUseOffset;
275 }
276 
277 void ToolRep2D::setVisibility()
278 {
279 // Logger::log("vm.log", "ToolRep2D::setVisibility(), offset=" + string_cast(showOffset()));
280  bool hasTool = mSlicer->getTool() ? true : false;
281 
282  if (cursor)
283  cursor->getActor()->SetVisibility(mUseCrosshair && hasTool);
284  if (center2Tool)
285  center2Tool->getActor()->SetVisibility(showOffset());
286  if (tool2Back)
287  tool2Back->getActor()->SetVisibility(mUseToolLine && hasTool);
288  if (centerPoint)
289  centerPoint->getActor()->SetVisibility(mUseToolLine && hasTool);
290  if (centerPoint)
291  centerPoint->getActor()->SetVisibility(showOffset() && !mMergeOffsetAndToolLine);
292  if (distanceText)
293  distanceText->getActor()->SetVisibility(mUseOffsetText && showOffset() && !mMergeOffsetAndToolLine);
294 }
295 
299 void ToolRep2D::createCrossHair(vtkRendererPtr renderer)
300 {
301  //Logger::log("vm.log", "<"+string_cast(__FUNCTION__)+">"+" new " );
302  cursor.reset( new CrossHair2D(renderer) ) ;
303  crossHairResized();
304 }
305 
309 void ToolRep2D::crossHairResized()
310 {
311  if (cursor)
312  {
313  double bordarOffset = 30.0;
314  QColor col = settings()->value("View2D/toolCrossHairColor").value<QColor>();
315  RGBColor color(col.redF(), col.greenF(), col.blueF());
316  Vector3D focalPoint(0.0,0.0,0.0);
317  //Logger::log("tool.log", "("+string_cast(__FUNCTION__)+")"+" mCross"+string_cast(cross));
318  cursor->setValue( focalPoint, int(mBB_vp.range()[0]), int(mBB_vp.range()[1]), bordarOffset, color );
319  }
320 }
321 
324 void ToolRep2D::createToolLine(vtkRendererPtr renderer, const Vector3D& centerPos )
325 {
326  // line from tooltip to offset point
327  center2Tool.reset(new LineSegment(renderer));
328  center2Tool->setPoints(centerPos, Vector3D(0.0, 0.0, 0.0), mOffsetLineColor, mStipplePattern);
329  center2Tool->setWidth(2);
330 
331  // line from back infinity to tooltip
332  tool2Back.reset(new LineSegment(renderer));
333  tool2Back->setPoints(Vector3D(0.0, 0.0, 0.0), Vector3D(0.0, 0.0, 0.0), mTooltipLineColor);
334  tool2Back->setWidth(2);
335 
336  // Add dot at offset point
337  centerPoint.reset(new OffsetPoint(renderer));
338  centerPoint->setValue(centerPos, mOffsetPointColor);
339  centerPoint->setRadius(4);
340  centerPoint->getActor()->VisibilityOff();
341 
342  // Add dot at tooltip point
343  toolPoint.reset(new OffsetPoint(renderer));
344  toolPoint->setValue(Vector3D(0.0, 0.0, 0.0), mTooltipPointColor);
345  toolPoint->setRadius(3);
346 }
347 
350 void ToolRep2D::createOffsetText(vtkRendererPtr renderer, const Vector3D& pos )
351 {
352  QColor color = QColor::fromRgbF(0.7372, 0.815, 0.6039);
353  distanceText.reset( new TextDisplay( "---", color, 18) );
354  distanceText->getActor()->GetPositionCoordinate()->SetCoordinateSystemToNormalizedViewport();
355  distanceText->textProperty()->SetJustificationToRight();
356  distanceText->setPosition(Vector3D(0.95, 0.95, 0.0));
357  renderer->AddActor( distanceText->getActor() );
358  updateOffsetText();
359 }
360 
365 void ToolRep2D::updateToolLine(const Vector3D& crossPos, const Vector3D& toolTipPos, const Vector3D toolTipBackPos)
366 {
367  if (!center2Tool || !tool2Back || !centerPoint || !toolPoint)
368  return;
369 
370  if (mMergeOffsetAndToolLine) // for ACS only
371  {
372  // Make entire line look like an offset line, since tooltip point will become projected
373  // into the planes set by the offset position, which may be seen as navigation error.
374  center2Tool->getActor()->SetVisibility(false);
375  tool2Back->updatePosition(crossPos, toolTipBackPos);
376  if (getOffset() > 0.01)
377  {
378  toolPoint->getActor()->SetVisibility(false);
379  centerPoint->getActor()->SetVisibility(true);
380  tool2Back->setColor(mOffsetLineColor);
381  tool2Back->setPattern(mStipplePattern);
382  }
383  else
384  {
385  toolPoint->getActor()->SetVisibility(true);
386  centerPoint->getActor()->SetVisibility(false);
387  tool2Back->setColor(mTooltipLineColor);
388  tool2Back->setPattern(0xffff);
389  }
390  }
391  else
392  {
393  center2Tool->updatePosition(crossPos, toolTipPos);
394  tool2Back->updatePosition(toolTipPos, toolTipBackPos);
395  if (getOffset() > 0.01)
396  {
397  centerPoint->getActor()->SetVisibility(true);
398  }
399  else
400  {
401  centerPoint->getActor()->SetVisibility(false);
402  }
403  }
404  centerPoint->update(crossPos);
405  toolPoint->update(toolTipPos);
406 }
407 
408 void ToolRep2D::updateOffsetText()
409 {
410  if (!distanceText)
411  {
412  return;
413  }
414  if (getOffset() > 2.0 && mUseOffsetText && showOffset())
415  {
416  distanceText->updateText("Offset: " + QString::number(getOffset(), 'g', 3) + " mm");
417  distanceText->getActor()->VisibilityOn();
418  }
419  else
420  {
421  distanceText->getActor()->VisibilityOff(); // doesnt work...
422  distanceText->updateText( "" ); // does work...
423  }
424 }
425 
426 } // namespace vm
boost::shared_ptr< class SpaceProvider > SpaceProviderPtr
virtual QString getType() const
Definition: cxToolRep2D.cpp:92
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
boost::shared_ptr< class SliceProxy > SliceProxyPtr
static boost::shared_ptr< REP > wrap_new(REP *object, QString uid)
Definition: cxRepImpl.h:83
virtual void removeRepActorsFromViewRenderer(ViewPtr view)
virtual void onModifiedStartRender()
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Definition: cxSettings.cpp:87
void setCrosshairColor(const QColor &color)
Helper for drawing a point in 2D.
virtual void addRepActorsToViewRenderer(ViewPtr view)
boost::shared_ptr< class View > ViewPtr
void setSliceProxy(SliceProxyPtr slicer)
boost::shared_ptr< class ToolRep2D > ToolRep2DPtr
void setToolOffsetPointColor(const QColor &color)
Vector3D cross(const Vector3D &a, const Vector3D &b)
compute cross product of a and b.
Definition: cxVector3D.cpp:62
Display a Tool in 2D.
Definition: cxToolRep2D.h:67
RGB color data.
vtkMatrix4x4Ptr getVtkMatrix(const Eigen::Affine3d *self)
vtkSmartPointer< class vtkRenderer > vtkRendererPtr
Helper for drawing a line in 2D.
void setTooltipLineColor(const QColor &color)
Helper for drawing text in 2D.
Transform3D createTransformTranslate(const Vector3D &translation)
double dot(const Vector3D &a, const Vector3D &b)
compute inner product (or dot product) of a and b.
Definition: cxVector3D.cpp:67
Settings * settings()
Shortcut for accessing the settings instance.
Definition: cxSettings.cpp: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.
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:63
bool similar(const CameraInfo &lhs, const CameraInfo &rhs, double tol)
void setUseCrosshair(bool on)
static ToolRep2DPtr New(SpaceProviderPtr spaceProvider, const QString &uid="")
Definition: cxToolRep2D.cpp:87
void setToolOffsetLineColor(const QColor &color)
Ultrasond probe. The tool has a Probe subinterface with a sector and a video stream.
Definition: cxTool.h:108
Helper for drawing a crosshair in 2D.
void setColorAndOpacity(vtkPropertyOrProperty2DPtr property, QColor color)
void setViewportData(const Transform3D &vpMs, const DoubleBoundingBox3D &vp)
void setTooltipPointColor(const QColor &color)
void setModified()
Definition: cxRepImpl.cpp:133
Namespace for all CustusX production code.