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