1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkLineRepresentation.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 "vtkLineRepresentation.h"
16 #include "vtkActor.h"
17 #include "vtkBox.h"
18 #include "vtkCallbackCommand.h"
19 #include "vtkCamera.h"
20 #include "vtkCellPicker.h"
21 #include "vtkConeSource.h"
22 #include "vtkFollower.h"
23 #include "vtkInteractorObserver.h"
24 #include "vtkLine.h"
25 #include "vtkLineSource.h"
26 #include "vtkMath.h"
27 #include "vtkObjectFactory.h"
28 #include "vtkPointHandleRepresentation3D.h"
29 #include "vtkPolyData.h"
30 #include "vtkPolyDataMapper.h"
31 #include "vtkProperty.h"
32 #include "vtkRenderWindowInteractor.h"
33 #include "vtkRenderer.h"
34 #include "vtkSphereSource.h"
35 #include "vtkVector.h"
36 #include "vtkVectorOperators.h"
37 #include "vtkVectorText.h"
38 #include "vtkWindow.h"
39
40 vtkStandardNewMacro(vtkLineRepresentation);
41
42 vtkCxxSetObjectMacro(vtkLineRepresentation, HandleRepresentation, vtkPointHandleRepresentation3D);
43
44 //------------------------------------------------------------------------------
vtkLineRepresentation()45 vtkLineRepresentation::vtkLineRepresentation()
46 {
47 // Handle size is in pixels for this widget
48 this->HandleSize = 5.0;
49
50 // By default, use one of these handles
51 this->HandleRepresentation = vtkPointHandleRepresentation3D::New();
52 this->HandleRepresentation->AllOff();
53 this->HandleRepresentation->SetHotSpotSize(1.0);
54 this->HandleRepresentation->SetPlaceFactor(1.0);
55 this->HandleRepresentation->TranslationModeOn();
56 this->Point1Representation = nullptr;
57 this->Point2Representation = nullptr;
58 this->LineHandleRepresentation = nullptr;
59 this->InstantiateHandleRepresentation();
60
61 // Miscellaneous parameters
62 this->Tolerance = 5;
63 this->Placed = 0;
64
65 // Represent the line
66 this->LineSource = vtkLineSource::New();
67 this->LineSource->SetResolution(5);
68 this->LineMapper = vtkPolyDataMapper::New();
69 this->LineMapper->SetInputConnection(this->LineSource->GetOutputPort());
70 this->LineActor = vtkActor::New();
71 this->LineActor->SetMapper(this->LineMapper);
72
73 this->DirectionalLine = false;
74
75 // Create the handles
76 this->Handle = new vtkActor*[2];
77 this->HandleMapper = new vtkPolyDataMapper*[2];
78 this->HandleGeometry = new vtkPolyDataAlgorithm*[2];
79 for (int i = 0; i < 2; i++)
80 {
81 vtkSphereSource* sphere = vtkSphereSource::New();
82 sphere->SetThetaResolution(16);
83 sphere->SetPhiResolution(8);
84
85 this->HandleGeometry[i] = sphere;
86 this->HandleMapper[i] = vtkPolyDataMapper::New();
87 this->HandleMapper[i]->SetInputConnection(this->HandleGeometry[i]->GetOutputPort());
88 this->Handle[i] = vtkActor::New();
89 this->Handle[i]->SetMapper(this->HandleMapper[i]);
90 }
91
92 // Set up the initial properties
93 this->CreateDefaultProperties();
94
95 // Pass the initial properties to the actors.
96 this->Handle[0]->SetProperty(this->EndPointProperty);
97 this->Point1Representation->SetProperty(this->EndPointProperty);
98 this->Handle[1]->SetProperty(this->EndPoint2Property);
99 this->Point2Representation->SetProperty(this->EndPoint2Property);
100 this->LineHandleRepresentation->SetProperty(this->EndPointProperty);
101 this->LineActor->SetProperty(this->LineProperty);
102
103 // Define the point coordinates
104 double bounds[6];
105 bounds[0] = -0.5;
106 bounds[1] = 0.5;
107 bounds[2] = -0.5;
108 bounds[3] = 0.5;
109 bounds[4] = -0.5;
110 bounds[5] = 0.5;
111 this->PlaceFactor = 1.0; // overload parent's value
112
113 // The distance text annotation
114 this->DistanceAnnotationVisibility = 0;
115 this->Distance = 0.0;
116 this->DistanceAnnotationFormat = new char[8];
117 snprintf(this->DistanceAnnotationFormat, 8, "%s", "%-#6.3g");
118 this->TextInput = vtkVectorText::New();
119 this->TextInput->SetText("0");
120 this->TextMapper = vtkPolyDataMapper::New();
121 this->TextMapper->SetInputConnection(this->TextInput->GetOutputPort());
122 this->TextActor = vtkFollower::New();
123 this->TextActor->SetMapper(this->TextMapper);
124 this->TextActor->GetProperty()->SetColor(1.0, 0.1, 0.0);
125
126 // This needs to be initialized before PlaceWidget is called.
127 this->InitializedDisplayPosition = 0;
128
129 this->ClampToBounds = 0;
130
131 // The bounding box
132 this->BoundingBox = vtkBox::New();
133
134 this->LinePicker = vtkCellPicker::New();
135 this->LinePicker->SetTolerance(0.005); // need some fluff
136 this->LinePicker->AddPickList(this->LineActor);
137 this->LinePicker->PickFromListOn();
138
139 this->RepresentationState = vtkLineRepresentation::Outside;
140 this->AnnotationTextScaleInitialized = false;
141
142 // Initial creation of the widget, serves to initialize it.
143 // Call PlaceWidget() LAST in the constructor, as this method depends on ivar
144 // values.
145 this->PlaceWidget(bounds);
146 }
147
148 //------------------------------------------------------------------------------
~vtkLineRepresentation()149 vtkLineRepresentation::~vtkLineRepresentation()
150 {
151 if (this->HandleRepresentation)
152 {
153 this->HandleRepresentation->Delete();
154 }
155 if (this->Point1Representation)
156 {
157 this->Point1Representation->Delete();
158 }
159 if (this->Point2Representation)
160 {
161 this->Point2Representation->Delete();
162 }
163 if (this->LineHandleRepresentation)
164 {
165 this->LineHandleRepresentation->Delete();
166 }
167
168 this->LineActor->Delete();
169 this->LineMapper->Delete();
170 this->LineSource->Delete();
171
172 for (int i = 0; i < 2; i++)
173 {
174 this->HandleGeometry[i]->Delete();
175 this->HandleMapper[i]->Delete();
176 this->Handle[i]->Delete();
177 }
178 delete[] this->Handle;
179 delete[] this->HandleMapper;
180 delete[] this->HandleGeometry;
181
182 this->EndPointProperty->Delete();
183 this->SelectedEndPointProperty->Delete();
184 this->EndPoint2Property->Delete();
185 this->SelectedEndPoint2Property->Delete();
186 this->LineProperty->Delete();
187 this->SelectedLineProperty->Delete();
188
189 this->BoundingBox->Delete();
190
191 delete[] this->DistanceAnnotationFormat;
192 this->DistanceAnnotationFormat = nullptr;
193
194 this->TextInput->Delete();
195 this->TextMapper->Delete();
196 this->TextActor->Delete();
197 this->LinePicker->Delete();
198 }
199
200 //------------------------------------------------------------------------------
SetDirectionalLine(bool val)201 void vtkLineRepresentation::SetDirectionalLine(bool val)
202 {
203 if (this->DirectionalLine == val)
204 {
205 return;
206 }
207
208 this->DirectionalLine = val;
209 this->Modified();
210
211 if (this->DirectionalLine)
212 {
213 vtkConeSource* cone = vtkConeSource::New();
214 cone->SetResolution(16);
215 this->HandleGeometry[1]->Delete();
216 this->HandleGeometry[1] = cone;
217 }
218 else
219 {
220 vtkSphereSource* sphere = vtkSphereSource::New();
221 sphere->SetThetaResolution(16);
222 sphere->SetPhiResolution(8);
223 this->HandleGeometry[1]->Delete();
224 this->HandleGeometry[1] = sphere;
225 }
226 this->HandleMapper[1]->SetInputConnection(this->HandleGeometry[1]->GetOutputPort());
227 }
228
229 //------------------------------------------------------------------------------
GetDistance()230 double vtkLineRepresentation::GetDistance()
231 {
232 return this->Distance;
233 }
234
235 //------------------------------------------------------------------------------
InstantiateHandleRepresentation()236 void vtkLineRepresentation::InstantiateHandleRepresentation()
237 {
238 if (!this->Point1Representation)
239 {
240 this->Point1Representation = this->HandleRepresentation->NewInstance();
241 this->Point1Representation->ShallowCopy(this->HandleRepresentation);
242 }
243
244 if (!this->Point2Representation)
245 {
246 this->Point2Representation = this->HandleRepresentation->NewInstance();
247 this->Point2Representation->ShallowCopy(this->HandleRepresentation);
248 }
249
250 if (!this->LineHandleRepresentation)
251 {
252 this->LineHandleRepresentation = this->HandleRepresentation->NewInstance();
253 this->LineHandleRepresentation->ShallowCopy(this->HandleRepresentation);
254 }
255 }
256
257 //------------------------------------------------------------------------------
SetResolution(int r)258 void vtkLineRepresentation::SetResolution(int r)
259 {
260 this->LineSource->SetResolution(r);
261 }
262
263 //------------------------------------------------------------------------------
GetResolution()264 int vtkLineRepresentation::GetResolution()
265 {
266 return this->LineSource->GetResolution();
267 }
268
269 //------------------------------------------------------------------------------
GetPolyData(vtkPolyData * pd)270 void vtkLineRepresentation::GetPolyData(vtkPolyData* pd)
271 {
272 this->LineSource->Update();
273 pd->ShallowCopy(this->LineSource->GetOutput());
274 }
275
276 //-- Set/Get position of the three handles -----------------------------
277 // Point1
278 //------------------------------------------------------------------------------
GetPoint1WorldPosition(double pos[3])279 void vtkLineRepresentation::GetPoint1WorldPosition(double pos[3])
280 {
281 this->Point1Representation->GetWorldPosition(pos);
282 }
283
GetPoint1WorldPosition()284 double* vtkLineRepresentation::GetPoint1WorldPosition()
285 {
286 return this->Point1Representation->GetWorldPosition();
287 }
288
289 //------------------------------------------------------------------------------
GetPoint1DisplayPosition(double pos[3])290 void vtkLineRepresentation::GetPoint1DisplayPosition(double pos[3])
291 {
292 this->Point1Representation->GetDisplayPosition(pos);
293 }
294
GetPoint1DisplayPosition()295 double* vtkLineRepresentation::GetPoint1DisplayPosition()
296 {
297 return this->Point1Representation->GetDisplayPosition();
298 }
299
300 //------------------------------------------------------------------------------
SetPoint1WorldPosition(double x[3])301 void vtkLineRepresentation::SetPoint1WorldPosition(double x[3])
302 {
303 this->Point1Representation->SetWorldPosition(x);
304 this->LineSource->SetPoint1(x);
305 // double p[3];
306 // this->Point1Representation->GetDisplayPosition(p);
307 // this->Point1Representation->SetDisplayPosition(p);
308 }
309
310 //------------------------------------------------------------------------------
SetPoint1DisplayPosition(double x[3])311 void vtkLineRepresentation::SetPoint1DisplayPosition(double x[3])
312 {
313 this->Point1Representation->SetDisplayPosition(x);
314 double p[3];
315 this->Point1Representation->GetWorldPosition(p);
316 this->Point1Representation->SetWorldPosition(p);
317 }
318
319 // Point2
320 //------------------------------------------------------------------------------
GetPoint2WorldPosition(double pos[3])321 void vtkLineRepresentation::GetPoint2WorldPosition(double pos[3])
322 {
323 this->Point2Representation->GetWorldPosition(pos);
324 }
325
GetPoint2WorldPosition()326 double* vtkLineRepresentation::GetPoint2WorldPosition()
327 {
328 return this->Point2Representation->GetWorldPosition();
329 }
330
331 //------------------------------------------------------------------------------
GetPoint2DisplayPosition(double pos[3])332 void vtkLineRepresentation::GetPoint2DisplayPosition(double pos[3])
333 {
334 this->Point2Representation->GetDisplayPosition(pos);
335 }
336
GetPoint2DisplayPosition()337 double* vtkLineRepresentation::GetPoint2DisplayPosition()
338 {
339 return this->Point2Representation->GetDisplayPosition();
340 }
341
342 //------------------------------------------------------------------------------
SetPoint2WorldPosition(double x[3])343 void vtkLineRepresentation::SetPoint2WorldPosition(double x[3])
344 {
345 this->Point2Representation->SetWorldPosition(x);
346 this->LineSource->SetPoint2(x);
347 // double p[3];
348 // this->Point2Representation->GetDisplayPosition(p);
349 // this->Point2Representation->SetDisplayPosition(p);
350 }
351
352 //------------------------------------------------------------------------------
SetPoint2DisplayPosition(double x[3])353 void vtkLineRepresentation::SetPoint2DisplayPosition(double x[3])
354 {
355 this->Point2Representation->SetDisplayPosition(x);
356 double p[3];
357 this->Point2Representation->GetWorldPosition(p);
358 this->Point2Representation->SetWorldPosition(p);
359 }
360
361 //------------------------------------------------------------------------------
SetRenderer(vtkRenderer * ren)362 void vtkLineRepresentation::SetRenderer(vtkRenderer* ren)
363 {
364 this->HandleRepresentation->SetRenderer(ren);
365 this->Point1Representation->SetRenderer(ren);
366 this->Point2Representation->SetRenderer(ren);
367 this->LineHandleRepresentation->SetRenderer(ren);
368 this->Superclass::SetRenderer(ren);
369 }
370
371 //------------------------------------------------------------------------------
StartWidgetInteraction(double e[2])372 void vtkLineRepresentation::StartWidgetInteraction(double e[2])
373 {
374 // Store the start position
375 this->StartEventPosition[0] = e[0];
376 this->StartEventPosition[1] = e[1];
377 this->StartEventPosition[2] = 0.0;
378
379 // Store the start position
380 this->LastEventPosition[0] = e[0];
381 this->LastEventPosition[1] = e[1];
382 this->LastEventPosition[2] = 0.0;
383
384 // Get the coordinates of the three handles
385 this->Point1Representation->GetWorldPosition(this->StartP1);
386 this->Point2Representation->GetWorldPosition(this->StartP2);
387 this->LineHandleRepresentation->GetWorldPosition(this->StartLineHandle);
388
389 if (this->InteractionState == vtkLineRepresentation::Scaling)
390 {
391 double dp1[3], dp2[3];
392 this->Point1Representation->GetDisplayPosition(dp1);
393 this->Point2Representation->GetDisplayPosition(dp2);
394 this->Length =
395 sqrt((dp1[0] - dp2[0]) * (dp1[0] - dp2[0]) + (dp1[1] - dp2[1]) * (dp1[1] - dp2[1]));
396 }
397 }
398
399 //------------------------------------------------------------------------------
WidgetInteraction(double e[2])400 void vtkLineRepresentation::WidgetInteraction(double e[2])
401 {
402 if (this->InteractionState == vtkLineRepresentation::OnLine)
403 {
404 double x[3], p1[3], p2[3];
405
406 // Get the new position
407 this->LineHandleRepresentation->GetWorldPosition(x);
408
409 // Compute the delta from the previous position
410 p1[0] = this->StartP1[0] + x[0] - this->StartLineHandle[0];
411 p1[1] = this->StartP1[1] + x[1] - this->StartLineHandle[1];
412 p1[2] = this->StartP1[2] + x[2] - this->StartLineHandle[2];
413 p2[0] = this->StartP2[0] + x[0] - this->StartLineHandle[0];
414 p2[1] = this->StartP2[1] + x[1] - this->StartLineHandle[1];
415 p2[2] = this->StartP2[2] + x[2] - this->StartLineHandle[2];
416
417 this->Point1Representation->SetWorldPosition(p1);
418 this->Point2Representation->SetWorldPosition(p2);
419 }
420
421 else if (this->InteractionState == vtkLineRepresentation::Scaling)
422 { // scale about the center of the widget
423 double p1[3], p2[3], center[3];
424
425 this->Point1Representation->GetWorldPosition(p1);
426 this->Point2Representation->GetWorldPosition(p2);
427
428 double delta =
429 sqrt((this->StartEventPosition[0] - e[0]) * (this->StartEventPosition[0] - e[0]) +
430 (this->StartEventPosition[1] - e[1]) * (this->StartEventPosition[1] - e[1]));
431
432 double sf = 1.0;
433 if (this->Length != 0.0)
434 {
435 sf = 1.0 + delta / this->Length;
436 }
437 if ((e[1] - this->LastEventPosition[1]) < 0.0)
438 {
439 sf = 1 / sf;
440 }
441
442 for (int i = 0; i < 3; i++)
443 {
444 center[i] = (p1[i] + p2[i]) / 2.0;
445 p1[i] = center[i] + (p1[i] - center[i]) * sf;
446 p2[i] = center[i] + (p2[i] - center[i]) * sf;
447 }
448 this->Point1Representation->SetWorldPosition(p1);
449 this->Point2Representation->SetWorldPosition(p2);
450 }
451
452 else if (this->InteractionState == vtkLineRepresentation::TranslatingP1)
453 {
454 double x[3], p2[3];
455 // Get the new position
456 this->Point1Representation->GetWorldPosition(x);
457 for (int i = 0; i < 3; i++)
458 {
459 p2[i] = this->StartP2[i] + (x[i] - this->StartP1[i]);
460 }
461 this->Point2Representation->SetWorldPosition(p2);
462 }
463
464 else if (this->InteractionState == vtkLineRepresentation::TranslatingP2)
465 {
466 double x[3], p1[3];
467 // Get the new position
468 this->Point2Representation->GetWorldPosition(x);
469 for (int i = 0; i < 3; i++)
470 {
471 p1[i] = this->StartP1[i] + (x[i] - this->StartP2[i]);
472 }
473 this->Point1Representation->SetWorldPosition(p1);
474 }
475
476 // Store the start position
477 this->LastEventPosition[0] = e[0];
478 this->LastEventPosition[1] = e[1];
479 this->LastEventPosition[2] = 0.0;
480 }
481
482 //------------------------------------------------------------------------------
PlaceWidget(double bds[6])483 void vtkLineRepresentation::PlaceWidget(double bds[6])
484 {
485 int i;
486 double bounds[6], center[3];
487
488 double placeFactor = this->PlaceFactor;
489 this->PlaceFactor = 1.0;
490 this->AdjustBounds(bds, bounds, center);
491 this->PlaceFactor = placeFactor;
492
493 for (i = 0; i < 6; i++)
494 {
495 this->InitialBounds[i] = bounds[i];
496 }
497 this->InitialLength = sqrt((bounds[1] - bounds[0]) * (bounds[1] - bounds[0]) +
498 (bounds[3] - bounds[2]) * (bounds[3] - bounds[2]) +
499 (bounds[5] - bounds[4]) * (bounds[5] - bounds[4]));
500
501 // When PlaceWidget() is invoked, the widget orientation is preserved, but it
502 // is allowed to translate and scale. This means it is centered in the
503 // bounding box, and the representation scales itself to intersect the sides
504 // of the bounding box. Thus we have to determine where Point1 and Point2
505 // intersect the bounding box.
506 double p1[3], p2[3], r[3], o[3], t, placedP1[3], placedP2[3];
507 this->LineSource->GetPoint1(p1);
508 this->LineSource->GetPoint2(p2);
509
510 // Okay, this looks really weird, we are shooting rays from OUTSIDE
511 // the bounding box back towards it. This is because the IntersectBox()
512 // method computes intersections only if the ray originates outside the
513 // bounding box.
514 r[0] = this->InitialLength * (p1[0] - p2[0]);
515 r[1] = this->InitialLength * (p1[1] - p2[1]);
516 r[2] = this->InitialLength * (p1[2] - p2[2]);
517 o[0] = center[0] - r[0];
518 o[1] = center[1] - r[1];
519 o[2] = center[2] - r[2];
520 vtkBox::IntersectBox(bounds, o, r, placedP1, t);
521 this->SetPoint1WorldPosition(placedP1);
522
523 r[0] = this->InitialLength * (p2[0] - p1[0]);
524 r[1] = this->InitialLength * (p2[1] - p1[1]);
525 r[2] = this->InitialLength * (p2[2] - p1[2]);
526 o[0] = center[0] - r[0];
527 o[1] = center[1] - r[1];
528 o[2] = center[2] - r[2];
529 vtkBox::IntersectBox(bounds, o, r, placedP2, t);
530 this->SetPoint2WorldPosition(placedP2);
531
532 // Initialize the center point
533 this->LineHandleRepresentation->SetWorldPosition(center);
534
535 // Position the handles at the end of the lines
536 this->Placed = 1;
537 this->ValidPick = 1;
538 this->BuildRepresentation();
539 }
540
541 //------------------------------------------------------------------------------
ComputeInteractionState(int x,int y,int vtkNotUsed (modify))542 int vtkLineRepresentation::ComputeInteractionState(int x, int y, int vtkNotUsed(modify))
543 {
544 // Check if we are on end points. Use the handles to determine this.
545 int p1State = this->Point1Representation->ComputeInteractionState(x, y, 0);
546 int p2State = this->Point2Representation->ComputeInteractionState(x, y, 0);
547 if (p1State == vtkHandleRepresentation::Nearby)
548 {
549 this->InteractionState = vtkLineRepresentation::OnP1;
550 this->SetRepresentationState(vtkLineRepresentation::OnP1);
551 }
552 else if (p2State == vtkHandleRepresentation::Nearby)
553 {
554 this->InteractionState = vtkLineRepresentation::OnP2;
555 this->SetRepresentationState(vtkLineRepresentation::OnP2);
556 }
557 else
558 {
559 this->InteractionState = vtkLineRepresentation::Outside;
560 }
561
562 // Okay if we're near a handle return, otherwise test the line
563 if (this->InteractionState != vtkLineRepresentation::Outside)
564 {
565 return this->InteractionState;
566 }
567
568 // Check if we are on edges
569 double pos1[3], pos2[3];
570 this->GetPoint1DisplayPosition(pos1);
571 this->GetPoint2DisplayPosition(pos2);
572
573 double p1[3], p2[3], xyz[3];
574 double t, closest[3];
575 xyz[0] = static_cast<double>(x);
576 xyz[1] = static_cast<double>(y);
577 p1[0] = static_cast<double>(pos1[0]);
578 p1[1] = static_cast<double>(pos1[1]);
579 p2[0] = static_cast<double>(pos2[0]);
580 p2[1] = static_cast<double>(pos2[1]);
581 xyz[2] = p1[2] = p2[2] = 0.0;
582
583 double tol2 = this->Tolerance * this->Tolerance;
584
585 int onLine = (vtkLine::DistanceToLine(xyz, p1, p2, t, closest) <= tol2);
586 if (onLine && t < 1.0 && t > 0.0)
587 {
588 this->InteractionState = vtkLineRepresentation::OnLine;
589 this->SetRepresentationState(vtkLineRepresentation::OnLine);
590 this->GetPoint1WorldPosition(pos1);
591 this->GetPoint2WorldPosition(pos2);
592
593 this->LinePicker->Pick(x, y, 0.0, this->Renderer);
594 this->LinePicker->GetPickPosition(closest);
595 this->LineHandleRepresentation->SetWorldPosition(closest);
596 }
597 else
598 {
599 this->InteractionState = vtkLineRepresentation::Outside;
600 this->SetRepresentationState(vtkLineRepresentation::Outside);
601 }
602
603 return this->InteractionState;
604 }
605
606 //------------------------------------------------------------------------------
SetRepresentationState(int state)607 void vtkLineRepresentation::SetRepresentationState(int state)
608 {
609 if (this->RepresentationState == state)
610 {
611 return;
612 }
613
614 state = (state < vtkLineRepresentation::Outside
615 ? vtkLineRepresentation::Outside
616 : (state > vtkLineRepresentation::Scaling ? vtkLineRepresentation::Scaling : state));
617
618 this->RepresentationState = state;
619 this->Modified();
620
621 if (state == vtkLineRepresentation::Outside)
622 {
623 this->HighlightPoint(0, 0);
624 this->HighlightPoint(1, 0);
625 this->HighlightLine(0);
626 }
627 else if (state == vtkLineRepresentation::OnP1)
628 {
629 this->HighlightPoint(0, 1);
630 this->HighlightPoint(1, 0);
631 this->HighlightLine(0);
632 }
633 else if (state == vtkLineRepresentation::OnP2)
634 {
635 this->HighlightPoint(0, 0);
636 this->HighlightPoint(1, 1);
637 this->HighlightLine(0);
638 }
639 else if (state == vtkLineRepresentation::OnLine)
640 {
641 this->HighlightPoint(0, 0);
642 this->HighlightPoint(1, 0);
643 this->HighlightLine(1);
644 }
645 else
646 {
647 this->HighlightPoint(0, 1);
648 this->HighlightPoint(1, 1);
649 this->HighlightLine(1);
650 }
651 }
652
653 //------------------------------------------------------------------------------
GetBounds()654 double* vtkLineRepresentation::GetBounds()
655 {
656 this->BuildRepresentation();
657 this->BoundingBox->SetBounds(this->LineActor->GetBounds());
658 this->BoundingBox->AddBounds(this->Handle[0]->GetBounds());
659 this->BoundingBox->AddBounds(this->Handle[1]->GetBounds());
660
661 return this->BoundingBox->GetBounds();
662 }
663
664 //------------------------------------------------------------------------------
CreateDefaultProperties()665 void vtkLineRepresentation::CreateDefaultProperties()
666 {
667 // Endpoint properties
668 this->EndPointProperty = vtkProperty::New();
669 this->EndPointProperty->SetColor(1, 1, 1);
670
671 this->SelectedEndPointProperty = vtkProperty::New();
672 this->SelectedEndPointProperty->SetColor(0, 1, 0);
673
674 this->EndPoint2Property = vtkProperty::New();
675 this->EndPoint2Property->SetColor(1, 1, 1);
676
677 this->SelectedEndPoint2Property = vtkProperty::New();
678 this->SelectedEndPoint2Property->SetColor(0, 1, 0);
679
680 // Line properties
681 this->LineProperty = vtkProperty::New();
682 this->LineProperty->SetAmbient(1.0);
683 this->LineProperty->SetAmbientColor(1.0, 1.0, 1.0);
684 this->LineProperty->SetLineWidth(2.0);
685
686 this->SelectedLineProperty = vtkProperty::New();
687 this->SelectedLineProperty->SetAmbient(1.0);
688 this->SelectedLineProperty->SetAmbientColor(0.0, 1.0, 0.0);
689 this->SelectedLineProperty->SetLineWidth(2.0);
690 }
691
692 //------------------------------------------------------------------------------
SizeHandles()693 void vtkLineRepresentation::SizeHandles()
694 {
695 // The SizeHandles() method depends on the LastPickPosition data member.
696 double radius =
697 this->vtkWidgetRepresentation::SizeHandlesInPixels(1.35, this->LineSource->GetPoint1());
698 static_cast<vtkSphereSource*>(this->HandleGeometry[0])->SetRadius(radius);
699
700 radius = this->vtkWidgetRepresentation::SizeHandlesInPixels(1.35, this->LineSource->GetPoint2());
701 if (this->DirectionalLine)
702 {
703 static_cast<vtkConeSource*>(this->HandleGeometry[1])->SetRadius(radius);
704 static_cast<vtkConeSource*>(this->HandleGeometry[1])->SetHeight(2.8 * radius);
705 }
706 else
707 {
708 static_cast<vtkSphereSource*>(this->HandleGeometry[1])->SetRadius(radius);
709 }
710 }
711
712 //------------------------------------------------------------------------------
BuildRepresentation()713 void vtkLineRepresentation::BuildRepresentation()
714 {
715 // Rebuild only if necessary
716 if (this->GetMTime() > this->BuildTime ||
717 this->Point1Representation->GetMTime() > this->BuildTime ||
718 this->Point2Representation->GetMTime() > this->BuildTime ||
719 this->LineHandleRepresentation->GetMTime() > this->BuildTime ||
720 (this->Renderer && this->Renderer->GetVTKWindow() &&
721 (this->Renderer->GetVTKWindow()->GetMTime() > this->BuildTime ||
722 this->Renderer->GetActiveCamera()->GetMTime() > this->BuildTime)))
723 {
724 if (!this->InitializedDisplayPosition && this->Renderer)
725 {
726 this->SetPoint1WorldPosition(this->LineSource->GetPoint1());
727 this->SetPoint2WorldPosition(this->LineSource->GetPoint2());
728 this->ValidPick = 1;
729 this->InitializedDisplayPosition = 1;
730 }
731
732 // Make sure that tolerance is consistent between handles and this representation
733 this->Point1Representation->SetTolerance(this->Tolerance);
734 this->Point2Representation->SetTolerance(this->Tolerance);
735 this->LineHandleRepresentation->SetTolerance(this->Tolerance);
736
737 // Retrieve end point information
738 double x1[3], x2[3];
739 this->GetPoint1WorldPosition(x1);
740
741 this->LineSource->SetPoint1(x1);
742 static_cast<vtkSphereSource*>(this->HandleGeometry[0])->SetCenter(x1);
743
744 this->GetPoint2WorldPosition(x2);
745 this->LineSource->SetPoint2(x2);
746 if (this->DirectionalLine)
747 {
748 static_cast<vtkConeSource*>(this->HandleGeometry[1])->SetCenter(x2);
749 vtkVector3d dir(x2);
750 dir = dir - vtkVector3d(x1);
751 static_cast<vtkConeSource*>(this->HandleGeometry[1])->SetDirection(dir.GetData());
752 }
753 else
754 {
755 static_cast<vtkSphereSource*>(this->HandleGeometry[1])->SetCenter(x2);
756 }
757
758 this->Distance = sqrt(vtkMath::Distance2BetweenPoints(x1, x2));
759
760 // Place the DistanceAnnotation right in between the two points.
761 double x[3] = { (x1[0] + x2[0]) / 2.0, (x1[1] + x2[1]) / 2.0, (x1[2] + x2[2]) / 2.0 };
762 char string[512];
763 snprintf(string, sizeof(string), this->DistanceAnnotationFormat, this->Distance);
764 this->TextInput->SetText(string);
765 this->TextActor->SetPosition(x);
766 if (this->Renderer)
767 {
768 this->TextActor->SetCamera(this->Renderer->GetActiveCamera());
769 }
770
771 if (!this->AnnotationTextScaleInitialized)
772 {
773 // If a font size hasn't been specified by the user, scale the text
774 // (font size) according to the length of the line widget.
775 this->TextActor->SetScale(
776 this->Distance / 10.0, this->Distance / 10.0, this->Distance / 10.0);
777 }
778
779 this->SizeHandles();
780 this->BuildTime.Modified();
781 }
782 }
783
784 //------------------------------------------------------------------------------
HighlightPoint(int ptId,int highlight)785 void vtkLineRepresentation::HighlightPoint(int ptId, int highlight)
786 {
787 if (ptId == 0)
788 {
789 if (highlight)
790 {
791 this->Handle[0]->SetProperty(this->SelectedEndPointProperty);
792 this->Point1Representation->SetSelectedProperty(this->SelectedEndPointProperty);
793 }
794 else
795 {
796 this->Handle[0]->SetProperty(this->EndPointProperty);
797 this->Point1Representation->SetProperty(this->EndPointProperty);
798 }
799 }
800 else if (ptId == 1)
801 {
802 if (highlight)
803 {
804 this->Handle[1]->SetProperty(this->SelectedEndPoint2Property);
805 this->Point2Representation->SetSelectedProperty(this->SelectedEndPoint2Property);
806 }
807 else
808 {
809 this->Handle[1]->SetProperty(this->EndPoint2Property);
810 this->Point2Representation->SetProperty(this->EndPoint2Property);
811 }
812 }
813 else // if ( ptId == 2 )
814 {
815 if (highlight)
816 {
817 this->LineHandleRepresentation->SetSelectedProperty(this->SelectedEndPointProperty);
818 }
819 else
820 {
821 this->LineHandleRepresentation->SetProperty(this->EndPointProperty);
822 }
823 }
824 }
825
826 //------------------------------------------------------------------------------
HighlightLine(int highlight)827 void vtkLineRepresentation::HighlightLine(int highlight)
828 {
829 if (highlight)
830 {
831 this->LineActor->SetProperty(this->SelectedLineProperty);
832 }
833 else
834 {
835 this->LineActor->SetProperty(this->LineProperty);
836 }
837 }
838
839 //------------------------------------------------------------------------------
SetLineColor(double r,double g,double b)840 void vtkLineRepresentation::SetLineColor(double r, double g, double b)
841 {
842 if (this->GetLineProperty())
843 {
844 this->GetLineProperty()->SetColor(r, g, b);
845 }
846 }
847
848 //------------------------------------------------------------------------------
ClampPosition(double x[3])849 void vtkLineRepresentation::ClampPosition(double x[3])
850 {
851 for (int i = 0; i < 3; i++)
852 {
853 if (x[i] < this->InitialBounds[2 * i])
854 {
855 x[i] = this->InitialBounds[2 * i];
856 }
857 if (x[i] > this->InitialBounds[2 * i + 1])
858 {
859 x[i] = this->InitialBounds[2 * i + 1];
860 }
861 }
862 }
863
864 //------------------------------------------------------------------------------
InBounds(double x[3])865 int vtkLineRepresentation::InBounds(double x[3])
866 {
867 for (int i = 0; i < 3; i++)
868 {
869 if (x[i] < this->InitialBounds[2 * i] || x[i] > this->InitialBounds[2 * i + 1])
870 {
871 return 0;
872 }
873 }
874 return 1;
875 }
876
877 //------------------------------------------------------------------------------
GetActors(vtkPropCollection * pc)878 void vtkLineRepresentation::GetActors(vtkPropCollection* pc)
879 {
880 this->LineActor->GetActors(pc);
881 this->Handle[0]->GetActors(pc);
882 this->Handle[1]->GetActors(pc);
883 this->TextActor->GetActors(pc);
884 }
885
886 //------------------------------------------------------------------------------
ReleaseGraphicsResources(vtkWindow * w)887 void vtkLineRepresentation::ReleaseGraphicsResources(vtkWindow* w)
888 {
889 this->LineActor->ReleaseGraphicsResources(w);
890 this->Handle[0]->ReleaseGraphicsResources(w);
891 this->Handle[1]->ReleaseGraphicsResources(w);
892 this->TextActor->ReleaseGraphicsResources(w);
893 }
894
895 //------------------------------------------------------------------------------
RenderOpaqueGeometry(vtkViewport * v)896 int vtkLineRepresentation::RenderOpaqueGeometry(vtkViewport* v)
897 {
898 int count = 0;
899 this->BuildRepresentation();
900 count += this->LineActor->RenderOpaqueGeometry(v);
901 count += this->Handle[0]->RenderOpaqueGeometry(v);
902 count += this->Handle[1]->RenderOpaqueGeometry(v);
903 if (this->DistanceAnnotationVisibility)
904 {
905 count += this->TextActor->RenderOpaqueGeometry(v);
906 }
907
908 return count;
909 }
910
911 //------------------------------------------------------------------------------
RenderTranslucentPolygonalGeometry(vtkViewport * v)912 int vtkLineRepresentation::RenderTranslucentPolygonalGeometry(vtkViewport* v)
913 {
914 int count = 0;
915 this->BuildRepresentation();
916 count += this->LineActor->RenderTranslucentPolygonalGeometry(v);
917 count += this->Handle[0]->RenderTranslucentPolygonalGeometry(v);
918 count += this->Handle[1]->RenderTranslucentPolygonalGeometry(v);
919 if (this->DistanceAnnotationVisibility)
920 {
921 count += this->TextActor->RenderTranslucentPolygonalGeometry(v);
922 }
923
924 return count;
925 }
926
927 //------------------------------------------------------------------------------
HasTranslucentPolygonalGeometry()928 vtkTypeBool vtkLineRepresentation::HasTranslucentPolygonalGeometry()
929 {
930 int result = 0;
931 this->BuildRepresentation();
932 result |= this->LineActor->HasTranslucentPolygonalGeometry();
933 result |= this->Handle[0]->HasTranslucentPolygonalGeometry();
934 result |= this->Handle[1]->HasTranslucentPolygonalGeometry();
935 if (this->DistanceAnnotationVisibility)
936 {
937 result |= this->TextActor->HasTranslucentPolygonalGeometry();
938 }
939
940 return result;
941 }
942
943 //------------------------------------------------------------------------------
GetMTime()944 vtkMTimeType vtkLineRepresentation::GetMTime()
945 {
946 vtkMTimeType mTime = this->Superclass::GetMTime();
947 vtkMTimeType mTime2 = this->Point1Representation->GetMTime();
948 mTime = (mTime2 > mTime ? mTime2 : mTime);
949 mTime2 = this->Point2Representation->GetMTime();
950 mTime = (mTime2 > mTime ? mTime2 : mTime);
951 mTime2 = this->LineHandleRepresentation->GetMTime();
952 mTime = (mTime2 > mTime ? mTime2 : mTime);
953
954 return mTime;
955 }
956
957 //------------------------------------------------------------------------------
SetRestrictFlag(int restrict_flag)958 void vtkLineRepresentation::SetRestrictFlag(int restrict_flag)
959 {
960 VTK_LEGACY_BODY(vtkLineRepresentation::SetRestricFlag, "VTK 9");
961 this->GetPoint1Representation()->SetTranslationAxis(restrict_flag - 1);
962 this->GetPoint2Representation()->SetTranslationAxis(restrict_flag - 1);
963 this->GetLineHandleRepresentation()->SetTranslationAxis(restrict_flag - 1);
964 }
965
966 //------------------------------------------------------------------------------
SetDistanceAnnotationScale(double scale[3])967 void vtkLineRepresentation::SetDistanceAnnotationScale(double scale[3])
968 {
969 this->TextActor->SetScale(scale);
970 this->AnnotationTextScaleInitialized = true;
971 }
972
973 //------------------------------------------------------------------------------
GetDistanceAnnotationScale()974 double* vtkLineRepresentation::GetDistanceAnnotationScale()
975 {
976 return this->TextActor->GetScale();
977 }
978
979 //------------------------------------------------------------------------------
GetDistanceAnnotationProperty()980 vtkProperty* vtkLineRepresentation::GetDistanceAnnotationProperty()
981 {
982 return this->TextActor->GetProperty();
983 }
984
985 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)986 void vtkLineRepresentation::PrintSelf(ostream& os, vtkIndent indent)
987 {
988 this->Superclass::PrintSelf(os, indent);
989
990 if (this->LineProperty)
991 {
992 os << indent << "Line Property: " << this->LineProperty << "\n";
993 }
994 else
995 {
996 os << indent << "Line Property: (none)\n";
997 }
998 if (this->SelectedLineProperty)
999 {
1000 os << indent << "Selected Line Property: " << this->SelectedLineProperty << "\n";
1001 }
1002 else
1003 {
1004 os << indent << "Selected Line Property: (none)\n";
1005 }
1006
1007 if (this->EndPointProperty)
1008 {
1009 os << indent << "End Point Property: " << this->EndPointProperty << "\n";
1010 }
1011 else
1012 {
1013 os << indent << "End Point Property: (none)\n";
1014 }
1015 if (this->SelectedEndPointProperty)
1016 {
1017 os << indent << "Selected End Point Property: " << this->SelectedEndPointProperty << "\n";
1018 }
1019 else
1020 {
1021 os << indent << "Selected End Point Property: (none)\n";
1022 }
1023
1024 if (this->EndPoint2Property)
1025 {
1026 os << indent << "End Point Property: " << this->EndPoint2Property << "\n";
1027 }
1028 else
1029 {
1030 os << indent << "End Point Property: (none)\n";
1031 }
1032 if (this->SelectedEndPoint2Property)
1033 {
1034 os << indent << "Selected End Point Property: " << this->SelectedEndPoint2Property << "\n";
1035 }
1036 else
1037 {
1038 os << indent << "Selected End Point Property: (none)\n";
1039 }
1040
1041 os << indent << "Tolerance: " << this->Tolerance << "\n";
1042
1043 os << indent << "Constrain To Bounds: " << (this->ClampToBounds ? "On\n" : "Off\n");
1044
1045 int res = this->LineSource->GetResolution();
1046 double* pt1 = this->LineSource->GetPoint1();
1047 double* pt2 = this->LineSource->GetPoint2();
1048
1049 os << indent << "Resolution: " << res << "\n";
1050 os << indent << "Point 1: (" << pt1[0] << ", " << pt1[1] << ", " << pt1[2] << ")\n";
1051 os << indent << "Point 2: (" << pt2[0] << ", " << pt2[1] << ", " << pt2[2] << ")\n";
1052
1053 os << indent << "Point1 Representation: ";
1054 this->Point1Representation->PrintSelf(os, indent.GetNextIndent());
1055
1056 os << indent << "Point2 Representation: ";
1057 this->Point2Representation->PrintSelf(os, indent.GetNextIndent());
1058
1059 os << indent << "Line Handle Representation: ";
1060 this->LineHandleRepresentation->PrintSelf(os, indent.GetNextIndent());
1061
1062 os << indent << "Representation State: " << this->RepresentationState << "\n";
1063 os << indent << "Directional Line: " << this->DirectionalLine << "\n";
1064 os << "\n";
1065
1066 os << indent << "DistanceAnnotationVisibility: ";
1067 if (this->DistanceAnnotationVisibility)
1068 {
1069 os << this->DistanceAnnotationVisibility << "\n";
1070 }
1071 else
1072 {
1073 os << "(none)\n";
1074 }
1075
1076 os << indent << "DistanceAnnotationFormat: ";
1077 if (this->DistanceAnnotationFormat)
1078 {
1079 os << this->DistanceAnnotationFormat << "\n";
1080 }
1081 else
1082 {
1083 os << "(none)\n";
1084 }
1085
1086 os << indent << "TextActor: ";
1087 if (this->TextActor)
1088 {
1089 os << this->TextActor << "\n";
1090 }
1091 else
1092 {
1093 os << "(none)\n";
1094 }
1095
1096 // this->InteractionState is printed in superclass
1097 // this is commented to avoid PrintSelf errors
1098 }
1099