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