Fraxinus  16.5.0-fx-rc4
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 "cxSliceProxy.h"
44 #include "cxTool.h"
45 #include "cxView.h"
46 
47 #include "cxTypeConversions.h"
48 #include "cxProbeSector.h"
49 #include "cxSpaceProvider.h"
50 
51 namespace cx
52 {
53 
54 ToolRep2D::ToolRep2D(SpaceProviderPtr spaceProvider) :
55  RepImpl(),
56  mSpaceProvider(spaceProvider),
57  m_vpMs(Transform3D::Identity()),
58  mBB_vp(0, 1, 0, 1, 0, 1),
59  mTooltipPointColor(0.96, 0.87, 0.17),
60  mOffsetPointColor(0.96, 0.87, 0.17),
61  mTooltipLineColor(0.25, 0.87, 0.16),
62  mOffsetLineColor(1.0, 0.8, 0.0),
63  mStipplePattern(0xffff)
64 {
65  mUseOffset = true;
66  mUseCrosshair = false;
67  mUseToolLine = true;
68  mUseOffsetText = false;
69  mMergeOffsetAndToolLine = false;
70  mProbeSector.reset(new ProbeSector());
71  mProbeSectorPolyDataMapper = vtkPolyDataMapperPtr::New();
72  mProbeSectorActor = vtkActorPtr::New();
73 }
74 
76 {
77 }
78 
79 ToolRep2DPtr ToolRep2D::New(SpaceProviderPtr spaceProvider, const QString& uid)
80 {
81  return wrap_new(new ToolRep2D(spaceProvider), uid);
82 }
83 
84 QString ToolRep2D::getType() const
85 {
86  return "vm::ToolRep2D";
87 }
88 
89 double ToolRep2D::getOffset()
90 {
91  if (mSlicer->getTool() && showOffset())
92  return mSlicer->getTool()->getTooltipOffset();
93  return 0.0;
94 }
95 
100 {
101  m_vpMs = vpMs;
102  mBB_vp = vp;
103 
104  crossHairResized();
105  this->setModified();
106 }
107 
111 {
112  if (mSlicer)
113  {
114  disconnect(mSlicer.get(), SIGNAL(transformChanged(Transform3D)), this, SLOT(sliceTransformChangedSlot(Transform3D)));
115  disconnect(mSlicer.get(), SIGNAL(toolTransformAndTimestamp(Transform3D,double)), this, SLOT(toolTransformAndTimestampSlot(Transform3D,double)));
116  disconnect(mSlicer.get(), SIGNAL(toolVisible(bool)), this, SLOT(toolVisibleSlot(bool)));
117  }
118 
119  mSlicer = slicer;
120 
121  connect(mSlicer.get(), SIGNAL(transformChanged(Transform3D)), this, SLOT(sliceTransformChangedSlot(Transform3D)));
122  connect(mSlicer.get(), SIGNAL(toolTransformAndTimestamp(Transform3D,double)), this, SLOT(toolTransformAndTimestampSlot(Transform3D,double)));
123  connect(mSlicer.get(), SIGNAL(toolVisible(bool)), this, SLOT(toolVisibleSlot(bool)));
124 }
125 
129 {
130  mUseOffset = on;
131  setVisibility();
132 }
133 
137 {
138  mUseCrosshair = on;
139  setVisibility();
140 }
141 
145 {
146  mUseToolLine = on;
147  setVisibility();
148 }
149 
153 {
154  mUseOffsetText = on;
155  setVisibility();
156 }
157 
163 {
164  mMergeOffsetAndToolLine = on;
165  setVisibility();
166 }
167 
169 {
170  createToolLine(view->getRenderer(), Vector3D(0,0,0));
171  createCrossHair(view->getRenderer() );
172  createOffsetText(view->getRenderer(), Vector3D(0,0,0));
173  view->getRenderer()->AddActor(mProbeSectorActor);
174  setVisibility();
175  this->setModified();
176 }
177 
179 {
180  cursor.reset();
181  center2Tool.reset();
182  tool2Back.reset();
183  centerPoint.reset();
184  toolPoint.reset();
185  distanceText.reset();
186  view->getRenderer()->RemoveActor(mProbeSectorActor);
187 }
188 
189 void ToolRep2D::sliceTransformChangedSlot(Transform3D sMr)
190 {
191  this->setModified();
192 }
193 
194 void ToolRep2D::toolTransformAndTimestampSlot(Transform3D prMt, double timestamp)
195 {
196  this->setModified();
197 }
198 
199 void ToolRep2D::toolVisibleSlot(bool visible)
200 {
201  setVisibility();
202  this->setModified();
203 }
204 
206 {
207  this->update();
208 }
209 
210 void ToolRep2D::update()
211 {
212  if (!mSlicer->getTool())
213  return;
214 
215  Transform3D prMt = Transform3D::Identity();
216  if (mSlicer->getTool())
217  {
218  prMt = mSlicer->getTool()->get_prMt();
219  }
220  Transform3D rMpr = mSpaceProvider->get_rMpr();
221  Transform3D sMr = mSlicer->get_sMr();
222  Transform3D sMt = sMr*rMpr*prMt;
223  Transform3D vpMt = m_vpMs*sMt;
224 
225  // only show probe if aligned with the slice plane:
226  double dotted = dot(Vector3D(0,0,1),sMt.vector(Vector3D(1,0,0)));
227  bool aligned = similar(fabs(dotted), 1.0, 0.1);
228  if (this->showProbe() && aligned)
229  {
231 
232  mProbeSector->setData(mSlicer->getTool()->getProbe()->getProbeDefinition());
233  Transform3D tMu = mProbeSector->get_tMu();
234  mProbeSectorPolyDataMapper->SetInputData(mProbeSector->getSectorLinesOnly());
235  if (mProbeSectorPolyDataMapper->GetInput())
236  {
237  mProbeSectorActor->SetMapper(mProbeSectorPolyDataMapper);
238  }
239  mProbeSectorActor->SetUserMatrix((T*sMt*tMu).getVtkMatrix());
240  mProbeSectorActor->SetVisibility(mSlicer->getTool()->getVisible());
241  }
242  else
243  {
244  mProbeSectorActor->SetVisibility(false);
245  }
246 
247  Vector3D cross = vpMt.coord(getOffset() * Vector3D(0,0,1)); // zero position plus offset along z
248  Vector3D tooltip = vpMt.coord(Vector3D(0,0,0)); // the zero position
249  Vector3D toolback = vpMt.coord(Vector3D(0,0,-1000)); // a point 1m backwards in z
250 
251  if (cursor)
252  {
253  cursor->update(cross, mBB_vp);
254  }
255  updateOffsetText();
256  updateToolLine(cross, tooltip, toolback);
257 }
258 
260 {
261  return mSlicer->getTool() && mSlicer->getTool()->hasType(Tool::TOOL_US_PROBE);
262 }
264 {
265  return mSlicer->getTool() && mUseOffset;
266 }
267 
268 void ToolRep2D::setVisibility()
269 {
270 // Logger::log("vm.log", "ToolRep2D::setVisibility(), offset=" + string_cast(showOffset()));
271  bool hasTool = mSlicer->getTool() ? true : false;
272 
273  if (cursor)
274  cursor->getActor()->SetVisibility(mUseCrosshair && hasTool);
275  if (center2Tool)
276  center2Tool->getActor()->SetVisibility(showOffset());
277  if (tool2Back)
278  tool2Back->getActor()->SetVisibility(mUseToolLine && hasTool);
279  if (centerPoint)
280  centerPoint->getActor()->SetVisibility(mUseToolLine && hasTool);
281  if (centerPoint)
282  centerPoint->getActor()->SetVisibility(showOffset() && !mMergeOffsetAndToolLine);
283  if (distanceText)
284  distanceText->getActor()->SetVisibility(mUseOffsetText && showOffset() && !mMergeOffsetAndToolLine);
285 }
286 
290 void ToolRep2D::createCrossHair(vtkRendererPtr renderer)
291 {
292  //Logger::log("vm.log", "<"+string_cast(__FUNCTION__)+">"+" new " );
293  cursor.reset( new CrossHair2D(renderer) ) ;
294  crossHairResized();
295 }
296 
300 void ToolRep2D::crossHairResized()
301 {
302  if (cursor)
303  {
304  double bordarOffset = 30.0;
305  RGBColor color(1.0, 0.8, 0.0);
306  Vector3D focalPoint(0.0,0.0,0.0);
307  //Logger::log("tool.log", "("+string_cast(__FUNCTION__)+")"+" mCross"+string_cast(cross));
308  //cursor->setValue( focalPoint, mBB_vp.range()[0], mBB_vp.range()[1], bordarOffset, color );
309  cursor->setValue( focalPoint, int(mBB_vp.range()[0]), int(mBB_vp.range()[1]), bordarOffset, color );
310  }
311 }
312 
315 void ToolRep2D::createToolLine(vtkRendererPtr renderer, const Vector3D& centerPos )
316 {
317  // line from tooltip to offset point
318  center2Tool.reset(new LineSegment(renderer));
319  center2Tool->setPoints(centerPos, Vector3D(0.0, 0.0, 0.0), mOffsetLineColor, mStipplePattern);
320  center2Tool->setWidth(2);
321 
322  // line from back infinity to tooltip
323  tool2Back.reset(new LineSegment(renderer));
324  tool2Back->setPoints(Vector3D(0.0, 0.0, 0.0), Vector3D(0.0, 0.0, 0.0), mTooltipLineColor);
325  tool2Back->setWidth(2);
326 
327  // Add dot at offset point
328  centerPoint.reset(new OffsetPoint(renderer));
329  centerPoint->setValue(centerPos, mOffsetPointColor);
330  centerPoint->setRadius(4);
331  centerPoint->getActor()->VisibilityOff();
332 
333  // Add dot at tooltip point
334  toolPoint.reset(new OffsetPoint(renderer));
335  toolPoint->setValue(Vector3D(0.0, 0.0, 0.0), mTooltipPointColor);
336  toolPoint->setRadius(3);
337 }
338 
341 void ToolRep2D::createOffsetText(vtkRendererPtr renderer, const Vector3D& pos )
342 {
343  QColor color = QColor::fromRgbF(0.7372, 0.815, 0.6039);
344  distanceText.reset( new TextDisplay( "---", color, 18) );
345  distanceText->getActor()->GetPositionCoordinate()->SetCoordinateSystemToNormalizedViewport();
346  distanceText->textProperty()->SetJustificationToRight();
347  distanceText->setPosition(Vector3D(0.95, 0.95, 0.0));
348  renderer->AddActor( distanceText->getActor() );
349  updateOffsetText();
350 }
351 
356 void ToolRep2D::updateToolLine(const Vector3D& crossPos, const Vector3D& toolTipPos, const Vector3D toolTipBackPos)
357 {
358  if (!center2Tool || !tool2Back || !centerPoint || !toolPoint)
359  return;
360 
361  if (mMergeOffsetAndToolLine) // for ACS only
362  {
363  // Make entire line look like an offset line, since tooltip point will become projected
364  // into the planes set by the offset position, which may be seen as navigation error.
365  center2Tool->getActor()->SetVisibility(false);
366  tool2Back->updatePosition(crossPos, toolTipBackPos);
367  if (getOffset() > 0.01)
368  {
369  toolPoint->getActor()->SetVisibility(false);
370  centerPoint->getActor()->SetVisibility(true);
371  tool2Back->setColor(mOffsetLineColor);
372  tool2Back->setPattern(mStipplePattern);
373  }
374  else
375  {
376  toolPoint->getActor()->SetVisibility(true);
377  centerPoint->getActor()->SetVisibility(false);
378  tool2Back->setColor(mTooltipLineColor);
379  tool2Back->setPattern(0xffff);
380  }
381  }
382  else
383  {
384  center2Tool->updatePosition(crossPos, toolTipPos);
385  tool2Back->updatePosition(toolTipPos, toolTipBackPos);
386  if (getOffset() > 0.01)
387  {
388  centerPoint->getActor()->SetVisibility(true);
389  }
390  else
391  {
392  centerPoint->getActor()->SetVisibility(false);
393  }
394  }
395  centerPoint->update(crossPos);
396  toolPoint->update(toolTipPos);
397 }
398 
399 void ToolRep2D::updateOffsetText()
400 {
401  if (!distanceText)
402  {
403  return;
404  }
405  if (getOffset() > 2.0 && mUseOffsetText && showOffset())
406  {
407  distanceText->updateText("Offset: " + QString::number(getOffset(), 'g', 3) + " mm");
408  distanceText->getActor()->VisibilityOn();
409  }
410  else
411  {
412  distanceText->getActor()->VisibilityOff(); // doesnt work...
413  distanceText->updateText( "" ); // does work...
414  }
415 }
416 
417 } // namespace vm
boost::shared_ptr< class SpaceProvider > SpaceProviderPtr
virtual QString getType() const
Definition: cxToolRep2D.cpp:84
void setUseOffsetText(bool on)
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()
virtual void addRepActorsToViewRenderer(ViewPtr view)
boost::shared_ptr< class View > ViewPtr
void setSliceProxy(SliceProxyPtr slicer)
boost::shared_ptr< class ToolRep2D > ToolRep2DPtr
bool similar(const DoubleBoundingBox3D &a, const DoubleBoundingBox3D &b, double tol)
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
vtkMatrix4x4Ptr getVtkMatrix(const Eigen::Affine3d *self)
vtkSmartPointer< class vtkRenderer > vtkRendererPtr
void setMergeOffsetAndToolLine(bool on)
Transform3D createTransformTranslate(const Vector3D &translation)
void setUseToolLine(bool on)
double dot(const Vector3D &a, const Vector3D &b)
compute inner product (or dot product) of a and b.
Definition: cxVector3D.cpp:67
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.
cxLogicManager_EXPORT SpaceProviderPtr spaceProvider()
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:63
void setUseCrosshair(bool on)
void setUseOffset(bool on)
static ToolRep2DPtr New(SpaceProviderPtr spaceProvider, const QString &uid="")
Definition: cxToolRep2D.cpp:79
Ultrasond probe. The tool has a Probe subinterface with a sector and a video stream.
Definition: cxTool.h:108
void setViewportData(const Transform3D &vpMs, const DoubleBoundingBox3D &vp)
Definition: cxToolRep2D.cpp:99
void setModified()
Definition: cxRepImpl.cpp:132