CustusX  22.04-rc5
An IGT application
cxVtkHelperClasses.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 "cxVtkHelperClasses.h"
15 
16 #include <vtkSphereSource.h>
17 #include <vtkLineSource.h>
18 #include <vtkPolyDataMapper2D.h>
19 #include <vtkProperty2D.h>
20 #include <vtkTextMapper.h>
21 #include <vtkTextProperty.h>
22 #include <vtkAxesActor.h>
23 #include <vtkCaptionActor2D.h>
24 #include <vtkMatrix4x4.h>
25 #include <vtkRenderer.h>
26 #include <vtkCursor2D.h>
27 #include <vtkLeaderActor2D.h>
28 #include "cxTypeConversions.h"
29 #include <vtkProperty.h>
30 #include "cxBoundingBox3D.h"
31 #include "cxLogger.h"
32 
33 #include "vtkOverrideInformationCollection.h"
34 #include "vtkObjectFactory.h"
35 
36 // --------------------------------------------------------
37 namespace cx
38 {
39 
41 {
42  Vector3D retval(color.redF(), color.greenF(), color.blueF());
43  return retval;
44 }
45 
46 
48 
50 {
51  for (unsigned i=0; i<size(); ++i)
52  elems[i] = t.elems[i];
53 }
54 
56 {
57  if (this!=&t)
58  {
59  for (unsigned i=0; i<size(); ++i)
60  elems[i] = t.elems[i];
61  }
62  return *this;
63 }
64 
65 RGBColor& RGBColor::operator=(const QColor& t)
66 {
67  elems[0] = t.redF();
68  elems[1] = t.greenF();
69  elems[2] = t.blueF();
70  return *this;
71 }
72 
74 {
75  elems[0] = c.redF();
76  elems[1] = c.greenF();
77  elems[2] = c.blueF();
78 }
79 
80 RGBColor::RGBColor(double r, double g, double b)
81 {
82  elems[0] = r;
83  elems[1] = g;
84  elems[2] = b;
85 }
86 
87 RGBColor::RGBColor(const double* rgb)
88 {
89  elems[0] = rgb[0];
90  elems[1] = rgb[1];
91  elems[2] = rgb[2];
92 }
93 
94 
95 // --------------------------------------------------------
96 // OFFSEET POINT CLASS
97 // --------------------------------------------------------
98 
99 
101 {
102  mRenderer = renderer;
103  source = vtkSphereSourcePtr::New() ;
104  source->SetRadius( 4);
105 
106  mapper = vtkPolyDataMapper2DPtr::New() ;
107  mapper->SetInputConnection(source->GetOutputPort() );
108 
109  actor = vtkActor2DPtr::New();
110  actor->SetMapper(mapper);
111  mRenderer->AddActor(actor);
112 }
113 
115 {
116  mRenderer->RemoveActor(actor);
117 }
118 
119 void OffsetPoint::setRadius(int radius)
120 {
121  source->SetRadius(radius);
122 }
123 
125 {
126  actor->GetProperty()->SetColor(color.begin());
127  actor->SetPosition(point.begin());
128 }
129 
131 {
132  actor->GetProperty()->SetColor(color.begin());
133  actor->SetPosition(point.begin());
134 }
135 
136 void OffsetPoint::update( const Vector3D& position )
137 {
138  Vector3D p = position;
139  actor->SetPosition ( p.begin() );
140 }
141 
143 {
144  return actor;
145 }
146 
147 
148 //---------------------------------------------------------//
149 // LINESEGMENT CLASS
150 //---------------------------------------------------------//
151 
152 
154 {
155  mRenderer = renderer;
156  source = vtkLineSourcePtr::New();
157  mapper2d = vtkPolyDataMapper2DPtr::New();
158  actor2d = vtkActor2DPtr::New();
159 }
160 
162 {
163  mRenderer->RemoveActor(actor2d);
164 }
165 
166 void LineSegment::setPoints(Vector3D point1, Vector3D point2, RGBColor color, int stipplePattern)
167 {
168  source->SetPoint1(point1.begin());
169  source->SetPoint2(point2.begin());
170  mapper2d->SetInputConnection(source->GetOutputPort());
171  actor2d->SetMapper(mapper2d);
172  actor2d->GetProperty()->SetColor(color.begin());
173  actor2d->GetProperty()->SetLineStipplePattern(stipplePattern);
174  mRenderer->AddActor(actor2d);
175 }
176 
178 {
179  source->SetResolution(res);
180 }
181 
182 void LineSegment::setWidth(float width)
183 {
184  actor2d->GetProperty()->SetLineWidth(width);
185 }
186 
188 {
189  source->SetPoint1(point1.begin());
190  source->SetPoint2(point2.begin());
191 }
192 
194 {
195  actor2d->GetProperty()->SetColor(color.begin());
196 }
197 
198 void LineSegment::setPattern(int stipplePattern)
199 {
200  actor2d->GetProperty()->SetLineStipplePattern(stipplePattern);
201 }
202 
204 {
205  return actor2d;
206 }
207 
208 // --------------------------------------------------------
209 // CROSS HAIR CLASS
210 // --------------------------------------------------------
211 
213 {
214  mRenderer = renderer;
215  mCursor2D = vtkCursor2DPtr::New();
216  mapper = vtkPolyDataMapper2DPtr::New();
217  mapper->SetInputConnection ( mCursor2D->GetOutputPort() );
218 
219  actor = vtkActor2DPtr::New();
220  actor->SetMapper ( mapper );
221  mRenderer->AddActor ( actor );
222 }
223 
225 {
226  mRenderer->RemoveActor(actor);
227 }
228 
229 void CrossHair2D::setValue(const Vector3D& focalPoint, int width, int height, double bordarOffset, const RGBColor& color )
230 {
231  RGBColor c = color;
232  Vector3D p = focalPoint;
233  bordarOffset = 0.0;
234  mCursor2D->SetModelBounds ( bordarOffset, width - bordarOffset, bordarOffset, height - bordarOffset, 0.0, 0.0 );
235  mCursor2D->SetFocalPoint ( p[0]/2, p[1]/2, 0.0 );
236  mCursor2D->SetRadius ( 5 );
237  mCursor2D->AllOff();
238  mCursor2D->AxesOn();
239  mCursor2D->PointOn();
240  mCursor2D->OutlineOff();
241  actor->GetProperty()-> SetColor ( c.begin() );
242 }
243 
246 void CrossHair2D::updateRegCross( const Vector3D& crossPos )
247 {
248  Vector3D cp = crossPos;
249  if ( mCursor2D )
250  {
251  mCursor2D->SetModelBounds( cp[0]-50, cp[0]+50, cp[1]-50, cp[1]+50, 0.0, 0.0 );
252  mCursor2D->SetFocalPoint ( cp.begin() );
253  mCursor2D->Update();
254  }
255 }
256 void CrossHair2D::update( const Vector3D& crossPos, const DoubleBoundingBox3D& vp)
257 {
258  Vector3D cp = crossPos;
259  cp[2] = 0.0; // make it fit inside the z bounds.
260 
261  DoubleBoundingBox3D bb = vp;
262  if (!bb.contains(cp))
263  {
264  mCursor2D->AllOff();
265  }
266  else
267  {
268  mCursor2D->AllOff();
269  mCursor2D->AxesOn();
270  mCursor2D->PointOn();
271  mCursor2D->OutlineOff();
272  }
273 
274  if ( mCursor2D )
275  {
276  mCursor2D->SetFocalPoint ( cp.begin() );
277  mCursor2D->Update();
278  }
279  if (mapper)
280  {
281  //mapper->Update();
282  }
283 }
284 
286 {
287  return actor;
288 }
289 
290 // --------------------------------------------------------
291 // TEXT DISPLAY CLASS
292 // --------------------------------------------------------
293 TextDisplay::TextDisplay( const QString& text, const QColor &color, int fontsize )
294 {
295  this->text = text;
296 // Vector3D c = color;
297 // this->forceUseVtkTextMapper();
298  mapper = vtkTextMapperPtr::New();
299  mapper->SetInput( cstring_cast(text) );
300  this->setColor(color);
301  mapper->GetTextProperty()->SetFontSize( fontsize );
302 
303  actor= vtkActor2DPtr::New();
304  actor->SetMapper( mapper );
305  maxWidth = 0;
306 }
307 
309 {
310  //Force the use of vtkTextMapper instead of vtkOpenGLFreeTypeTextMapper
311  //Copied from TestFreeTypeTextMapper.cxx
312 
313  // Remove any override to the class to ensure that the actual vtkTextMapper
314  // class is being tested:
315  vtkNew<vtkOverrideInformationCollection> overrides;
316  vtkObjectFactory::GetOverrideInformation("vtkTextMapper",
317  overrides.GetPointer());
318  overrides->InitTraversal();
319  while (vtkOverrideInformation *override = overrides->GetNextItem())
320  {
321  if (vtkObjectFactory *factory = override->GetObjectFactory())
322  {
323  vtkObjectFactory::UnRegisterFactory(factory);
324  }
325  }
326  verifyVtkTextMapper();
327 }
328 
329 void TextDisplay::verifyVtkTextMapper()
330 {
331  vtkNew<vtkTextMapper> nameChecker;
332  if (vtkStdString(nameChecker->GetClassName()) != "vtkTextMapper")
333  {
334  reportError("Needed a vtkTextMapper instance, got " + QString(nameChecker->GetClassName()));
335  }
336 }
337 
338 void TextDisplay::setColor(QColor color)
339 {
340  mapper->GetTextProperty()->SetColor(getColorAsVector3D(color).begin() );
341 }
342 
344 {
345  if (mRenderer)
346  mRenderer->RemoveActor(actor);
347  mRenderer = renderer;
348  if (mRenderer)
349  mRenderer->AddActor(actor);
350 }
351 
353 {
354  this->setRenderer(vtkRendererPtr());
355 }
356 
357 void TextDisplay::setMaxWidth( int width, vtkViewport *vp)
358 {
359  maxWidth = width;
360  QStringList components = text.split("\n");
361  for (QStringList::iterator it = components.begin(); it != components.end(); ++it)
362  {
363  this->verifyVtkTextMapper();
364  vtkTextMapperPtr line = vtkTextMapperPtr::New();
365  bool changed = false;
366  line->SetInput( it->toLatin1().constData() );
367  line->SetTextProperty(mapper->GetTextProperty());
368  while((*it).length() > 0 && line->GetWidth(vp) > maxWidth)
369  {
370  (*it).chop(1);
371  line->SetInput( QString("%1...").arg(*it).toLatin1().constData() );
372  changed = true;
373  }
374  if (changed)
375  {
376  (*it).append("...");
377  }
378  }
379  QString newString = components.join("\n");
380  mapper->SetInput( newString.toLatin1().constData() );
381 }
382 
384 {
385  return maxWidth;
386 }
387 
388 int TextDisplay::getWidth( vtkViewport *vp)
389 {
390  return mapper->GetWidth( vp );
391 }
392 
394 {
395  actor->SetPosition( pos[0], pos[1] );
396 }
397 
398 void TextDisplay::setPosition( float x, float y )
399 {
400  actor->SetPosition( x, y );
401 }
402 
403 void TextDisplay::updateText( const QString& text)
404 {
405  QString input = text;
406  //VTK has a bug which leaves a white square where the text was, if the text is replaced with no text.
407  //E.g. the volume name when removing the last visible voulume. So we add a space instead of an empty text.
408  if(input.isEmpty())
409  input = " ";
410 
411  if (input == QString(mapper->GetInput()))
412  return;
413 
414  mapper->SetInput( cstring_cast(input) );
415  actor->Modified();
416 }
417 
418 vtkTextProperty* TextDisplay::textProperty()
419 {
420  return mapper->GetTextProperty();
421 }
422 
424 {
425  return actor;
426 }
427 
429 {
430  mapper->GetTextProperty()->SetJustificationToCentered() ;
431  mapper->GetTextProperty()->SetVerticalJustificationToCentered() ;
432 }
433 
434 // --------------------------------------------------------
435 // Axes3D CLASS
436 // --------------------------------------------------------
437 
438 Axes3D::Axes3D(vtkRendererPtr renderer) : mRenderer(renderer)
439 {
440  mAxes = vtkSmartPointer<vtkAxesActor>::New();
441 
442  setCaption(mAxes->GetXAxisCaptionActor2D(), "x", RGBColor(1,0,0));
443  setCaption(mAxes->GetYAxisCaptionActor2D(), "y", RGBColor(0,1,0));
444  setCaption(mAxes->GetZAxisCaptionActor2D(), "z", RGBColor(0,0,1));
445 
446  //SW_LOG("total len %s", string_cast(Vector3D(axes->GetTotalLength())).c_str());
447  //SW_LOG("scale %s", string_cast(Vector3D(mAxes->GetScale())).c_str());
448 
449  setPosition(Transform3D::Identity());
450 
451  Vector3D len(mAxes->GetNormalizedShaftLength());
452  //SW_LOG("len %s", string_cast(len).c_str());
453  //len = Vector3D(0.1,0.1,0.1);
454  mAxes->SetNormalizedShaftLength(len.begin());
455 
456  if (mRenderer)
457  mRenderer->AddActor(mAxes);
458 }
459 
463 {
464  double scale = 20;
465  //axes->SetScale(Vector3D(scale,scale,scale).begin());
466  Transform3D S = createTransformScale(Vector3D(scale,scale,scale));
467 
468  mAxes->SetUserMatrix((S*pos).getVtkMatrix());
469 }
470 
472 {
473  if (mRenderer)
474  mRenderer->RemoveActor(mAxes);
475 }
476 
478 {
479  return mAxes;
480 }
481 
482 void Axes3D::setCaption(vtkCaptionActor2D* captionActor, const QString& caption, RGBColor color)
483 {
484  captionActor->SetCaption(cstring_cast(caption));
485  captionActor->GetCaptionTextProperty()->SetColor(color.begin());
486 
487  double fontsize = 0.02;
488  captionActor->SetWidth(fontsize);
489  captionActor->SetHeight(fontsize);
490 }
491 
492 }// namespace vm
493 // --------------------------------------------------------
vtkActor2DPtr getActor()
vtkTextProperty * textProperty()
void reportError(QString msg)
Definition: cxLogger.cpp:71
void updateRegCross(const Vector3D &crossPos)
Vector3D getColorAsVector3D(QColor color)
Scalar * begin()
RGBColor & operator=(const RGBColor &t)
void setResolution(int res)
Transform3D createTransformScale(const Vector3D &scale_)
vtkSmartPointer< class vtkActor2D > vtkActor2DPtr
vtkSmartPointer< class vtkTextMapper > vtkTextMapperPtr
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
void setPoints(Vector3D point1, Vector3D point2, RGBColor color, int stipplePattern=0xFFFF)
cstring_cast_Placeholder cstring_cast(const T &val)
void setRadius(int radius)
void update(const Vector3D &crossPos, const DoubleBoundingBox3D &vp)
void setColor(RGBColor color)
void setWidth(float width)
LineSegment(vtkRendererPtr renderer)
void updatePosition(Vector3D point1, Vector3D point2)
vtkProp3DPtr getProp()
void setMaxWidth(int width, vtkViewport *vp)
void setColor(QColor color)
void setValue(Vector3D point, RGBColor color)
RGB color data.
void setPosition(float x, float y)
void setPosition(const Transform3D &pos)
vtkMatrix4x4Ptr getVtkMatrix(const Eigen::Affine3d *self)
CrossHair2D(vtkRendererPtr renderer)
vtkActor2DPtr getActor()
vtkSmartPointer< class vtkRenderer > vtkRendererPtr
int getWidth(vtkViewport *vp)
void setValue(const Vector3D &focalPoint, int width, int height, double bordarOffset, const RGBColor &color)
vtkActor2DPtr getActor()
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.
TextDisplay(const QString &text, const QColor &color, int fontsize)
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:42
vtkSmartPointer< class vtkProp3D > vtkProp3DPtr
void updateText(const QString &text)
Axes3D(vtkRendererPtr renderer=vtkRendererPtr())
static void forceUseVtkTextMapper()
OffsetPoint(vtkRendererPtr renderer)
void setPattern(int stipplePattern)
vtkActor2DPtr getActor()
void update(const Vector3D &point)
bool contains(const Vector3D &p) const
void setRenderer(vtkRendererPtr renderer)
Namespace for all CustusX production code.