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