1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkDistanceRepresentation3D.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 #include "vtkDistanceRepresentation3D.h"
16 #include "vtkPointHandleRepresentation3D.h"
17 #include "vtkPolyDataMapper.h"
18 #include "vtkPoints.h"
19 #include "vtkCellArray.h"
20 #include "vtkPolyData.h"
21 #include "vtkPolyDataMapper.h"
22 #include "vtkActor.h"
23 #include "vtkVectorText.h"
24 #include "vtkFollower.h"
25 #include "vtkCamera.h"
26 #include "vtkProperty.h"
27 #include "vtkCoordinate.h"
28 #include "vtkRenderer.h"
29 #include "vtkObjectFactory.h"
30 #include "vtkInteractorObserver.h"
31 #include "vtkMath.h"
32 #include "vtkWindow.h"
33 #include "vtkSmartPointer.h"
34 #include "vtkBox.h"
35 #include "vtkGlyph3D.h"
36 #include "vtkCylinderSource.h"
37 #include "vtkDoubleArray.h"
38 #include "vtkPointData.h"
39 #include "vtkTransformPolyDataFilter.h"
40 #include "vtkTransform.h"
41 #include "vtkSmartPointer.h"
42 
43 vtkStandardNewMacro(vtkDistanceRepresentation3D);
44 
45 //----------------------------------------------------------------------
vtkDistanceRepresentation3D()46 vtkDistanceRepresentation3D::vtkDistanceRepresentation3D()
47 {
48   // By default, use one of these handles
49   this->HandleRepresentation  = vtkPointHandleRepresentation3D::New();
50 
51   // The line
52   this->LinePoints = vtkPoints::New();
53   this->LinePoints->SetDataTypeToDouble();
54   this->LinePoints->SetNumberOfPoints(2);
55   this->LinePolyData = vtkPolyData::New();
56   this->LinePolyData->SetPoints(this->LinePoints);
57   vtkSmartPointer<vtkCellArray> line = vtkSmartPointer<vtkCellArray>::New();
58   line->InsertNextCell(2);
59   line->InsertCellPoint(0);
60   line->InsertCellPoint(1);
61   this->LinePolyData->SetLines(line);
62   this->LineMapper = vtkPolyDataMapper::New();
63   this->LineMapper->SetInputData(this->LinePolyData);
64   this->LineActor = vtkActor::New();
65   this->LineActor->SetMapper(this->LineMapper);
66 
67   // The label
68   this->LabelText = vtkVectorText::New();
69   this->LabelMapper = vtkPolyDataMapper::New();
70   this->LabelMapper->SetInputConnection(this->LabelText->GetOutputPort());
71   this->LabelActor = vtkFollower::New();
72   this->LabelActor->SetMapper(this->LabelMapper);
73 
74   // The tick marks
75   this->GlyphPoints = vtkPoints::New();
76   this->GlyphPoints->SetDataTypeToDouble();
77   this->GlyphVectors = vtkDoubleArray::New();
78   this->GlyphVectors->SetNumberOfComponents(3);
79   this->GlyphPolyData = vtkPolyData::New();
80   this->GlyphPolyData->SetPoints(this->GlyphPoints);
81   this->GlyphPolyData->GetPointData()->SetVectors(this->GlyphVectors);
82   this->GlyphCylinder = vtkCylinderSource::New();
83   this->GlyphCylinder->SetRadius(0.5);
84   this->GlyphCylinder->SetHeight(0.1);
85   this->GlyphCylinder->SetResolution(12);
86   vtkSmartPointer<vtkTransform> xform = vtkSmartPointer<vtkTransform>::New();
87   this->GlyphXForm = vtkTransformPolyDataFilter::New();
88   this->GlyphXForm->SetInputConnection(this->GlyphCylinder->GetOutputPort());
89   this->GlyphXForm->SetTransform(xform);
90   xform->RotateZ(90);
91   this->Glyph3D = vtkGlyph3D::New();
92   this->Glyph3D->SetOutputPointsPrecision(vtkAlgorithm::DOUBLE_PRECISION);
93   this->Glyph3D->SetInputData(this->GlyphPolyData);
94   this->Glyph3D->SetSourceConnection(this->GlyphXForm->GetOutputPort());
95   this->Glyph3D->SetScaleModeToDataScalingOff();
96   this->GlyphMapper = vtkPolyDataMapper::New();
97   this->GlyphMapper->SetInputConnection(this->Glyph3D->GetOutputPort());
98   this->GlyphActor = vtkActor::New();
99   this->GlyphActor->SetMapper(this->GlyphMapper);
100 
101   this->Distance = 0.0;
102 
103   // The bounding box
104   this->BoundingBox = vtkBox::New();
105 
106   // Scaling the label
107   this->LabelScaleSpecified = false;
108 
109   // Controlling scaling and label position
110   this->GlyphScale = 1.0;
111   this->GlyphScaleSpecified = false;
112   this->LabelPosition = 0.5;
113   this->MaximumNumberOfRulerTicks = 99;
114 }
115 
116 //----------------------------------------------------------------------
~vtkDistanceRepresentation3D()117 vtkDistanceRepresentation3D::~vtkDistanceRepresentation3D()
118 {
119   this->LinePoints->Delete();
120   this->LinePolyData->Delete();
121   this->LineMapper->Delete();
122   this->LineActor->Delete();
123 
124   this->LabelText->Delete();
125   this->LabelMapper->Delete();
126   this->LabelActor->Delete();
127 
128   this->GlyphPoints->Delete();
129   this->GlyphVectors->Delete();
130   this->GlyphPolyData->Delete();
131   this->GlyphCylinder->Delete();
132   this->GlyphXForm->Delete();
133   this->Glyph3D->Delete();
134   this->GlyphMapper->Delete();
135   this->GlyphActor->Delete();
136 
137   this->BoundingBox->Delete();
138 }
139 
140 //----------------------------------------------------------------------
SetLabelActor(vtkFollower * fol)141 void vtkDistanceRepresentation3D::SetLabelActor(vtkFollower *fol)
142 {
143   if (fol == this->LabelActor)
144   {
145     return;
146   }
147 
148   if (fol)
149   {
150     fol->Register(this);
151     fol->SetMapper(this->LabelMapper);
152   }
153 
154   if (this->LabelActor)
155   {
156     this->LabelActor->ReleaseGraphicsResources(nullptr);
157     this->LabelActor->UnRegister(this);
158     this->LabelActor = nullptr;
159   }
160 
161   this->LabelActor = fol;
162   this->Modified();
163 }
164 
165 //----------------------------------------------------------------------
GetPoint1WorldPosition(double pos[3])166 void vtkDistanceRepresentation3D::GetPoint1WorldPosition(double pos[3])
167 {
168   this->Point1Representation->GetWorldPosition(pos);
169 }
170 
171 //----------------------------------------------------------------------
GetPoint2WorldPosition(double pos[3])172 void vtkDistanceRepresentation3D::GetPoint2WorldPosition(double pos[3])
173 {
174   this->Point2Representation->GetWorldPosition(pos);
175 }
176 
177 //----------------------------------------------------------------------
GetPoint1WorldPosition()178 double* vtkDistanceRepresentation3D::GetPoint1WorldPosition()
179 {
180   if (!this->Point1Representation)
181   {
182     static double temp[3]=  {0, 0, 0};
183     return temp;
184   }
185   return this->Point1Representation->GetWorldPosition();
186 }
187 
188 //----------------------------------------------------------------------
GetPoint2WorldPosition()189 double* vtkDistanceRepresentation3D::GetPoint2WorldPosition()
190 {
191   if (!this->Point2Representation)
192   {
193     static double temp[3]=  {0, 0, 0};
194     return temp;
195   }
196   return this->Point2Representation->GetWorldPosition();
197 }
198 
199 //----------------------------------------------------------------------
SetPoint1DisplayPosition(double x[3])200 void vtkDistanceRepresentation3D::SetPoint1DisplayPosition(double x[3])
201 {
202   this->Point1Representation->SetDisplayPosition(x);
203   double p[3];
204   this->Point1Representation->GetWorldPosition(p);
205   this->Point1Representation->SetWorldPosition(p);
206 }
207 
208 //----------------------------------------------------------------------
SetPoint2DisplayPosition(double x[3])209 void vtkDistanceRepresentation3D::SetPoint2DisplayPosition(double x[3])
210 {
211   this->Point2Representation->SetDisplayPosition(x);
212   double p[3];
213   this->Point2Representation->GetWorldPosition(p);
214   this->Point2Representation->SetWorldPosition(p);
215 }
216 
217 //----------------------------------------------------------------------
SetPoint1WorldPosition(double x[3])218 void vtkDistanceRepresentation3D::SetPoint1WorldPosition(double x[3])
219 {
220   if (this->Point1Representation)
221   {
222     this->Point1Representation->SetWorldPosition(x);
223   }
224 }
225 
226 //----------------------------------------------------------------------
SetPoint2WorldPosition(double x[3])227 void vtkDistanceRepresentation3D::SetPoint2WorldPosition(double x[3])
228 {
229   if (this->Point2Representation)
230   {
231     this->Point2Representation->SetWorldPosition(x);
232   }
233 }
234 
235 //----------------------------------------------------------------------
GetPoint1DisplayPosition(double pos[3])236 void vtkDistanceRepresentation3D::GetPoint1DisplayPosition(double pos[3])
237 {
238   this->Point1Representation->GetDisplayPosition(pos);
239   pos[2] = 0.0;
240 }
241 
242 //----------------------------------------------------------------------
GetPoint2DisplayPosition(double pos[3])243 void vtkDistanceRepresentation3D::GetPoint2DisplayPosition(double pos[3])
244 {
245   this->Point2Representation->GetDisplayPosition(pos);
246   pos[2] = 0.0;
247 }
248 
249 //----------------------------------------------------------------------
GetBounds()250 double *vtkDistanceRepresentation3D::GetBounds()
251 {
252   if(this->Point1Representation && this->Point2Representation)
253   {
254     this->BuildRepresentation();
255     this->BoundingBox->SetBounds(this->Point1Representation->GetBounds());
256     this->BoundingBox->AddBounds(this->Point2Representation->GetBounds());
257   }
258   this->BoundingBox->AddBounds(this->LineActor->GetBounds());
259 
260   return this->BoundingBox->GetBounds();
261 }
262 
263 //----------------------------------------------------------------------
BuildRepresentation()264 void vtkDistanceRepresentation3D::BuildRepresentation()
265 {
266   if ( this->GetMTime() > this->BuildTime ||
267        this->LabelActor->GetMTime() > this->BuildTime ||
268        this->BoundingBox->GetMTime() > this->BuildTime ||
269        this->GlyphActor->GetMTime() > this->BuildTime ||
270        this->LineActor->GetMTime() > this->BuildTime ||
271        this->Point1Representation->GetMTime() > this->BuildTime ||
272        this->Point2Representation->GetMTime() > this->BuildTime ||
273        (this->Renderer && this->Renderer->GetVTKWindow() &&
274         this->Renderer->GetVTKWindow()->GetMTime() > this->BuildTime) )
275   {
276     this->Superclass::BuildRepresentation();
277 
278     // Okay, compute the distance and set the label
279     double p1[3], p2[3];
280     this->Point1Representation->GetWorldPosition(p1);
281     this->Point2Representation->GetWorldPosition(p2);
282     this->Distance = sqrt(vtkMath::Distance2BetweenPoints(p1,p2));
283 
284     // Line
285     this->LinePoints->SetPoint(0,p1);
286     this->LinePoints->SetPoint(1,p2);
287     this->LinePoints->Modified();
288 
289     // Label
290     char string[512];
291     snprintf(string, sizeof(string), this->LabelFormat, this->Distance,
292       fabs(p1[0] - p2[0]), fabs(p1[1] - p2[1]), fabs(p1[2] - p2[2]));
293     this->LabelText->SetText(string);
294     this->UpdateLabelPosition();
295     if (this->Renderer) //make the label face the camera
296     {
297       this->LabelActor->SetCamera( this->Renderer->GetActiveCamera() );
298     }
299 
300     if (!this->LabelScaleSpecified)
301     {
302       // If a font size hasn't been specified by the user, scale the text
303       // (font size) according to the length of the line widget.
304       this->LabelActor->SetScale(
305           this->Distance/20.0, this->Distance/20.0, this->Distance/20.0 );
306     }
307 
308     // Ticks - generate points that are glyphed
309     int i, numTicks;
310     double v21[3], x[3];
311     v21[0] =  p2[0] - p1[0]; v21[1] =  p2[1] - p1[1]; v21[2] =  p2[2] - p1[2];
312     vtkMath::Normalize(v21);
313     this->GlyphPoints->Reset();
314     this->GlyphPoints->Modified();
315     this->GlyphVectors->Reset();
316     if (this->GlyphScaleSpecified)
317     {
318       this->Glyph3D->SetScaleFactor(this->GlyphScale);
319     }
320     else
321     {
322       this->Glyph3D->SetScaleFactor(this->Distance/40);
323     }
324     double distance;
325     if ( this->RulerMode ) // specified tick separation
326     {
327       numTicks = (this->RulerDistance <= 0.0 ? 1 : static_cast<int>(this->Distance / this->RulerDistance));
328       numTicks = (numTicks > this->MaximumNumberOfRulerTicks ? this->MaximumNumberOfRulerTicks : numTicks);
329       distance = this->RulerDistance;
330     }
331     else //evenly spaced
332     {
333       numTicks = this->NumberOfRulerTicks;
334       distance = this->Distance / (numTicks + 1);
335     }
336     for (i=1; i <= numTicks; ++i)
337     {
338       x[0] = p1[0] + i*v21[0]*distance;
339       x[1] = p1[1] + i*v21[1]*distance;
340       x[2] = p1[2] + i*v21[2]*distance;
341       this->GlyphPoints->InsertNextPoint(x);
342       this->GlyphVectors->InsertNextTuple(v21);
343     }
344 
345     this->BuildTime.Modified();
346   }
347 }
348 
349 //----------------------------------------------------------------------
350 void vtkDistanceRepresentation3D::
ReleaseGraphicsResources(vtkWindow * w)351 ReleaseGraphicsResources(vtkWindow *w)
352 {
353   this->LineActor->ReleaseGraphicsResources(w);
354   this->LabelActor->ReleaseGraphicsResources(w);
355   this->GlyphActor->ReleaseGraphicsResources(w);
356 }
357 
358 
359 //----------------------------------------------------------------------
360 int vtkDistanceRepresentation3D::
RenderOpaqueGeometry(vtkViewport * v)361 RenderOpaqueGeometry(vtkViewport *v)
362 {
363   this->BuildRepresentation();
364 
365   this->LineActor->RenderOpaqueGeometry(v);
366   this->LabelActor->RenderOpaqueGeometry(v);
367   this->GlyphActor->RenderOpaqueGeometry(v);
368 
369   return 3;
370 }
371 
372 //----------------------------------------------------------------------
373 int vtkDistanceRepresentation3D::
RenderTranslucentPolygonalGeometry(vtkViewport * v)374 RenderTranslucentPolygonalGeometry(vtkViewport *v)
375 {
376   this->BuildRepresentation();
377 
378   this->LineActor->RenderTranslucentPolygonalGeometry(v);
379   this->LabelActor->RenderTranslucentPolygonalGeometry(v);
380   this->GlyphActor->RenderTranslucentPolygonalGeometry(v);
381 
382   return 3;
383 }
384 
385 //----------------------------------------------------------------------
SetLabelScale(double scale[3])386 void vtkDistanceRepresentation3D::SetLabelScale( double scale[3] )
387 {
388   this->LabelActor->SetScale( scale );
389   this->LabelScaleSpecified = true;
390 }
391 
392 //----------------------------------------------------------------------
GetLabelScale()393 double * vtkDistanceRepresentation3D::GetLabelScale()
394 {
395   return this->LabelActor->GetScale();
396 }
397 
398 //----------------------------------------------------------------------------
GetLabelProperty()399 vtkProperty * vtkDistanceRepresentation3D::GetLabelProperty()
400 {
401   return this->LabelActor->GetProperty();
402 }
403 
404 //----------------------------------------------------------------------
SetGlyphScale(double scale)405 void vtkDistanceRepresentation3D::SetGlyphScale( double scale )
406 {
407   this->GlyphScale = scale;
408   this->GlyphScaleSpecified = true;
409 }
410 
411 //----------------------------------------------------------------------------
GetLineProperty()412 vtkProperty * vtkDistanceRepresentation3D::GetLineProperty()
413 {
414   return this->LineActor->GetProperty();
415 }
416 
417 //----------------------------------------------------------------------
SetLabelPosition(double labelPosition)418 void vtkDistanceRepresentation3D::SetLabelPosition(double labelPosition)
419 {
420   vtkDebugMacro(<< this->GetClassName() << " (" << this << "): setting LabelPosition to " << labelPosition);
421 
422   if (this->LabelPosition == labelPosition)
423   {
424     ;
425   }
426   else
427   {
428     this->LabelPosition = labelPosition;
429   }
430   this->UpdateLabelPosition();
431 }
432 
433 //----------------------------------------------------------------------
UpdateLabelPosition()434 void vtkDistanceRepresentation3D::UpdateLabelPosition()
435 {
436   if (!this->Point1Representation ||
437       !this->Point2Representation)
438   {
439     return;
440   }
441 
442   // get the end points
443   double p1[3], p2[3];
444   this->Point1Representation->GetWorldPosition(p1);
445   this->Point2Representation->GetWorldPosition(p2);
446   double pos[3];
447 
448   pos[0] = p1[0] + (p2[0] - p1[0]) * this->LabelPosition;
449   pos[1] = p1[1] + (p2[1] - p1[1]) * this->LabelPosition;
450   pos[2] = p1[2] + (p2[2] - p1[2]) * this->LabelPosition;
451 
452   // and set it on the actor
453   double * actorPos = this->LabelActor->GetPosition();
454   double diff = sqrt(vtkMath::Distance2BetweenPoints(pos, actorPos));
455   if (diff > 0.001)
456   {
457     this->LabelActor->SetPosition(pos);
458   }
459 }
460 
461 //----------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)462 void vtkDistanceRepresentation3D::PrintSelf(ostream& os, vtkIndent indent)
463 {
464   //Superclass typedef defined in vtkTypeMacro() found in vtkSetGet.h
465   this->Superclass::PrintSelf(os,indent);
466 
467   os << indent << "Distance: " << this->Distance << endl;
468   os << indent << "Label Scale Specified: " << (this->LabelScaleSpecified ? "true" : "false") << endl;
469   os << indent << "Label Position: " << this->LabelPosition << endl;
470   os << indent << "Maximum Number Of Ticks: " << this->MaximumNumberOfRulerTicks << endl;
471   os << indent << "Glyph Scale: " << this->GlyphScale << endl;
472   os << indent << "LabelActor: " << this->LabelActor << endl;
473   os << indent << "GlyphActor: " << this->GlyphActor << endl;
474 }
475