1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkImplicitPlaneWidget.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 "vtkImplicitPlaneWidget.h"
16 
17 #include "vtkActor.h"
18 #include "vtkAssemblyNode.h"
19 #include "vtkAssemblyPath.h"
20 #include "vtkCallbackCommand.h"
21 #include "vtkCamera.h"
22 #include "vtkCellPicker.h"
23 #include "vtkConeSource.h"
24 #include "vtkCutter.h"
25 #include "vtkFeatureEdges.h"
26 #include "vtkImageData.h"
27 #include "vtkLineSource.h"
28 #include "vtkMath.h"
29 #include "vtkObjectFactory.h"
30 #include "vtkOutlineFilter.h"
31 #include "vtkPickingManager.h"
32 #include "vtkPlane.h"
33 #include "vtkPolyData.h"
34 #include "vtkPolyDataMapper.h"
35 #include "vtkProperty.h"
36 #include "vtkRenderWindowInteractor.h"
37 #include "vtkRenderer.h"
38 #include "vtkSphereSource.h"
39 #include "vtkTransform.h"
40 #include "vtkTubeFilter.h"
41 
42 vtkStandardNewMacro(vtkImplicitPlaneWidget);
43 
44 //------------------------------------------------------------------------------
vtkImplicitPlaneWidget()45 vtkImplicitPlaneWidget::vtkImplicitPlaneWidget()
46 {
47   this->DiagonalRatio = 0.3;
48   this->State = vtkImplicitPlaneWidget::Start;
49   this->EventCallbackCommand->SetCallback(vtkImplicitPlaneWidget::ProcessEvents);
50 
51   this->NormalToXAxis = 0;
52   this->NormalToYAxis = 0;
53   this->NormalToZAxis = 0;
54 
55   // Build the representation of the widget
56   //
57   this->Plane = vtkPlane::New();
58   this->Plane->SetNormal(0, 0, 1);
59   this->Plane->SetOrigin(0, 0, 0);
60 
61   this->Box = vtkImageData::New();
62   this->Box->SetDimensions(2, 2, 2);
63   this->Outline = vtkOutlineFilter::New();
64   this->Outline->SetInputData(this->Box);
65   this->OutlineMapper = vtkPolyDataMapper::New();
66   this->OutlineMapper->SetInputConnection(this->Outline->GetOutputPort());
67   this->OutlineActor = vtkActor::New();
68   this->OutlineActor->SetMapper(this->OutlineMapper);
69   this->OutlineTranslation = 1;
70   this->ScaleEnabled = 1;
71   this->OutsideBounds = 1;
72 
73   this->Cutter = vtkCutter::New();
74   this->Cutter->SetInputData(this->Box);
75   this->Cutter->SetCutFunction(this->Plane);
76   this->CutMapper = vtkPolyDataMapper::New();
77   this->CutMapper->SetInputConnection(this->Cutter->GetOutputPort());
78   this->CutActor = vtkActor::New();
79   this->CutActor->SetMapper(this->CutMapper);
80   this->DrawPlane = 1;
81 
82   this->Edges = vtkFeatureEdges::New();
83   this->Edges->SetInputConnection(this->Cutter->GetOutputPort());
84   this->EdgesTuber = vtkTubeFilter::New();
85   this->EdgesTuber->SetInputConnection(this->Edges->GetOutputPort());
86   this->EdgesTuber->SetNumberOfSides(12);
87   this->EdgesMapper = vtkPolyDataMapper::New();
88   this->EdgesMapper->SetInputConnection(this->EdgesTuber->GetOutputPort());
89   this->EdgesActor = vtkActor::New();
90   this->EdgesActor->SetMapper(this->EdgesMapper);
91   this->Tubing = 1; // control whether tubing is on
92 
93   // Create the + plane normal
94   this->LineSource = vtkLineSource::New();
95   this->LineSource->SetResolution(1);
96   this->LineMapper = vtkPolyDataMapper::New();
97   this->LineMapper->SetInputConnection(this->LineSource->GetOutputPort());
98   this->LineActor = vtkActor::New();
99   this->LineActor->SetMapper(this->LineMapper);
100 
101   this->ConeSource = vtkConeSource::New();
102   this->ConeSource->SetResolution(12);
103   this->ConeSource->SetAngle(25.0);
104   this->ConeMapper = vtkPolyDataMapper::New();
105   this->ConeMapper->SetInputConnection(this->ConeSource->GetOutputPort());
106   this->ConeActor = vtkActor::New();
107   this->ConeActor->SetMapper(this->ConeMapper);
108 
109   // Create the - plane normal
110   this->LineSource2 = vtkLineSource::New();
111   this->LineSource2->SetResolution(1);
112   this->LineMapper2 = vtkPolyDataMapper::New();
113   this->LineMapper2->SetInputConnection(this->LineSource2->GetOutputPort());
114   this->LineActor2 = vtkActor::New();
115   this->LineActor2->SetMapper(this->LineMapper2);
116 
117   this->ConeSource2 = vtkConeSource::New();
118   this->ConeSource2->SetResolution(12);
119   this->ConeSource2->SetAngle(25.0);
120   this->ConeMapper2 = vtkPolyDataMapper::New();
121   this->ConeMapper2->SetInputConnection(this->ConeSource2->GetOutputPort());
122   this->ConeActor2 = vtkActor::New();
123   this->ConeActor2->SetMapper(this->ConeMapper2);
124 
125   // Create the origin handle
126   this->Sphere = vtkSphereSource::New();
127   this->Sphere->SetThetaResolution(16);
128   this->Sphere->SetPhiResolution(8);
129   this->SphereMapper = vtkPolyDataMapper::New();
130   this->SphereMapper->SetInputConnection(this->Sphere->GetOutputPort());
131   this->SphereActor = vtkActor::New();
132   this->SphereActor->SetMapper(this->SphereMapper);
133   this->OriginTranslation = 1;
134 
135   this->Transform = vtkTransform::New();
136 
137   // Define the point coordinates
138   double bounds[6];
139   bounds[0] = -0.5;
140   bounds[1] = 0.5;
141   bounds[2] = -0.5;
142   bounds[3] = 0.5;
143   bounds[4] = -0.5;
144   bounds[5] = 0.5;
145 
146   // Initial creation of the widget, serves to initialize it
147   this->PlaceWidget(bounds);
148 
149   // Manage the picking stuff
150   this->Picker = vtkCellPicker::New();
151   this->Picker->SetTolerance(0.005);
152   this->Picker->AddPickList(this->CutActor);
153   this->Picker->AddPickList(this->LineActor);
154   this->Picker->AddPickList(this->ConeActor);
155   this->Picker->AddPickList(this->LineActor2);
156   this->Picker->AddPickList(this->ConeActor2);
157   this->Picker->AddPickList(this->SphereActor);
158   this->Picker->AddPickList(this->OutlineActor);
159   this->Picker->PickFromListOn();
160 
161   // Set up the initial properties
162   this->CreateDefaultProperties();
163 }
164 
165 //------------------------------------------------------------------------------
~vtkImplicitPlaneWidget()166 vtkImplicitPlaneWidget::~vtkImplicitPlaneWidget()
167 {
168   this->Plane->Delete();
169   this->Box->Delete();
170   this->Outline->Delete();
171   this->OutlineMapper->Delete();
172   this->OutlineActor->Delete();
173 
174   this->Cutter->Delete();
175   this->CutMapper->Delete();
176   this->CutActor->Delete();
177 
178   this->Edges->Delete();
179   this->EdgesTuber->Delete();
180   this->EdgesMapper->Delete();
181   this->EdgesActor->Delete();
182 
183   this->LineSource->Delete();
184   this->LineMapper->Delete();
185   this->LineActor->Delete();
186 
187   this->ConeSource->Delete();
188   this->ConeMapper->Delete();
189   this->ConeActor->Delete();
190 
191   this->LineSource2->Delete();
192   this->LineMapper2->Delete();
193   this->LineActor2->Delete();
194 
195   this->ConeSource2->Delete();
196   this->ConeMapper2->Delete();
197   this->ConeActor2->Delete();
198 
199   this->Sphere->Delete();
200   this->SphereMapper->Delete();
201   this->SphereActor->Delete();
202 
203   this->Transform->Delete();
204 
205   this->Picker->Delete();
206 
207   this->NormalProperty->Delete();
208   this->SelectedNormalProperty->Delete();
209   this->PlaneProperty->Delete();
210   this->SelectedPlaneProperty->Delete();
211   this->OutlineProperty->Delete();
212   this->SelectedOutlineProperty->Delete();
213   this->EdgesProperty->Delete();
214 }
215 
216 //------------------------------------------------------------------------------
SetEnabled(int enabling)217 void vtkImplicitPlaneWidget::SetEnabled(int enabling)
218 {
219   if (!this->Interactor)
220   {
221     vtkErrorMacro(<< "The interactor must be set prior to enabling/disabling widget");
222     return;
223   }
224 
225   if (enabling) //------------------------------------------------------------
226   {
227     vtkDebugMacro(<< "Enabling plane widget");
228 
229     if (this->Enabled) // already enabled, just return
230     {
231       return;
232     }
233 
234     if (!this->CurrentRenderer)
235     {
236       this->SetCurrentRenderer(this->Interactor->FindPokedRenderer(
237         this->Interactor->GetLastEventPosition()[0], this->Interactor->GetLastEventPosition()[1]));
238       if (this->CurrentRenderer == nullptr)
239       {
240         return;
241       }
242     }
243 
244     this->Enabled = 1;
245 
246     // listen for the following events
247     vtkRenderWindowInteractor* i = this->Interactor;
248     i->AddObserver(vtkCommand::MouseMoveEvent, this->EventCallbackCommand, this->Priority);
249     i->AddObserver(vtkCommand::LeftButtonPressEvent, this->EventCallbackCommand, this->Priority);
250     i->AddObserver(vtkCommand::LeftButtonReleaseEvent, this->EventCallbackCommand, this->Priority);
251     i->AddObserver(vtkCommand::MiddleButtonPressEvent, this->EventCallbackCommand, this->Priority);
252     i->AddObserver(
253       vtkCommand::MiddleButtonReleaseEvent, this->EventCallbackCommand, this->Priority);
254     i->AddObserver(vtkCommand::RightButtonPressEvent, this->EventCallbackCommand, this->Priority);
255     i->AddObserver(vtkCommand::RightButtonReleaseEvent, this->EventCallbackCommand, this->Priority);
256 
257     // add the outline
258     this->CurrentRenderer->AddActor(this->OutlineActor);
259     this->OutlineActor->SetProperty(this->OutlineProperty);
260 
261     // add the edges
262     this->CurrentRenderer->AddActor(this->EdgesActor);
263     this->EdgesActor->SetProperty(this->EdgesProperty);
264 
265     // add the normal vector
266     this->CurrentRenderer->AddActor(this->LineActor);
267     this->LineActor->SetProperty(this->NormalProperty);
268     this->CurrentRenderer->AddActor(this->ConeActor);
269     this->ConeActor->SetProperty(this->NormalProperty);
270 
271     this->CurrentRenderer->AddActor(this->LineActor2);
272     this->LineActor2->SetProperty(this->NormalProperty);
273     this->CurrentRenderer->AddActor(this->ConeActor2);
274     this->ConeActor2->SetProperty(this->NormalProperty);
275 
276     // add the origin handle
277     this->CurrentRenderer->AddActor(this->SphereActor);
278     this->SphereActor->SetProperty(this->NormalProperty);
279 
280     // add the plane (if desired)
281     if (this->DrawPlane)
282     {
283       this->CurrentRenderer->AddActor(this->CutActor);
284     }
285     this->CutActor->SetProperty(this->PlaneProperty);
286 
287     this->UpdateRepresentation();
288     this->SizeHandles();
289     this->RegisterPickers();
290     this->InvokeEvent(vtkCommand::EnableEvent, nullptr);
291   }
292 
293   else // disabling----------------------------------------------------------
294   {
295     vtkDebugMacro(<< "Disabling plane widget");
296 
297     if (!this->Enabled) // already disabled, just return
298     {
299       return;
300     }
301 
302     this->Enabled = 0;
303 
304     // don't listen for events any more
305     this->Interactor->RemoveObserver(this->EventCallbackCommand);
306 
307     // turn off the various actors
308     this->CurrentRenderer->RemoveActor(this->OutlineActor);
309     this->CurrentRenderer->RemoveActor(this->EdgesActor);
310     this->CurrentRenderer->RemoveActor(this->LineActor);
311     this->CurrentRenderer->RemoveActor(this->ConeActor);
312     this->CurrentRenderer->RemoveActor(this->LineActor2);
313     this->CurrentRenderer->RemoveActor(this->ConeActor2);
314     this->CurrentRenderer->RemoveActor(this->SphereActor);
315     this->CurrentRenderer->RemoveActor(this->CutActor);
316 
317     this->InvokeEvent(vtkCommand::DisableEvent, nullptr);
318     this->SetCurrentRenderer(nullptr);
319     this->UnRegisterPickers();
320   }
321 
322   this->Interactor->Render();
323 }
324 
325 //------------------------------------------------------------------------------
ProcessEvents(vtkObject * vtkNotUsed (object),unsigned long event,void * clientdata,void * vtkNotUsed (calldata))326 void vtkImplicitPlaneWidget::ProcessEvents(
327   vtkObject* vtkNotUsed(object), unsigned long event, void* clientdata, void* vtkNotUsed(calldata))
328 {
329   vtkImplicitPlaneWidget* self = reinterpret_cast<vtkImplicitPlaneWidget*>(clientdata);
330 
331   // okay, let's do the right thing
332   switch (event)
333   {
334     case vtkCommand::LeftButtonPressEvent:
335       self->OnLeftButtonDown();
336       break;
337     case vtkCommand::LeftButtonReleaseEvent:
338       self->OnLeftButtonUp();
339       break;
340     case vtkCommand::MiddleButtonPressEvent:
341       self->OnMiddleButtonDown();
342       break;
343     case vtkCommand::MiddleButtonReleaseEvent:
344       self->OnMiddleButtonUp();
345       break;
346     case vtkCommand::RightButtonPressEvent:
347       self->OnRightButtonDown();
348       break;
349     case vtkCommand::RightButtonReleaseEvent:
350       self->OnRightButtonUp();
351       break;
352     case vtkCommand::MouseMoveEvent:
353       self->OnMouseMove();
354       break;
355   }
356 }
357 
358 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)359 void vtkImplicitPlaneWidget::PrintSelf(ostream& os, vtkIndent indent)
360 {
361   this->Superclass::PrintSelf(os, indent);
362 
363   if (this->NormalProperty)
364   {
365     os << indent << "Normal Property: " << this->NormalProperty << "\n";
366   }
367   else
368   {
369     os << indent << "Normal Property: (none)\n";
370   }
371   if (this->SelectedNormalProperty)
372   {
373     os << indent << "Selected Normal Property: " << this->SelectedNormalProperty << "\n";
374   }
375   else
376   {
377     os << indent << "Selected Normal Property: (none)\n";
378   }
379 
380   if (this->PlaneProperty)
381   {
382     os << indent << "Plane Property: " << this->PlaneProperty << "\n";
383   }
384   else
385   {
386     os << indent << "Plane Property: (none)\n";
387   }
388   if (this->SelectedPlaneProperty)
389   {
390     os << indent << "Selected Plane Property: " << this->SelectedPlaneProperty << "\n";
391   }
392   else
393   {
394     os << indent << "Selected Plane Property: (none)\n";
395   }
396 
397   if (this->OutlineProperty)
398   {
399     os << indent << "Outline Property: " << this->OutlineProperty << "\n";
400   }
401   else
402   {
403     os << indent << "Outline Property: (none)\n";
404   }
405   if (this->SelectedOutlineProperty)
406   {
407     os << indent << "Selected Outline Property: " << this->SelectedOutlineProperty << "\n";
408   }
409   else
410   {
411     os << indent << "Selected Outline Property: (none)\n";
412   }
413 
414   if (this->EdgesProperty)
415   {
416     os << indent << "Edges Property: " << this->EdgesProperty << "\n";
417   }
418   else
419   {
420     os << indent << "Edges Property: (none)\n";
421   }
422 
423   os << indent << "Normal To X Axis: " << (this->NormalToXAxis ? "On" : "Off") << "\n";
424   os << indent << "Normal To Y Axis: " << (this->NormalToYAxis ? "On" : "Off") << "\n";
425   os << indent << "Normal To Z Axis: " << (this->NormalToZAxis ? "On" : "Off") << "\n";
426 
427   os << indent << "Tubing: " << (this->Tubing ? "On" : "Off") << "\n";
428   os << indent << "Origin Translation: " << (this->OriginTranslation ? "On" : "Off") << "\n";
429   os << indent << "Outline Translation: " << (this->OutlineTranslation ? "On" : "Off") << "\n";
430   os << indent << "Outside Bounds: " << (this->OutsideBounds ? "On" : "Off") << "\n";
431   os << indent << "Scale Enabled: " << (this->ScaleEnabled ? "On" : "Off") << "\n";
432   os << indent << "Draw Plane: " << (this->DrawPlane ? "On" : "Off") << "\n";
433 
434   os << indent << "Diagonal Ratio: " << this->DiagonalRatio << "\n";
435 }
436 
437 //------------------------------------------------------------------------------
HighlightNormal(int highlight)438 void vtkImplicitPlaneWidget::HighlightNormal(int highlight)
439 {
440   if (highlight)
441   {
442     this->LineActor->SetProperty(this->SelectedNormalProperty);
443     this->ConeActor->SetProperty(this->SelectedNormalProperty);
444     this->LineActor2->SetProperty(this->SelectedNormalProperty);
445     this->ConeActor2->SetProperty(this->SelectedNormalProperty);
446     this->SphereActor->SetProperty(this->SelectedNormalProperty);
447   }
448   else
449   {
450     this->LineActor->SetProperty(this->NormalProperty);
451     this->ConeActor->SetProperty(this->NormalProperty);
452     this->LineActor2->SetProperty(this->NormalProperty);
453     this->ConeActor2->SetProperty(this->NormalProperty);
454     this->SphereActor->SetProperty(this->NormalProperty);
455   }
456 }
457 
458 //------------------------------------------------------------------------------
HighlightPlane(int highlight)459 void vtkImplicitPlaneWidget::HighlightPlane(int highlight)
460 {
461   if (highlight)
462   {
463     this->CutActor->SetProperty(this->SelectedPlaneProperty);
464   }
465   else
466   {
467     this->CutActor->SetProperty(this->PlaneProperty);
468   }
469 }
470 
471 //------------------------------------------------------------------------------
HighlightOutline(int highlight)472 void vtkImplicitPlaneWidget::HighlightOutline(int highlight)
473 {
474   if (highlight)
475   {
476     this->OutlineActor->SetProperty(this->SelectedOutlineProperty);
477   }
478   else
479   {
480     this->OutlineActor->SetProperty(this->OutlineProperty);
481   }
482 }
483 
484 //------------------------------------------------------------------------------
OnLeftButtonDown()485 void vtkImplicitPlaneWidget::OnLeftButtonDown()
486 {
487   // We're only here if we are enabled
488   int X = this->Interactor->GetEventPosition()[0];
489   int Y = this->Interactor->GetEventPosition()[1];
490 
491   // Okay, we can process this. See if we've picked anything.
492   // Make sure it's in the activated renderer
493   if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y))
494   {
495     this->State = vtkImplicitPlaneWidget::Outside;
496     return;
497   }
498 
499   vtkAssemblyPath* path = this->GetAssemblyPath(X, Y, 0., this->Picker);
500 
501   if (path == nullptr) // not picking this widget
502   {
503     this->HighlightPlane(0);
504     this->HighlightNormal(0);
505     this->HighlightOutline(0);
506     this->State = vtkImplicitPlaneWidget::Outside;
507     return;
508   }
509 
510   vtkProp* prop = path->GetFirstNode()->GetViewProp();
511   this->ValidPick = 1;
512   this->Picker->GetPickPosition(this->LastPickPosition);
513   if (prop == this->ConeActor || prop == this->LineActor || prop == this->ConeActor2 ||
514     prop == this->LineActor2)
515   {
516     this->HighlightPlane(1);
517     this->HighlightNormal(1);
518     this->State = vtkImplicitPlaneWidget::Rotating;
519   }
520   else if (prop == this->CutActor)
521   {
522     this->HighlightPlane(1);
523     this->State = vtkImplicitPlaneWidget::Pushing;
524   }
525   else if (prop == this->SphereActor)
526   {
527     if (this->OriginTranslation)
528     {
529       this->HighlightNormal(1);
530       this->State = vtkImplicitPlaneWidget::MovingOrigin;
531     }
532     else
533     {
534       return;
535     }
536   }
537   else
538   {
539     if (this->OutlineTranslation)
540     {
541       this->HighlightOutline(1);
542       this->State = vtkImplicitPlaneWidget::MovingOutline;
543     }
544     else
545     {
546       return;
547     }
548   }
549 
550   this->EventCallbackCommand->SetAbortFlag(1);
551   this->StartInteraction();
552   this->InvokeEvent(vtkCommand::StartInteractionEvent, nullptr);
553   this->Interactor->Render();
554 }
555 
556 //------------------------------------------------------------------------------
OnLeftButtonUp()557 void vtkImplicitPlaneWidget::OnLeftButtonUp()
558 {
559   if (this->State == vtkImplicitPlaneWidget::Outside)
560   {
561     return;
562   }
563 
564   this->State = vtkImplicitPlaneWidget::Start;
565   this->HighlightPlane(0);
566   this->HighlightOutline(0);
567   this->HighlightNormal(0);
568   this->SizeHandles();
569 
570   this->EventCallbackCommand->SetAbortFlag(1);
571   this->EndInteraction();
572   this->InvokeEvent(vtkCommand::EndInteractionEvent, nullptr);
573   this->Interactor->Render();
574 }
575 
576 //------------------------------------------------------------------------------
OnMiddleButtonDown()577 void vtkImplicitPlaneWidget::OnMiddleButtonDown()
578 {
579   int X = this->Interactor->GetEventPosition()[0];
580   int Y = this->Interactor->GetEventPosition()[1];
581 
582   // Okay, we can process this. See if we've picked anything.
583   // Make sure it's in the activated renderer
584   if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y))
585   {
586     this->State = vtkImplicitPlaneWidget::Outside;
587     return;
588   }
589 
590   // Okay, we can process this.
591   vtkAssemblyPath* path = this->GetAssemblyPath(X, Y, 0., this->Picker);
592 
593   if (path == nullptr) // nothing picked
594   {
595     this->State = vtkImplicitPlaneWidget::Outside;
596     return;
597   }
598 
599   this->ValidPick = 1;
600   this->Picker->GetPickPosition(this->LastPickPosition);
601   this->State = vtkImplicitPlaneWidget::MovingPlane;
602   this->HighlightNormal(1);
603   this->HighlightPlane(1);
604 
605   this->EventCallbackCommand->SetAbortFlag(1);
606   this->StartInteraction();
607   this->InvokeEvent(vtkCommand::StartInteractionEvent, nullptr);
608   this->Interactor->Render();
609 }
610 
611 //------------------------------------------------------------------------------
OnMiddleButtonUp()612 void vtkImplicitPlaneWidget::OnMiddleButtonUp()
613 {
614   if (this->State == vtkImplicitPlaneWidget::Outside)
615   {
616     return;
617   }
618 
619   this->State = vtkImplicitPlaneWidget::Start;
620   this->HighlightPlane(0);
621   this->HighlightOutline(0);
622   this->HighlightNormal(0);
623   this->SizeHandles();
624 
625   this->EventCallbackCommand->SetAbortFlag(1);
626   this->EndInteraction();
627   this->InvokeEvent(vtkCommand::EndInteractionEvent, nullptr);
628   this->Interactor->Render();
629 }
630 
631 //------------------------------------------------------------------------------
OnRightButtonDown()632 void vtkImplicitPlaneWidget::OnRightButtonDown()
633 {
634   if (this->ScaleEnabled)
635   {
636     this->State = vtkImplicitPlaneWidget::Scaling;
637 
638     int X = this->Interactor->GetEventPosition()[0];
639     int Y = this->Interactor->GetEventPosition()[1];
640 
641     // Okay, we can process this. See if we've picked anything.
642     // Make sure it's in the activated renderer
643     if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y))
644     {
645       this->State = vtkImplicitPlaneWidget::Outside;
646       return;
647     }
648 
649     // Okay, we can process this. Try to pick handles first;
650     // if no handles picked, then pick the bounding box.
651     vtkAssemblyPath* path = this->GetAssemblyPath(X, Y, 0., this->Picker);
652 
653     if (path == nullptr) // nothing picked
654     {
655       this->State = vtkImplicitPlaneWidget::Outside;
656       return;
657     }
658 
659     this->ValidPick = 1;
660     this->Picker->GetPickPosition(this->LastPickPosition);
661     this->HighlightPlane(1);
662     this->HighlightOutline(1);
663     this->HighlightNormal(1);
664 
665     this->EventCallbackCommand->SetAbortFlag(1);
666     this->StartInteraction();
667     this->InvokeEvent(vtkCommand::StartInteractionEvent, nullptr);
668     this->Interactor->Render();
669   }
670 }
671 
672 //------------------------------------------------------------------------------
OnRightButtonUp()673 void vtkImplicitPlaneWidget::OnRightButtonUp()
674 {
675   if (this->State == vtkImplicitPlaneWidget::Outside)
676   {
677     return;
678   }
679 
680   this->State = vtkImplicitPlaneWidget::Start;
681   this->HighlightPlane(0);
682   this->HighlightOutline(0);
683   this->HighlightNormal(0);
684   this->SizeHandles();
685 
686   this->EventCallbackCommand->SetAbortFlag(1);
687   this->EndInteraction();
688   this->InvokeEvent(vtkCommand::EndInteractionEvent, nullptr);
689   this->Interactor->Render();
690 }
691 
692 //------------------------------------------------------------------------------
OnMouseMove()693 void vtkImplicitPlaneWidget::OnMouseMove()
694 {
695   // See whether we're active
696   if (this->State == vtkImplicitPlaneWidget::Outside ||
697     this->State == vtkImplicitPlaneWidget::Start)
698   {
699     return;
700   }
701 
702   int X = this->Interactor->GetEventPosition()[0];
703   int Y = this->Interactor->GetEventPosition()[1];
704 
705   // Do different things depending on state
706   // Calculations everybody does
707   double focalPoint[4], pickPoint[4], prevPickPoint[4];
708   double z, vpn[3];
709 
710   vtkCamera* camera = this->CurrentRenderer->GetActiveCamera();
711   if (!camera)
712   {
713     return;
714   }
715 
716   // Compute the two points defining the motion vector
717   this->ComputeWorldToDisplay(
718     this->LastPickPosition[0], this->LastPickPosition[1], this->LastPickPosition[2], focalPoint);
719   z = focalPoint[2];
720   this->ComputeDisplayToWorld(double(this->Interactor->GetLastEventPosition()[0]),
721     double(this->Interactor->GetLastEventPosition()[1]), z, prevPickPoint);
722   this->ComputeDisplayToWorld(double(X), double(Y), z, pickPoint);
723 
724   // Process the motion
725   if (this->State == vtkImplicitPlaneWidget::MovingPlane)
726   {
727     this->TranslatePlane(prevPickPoint, pickPoint);
728   }
729   else if (this->State == vtkImplicitPlaneWidget::MovingOutline)
730   {
731     this->TranslateOutline(prevPickPoint, pickPoint);
732   }
733   else if (this->State == vtkImplicitPlaneWidget::MovingOrigin)
734   {
735     this->TranslateOrigin(prevPickPoint, pickPoint);
736   }
737   else if (this->State == vtkImplicitPlaneWidget::Pushing)
738   {
739     this->Push(prevPickPoint, pickPoint);
740   }
741   else if (this->State == vtkImplicitPlaneWidget::Scaling)
742   {
743     this->Scale(prevPickPoint, pickPoint, X, Y);
744   }
745   else if (this->State == vtkImplicitPlaneWidget::Rotating)
746   {
747     camera->GetViewPlaneNormal(vpn);
748     this->Rotate(X, Y, prevPickPoint, pickPoint, vpn);
749   }
750 
751   // Interact, if desired
752   this->EventCallbackCommand->SetAbortFlag(1);
753   this->InvokeEvent(vtkCommand::InteractionEvent, nullptr);
754 
755   this->Interactor->Render();
756 }
757 
758 //------------------------------------------------------------------------------
Rotate(int X,int Y,double * p1,double * p2,double * vpn)759 void vtkImplicitPlaneWidget::Rotate(int X, int Y, double* p1, double* p2, double* vpn)
760 {
761   double v[3];    // vector of motion
762   double axis[3]; // axis of rotation
763   double theta;   // rotation angle
764 
765   // mouse motion vector in world space
766   v[0] = p2[0] - p1[0];
767   v[1] = p2[1] - p1[1];
768   v[2] = p2[2] - p1[2];
769 
770   double* origin = this->Plane->GetOrigin();
771   double* normal = this->Plane->GetNormal();
772 
773   // Create axis of rotation and angle of rotation
774   vtkMath::Cross(vpn, v, axis);
775   if (vtkMath::Normalize(axis) == 0.0)
776   {
777     return;
778   }
779   const int* size = this->CurrentRenderer->GetSize();
780   double l2 = (X - this->Interactor->GetLastEventPosition()[0]) *
781       (X - this->Interactor->GetLastEventPosition()[0]) +
782     (Y - this->Interactor->GetLastEventPosition()[1]) *
783       (Y - this->Interactor->GetLastEventPosition()[1]);
784   theta = 360.0 * sqrt(l2 / (size[0] * size[0] + size[1] * size[1]));
785 
786   // Manipulate the transform to reflect the rotation
787   this->Transform->Identity();
788   this->Transform->Translate(origin[0], origin[1], origin[2]);
789   this->Transform->RotateWXYZ(theta, axis);
790   this->Transform->Translate(-origin[0], -origin[1], -origin[2]);
791 
792   // Set the new normal
793   double nNew[3];
794   this->Transform->TransformNormal(normal, nNew);
795   this->Plane->SetNormal(nNew);
796 
797   this->UpdateRepresentation();
798 }
799 
800 //------------------------------------------------------------------------------
801 // Loop through all points and translate them
TranslatePlane(double * p1,double * p2)802 void vtkImplicitPlaneWidget::TranslatePlane(double* p1, double* p2)
803 {
804   // Get the motion vector
805   double v[3];
806   v[0] = p2[0] - p1[0];
807   v[1] = p2[1] - p1[1];
808   v[2] = p2[2] - p1[2];
809 
810   // Translate the plane
811   double oNew[3];
812   double* origin = this->Plane->GetOrigin();
813   oNew[0] = origin[0] + v[0];
814   oNew[1] = origin[1] + v[1];
815   oNew[2] = origin[2] + v[2];
816   this->Plane->SetOrigin(oNew);
817 
818   this->UpdateRepresentation();
819 }
820 
821 //------------------------------------------------------------------------------
822 // Loop through all points and translate them
TranslateOutline(double * p1,double * p2)823 void vtkImplicitPlaneWidget::TranslateOutline(double* p1, double* p2)
824 {
825   // Get the motion vector
826   double v[3];
827   v[0] = p2[0] - p1[0];
828   v[1] = p2[1] - p1[1];
829   v[2] = p2[2] - p1[2];
830 
831   // Translate the bounding box
832   double* origin = this->Box->GetOrigin();
833   double oNew[3];
834   oNew[0] = origin[0] + v[0];
835   oNew[1] = origin[1] + v[1];
836   oNew[2] = origin[2] + v[2];
837   this->Box->SetOrigin(oNew);
838 
839   // Translate the plane
840   origin = this->Plane->GetOrigin();
841   oNew[0] = origin[0] + v[0];
842   oNew[1] = origin[1] + v[1];
843   oNew[2] = origin[2] + v[2];
844   this->Plane->SetOrigin(oNew);
845 
846   this->UpdateRepresentation();
847 }
848 
849 //------------------------------------------------------------------------------
850 // Loop through all points and translate them
TranslateOrigin(double * p1,double * p2)851 void vtkImplicitPlaneWidget::TranslateOrigin(double* p1, double* p2)
852 {
853   // Get the motion vector
854   double v[3];
855   v[0] = p2[0] - p1[0];
856   v[1] = p2[1] - p1[1];
857   v[2] = p2[2] - p1[2];
858 
859   // Add to the current point, project back down onto plane
860   double* o = this->Plane->GetOrigin();
861   double* n = this->Plane->GetNormal();
862   double newOrigin[3];
863 
864   newOrigin[0] = o[0] + v[0];
865   newOrigin[1] = o[1] + v[1];
866   newOrigin[2] = o[2] + v[2];
867 
868   vtkPlane::ProjectPoint(newOrigin, o, n, newOrigin);
869   this->SetOrigin(newOrigin[0], newOrigin[1], newOrigin[2]);
870   this->UpdateRepresentation();
871 }
872 
873 //------------------------------------------------------------------------------
Scale(double * p1,double * p2,int vtkNotUsed (X),int Y)874 void vtkImplicitPlaneWidget::Scale(double* p1, double* p2, int vtkNotUsed(X), int Y)
875 {
876   // Get the motion vector
877   double v[3];
878   v[0] = p2[0] - p1[0];
879   v[1] = p2[1] - p1[1];
880   v[2] = p2[2] - p1[2];
881 
882   double* o = this->Plane->GetOrigin();
883 
884   // Compute the scale factor
885   double sf = vtkMath::Norm(v) / this->Outline->GetOutput()->GetLength();
886   if (Y > this->Interactor->GetLastEventPosition()[1])
887   {
888     sf = 1.0 + sf;
889   }
890   else
891   {
892     sf = 1.0 - sf;
893   }
894 
895   this->Transform->Identity();
896   this->Transform->Translate(o[0], o[1], o[2]);
897   this->Transform->Scale(sf, sf, sf);
898   this->Transform->Translate(-o[0], -o[1], -o[2]);
899 
900   double* origin = this->Box->GetOrigin();
901   double* spacing = this->Box->GetSpacing();
902   double oNew[3], p[3], pNew[3];
903   p[0] = origin[0] + spacing[0];
904   p[1] = origin[1] + spacing[1];
905   p[2] = origin[2] + spacing[2];
906 
907   this->Transform->TransformPoint(origin, oNew);
908   this->Transform->TransformPoint(p, pNew);
909 
910   this->Box->SetOrigin(oNew);
911   this->Box->SetSpacing((pNew[0] - oNew[0]), (pNew[1] - oNew[1]), (pNew[2] - oNew[2]));
912 
913   this->UpdateRepresentation();
914 }
915 
916 //------------------------------------------------------------------------------
Push(double * p1,double * p2)917 void vtkImplicitPlaneWidget::Push(double* p1, double* p2)
918 {
919   // Get the motion vector
920   double v[3];
921   v[0] = p2[0] - p1[0];
922   v[1] = p2[1] - p1[1];
923   v[2] = p2[2] - p1[2];
924 
925   this->Plane->Push(vtkMath::Dot(v, this->Plane->GetNormal()));
926   this->SetOrigin(this->Plane->GetOrigin());
927   this->UpdateRepresentation();
928 }
929 
930 //------------------------------------------------------------------------------
CreateDefaultProperties()931 void vtkImplicitPlaneWidget::CreateDefaultProperties()
932 {
933   // Normal properties
934   this->NormalProperty = vtkProperty::New();
935   this->NormalProperty->SetColor(1, 1, 1);
936   this->NormalProperty->SetLineWidth(2);
937 
938   this->SelectedNormalProperty = vtkProperty::New();
939   this->SelectedNormalProperty->SetColor(1, 0, 0);
940   this->NormalProperty->SetLineWidth(2);
941 
942   // Plane properties
943   this->PlaneProperty = vtkProperty::New();
944   this->PlaneProperty->SetAmbient(1.0);
945   this->PlaneProperty->SetAmbientColor(1.0, 1.0, 1.0);
946 
947   this->SelectedPlaneProperty = vtkProperty::New();
948   this->SelectedPlaneProperty->SetAmbient(1.0);
949   this->SelectedPlaneProperty->SetAmbientColor(0.0, 1.0, 0.0);
950   this->SelectedPlaneProperty->SetOpacity(0.25);
951 
952   // Outline properties
953   this->OutlineProperty = vtkProperty::New();
954   this->OutlineProperty->SetAmbient(1.0);
955   this->OutlineProperty->SetAmbientColor(1.0, 1.0, 1.0);
956 
957   this->SelectedOutlineProperty = vtkProperty::New();
958   this->SelectedOutlineProperty->SetAmbient(1.0);
959   this->SelectedOutlineProperty->SetAmbientColor(0.0, 1.0, 0.0);
960 
961   // Edge property
962   this->EdgesProperty = vtkProperty::New();
963 }
964 
965 //------------------------------------------------------------------------------
RegisterPickers()966 void vtkImplicitPlaneWidget::RegisterPickers()
967 {
968   vtkPickingManager* pm = this->GetPickingManager();
969   if (!pm)
970   {
971     return;
972   }
973   pm->AddPicker(this->Picker, this);
974 }
975 
976 //------------------------------------------------------------------------------
PlaceWidget(double bds[6])977 void vtkImplicitPlaneWidget::PlaceWidget(double bds[6])
978 {
979   int i;
980   double bounds[6], origin[3];
981 
982   this->AdjustBounds(bds, bounds, origin);
983 
984   // Set up the bounding box
985   this->Box->SetOrigin(bounds[0], bounds[2], bounds[4]);
986   this->Box->SetSpacing((bounds[1] - bounds[0]), (bounds[3] - bounds[2]), (bounds[5] - bounds[4]));
987   this->Outline->Update();
988 
989   this->LineSource->SetPoint1(this->Plane->GetOrigin());
990   if (this->NormalToYAxis)
991   {
992     this->Plane->SetNormal(0, 1, 0);
993     this->LineSource->SetPoint2(0, 1, 0);
994   }
995   else if (this->NormalToZAxis)
996   {
997     this->Plane->SetNormal(0, 0, 1);
998     this->LineSource->SetPoint2(0, 0, 1);
999   }
1000   else // default or x-normal
1001   {
1002     this->Plane->SetNormal(1, 0, 0);
1003     this->LineSource->SetPoint2(1, 0, 0);
1004   }
1005 
1006   for (i = 0; i < 6; i++)
1007   {
1008     this->InitialBounds[i] = bounds[i];
1009   }
1010 
1011   this->InitialLength = sqrt((bounds[1] - bounds[0]) * (bounds[1] - bounds[0]) +
1012     (bounds[3] - bounds[2]) * (bounds[3] - bounds[2]) +
1013     (bounds[5] - bounds[4]) * (bounds[5] - bounds[4]));
1014 
1015   this->UpdateRepresentation();
1016 
1017   this->SizeHandles();
1018 }
1019 
1020 //------------------------------------------------------------------------------
1021 // Description:
1022 // Set the origin of the plane.
SetOrigin(double x,double y,double z)1023 void vtkImplicitPlaneWidget::SetOrigin(double x, double y, double z)
1024 {
1025   double origin[3];
1026   origin[0] = x;
1027   origin[1] = y;
1028   origin[2] = z;
1029   this->SetOrigin(origin);
1030 }
1031 
1032 //------------------------------------------------------------------------------
1033 // Description:
1034 // Set the origin of the plane.
SetOrigin(double x[3])1035 void vtkImplicitPlaneWidget::SetOrigin(double x[3])
1036 {
1037   const double* bounds = this->Outline->GetOutput()->GetBounds();
1038   for (int i = 0; i < 3; i++)
1039   {
1040     if (x[i] < bounds[2 * i])
1041     {
1042       x[i] = bounds[2 * i];
1043     }
1044     else if (x[i] > bounds[2 * i + 1])
1045     {
1046       x[i] = bounds[2 * i + 1];
1047     }
1048   }
1049   this->Plane->SetOrigin(x);
1050   this->UpdateRepresentation();
1051 }
1052 
1053 //------------------------------------------------------------------------------
1054 // Description:
1055 // Get the origin of the plane.
GetOrigin()1056 double* vtkImplicitPlaneWidget::GetOrigin()
1057 {
1058   return this->Plane->GetOrigin();
1059 }
1060 
1061 //------------------------------------------------------------------------------
GetOrigin(double xyz[3])1062 void vtkImplicitPlaneWidget::GetOrigin(double xyz[3])
1063 {
1064   this->Plane->GetOrigin(xyz);
1065 }
1066 
1067 //------------------------------------------------------------------------------
1068 // Description:
1069 // Set the normal to the plane.
SetNormal(double x,double y,double z)1070 void vtkImplicitPlaneWidget::SetNormal(double x, double y, double z)
1071 {
1072   double n[3];
1073   n[0] = x;
1074   n[1] = y;
1075   n[2] = z;
1076   vtkMath::Normalize(n);
1077   this->Plane->SetNormal(n);
1078   this->UpdateRepresentation();
1079 }
1080 
1081 //------------------------------------------------------------------------------
1082 // Description:
1083 // Set the normal to the plane.
SetNormal(double n[3])1084 void vtkImplicitPlaneWidget::SetNormal(double n[3])
1085 {
1086   this->SetNormal(n[0], n[1], n[2]);
1087 }
1088 
1089 //------------------------------------------------------------------------------
1090 // Description:
1091 // Get the normal to the plane.
GetNormal()1092 double* vtkImplicitPlaneWidget::GetNormal()
1093 {
1094   return this->Plane->GetNormal();
1095 }
1096 
1097 //------------------------------------------------------------------------------
GetNormal(double xyz[3])1098 void vtkImplicitPlaneWidget::GetNormal(double xyz[3])
1099 {
1100   this->Plane->GetNormal(xyz);
1101 }
1102 
1103 //------------------------------------------------------------------------------
SetDrawPlane(vtkTypeBool drawPlane)1104 void vtkImplicitPlaneWidget::SetDrawPlane(vtkTypeBool drawPlane)
1105 {
1106   if (drawPlane == this->DrawPlane)
1107   {
1108     return;
1109   }
1110 
1111   this->Modified();
1112   this->DrawPlane = drawPlane;
1113   if (this->Enabled)
1114   {
1115     if (drawPlane)
1116     {
1117       this->CurrentRenderer->AddActor(this->CutActor);
1118     }
1119     else
1120     {
1121       this->CurrentRenderer->RemoveActor(this->CutActor);
1122     }
1123     this->Interactor->Render();
1124   }
1125 }
1126 
1127 //------------------------------------------------------------------------------
SetNormalToXAxis(vtkTypeBool var)1128 void vtkImplicitPlaneWidget::SetNormalToXAxis(vtkTypeBool var)
1129 {
1130   if (this->NormalToXAxis != var)
1131   {
1132     this->NormalToXAxis = var;
1133     this->Modified();
1134   }
1135   if (var)
1136   {
1137     this->NormalToYAxisOff();
1138     this->NormalToZAxisOff();
1139   }
1140 }
1141 
1142 //------------------------------------------------------------------------------
SetNormalToYAxis(vtkTypeBool var)1143 void vtkImplicitPlaneWidget::SetNormalToYAxis(vtkTypeBool var)
1144 {
1145   if (this->NormalToYAxis != var)
1146   {
1147     this->NormalToYAxis = var;
1148     this->Modified();
1149   }
1150   if (var)
1151   {
1152     this->NormalToXAxisOff();
1153     this->NormalToZAxisOff();
1154   }
1155 }
1156 
1157 //------------------------------------------------------------------------------
SetNormalToZAxis(vtkTypeBool var)1158 void vtkImplicitPlaneWidget::SetNormalToZAxis(vtkTypeBool var)
1159 {
1160   if (this->NormalToZAxis != var)
1161   {
1162     this->NormalToZAxis = var;
1163     this->Modified();
1164   }
1165   if (var)
1166   {
1167     this->NormalToXAxisOff();
1168     this->NormalToYAxisOff();
1169   }
1170 }
1171 
1172 //------------------------------------------------------------------------------
GetPolyData(vtkPolyData * pd)1173 void vtkImplicitPlaneWidget::GetPolyData(vtkPolyData* pd)
1174 {
1175   pd->ShallowCopy(this->Cutter->GetOutput());
1176 }
1177 
1178 //------------------------------------------------------------------------------
GetPolyDataAlgorithm()1179 vtkPolyDataAlgorithm* vtkImplicitPlaneWidget::GetPolyDataAlgorithm()
1180 {
1181   return this->Cutter;
1182 }
1183 
1184 //------------------------------------------------------------------------------
GetPlane(vtkPlane * plane)1185 void vtkImplicitPlaneWidget::GetPlane(vtkPlane* plane)
1186 {
1187   if (plane == nullptr)
1188   {
1189     return;
1190   }
1191 
1192   plane->SetNormal(this->Plane->GetNormal());
1193   plane->SetOrigin(this->Plane->GetOrigin());
1194 }
1195 
1196 //------------------------------------------------------------------------------
UpdatePlacement()1197 void vtkImplicitPlaneWidget::UpdatePlacement()
1198 {
1199   this->Outline->Update();
1200   this->Cutter->Update();
1201   this->Edges->Update();
1202   this->UpdateRepresentation();
1203 }
1204 
1205 //------------------------------------------------------------------------------
UpdateRepresentation()1206 void vtkImplicitPlaneWidget::UpdateRepresentation()
1207 {
1208   if (!this->CurrentRenderer)
1209   {
1210     return;
1211   }
1212 
1213   double* origin = this->Plane->GetOrigin();
1214   double* normal = this->Plane->GetNormal();
1215   double p2[3];
1216   if (!this->OutsideBounds)
1217   {
1218     const double* bounds = this->GetInput()->GetBounds();
1219     for (int i = 0; i < 3; i++)
1220     {
1221       if (origin[i] < bounds[2 * i])
1222       {
1223         origin[i] = bounds[2 * i];
1224       }
1225       else if (origin[i] > bounds[2 * i + 1])
1226       {
1227         origin[i] = bounds[2 * i + 1];
1228       }
1229     }
1230   }
1231 
1232   // Setup the plane normal
1233   double d = this->Outline->GetOutput()->GetLength();
1234 
1235   const double ratio = this->DiagonalRatio;
1236   p2[0] = origin[0] + ratio * d * normal[0];
1237   p2[1] = origin[1] + ratio * d * normal[1];
1238   p2[2] = origin[2] + ratio * d * normal[2];
1239 
1240   this->LineSource->SetPoint1(origin);
1241   this->LineSource->SetPoint2(p2);
1242   this->ConeSource->SetCenter(p2);
1243   this->ConeSource->SetDirection(normal);
1244 
1245   p2[0] = origin[0] - ratio * d * normal[0];
1246   p2[1] = origin[1] - ratio * d * normal[1];
1247   p2[2] = origin[2] - ratio * d * normal[2];
1248 
1249   this->LineSource2->SetPoint1(origin[0], origin[1], origin[2]);
1250   this->LineSource2->SetPoint2(p2);
1251   this->ConeSource2->SetCenter(p2);
1252   this->ConeSource2->SetDirection(normal[0], normal[1], normal[2]);
1253 
1254   // Set up the position handle
1255   this->Sphere->SetCenter(origin[0], origin[1], origin[2]);
1256 
1257   // Control the look of the edges
1258   if (this->Tubing)
1259   {
1260     this->EdgesMapper->SetInputConnection(this->EdgesTuber->GetOutputPort());
1261   }
1262   else
1263   {
1264     this->EdgesMapper->SetInputConnection(this->Edges->GetOutputPort());
1265   }
1266 }
1267 
1268 //------------------------------------------------------------------------------
SizeHandles()1269 void vtkImplicitPlaneWidget::SizeHandles()
1270 {
1271   double radius = this->vtk3DWidget::SizeHandles(1.35);
1272 
1273   this->ConeSource->SetHeight(2.0 * radius);
1274   this->ConeSource->SetRadius(radius);
1275   this->ConeSource2->SetHeight(2.0 * radius);
1276   this->ConeSource2->SetRadius(radius);
1277 
1278   this->Sphere->SetRadius(radius);
1279 
1280   this->EdgesTuber->SetRadius(0.25 * radius);
1281 }
1282