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