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