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