1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkImplicitCylinderRepresentation.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 "vtkImplicitCylinderRepresentation.h"
16 
17 #include "vtkActor.h"
18 #include "vtkAssemblyNode.h"
19 #include "vtkAssemblyPath.h"
20 #include "vtkBox.h"
21 #include "vtkCallbackCommand.h"
22 #include "vtkCamera.h"
23 #include "vtkCellArray.h"
24 #include "vtkCellPicker.h"
25 #include "vtkCommand.h"
26 #include "vtkConeSource.h"
27 #include "vtkCylinder.h"
28 #include "vtkDoubleArray.h"
29 #include "vtkFeatureEdges.h"
30 #include "vtkImageData.h"
31 #include "vtkInteractorObserver.h"
32 #include "vtkLineSource.h"
33 #include "vtkLookupTable.h"
34 #include "vtkMath.h"
35 #include "vtkObjectFactory.h"
36 #include "vtkOutlineFilter.h"
37 #include "vtkPickingManager.h"
38 #include "vtkPlane.h"
39 #include "vtkPointData.h"
40 #include "vtkPoints.h"
41 #include "vtkPolyData.h"
42 #include "vtkPolyDataMapper.h"
43 #include "vtkProperty.h"
44 #include "vtkRenderWindow.h"
45 #include "vtkRenderWindowInteractor.h"
46 #include "vtkRenderer.h"
47 #include "vtkSmartPointer.h"
48 #include "vtkSphereSource.h"
49 #include "vtkTransform.h"
50 #include "vtkTubeFilter.h"
51 #include "vtkWindow.h"
52 
53 #include <algorithm>
54 #include <cfloat> //for FLT_EPSILON
55 
56 vtkStandardNewMacro(vtkImplicitCylinderRepresentation);
57 
58 //------------------------------------------------------------------------------
vtkImplicitCylinderRepresentation()59 vtkImplicitCylinderRepresentation::vtkImplicitCylinderRepresentation()
60 {
61   this->AlongXAxis = 0;
62   this->AlongYAxis = 0;
63   this->AlongZAxis = 0;
64 
65   // Handle size is in pixels for this widget
66   this->HandleSize = 5.0;
67 
68   // Pushing operation
69   this->BumpDistance = 0.01;
70 
71   // Build the representation of the widget
72   //
73   this->Cylinder = vtkCylinder::New();
74   this->Cylinder->SetAxis(0, 0, 1);
75   this->Cylinder->SetCenter(0, 0, 0);
76   this->Cylinder->SetRadius(0.5);
77 
78   this->MinRadius = 0.01;
79   this->MaxRadius = 1.00;
80 
81   this->Resolution = 128;
82 
83   this->Box = vtkImageData::New();
84   this->Box->SetDimensions(2, 2, 2);
85   this->Outline = vtkOutlineFilter::New();
86   this->Outline->SetInputData(this->Box);
87   this->OutlineMapper = vtkPolyDataMapper::New();
88   this->OutlineMapper->SetInputConnection(this->Outline->GetOutputPort());
89   this->OutlineActor = vtkActor::New();
90   this->OutlineActor->SetMapper(this->OutlineMapper);
91   this->OutlineTranslation = 1;
92   this->ScaleEnabled = 1;
93   this->OutsideBounds = 1;
94   this->ConstrainToWidgetBounds = 1;
95 
96   this->Cyl = vtkPolyData::New();
97   vtkPoints* pts = vtkPoints::New();
98   pts->SetDataTypeToDouble();
99   this->Cyl->SetPoints(pts);
100   pts->Delete();
101   vtkCellArray* polys = vtkCellArray::New();
102   this->Cyl->SetPolys(polys);
103   polys->Delete();
104   vtkDoubleArray* normals = vtkDoubleArray::New();
105   normals->SetNumberOfComponents(3);
106   this->Cyl->GetPointData()->SetNormals(normals);
107   normals->Delete();
108   this->CylMapper = vtkPolyDataMapper::New();
109   this->CylMapper->SetInputData(this->Cyl);
110   this->CylActor = vtkActor::New();
111   this->CylActor->SetMapper(this->CylMapper);
112   this->DrawCylinder = 1;
113 
114   this->Edges = vtkFeatureEdges::New();
115   this->Edges->SetInputData(this->Cyl);
116   this->EdgesTuber = vtkTubeFilter::New();
117   this->EdgesTuber->SetInputConnection(this->Edges->GetOutputPort());
118   this->EdgesTuber->SetNumberOfSides(12);
119   this->EdgesMapper = vtkPolyDataMapper::New();
120   this->EdgesMapper->SetInputConnection(this->EdgesTuber->GetOutputPort());
121   this->EdgesActor = vtkActor::New();
122   this->EdgesActor->SetMapper(this->EdgesMapper);
123   this->Tubing = 1; // control whether tubing is on
124 
125   // Create the + cylinder axis
126   this->LineSource = vtkLineSource::New();
127   this->LineSource->SetResolution(1);
128   this->LineMapper = vtkPolyDataMapper::New();
129   this->LineMapper->SetInputConnection(this->LineSource->GetOutputPort());
130   this->LineActor = vtkActor::New();
131   this->LineActor->SetMapper(this->LineMapper);
132 
133   this->ConeSource = vtkConeSource::New();
134   this->ConeSource->SetResolution(12);
135   this->ConeSource->SetAngle(25.0);
136   this->ConeMapper = vtkPolyDataMapper::New();
137   this->ConeMapper->SetInputConnection(this->ConeSource->GetOutputPort());
138   this->ConeActor = vtkActor::New();
139   this->ConeActor->SetMapper(this->ConeMapper);
140 
141   // Create the - cylinder axis
142   this->LineSource2 = vtkLineSource::New();
143   this->LineSource2->SetResolution(1);
144   this->LineMapper2 = vtkPolyDataMapper::New();
145   this->LineMapper2->SetInputConnection(this->LineSource2->GetOutputPort());
146   this->LineActor2 = vtkActor::New();
147   this->LineActor2->SetMapper(this->LineMapper2);
148 
149   this->ConeSource2 = vtkConeSource::New();
150   this->ConeSource2->SetResolution(12);
151   this->ConeSource2->SetAngle(25.0);
152   this->ConeMapper2 = vtkPolyDataMapper::New();
153   this->ConeMapper2->SetInputConnection(this->ConeSource2->GetOutputPort());
154   this->ConeActor2 = vtkActor::New();
155   this->ConeActor2->SetMapper(this->ConeMapper2);
156 
157   // Create the center handle
158   this->Sphere = vtkSphereSource::New();
159   this->Sphere->SetThetaResolution(16);
160   this->Sphere->SetPhiResolution(8);
161   this->SphereMapper = vtkPolyDataMapper::New();
162   this->SphereMapper->SetInputConnection(this->Sphere->GetOutputPort());
163   this->SphereActor = vtkActor::New();
164   this->SphereActor->SetMapper(this->SphereMapper);
165 
166   this->Transform = vtkTransform::New();
167 
168   // Define the point coordinates
169   double bounds[6];
170   bounds[0] = -0.5;
171   bounds[1] = 0.5;
172   bounds[2] = -0.5;
173   bounds[3] = 0.5;
174   bounds[4] = -0.5;
175   bounds[5] = 0.5;
176 
177   // Initial creation of the widget, serves to initialize it
178   this->PlaceWidget(bounds);
179 
180   // Manage the picking stuff
181   this->Picker = vtkCellPicker::New();
182   this->Picker->SetTolerance(0.005);
183   this->Picker->AddPickList(this->LineActor);
184   this->Picker->AddPickList(this->ConeActor);
185   this->Picker->AddPickList(this->LineActor2);
186   this->Picker->AddPickList(this->ConeActor2);
187   this->Picker->AddPickList(this->SphereActor);
188   this->Picker->AddPickList(this->OutlineActor);
189   this->Picker->PickFromListOn();
190 
191   this->CylPicker = vtkCellPicker::New();
192   this->CylPicker->SetTolerance(0.005);
193   this->CylPicker->AddPickList(this->CylActor);
194   this->CylPicker->AddPickList(this->EdgesActor);
195   this->CylPicker->PickFromListOn();
196 
197   // Set up the initial properties
198   this->CreateDefaultProperties();
199 
200   // Pass the initial properties to the actors.
201   this->LineActor->SetProperty(this->AxisProperty);
202   this->ConeActor->SetProperty(this->AxisProperty);
203   this->LineActor2->SetProperty(this->AxisProperty);
204   this->ConeActor2->SetProperty(this->AxisProperty);
205   this->SphereActor->SetProperty(this->AxisProperty);
206   this->CylActor->SetProperty(this->CylinderProperty);
207   this->OutlineActor->SetProperty(this->OutlineProperty);
208 
209   // The bounding box
210   this->BoundingBox = vtkBox::New();
211 
212   this->RepresentationState = vtkImplicitCylinderRepresentation::Outside;
213 
214   this->TranslationAxis = Axis::NONE;
215 }
216 
217 //------------------------------------------------------------------------------
~vtkImplicitCylinderRepresentation()218 vtkImplicitCylinderRepresentation::~vtkImplicitCylinderRepresentation()
219 {
220   this->Cylinder->Delete();
221   this->Box->Delete();
222   this->Outline->Delete();
223   this->OutlineMapper->Delete();
224   this->OutlineActor->Delete();
225 
226   this->Cyl->Delete();
227   this->CylMapper->Delete();
228   this->CylActor->Delete();
229 
230   this->Edges->Delete();
231   this->EdgesTuber->Delete();
232   this->EdgesMapper->Delete();
233   this->EdgesActor->Delete();
234 
235   this->LineSource->Delete();
236   this->LineMapper->Delete();
237   this->LineActor->Delete();
238 
239   this->ConeSource->Delete();
240   this->ConeMapper->Delete();
241   this->ConeActor->Delete();
242 
243   this->LineSource2->Delete();
244   this->LineMapper2->Delete();
245   this->LineActor2->Delete();
246 
247   this->ConeSource2->Delete();
248   this->ConeMapper2->Delete();
249   this->ConeActor2->Delete();
250 
251   this->Sphere->Delete();
252   this->SphereMapper->Delete();
253   this->SphereActor->Delete();
254 
255   this->Transform->Delete();
256 
257   this->Picker->Delete();
258   this->CylPicker->Delete();
259 
260   this->AxisProperty->Delete();
261   this->SelectedAxisProperty->Delete();
262   this->CylinderProperty->Delete();
263   this->SelectedCylinderProperty->Delete();
264   this->OutlineProperty->Delete();
265   this->SelectedOutlineProperty->Delete();
266   this->EdgesProperty->Delete();
267   this->BoundingBox->Delete();
268 }
269 
270 //------------------------------------------------------------------------------
ComputeInteractionState(int X,int Y,int vtkNotUsed (modify))271 int vtkImplicitCylinderRepresentation::ComputeInteractionState(int X, int Y, int vtkNotUsed(modify))
272 {
273   // See if anything has been selected
274   vtkAssemblyPath* path = this->GetAssemblyPath(X, Y, 0., this->Picker);
275 
276   // The second picker may need to be called. This is done because the cylinder
277   // wraps around things that can be picked; thus the cylinder is the selection
278   // of last resort.
279   if (path == nullptr)
280   {
281     this->CylPicker->Pick(X, Y, 0., this->Renderer);
282     path = this->CylPicker->GetPath();
283   }
284 
285   if (path == nullptr) // Nothing picked
286   {
287     this->SetRepresentationState(vtkImplicitCylinderRepresentation::Outside);
288     this->InteractionState = vtkImplicitCylinderRepresentation::Outside;
289     return this->InteractionState;
290   }
291 
292   // Something picked, continue
293   this->ValidPick = 1;
294 
295   // Depending on the interaction state (set by the widget) we modify
296   // this state based on what is picked.
297   if (this->InteractionState == vtkImplicitCylinderRepresentation::Moving)
298   {
299     vtkProp* prop = path->GetFirstNode()->GetViewProp();
300     if (prop == this->ConeActor || prop == this->LineActor || prop == this->ConeActor2 ||
301       prop == this->LineActor2)
302     {
303       this->InteractionState = vtkImplicitCylinderRepresentation::RotatingAxis;
304       this->SetRepresentationState(vtkImplicitCylinderRepresentation::RotatingAxis);
305     }
306     else if (prop == this->CylActor || prop == EdgesActor)
307     {
308       this->InteractionState = vtkImplicitCylinderRepresentation::AdjustingRadius;
309       this->SetRepresentationState(vtkImplicitCylinderRepresentation::AdjustingRadius);
310     }
311     else if (prop == this->SphereActor)
312     {
313       this->InteractionState = vtkImplicitCylinderRepresentation::MovingCenter;
314       this->SetRepresentationState(vtkImplicitCylinderRepresentation::MovingCenter);
315     }
316     else
317     {
318       if (this->OutlineTranslation)
319       {
320         this->InteractionState = vtkImplicitCylinderRepresentation::MovingOutline;
321         this->SetRepresentationState(vtkImplicitCylinderRepresentation::MovingOutline);
322       }
323       else
324       {
325         this->InteractionState = vtkImplicitCylinderRepresentation::Outside;
326         this->SetRepresentationState(vtkImplicitCylinderRepresentation::Outside);
327       }
328     }
329   }
330 
331   // We may add a condition to allow the camera to work IO scaling
332   else if (this->InteractionState != vtkImplicitCylinderRepresentation::Scaling)
333   {
334     this->InteractionState = vtkImplicitCylinderRepresentation::Outside;
335   }
336 
337   return this->InteractionState;
338 }
339 
340 //------------------------------------------------------------------------------
SetRepresentationState(int state)341 void vtkImplicitCylinderRepresentation::SetRepresentationState(int state)
342 {
343   if (this->RepresentationState == state)
344   {
345     return;
346   }
347 
348   // Clamp the state
349   state = (state < vtkImplicitCylinderRepresentation::Outside
350       ? vtkImplicitCylinderRepresentation::Outside
351       : (state > vtkImplicitCylinderRepresentation::Scaling
352             ? vtkImplicitCylinderRepresentation::Scaling
353             : state));
354 
355   this->RepresentationState = state;
356   this->Modified();
357 
358   if (state == vtkImplicitCylinderRepresentation::RotatingAxis)
359   {
360     this->HighlightNormal(1);
361     this->HighlightCylinder(1);
362   }
363   else if (state == vtkImplicitCylinderRepresentation::AdjustingRadius)
364   {
365     this->HighlightCylinder(1);
366   }
367   else if (state == vtkImplicitCylinderRepresentation::MovingCenter)
368   {
369     this->HighlightNormal(1);
370   }
371   else if (state == vtkImplicitCylinderRepresentation::MovingOutline)
372   {
373     this->HighlightOutline(1);
374   }
375   else if (state == vtkImplicitCylinderRepresentation::Scaling && this->ScaleEnabled)
376   {
377     this->HighlightNormal(1);
378     this->HighlightCylinder(1);
379     this->HighlightOutline(1);
380   }
381   else if (state == vtkImplicitCylinderRepresentation::TranslatingCenter)
382   {
383     this->HighlightNormal(1);
384   }
385   else
386   {
387     this->HighlightNormal(0);
388     this->HighlightCylinder(0);
389     this->HighlightOutline(0);
390   }
391 }
392 
393 //------------------------------------------------------------------------------
StartWidgetInteraction(double e[2])394 void vtkImplicitCylinderRepresentation::StartWidgetInteraction(double e[2])
395 {
396   this->StartEventPosition[0] = e[0];
397   this->StartEventPosition[1] = e[1];
398   this->StartEventPosition[2] = 0.0;
399 
400   this->LastEventPosition[0] = e[0];
401   this->LastEventPosition[1] = e[1];
402   this->LastEventPosition[2] = 0.0;
403 }
404 
405 //------------------------------------------------------------------------------
WidgetInteraction(double e[2])406 void vtkImplicitCylinderRepresentation::WidgetInteraction(double e[2])
407 {
408   // Do different things depending on state
409   // Calculations everybody does
410   double focalPoint[4], pickPoint[4], prevPickPoint[4];
411   double z, vpn[3];
412 
413   vtkCamera* camera = this->Renderer->GetActiveCamera();
414   if (!camera)
415   {
416     return;
417   }
418 
419   // Compute the two points defining the motion vector
420   double pos[3];
421   this->Picker->GetPickPosition(pos);
422   vtkInteractorObserver::ComputeWorldToDisplay(this->Renderer, pos[0], pos[1], pos[2], focalPoint);
423   z = focalPoint[2];
424   vtkInteractorObserver::ComputeDisplayToWorld(
425     this->Renderer, this->LastEventPosition[0], this->LastEventPosition[1], z, prevPickPoint);
426   vtkInteractorObserver::ComputeDisplayToWorld(this->Renderer, e[0], e[1], z, pickPoint);
427 
428   // Process the motion
429   if (this->InteractionState == vtkImplicitCylinderRepresentation::MovingOutline)
430   {
431     this->TranslateOutline(prevPickPoint, pickPoint);
432   }
433   else if (this->InteractionState == vtkImplicitCylinderRepresentation::MovingCenter)
434   {
435     this->TranslateCenter(prevPickPoint, pickPoint);
436   }
437   else if (this->InteractionState == vtkImplicitCylinderRepresentation::TranslatingCenter)
438   {
439     this->TranslateCenterOnAxis(prevPickPoint, pickPoint);
440   }
441   else if (this->InteractionState == vtkImplicitCylinderRepresentation::AdjustingRadius)
442   {
443     this->AdjustRadius(e[0], e[1], prevPickPoint, pickPoint);
444   }
445   else if (this->InteractionState == vtkImplicitCylinderRepresentation::Scaling &&
446     this->ScaleEnabled)
447   {
448     this->Scale(prevPickPoint, pickPoint, e[0], e[1]);
449   }
450   else if (this->InteractionState == vtkImplicitCylinderRepresentation::RotatingAxis)
451   {
452     camera->GetViewPlaneNormal(vpn);
453     this->Rotate(e[0], e[1], prevPickPoint, pickPoint, vpn);
454   }
455 
456   this->LastEventPosition[0] = e[0];
457   this->LastEventPosition[1] = e[1];
458   this->LastEventPosition[2] = 0.0;
459 }
460 
461 //------------------------------------------------------------------------------
EndWidgetInteraction(double vtkNotUsed (e)[2])462 void vtkImplicitCylinderRepresentation::EndWidgetInteraction(double vtkNotUsed(e)[2])
463 {
464   this->SetRepresentationState(vtkImplicitCylinderRepresentation::Outside);
465 }
466 
467 //------------------------------------------------------------------------------
GetBounds()468 double* vtkImplicitCylinderRepresentation::GetBounds()
469 {
470   this->BuildRepresentation();
471   this->BoundingBox->SetBounds(this->OutlineActor->GetBounds());
472   this->BoundingBox->AddBounds(this->CylActor->GetBounds());
473   this->BoundingBox->AddBounds(this->EdgesActor->GetBounds());
474   this->BoundingBox->AddBounds(this->ConeActor->GetBounds());
475   this->BoundingBox->AddBounds(this->LineActor->GetBounds());
476   this->BoundingBox->AddBounds(this->ConeActor2->GetBounds());
477   this->BoundingBox->AddBounds(this->LineActor2->GetBounds());
478   this->BoundingBox->AddBounds(this->SphereActor->GetBounds());
479 
480   return this->BoundingBox->GetBounds();
481 }
482 
483 //------------------------------------------------------------------------------
GetActors(vtkPropCollection * pc)484 void vtkImplicitCylinderRepresentation::GetActors(vtkPropCollection* pc)
485 {
486   this->OutlineActor->GetActors(pc);
487   this->CylActor->GetActors(pc);
488   this->EdgesActor->GetActors(pc);
489   this->ConeActor->GetActors(pc);
490   this->LineActor->GetActors(pc);
491   this->ConeActor2->GetActors(pc);
492   this->LineActor2->GetActors(pc);
493   this->SphereActor->GetActors(pc);
494 }
495 
496 //------------------------------------------------------------------------------
ReleaseGraphicsResources(vtkWindow * w)497 void vtkImplicitCylinderRepresentation::ReleaseGraphicsResources(vtkWindow* w)
498 {
499   this->OutlineActor->ReleaseGraphicsResources(w);
500   this->CylActor->ReleaseGraphicsResources(w);
501   this->EdgesActor->ReleaseGraphicsResources(w);
502   this->ConeActor->ReleaseGraphicsResources(w);
503   this->LineActor->ReleaseGraphicsResources(w);
504   this->ConeActor2->ReleaseGraphicsResources(w);
505   this->LineActor2->ReleaseGraphicsResources(w);
506   this->SphereActor->ReleaseGraphicsResources(w);
507 }
508 
509 //------------------------------------------------------------------------------
RenderOpaqueGeometry(vtkViewport * v)510 int vtkImplicitCylinderRepresentation::RenderOpaqueGeometry(vtkViewport* v)
511 {
512   int count = 0;
513   this->BuildRepresentation();
514   count += this->OutlineActor->RenderOpaqueGeometry(v);
515   count += this->EdgesActor->RenderOpaqueGeometry(v);
516   count += this->ConeActor->RenderOpaqueGeometry(v);
517   count += this->LineActor->RenderOpaqueGeometry(v);
518   count += this->ConeActor2->RenderOpaqueGeometry(v);
519   count += this->LineActor2->RenderOpaqueGeometry(v);
520   count += this->SphereActor->RenderOpaqueGeometry(v);
521 
522   if (this->DrawCylinder)
523   {
524     count += this->CylActor->RenderOpaqueGeometry(v);
525   }
526 
527   return count;
528 }
529 
530 //------------------------------------------------------------------------------
RenderTranslucentPolygonalGeometry(vtkViewport * v)531 int vtkImplicitCylinderRepresentation::RenderTranslucentPolygonalGeometry(vtkViewport* v)
532 {
533   int count = 0;
534   this->BuildRepresentation();
535   count += this->OutlineActor->RenderTranslucentPolygonalGeometry(v);
536   count += this->EdgesActor->RenderTranslucentPolygonalGeometry(v);
537   count += this->ConeActor->RenderTranslucentPolygonalGeometry(v);
538   count += this->LineActor->RenderTranslucentPolygonalGeometry(v);
539   count += this->ConeActor2->RenderTranslucentPolygonalGeometry(v);
540   count += this->LineActor2->RenderTranslucentPolygonalGeometry(v);
541   count += this->SphereActor->RenderTranslucentPolygonalGeometry(v);
542 
543   if (this->DrawCylinder)
544   {
545     count += this->CylActor->RenderTranslucentPolygonalGeometry(v);
546   }
547 
548   return count;
549 }
550 
551 //------------------------------------------------------------------------------
HasTranslucentPolygonalGeometry()552 vtkTypeBool vtkImplicitCylinderRepresentation::HasTranslucentPolygonalGeometry()
553 {
554   int result = 0;
555   result |= this->OutlineActor->HasTranslucentPolygonalGeometry();
556   result |= this->EdgesActor->HasTranslucentPolygonalGeometry();
557   result |= this->ConeActor->HasTranslucentPolygonalGeometry();
558   result |= this->LineActor->HasTranslucentPolygonalGeometry();
559   result |= this->ConeActor2->HasTranslucentPolygonalGeometry();
560   result |= this->LineActor2->HasTranslucentPolygonalGeometry();
561   result |= this->SphereActor->HasTranslucentPolygonalGeometry();
562 
563   if (this->DrawCylinder)
564   {
565     result |= this->CylActor->HasTranslucentPolygonalGeometry();
566   }
567 
568   return result;
569 }
570 
571 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)572 void vtkImplicitCylinderRepresentation::PrintSelf(ostream& os, vtkIndent indent)
573 {
574   this->Superclass::PrintSelf(os, indent);
575 
576   os << indent << "Min Radius: " << this->MinRadius << "\n";
577   os << indent << "Max Radius: " << this->MaxRadius << "\n";
578 
579   os << indent << "Resolution: " << this->Resolution << "\n";
580 
581   if (this->AxisProperty)
582   {
583     os << indent << "Axis Property: " << this->AxisProperty << "\n";
584   }
585   else
586   {
587     os << indent << "Axis Property: (none)\n";
588   }
589   if (this->SelectedAxisProperty)
590   {
591     os << indent << "Selected Axis Property: " << this->SelectedAxisProperty << "\n";
592   }
593   else
594   {
595     os << indent << "Selected Axis Property: (none)\n";
596   }
597 
598   if (this->CylinderProperty)
599   {
600     os << indent << "Cylinder Property: " << this->CylinderProperty << "\n";
601   }
602   else
603   {
604     os << indent << "Cylinder Property: (none)\n";
605   }
606   if (this->SelectedCylinderProperty)
607   {
608     os << indent << "Selected Cylinder Property: " << this->SelectedCylinderProperty << "\n";
609   }
610   else
611   {
612     os << indent << "Selected Cylinder Property: (none)\n";
613   }
614 
615   if (this->OutlineProperty)
616   {
617     os << indent << "Outline Property: " << this->OutlineProperty << "\n";
618   }
619   else
620   {
621     os << indent << "Outline Property: (none)\n";
622   }
623   if (this->SelectedOutlineProperty)
624   {
625     os << indent << "Selected Outline Property: " << this->SelectedOutlineProperty << "\n";
626   }
627   else
628   {
629     os << indent << "Selected Outline Property: (none)\n";
630   }
631 
632   if (this->EdgesProperty)
633   {
634     os << indent << "Edges Property: " << this->EdgesProperty << "\n";
635   }
636   else
637   {
638     os << indent << "Edges Property: (none)\n";
639   }
640 
641   os << indent << "Along X Axis: " << (this->AlongXAxis ? "On" : "Off") << "\n";
642   os << indent << "Along Y Axis: " << (this->AlongYAxis ? "On" : "Off") << "\n";
643   os << indent << "ALong Z Axis: " << (this->AlongZAxis ? "On" : "Off") << "\n";
644 
645   os << indent << "Widget Bounds: " << this->WidgetBounds[0] << ", " << this->WidgetBounds[1]
646      << ", " << this->WidgetBounds[2] << ", " << this->WidgetBounds[3] << ", "
647      << this->WidgetBounds[4] << ", " << this->WidgetBounds[5] << "\n";
648 
649   os << indent << "Tubing: " << (this->Tubing ? "On" : "Off") << "\n";
650   os << indent << "Outline Translation: " << (this->OutlineTranslation ? "On" : "Off") << "\n";
651   os << indent << "Outside Bounds: " << (this->OutsideBounds ? "On" : "Off") << "\n";
652   os << indent << "Constrain to Widget Bounds: " << (this->ConstrainToWidgetBounds ? "On" : "Off")
653      << "\n";
654   os << indent << "Scale Enabled: " << (this->ScaleEnabled ? "On" : "Off") << "\n";
655   os << indent << "Draw Cylinder: " << (this->DrawCylinder ? "On" : "Off") << "\n";
656   os << indent << "Bump Distance: " << this->BumpDistance << "\n";
657 
658   os << indent << "Representation State: ";
659   switch (this->RepresentationState)
660   {
661     case Outside:
662       os << "Outside\n";
663       break;
664     case Moving:
665       os << "Moving\n";
666       break;
667     case MovingOutline:
668       os << "MovingOutline\n";
669       break;
670     case MovingCenter:
671       os << "MovingCenter\n";
672       break;
673     case RotatingAxis:
674       os << "RotatingAxis\n";
675       break;
676     case AdjustingRadius:
677       os << "AdjustingRadius\n";
678       break;
679     case Scaling:
680       os << "Scaling\n";
681       break;
682     case TranslatingCenter:
683       os << "TranslatingCenter\n";
684       break;
685   }
686 
687   // this->InteractionState is printed in superclass
688   // this is commented to avoid PrintSelf errors
689 }
690 
691 //------------------------------------------------------------------------------
HighlightNormal(int highlight)692 void vtkImplicitCylinderRepresentation::HighlightNormal(int highlight)
693 {
694   if (highlight)
695   {
696     this->LineActor->SetProperty(this->SelectedAxisProperty);
697     this->ConeActor->SetProperty(this->SelectedAxisProperty);
698     this->LineActor2->SetProperty(this->SelectedAxisProperty);
699     this->ConeActor2->SetProperty(this->SelectedAxisProperty);
700     this->SphereActor->SetProperty(this->SelectedAxisProperty);
701   }
702   else
703   {
704     this->LineActor->SetProperty(this->AxisProperty);
705     this->ConeActor->SetProperty(this->AxisProperty);
706     this->LineActor2->SetProperty(this->AxisProperty);
707     this->ConeActor2->SetProperty(this->AxisProperty);
708     this->SphereActor->SetProperty(this->AxisProperty);
709   }
710 }
711 
712 //------------------------------------------------------------------------------
HighlightCylinder(int highlight)713 void vtkImplicitCylinderRepresentation::HighlightCylinder(int highlight)
714 {
715   if (highlight)
716   {
717     this->CylActor->SetProperty(this->SelectedCylinderProperty);
718   }
719   else
720   {
721     this->CylActor->SetProperty(this->CylinderProperty);
722   }
723 }
724 
725 //------------------------------------------------------------------------------
HighlightOutline(int highlight)726 void vtkImplicitCylinderRepresentation::HighlightOutline(int highlight)
727 {
728   if (highlight)
729   {
730     this->OutlineActor->SetProperty(this->SelectedOutlineProperty);
731   }
732   else
733   {
734     this->OutlineActor->SetProperty(this->OutlineProperty);
735   }
736 }
737 
738 //------------------------------------------------------------------------------
Rotate(double X,double Y,double * p1,double * p2,double * vpn)739 void vtkImplicitCylinderRepresentation::Rotate(
740   double X, double Y, double* p1, double* p2, double* vpn)
741 {
742   double v[3];    // vector of motion
743   double axis[3]; // axis of rotation
744   double theta;   // rotation angle
745 
746   // mouse motion vector in world space
747   v[0] = p2[0] - p1[0];
748   v[1] = p2[1] - p1[1];
749   v[2] = p2[2] - p1[2];
750 
751   double* center = this->Cylinder->GetCenter();
752   double* cylAxis = this->Cylinder->GetAxis();
753 
754   // Create axis of rotation and angle of rotation
755   vtkMath::Cross(vpn, v, axis);
756   if (vtkMath::Normalize(axis) == 0.0)
757   {
758     return;
759   }
760   const int* size = this->Renderer->GetSize();
761   double l2 = (X - this->LastEventPosition[0]) * (X - this->LastEventPosition[0]) +
762     (Y - this->LastEventPosition[1]) * (Y - this->LastEventPosition[1]);
763   theta = 360.0 * sqrt(l2 / (size[0] * size[0] + size[1] * size[1]));
764 
765   // Manipulate the transform to reflect the rotation
766   this->Transform->Identity();
767   this->Transform->Translate(center[0], center[1], center[2]);
768   this->Transform->RotateWXYZ(theta, axis);
769   this->Transform->Translate(-center[0], -center[1], -center[2]);
770 
771   // Set the new normal
772   double aNew[3];
773   this->Transform->TransformNormal(cylAxis, aNew);
774   this->SetAxis(aNew);
775 }
776 
777 //------------------------------------------------------------------------------
778 // Loop through all points and translate them
TranslateOutline(double * p1,double * p2)779 void vtkImplicitCylinderRepresentation::TranslateOutline(double* p1, double* p2)
780 {
781   // Get the motion vector
782   double v[3] = { 0, 0, 0 };
783 
784   if (!this->IsTranslationConstrained())
785   {
786     v[0] = p2[0] - p1[0];
787     v[1] = p2[1] - p1[1];
788     v[2] = p2[2] - p1[2];
789   }
790   else
791   {
792     assert(this->TranslationAxis > -1 && this->TranslationAxis < 3 &&
793       "this->TranslationAxis out of bounds");
794     v[this->TranslationAxis] = p2[this->TranslationAxis] - p1[this->TranslationAxis];
795   }
796 
797   // Translate the bounding box
798   double* origin = this->Box->GetOrigin();
799   double oNew[3];
800   oNew[0] = origin[0] + v[0];
801   oNew[1] = origin[1] + v[1];
802   oNew[2] = origin[2] + v[2];
803   this->Box->SetOrigin(oNew);
804   this->Box->GetBounds(this->WidgetBounds);
805 
806   // Translate the cylinder
807   origin = this->Cylinder->GetCenter();
808   oNew[0] = origin[0] + v[0];
809   oNew[1] = origin[1] + v[1];
810   oNew[2] = origin[2] + v[2];
811   this->Cylinder->SetCenter(oNew);
812 
813   this->BuildRepresentation();
814 }
815 
816 //------------------------------------------------------------------------------
817 // Loop through all points and translate them
TranslateCenter(double * p1,double * p2)818 void vtkImplicitCylinderRepresentation::TranslateCenter(double* p1, double* p2)
819 {
820   // Get the motion vector
821   double v[3] = { 0, 0, 0 };
822 
823   if (!this->IsTranslationConstrained())
824   {
825     v[0] = p2[0] - p1[0];
826     v[1] = p2[1] - p1[1];
827     v[2] = p2[2] - p1[2];
828   }
829   else
830   {
831     assert(this->TranslationAxis > -1 && this->TranslationAxis < 3 &&
832       "this->TranslationAxis out of bounds");
833     v[this->TranslationAxis] = p2[this->TranslationAxis] - p1[this->TranslationAxis];
834   }
835 
836   // Add to the current point, project back down onto plane
837   double* c = this->Cylinder->GetCenter();
838   double* a = this->Cylinder->GetAxis();
839   double newCenter[3];
840 
841   newCenter[0] = c[0] + v[0];
842   newCenter[1] = c[1] + v[1];
843   newCenter[2] = c[2] + v[2];
844 
845   vtkPlane::ProjectPoint(newCenter, c, a, newCenter);
846   this->SetCenter(newCenter[0], newCenter[1], newCenter[2]);
847   this->BuildRepresentation();
848 }
849 
850 //------------------------------------------------------------------------------
851 // Translate the center on the axis
TranslateCenterOnAxis(double * p1,double * p2)852 void vtkImplicitCylinderRepresentation::TranslateCenterOnAxis(double* p1, double* p2)
853 {
854   // Get the motion vector
855   double v[3];
856   v[0] = p2[0] - p1[0];
857   v[1] = p2[1] - p1[1];
858   v[2] = p2[2] - p1[2];
859 
860   // Add to the current point, project back down onto plane
861   double* c = this->Cylinder->GetCenter();
862   double* a = this->Cylinder->GetAxis();
863   double newCenter[3];
864 
865   newCenter[0] = c[0] + v[0];
866   newCenter[1] = c[1] + v[1];
867   newCenter[2] = c[2] + v[2];
868 
869   // Normalize the axis vector
870   const double imag = 1. / std::max(1.0e-100, sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]));
871   double an[3];
872   an[0] = a[0] * imag;
873   an[1] = a[1] * imag;
874   an[2] = a[2] * imag;
875 
876   // Project the point on the axis vector
877   double u[3];
878   u[0] = newCenter[0] - c[0];
879   u[1] = newCenter[1] - c[1];
880   u[2] = newCenter[2] - c[2];
881   double dot = an[0] * u[0] + an[1] * u[1] + an[2] * u[2];
882   newCenter[0] = c[0] + an[0] * dot;
883   newCenter[1] = c[1] + an[1] * dot;
884   newCenter[2] = c[2] + an[2] * dot;
885 
886   this->SetCenter(newCenter[0], newCenter[1], newCenter[2]);
887   this->BuildRepresentation();
888 }
889 
890 //------------------------------------------------------------------------------
Scale(double * p1,double * p2,double vtkNotUsed (X),double Y)891 void vtkImplicitCylinderRepresentation::Scale(
892   double* p1, double* p2, double vtkNotUsed(X), double Y)
893 {
894   // Get the motion vector
895   double v[3];
896   v[0] = p2[0] - p1[0];
897   v[1] = p2[1] - p1[1];
898   v[2] = p2[2] - p1[2];
899 
900   double* o = this->Cylinder->GetCenter();
901 
902   // Compute the scale factor
903   double sf = vtkMath::Norm(v) / this->Outline->GetOutput()->GetLength();
904   if (Y > this->LastEventPosition[1])
905   {
906     sf = 1.0 + sf;
907   }
908   else
909   {
910     sf = 1.0 - sf;
911   }
912 
913   this->Transform->Identity();
914   this->Transform->Translate(o[0], o[1], o[2]);
915   this->Transform->Scale(sf, sf, sf);
916   this->Transform->Translate(-o[0], -o[1], -o[2]);
917 
918   double* origin = this->Box->GetOrigin();
919   double* spacing = this->Box->GetSpacing();
920   double oNew[3], p[3], pNew[3];
921   p[0] = origin[0] + spacing[0];
922   p[1] = origin[1] + spacing[1];
923   p[2] = origin[2] + spacing[2];
924 
925   this->Transform->TransformPoint(origin, oNew);
926   this->Transform->TransformPoint(p, pNew);
927 
928   this->Box->SetOrigin(oNew);
929   this->Box->SetSpacing((pNew[0] - oNew[0]), (pNew[1] - oNew[1]), (pNew[2] - oNew[2]));
930   this->Box->GetBounds(this->WidgetBounds);
931 
932   this->BuildRepresentation();
933 }
934 
935 //------------------------------------------------------------------------------
AdjustRadius(double vtkNotUsed (X),double Y,double * p1,double * p2)936 void vtkImplicitCylinderRepresentation::AdjustRadius(
937   double vtkNotUsed(X), double Y, double* p1, double* p2)
938 {
939   if (Y == this->LastEventPosition[1])
940   {
941     return;
942   }
943 
944   double dr, radius = this->Cylinder->GetRadius();
945   double v[3]; // vector of motion
946   v[0] = p2[0] - p1[0];
947   v[1] = p2[1] - p1[1];
948   v[2] = p2[2] - p1[2];
949   double l = sqrt(vtkMath::Dot(v, v));
950 
951   dr = l / 4;
952   if (Y < this->LastEventPosition[1])
953   {
954     dr *= -1.0;
955   }
956 
957   this->SetRadius(radius + dr);
958   this->BuildRepresentation();
959 }
960 
961 //------------------------------------------------------------------------------
CreateDefaultProperties()962 void vtkImplicitCylinderRepresentation::CreateDefaultProperties()
963 {
964   // Cylinder properties
965   this->CylinderProperty = vtkProperty::New();
966   this->CylinderProperty->SetAmbient(1.0);
967   this->CylinderProperty->SetAmbientColor(1.0, 1.0, 1.0);
968   this->CylinderProperty->SetOpacity(0.5);
969   this->CylActor->SetProperty(this->CylinderProperty);
970 
971   this->SelectedCylinderProperty = vtkProperty::New();
972   this->SelectedCylinderProperty->SetAmbient(1.0);
973   this->SelectedCylinderProperty->SetAmbientColor(0.0, 1.0, 0.0);
974   this->SelectedCylinderProperty->SetOpacity(0.25);
975 
976   // Cylinder axis properties
977   this->AxisProperty = vtkProperty::New();
978   this->AxisProperty->SetColor(1, 1, 1);
979   this->AxisProperty->SetLineWidth(2);
980 
981   this->SelectedAxisProperty = vtkProperty::New();
982   this->SelectedAxisProperty->SetColor(1, 0, 0);
983   this->SelectedAxisProperty->SetLineWidth(2);
984 
985   // Outline properties
986   this->OutlineProperty = vtkProperty::New();
987   this->OutlineProperty->SetAmbient(1.0);
988   this->OutlineProperty->SetAmbientColor(1.0, 1.0, 1.0);
989 
990   this->SelectedOutlineProperty = vtkProperty::New();
991   this->SelectedOutlineProperty->SetAmbient(1.0);
992   this->SelectedOutlineProperty->SetAmbientColor(0.0, 1.0, 0.0);
993 
994   // Edge property
995   this->EdgesProperty = vtkProperty::New();
996   this->EdgesProperty->SetAmbient(1.0);
997   this->EdgesProperty->SetAmbientColor(1.0, 1.0, 1.0);
998 }
999 
1000 //------------------------------------------------------------------------------
SetEdgeColor(vtkLookupTable * lut)1001 void vtkImplicitCylinderRepresentation::SetEdgeColor(vtkLookupTable* lut)
1002 {
1003   this->EdgesMapper->SetLookupTable(lut);
1004 }
1005 
1006 //------------------------------------------------------------------------------
SetEdgeColor(double r,double g,double b)1007 void vtkImplicitCylinderRepresentation::SetEdgeColor(double r, double g, double b)
1008 {
1009   vtkSmartPointer<vtkLookupTable> lookupTable = vtkSmartPointer<vtkLookupTable>::New();
1010 
1011   lookupTable->SetTableRange(0.0, 1.0);
1012   lookupTable->SetNumberOfTableValues(1);
1013   lookupTable->SetTableValue(0, r, g, b);
1014   lookupTable->Build();
1015 
1016   this->SetEdgeColor(lookupTable);
1017 }
1018 
1019 //------------------------------------------------------------------------------
SetEdgeColor(double c[3])1020 void vtkImplicitCylinderRepresentation::SetEdgeColor(double c[3])
1021 {
1022   this->SetEdgeColor(c[0], c[1], c[2]);
1023 }
1024 
1025 //------------------------------------------------------------------------------
PlaceWidget(double bds[6])1026 void vtkImplicitCylinderRepresentation::PlaceWidget(double bds[6])
1027 {
1028   int i;
1029   double bounds[6], origin[3];
1030 
1031   this->AdjustBounds(bds, bounds, origin);
1032 
1033   // Set up the bounding box
1034   this->Box->SetOrigin(bounds[0], bounds[2], bounds[4]);
1035   this->Box->SetSpacing((bounds[1] - bounds[0]), (bounds[3] - bounds[2]), (bounds[5] - bounds[4]));
1036   this->Outline->Update();
1037 
1038   this->LineSource->SetPoint1(this->Cylinder->GetCenter());
1039   if (this->AlongYAxis)
1040   {
1041     this->Cylinder->SetAxis(0, 1, 0);
1042     this->LineSource->SetPoint2(0, 1, 0);
1043   }
1044   else if (this->AlongZAxis)
1045   {
1046     this->Cylinder->SetAxis(0, 0, 1);
1047     this->LineSource->SetPoint2(0, 0, 1);
1048   }
1049   else // default or x-normal
1050   {
1051     this->Cylinder->SetAxis(1, 0, 0);
1052     this->LineSource->SetPoint2(1, 0, 0);
1053   }
1054 
1055   for (i = 0; i < 6; i++)
1056   {
1057     this->InitialBounds[i] = bounds[i];
1058     this->WidgetBounds[i] = bounds[i];
1059   }
1060 
1061   this->InitialLength = sqrt((bounds[1] - bounds[0]) * (bounds[1] - bounds[0]) +
1062     (bounds[3] - bounds[2]) * (bounds[3] - bounds[2]) +
1063     (bounds[5] - bounds[4]) * (bounds[5] - bounds[4]));
1064 
1065   this->ValidPick = 1; // since we have positioned the widget successfully
1066   this->BuildRepresentation();
1067 }
1068 
1069 //------------------------------------------------------------------------------
1070 // Set the center of the cylinder.
SetCenter(double x,double y,double z)1071 void vtkImplicitCylinderRepresentation::SetCenter(double x, double y, double z)
1072 {
1073   double center[3];
1074   center[0] = x;
1075   center[1] = y;
1076   center[2] = z;
1077   this->SetCenter(center);
1078 }
1079 
1080 //------------------------------------------------------------------------------
1081 // Set the center of the cylinder. Note that the center is clamped slightly inside
1082 // the bounding box or the cylinder tends to disappear as it hits the boundary.
SetCenter(double x[3])1083 void vtkImplicitCylinderRepresentation::SetCenter(double x[3])
1084 {
1085   this->Cylinder->SetCenter(x);
1086   this->BuildRepresentation();
1087 }
1088 
1089 //------------------------------------------------------------------------------
1090 // Get the center of the cylinder.
GetCenter()1091 double* vtkImplicitCylinderRepresentation::GetCenter()
1092 {
1093   return this->Cylinder->GetCenter();
1094 }
1095 
1096 //------------------------------------------------------------------------------
GetCenter(double xyz[3])1097 void vtkImplicitCylinderRepresentation::GetCenter(double xyz[3])
1098 {
1099   return this->Cylinder->GetCenter(xyz);
1100 }
1101 
1102 //------------------------------------------------------------------------------
1103 // Set the axis of the cylinder.
SetAxis(double x,double y,double z)1104 void vtkImplicitCylinderRepresentation::SetAxis(double x, double y, double z)
1105 {
1106   double n[3], n2[3];
1107   n[0] = x;
1108   n[1] = y;
1109   n[2] = z;
1110   vtkMath::Normalize(n);
1111 
1112   this->Cylinder->GetAxis(n2);
1113   if (n[0] != n2[0] || n[1] != n2[1] || n[2] != n2[2])
1114   {
1115     this->Cylinder->SetAxis(n);
1116     this->Modified();
1117   }
1118 }
1119 
1120 //------------------------------------------------------------------------------
1121 // Set the axis the cylinder.
SetAxis(double n[3])1122 void vtkImplicitCylinderRepresentation::SetAxis(double n[3])
1123 {
1124   this->SetAxis(n[0], n[1], n[2]);
1125 }
1126 
1127 //------------------------------------------------------------------------------
1128 // Get the axis of the cylinder.
GetAxis()1129 double* vtkImplicitCylinderRepresentation::GetAxis()
1130 {
1131   return this->Cylinder->GetAxis();
1132 }
1133 
1134 //------------------------------------------------------------------------------
GetAxis(double xyz[3])1135 void vtkImplicitCylinderRepresentation::GetAxis(double xyz[3])
1136 {
1137   return this->Cylinder->GetAxis(xyz);
1138 }
1139 
1140 //------------------------------------------------------------------------------
1141 // Set the radius the cylinder. The radius must be a positive number.
SetRadius(double radius)1142 void vtkImplicitCylinderRepresentation::SetRadius(double radius)
1143 {
1144   if (this->ConstrainToWidgetBounds)
1145   {
1146     double minRadius = this->Outline->GetOutput()->GetLength() * this->MinRadius;
1147     double maxRadius = this->Outline->GetOutput()->GetLength() * this->MaxRadius;
1148 
1149     radius = std::min(maxRadius, std::max(minRadius, radius));
1150   }
1151   this->Cylinder->SetRadius(radius);
1152   this->BuildRepresentation();
1153 }
1154 
1155 //------------------------------------------------------------------------------
1156 // Get the radius the cylinder.
GetRadius()1157 double vtkImplicitCylinderRepresentation::GetRadius()
1158 {
1159   return this->Cylinder->GetRadius();
1160 }
1161 
1162 //------------------------------------------------------------------------------
SetDrawCylinder(vtkTypeBool drawCyl)1163 void vtkImplicitCylinderRepresentation::SetDrawCylinder(vtkTypeBool drawCyl)
1164 {
1165   if (drawCyl == this->DrawCylinder)
1166   {
1167     return;
1168   }
1169 
1170   this->Modified();
1171   this->DrawCylinder = drawCyl;
1172   this->BuildRepresentation();
1173 }
1174 
1175 //------------------------------------------------------------------------------
SetAlongXAxis(vtkTypeBool var)1176 void vtkImplicitCylinderRepresentation::SetAlongXAxis(vtkTypeBool var)
1177 {
1178   if (this->AlongXAxis != var)
1179   {
1180     this->AlongXAxis = var;
1181     this->Modified();
1182   }
1183   if (var)
1184   {
1185     this->AlongYAxisOff();
1186     this->AlongZAxisOff();
1187   }
1188 }
1189 
1190 //------------------------------------------------------------------------------
SetAlongYAxis(vtkTypeBool var)1191 void vtkImplicitCylinderRepresentation::SetAlongYAxis(vtkTypeBool var)
1192 {
1193   if (this->AlongYAxis != var)
1194   {
1195     this->AlongYAxis = var;
1196     this->Modified();
1197   }
1198   if (var)
1199   {
1200     this->AlongXAxisOff();
1201     this->AlongZAxisOff();
1202   }
1203 }
1204 
1205 //------------------------------------------------------------------------------
SetAlongZAxis(vtkTypeBool var)1206 void vtkImplicitCylinderRepresentation::SetAlongZAxis(vtkTypeBool var)
1207 {
1208   if (this->AlongZAxis != var)
1209   {
1210     this->AlongZAxis = var;
1211     this->Modified();
1212   }
1213   if (var)
1214   {
1215     this->AlongXAxisOff();
1216     this->AlongYAxisOff();
1217   }
1218 }
1219 
1220 //------------------------------------------------------------------------------
GetPolyData(vtkPolyData * pd)1221 void vtkImplicitCylinderRepresentation::GetPolyData(vtkPolyData* pd)
1222 {
1223   pd->ShallowCopy(this->Cyl);
1224 }
1225 
1226 //------------------------------------------------------------------------------
GetCylinder(vtkCylinder * cyl)1227 void vtkImplicitCylinderRepresentation::GetCylinder(vtkCylinder* cyl)
1228 {
1229   if (cyl == nullptr)
1230   {
1231     return;
1232   }
1233 
1234   cyl->SetAxis(this->Cylinder->GetAxis());
1235   cyl->SetCenter(this->Cylinder->GetCenter());
1236   cyl->SetRadius(this->Cylinder->GetRadius());
1237 }
1238 
1239 //------------------------------------------------------------------------------
UpdatePlacement()1240 void vtkImplicitCylinderRepresentation::UpdatePlacement()
1241 {
1242   this->BuildRepresentation();
1243   this->Outline->Update();
1244   this->Edges->Update();
1245 }
1246 
1247 //------------------------------------------------------------------------------
BumpCylinder(int dir,double factor)1248 void vtkImplicitCylinderRepresentation::BumpCylinder(int dir, double factor)
1249 {
1250   // Compute the distance
1251   double d = this->InitialLength * this->BumpDistance * factor;
1252 
1253   // Push the cylinder
1254   this->PushCylinder((dir > 0 ? d : -d));
1255 }
1256 
1257 //------------------------------------------------------------------------------
PushCylinder(double d)1258 void vtkImplicitCylinderRepresentation::PushCylinder(double d)
1259 {
1260   vtkCamera* camera = this->Renderer->GetActiveCamera();
1261   if (!camera)
1262   {
1263     return;
1264   }
1265   double vpn[3], center[3];
1266   camera->GetViewPlaneNormal(vpn);
1267   this->Cylinder->GetCenter(center);
1268 
1269   center[0] += d * vpn[0];
1270   center[1] += d * vpn[1];
1271   center[2] += d * vpn[2];
1272 
1273   this->Cylinder->SetCenter(center);
1274   this->BuildRepresentation();
1275 }
1276 
1277 //------------------------------------------------------------------------------
BuildRepresentation()1278 void vtkImplicitCylinderRepresentation::BuildRepresentation()
1279 {
1280   if (!this->Renderer || !this->Renderer->GetRenderWindow())
1281   {
1282     return;
1283   }
1284 
1285   vtkInformation* info = this->GetPropertyKeys();
1286   this->OutlineActor->SetPropertyKeys(info);
1287   this->CylActor->SetPropertyKeys(info);
1288   this->EdgesActor->SetPropertyKeys(info);
1289   this->ConeActor->SetPropertyKeys(info);
1290   this->LineActor->SetPropertyKeys(info);
1291   this->ConeActor2->SetPropertyKeys(info);
1292   this->LineActor2->SetPropertyKeys(info);
1293   this->SphereActor->SetPropertyKeys(info);
1294 
1295   if (this->GetMTime() > this->BuildTime || this->Cylinder->GetMTime() > this->BuildTime ||
1296     this->Renderer->GetRenderWindow()->GetMTime() > this->BuildTime)
1297   {
1298     double* center = this->Cylinder->GetCenter();
1299     double* axis = this->Cylinder->GetAxis();
1300 
1301     double bounds[6];
1302     std::copy(this->WidgetBounds, this->WidgetBounds + 6, bounds);
1303 
1304     double p2[3];
1305     if (!this->OutsideBounds)
1306     {
1307       // restrict the center inside InitialBounds
1308       double* ibounds = this->InitialBounds;
1309       for (int i = 0; i < 3; i++)
1310       {
1311         if (center[i] < ibounds[2 * i])
1312         {
1313           center[i] = ibounds[2 * i];
1314         }
1315         else if (center[i] > ibounds[2 * i + 1])
1316         {
1317           center[i] = ibounds[2 * i + 1];
1318         }
1319       }
1320     }
1321 
1322     if (this->ConstrainToWidgetBounds)
1323     {
1324       if (!this->OutsideBounds)
1325       {
1326         // center cannot move outside InitialBounds. Therefore, restrict
1327         // movement of the Box.
1328         double v[3] = { 0.0, 0.0, 0.0 };
1329         for (int i = 0; i < 3; ++i)
1330         {
1331           if (center[i] <= bounds[2 * i])
1332           {
1333             v[i] = center[i] - bounds[2 * i] - FLT_EPSILON;
1334           }
1335           else if (center[i] >= bounds[2 * i + 1])
1336           {
1337             v[i] = center[i] - bounds[2 * i + 1] + FLT_EPSILON;
1338           }
1339           bounds[2 * i] += v[i];
1340           bounds[2 * i + 1] += v[i];
1341         }
1342       }
1343 
1344       // restrict center inside bounds
1345       for (int i = 0; i < 3; ++i)
1346       {
1347         if (center[i] <= bounds[2 * i])
1348         {
1349           center[i] = bounds[2 * i] + FLT_EPSILON;
1350         }
1351         if (center[i] >= bounds[2 * i + 1])
1352         {
1353           center[i] = bounds[2 * i + 1] - FLT_EPSILON;
1354         }
1355       }
1356     }
1357     else // cylinder can move freely, adjust the bounds to change with it
1358     {
1359       double offset = this->Cylinder->GetRadius() * 1.2;
1360       for (int i = 0; i < 3; ++i)
1361       {
1362         bounds[2 * i] = vtkMath::Min(center[i] - offset, this->WidgetBounds[2 * i]);
1363         bounds[2 * i + 1] = vtkMath::Max(center[i] + offset, this->WidgetBounds[2 * i + 1]);
1364       }
1365     }
1366 
1367     this->Box->SetOrigin(bounds[0], bounds[2], bounds[4]);
1368     this->Box->SetSpacing(
1369       (bounds[1] - bounds[0]), (bounds[3] - bounds[2]), (bounds[5] - bounds[4]));
1370     this->Outline->Update();
1371 
1372     // Setup the cylinder axis
1373     double d = this->Outline->GetOutput()->GetLength();
1374 
1375     p2[0] = center[0] + 0.30 * d * axis[0];
1376     p2[1] = center[1] + 0.30 * d * axis[1];
1377     p2[2] = center[2] + 0.30 * d * axis[2];
1378 
1379     this->LineSource->SetPoint1(center);
1380     this->LineSource->SetPoint2(p2);
1381     this->ConeSource->SetCenter(p2);
1382     this->ConeSource->SetDirection(axis);
1383 
1384     p2[0] = center[0] - 0.30 * d * axis[0];
1385     p2[1] = center[1] - 0.30 * d * axis[1];
1386     p2[2] = center[2] - 0.30 * d * axis[2];
1387 
1388     this->LineSource2->SetPoint1(center[0], center[1], center[2]);
1389     this->LineSource2->SetPoint2(p2);
1390     this->ConeSource2->SetCenter(p2);
1391     this->ConeSource2->SetDirection(axis[0], axis[1], axis[2]);
1392 
1393     // Set up the position handle
1394     this->Sphere->SetCenter(center[0], center[1], center[2]);
1395 
1396     // Control the look of the edges
1397     if (this->Tubing)
1398     {
1399       this->EdgesMapper->SetInputConnection(this->EdgesTuber->GetOutputPort());
1400     }
1401     else
1402     {
1403       this->EdgesMapper->SetInputConnection(this->Edges->GetOutputPort());
1404     }
1405 
1406     // Construct intersected cylinder
1407     this->BuildCylinder();
1408 
1409     this->SizeHandles();
1410     this->BuildTime.Modified();
1411   }
1412 }
1413 
1414 //------------------------------------------------------------------------------
SizeHandles()1415 void vtkImplicitCylinderRepresentation::SizeHandles()
1416 {
1417   double radius =
1418     this->vtkWidgetRepresentation::SizeHandlesInPixels(1.5, this->Sphere->GetCenter());
1419 
1420   this->ConeSource->SetHeight(2.0 * radius);
1421   this->ConeSource->SetRadius(radius);
1422   this->ConeSource2->SetHeight(2.0 * radius);
1423   this->ConeSource2->SetRadius(radius);
1424 
1425   this->Sphere->SetRadius(radius);
1426 
1427   this->EdgesTuber->SetRadius(0.25 * radius);
1428 }
1429 
1430 //------------------------------------------------------------------------------
1431 // Create cylinder polydata.  Basically build an oriented cylinder of
1432 // specified resolution.  Trim cylinder facets by performing
1433 // intersection tests. Note that some facets may be outside the
1434 // bounding box, in which cases they are discarded.
BuildCylinder()1435 void vtkImplicitCylinderRepresentation::BuildCylinder()
1436 {
1437   // Initialize the polydata
1438   this->Cyl->Reset();
1439   vtkPoints* pts = this->Cyl->GetPoints();
1440   vtkDataArray* normals = this->Cyl->GetPointData()->GetNormals();
1441   vtkCellArray* polys = this->Cyl->GetPolys();
1442 
1443   // Retrieve relevant parameters
1444   double* center = this->Cylinder->GetCenter();
1445   double* axis = this->Cylinder->GetAxis();
1446   double radius = this->Cylinder->GetRadius();
1447   int res = this->Resolution;
1448   double d = this->Outline->GetOutput()->GetLength();
1449 
1450   // We're gonna need a local coordinate system. Find a normal to the
1451   // cylinder axis. Then use cross product to find a third orthogonal
1452   // axis.
1453   int i;
1454   double n1[3], n2[3];
1455   for (i = 0; i < 3; i++)
1456   {
1457     // a little trick to find an othogonal normal
1458     if (axis[i] != 0.0)
1459     {
1460       n1[(i + 2) % 3] = 0.0;
1461       n1[(i + 1) % 3] = 1.0;
1462       n1[i] = -axis[(i + 1) % 3] / axis[i];
1463       break;
1464     }
1465   }
1466   vtkMath::Normalize(n1);
1467   vtkMath::Cross(axis, n1, n2);
1468 
1469   // Now create Resolution line segments. Initially the line segments
1470   // are made a little long to extend outside of the bounding
1471   // box. Later on we'll trim them to the bounding box.
1472   pts->SetNumberOfPoints(2 * res);
1473   normals->SetNumberOfTuples(2 * res);
1474 
1475   vtkIdType pid;
1476   double x[3], n[3], theta;
1477   double v[3];
1478   v[0] = d * axis[0];
1479   v[1] = d * axis[1];
1480   v[2] = d * axis[2];
1481   for (pid = 0; pid < res; ++pid)
1482   {
1483     theta = static_cast<double>(pid) / static_cast<double>(res) * 2.0 * vtkMath::Pi();
1484     for (i = 0; i < 3; ++i)
1485     {
1486       n[i] = n1[i] * cos(theta) + n2[i] * sin(theta);
1487       x[i] = center[i] + radius * n[i] + v[i];
1488     }
1489     pts->SetPoint(pid, x);
1490     normals->SetTuple(pid, n);
1491 
1492     for (i = 0; i < 3; ++i)
1493     {
1494       x[i] = center[i] + radius * n[i] - v[i];
1495     }
1496     pts->SetPoint(res + pid, x);
1497     normals->SetTuple(res + pid, n);
1498   }
1499 
1500   // Now trim the cylinder against the bounding box. Mark edges that do not
1501   // intersect the bounding box.
1502   bool edgeInside[VTK_MAX_CYL_RESOLUTION];
1503   double x1[3], x2[3], p1[3], p2[3], t1, t2;
1504   const double* bounds = this->Outline->GetOutput()->GetBounds();
1505   int plane1, plane2;
1506   for (pid = 0; pid < res; ++pid)
1507   {
1508     pts->GetPoint(pid, x1);
1509     pts->GetPoint(pid + res, x2);
1510     if (!vtkBox::IntersectWithLine(bounds, x1, x2, t1, t2, p1, p2, plane1, plane2))
1511     {
1512       edgeInside[pid] = false;
1513     }
1514     else
1515     {
1516       edgeInside[pid] = true;
1517       pts->SetPoint(pid, p1);
1518       pts->SetPoint(pid + res, p2);
1519     }
1520   }
1521 
1522   // Create polygons around cylinder. Make sure the edges of the polygon
1523   // are inside the widget's bounding box.
1524   vtkIdType ptIds[4];
1525   for (pid = 0; pid < res; ++pid)
1526   {
1527     if (edgeInside[pid] && edgeInside[(pid + 1) % res])
1528     {
1529       ptIds[0] = pid;
1530       ptIds[3] = (pid + 1) % res;
1531       ptIds[1] = ptIds[0] + res;
1532       ptIds[2] = ptIds[3] + res;
1533       polys->InsertNextCell(4, ptIds);
1534     }
1535   }
1536   polys->Modified();
1537 }
1538 
1539 //------------------------------------------------------------------------------
RegisterPickers()1540 void vtkImplicitCylinderRepresentation::RegisterPickers()
1541 {
1542   vtkPickingManager* pm = this->GetPickingManager();
1543   if (!pm)
1544   {
1545     return;
1546   }
1547   pm->AddPicker(this->Picker, this);
1548 }
1549