1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkBoxWidget.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 "vtkBoxWidget.h"
16 
17 #include "vtkActor.h"
18 #include "vtkAssemblyNode.h"
19 #include "vtkAssemblyPath.h"
20 #include "vtkCallbackCommand.h"
21 #include "vtkCamera.h"
22 #include "vtkCellArray.h"
23 #include "vtkCellPicker.h"
24 #include "vtkDoubleArray.h"
25 #include "vtkFloatArray.h"
26 #include "vtkMath.h"
27 #include "vtkObjectFactory.h"
28 #include "vtkPickingManager.h"
29 #include "vtkPlanes.h"
30 #include "vtkPolyData.h"
31 #include "vtkPolyDataMapper.h"
32 #include "vtkProperty.h"
33 #include "vtkRenderWindowInteractor.h"
34 #include "vtkRenderer.h"
35 #include "vtkSphereSource.h"
36 #include "vtkTransform.h"
37 
38 vtkStandardNewMacro(vtkBoxWidget);
39 
vtkBoxWidget()40 vtkBoxWidget::vtkBoxWidget()
41 {
42   this->State = vtkBoxWidget::Start;
43   this->EventCallbackCommand->SetCallback(vtkBoxWidget::ProcessEvents);
44 
45   // Enable/disable the translation, rotation, and scaling of the widget
46   this->TranslationEnabled = 1;
47   this->RotationEnabled = 1;
48   this->ScalingEnabled = 1;
49 
50   // Build the representation of the widget
51   int i;
52 
53   // Control orientation of normals
54   this->InsideOut = 0;
55   this->OutlineFaceWires = 0;
56   this->OutlineCursorWires = 1;
57 
58   // Construct the poly data representing the hex
59   this->HexPolyData = vtkPolyData::New();
60   this->HexMapper = vtkPolyDataMapper::New();
61   this->HexMapper->SetInputData(HexPolyData);
62   this->HexActor = vtkActor::New();
63   this->HexActor->SetMapper(this->HexMapper);
64 
65   // Construct initial points
66   this->Points = vtkPoints::New(VTK_DOUBLE);
67   this->Points->SetNumberOfPoints(15); // 8 corners; 6 faces; 1 center
68   this->HexPolyData->SetPoints(this->Points);
69 
70   // Construct connectivity for the faces. These are used to perform
71   // the picking.
72   vtkIdType pts[4];
73   vtkCellArray* cells = vtkCellArray::New();
74   cells->AllocateEstimate(6, 4);
75   pts[0] = 3;
76   pts[1] = 0;
77   pts[2] = 4;
78   pts[3] = 7;
79   cells->InsertNextCell(4, pts);
80   pts[0] = 1;
81   pts[1] = 2;
82   pts[2] = 6;
83   pts[3] = 5;
84   cells->InsertNextCell(4, pts);
85   pts[0] = 0;
86   pts[1] = 1;
87   pts[2] = 5;
88   pts[3] = 4;
89   cells->InsertNextCell(4, pts);
90   pts[0] = 2;
91   pts[1] = 3;
92   pts[2] = 7;
93   pts[3] = 6;
94   cells->InsertNextCell(4, pts);
95   pts[0] = 0;
96   pts[1] = 3;
97   pts[2] = 2;
98   pts[3] = 1;
99   cells->InsertNextCell(4, pts);
100   pts[0] = 4;
101   pts[1] = 5;
102   pts[2] = 6;
103   pts[3] = 7;
104   cells->InsertNextCell(4, pts);
105   this->HexPolyData->SetPolys(cells);
106   cells->Delete();
107   this->HexPolyData->BuildCells();
108 
109   // The face of the hexahedra
110   cells = vtkCellArray::New();
111   cells->AllocateEstimate(1, 4);
112   cells->InsertNextCell(4, pts); // temporary, replaced later
113   this->HexFacePolyData = vtkPolyData::New();
114   this->HexFacePolyData->SetPoints(this->Points);
115   this->HexFacePolyData->SetPolys(cells);
116   this->HexFaceMapper = vtkPolyDataMapper::New();
117   this->HexFaceMapper->SetInputData(HexFacePolyData);
118   this->HexFace = vtkActor::New();
119   this->HexFace->SetMapper(this->HexFaceMapper);
120   cells->Delete();
121 
122   // Create the outline for the hex
123   this->OutlinePolyData = vtkPolyData::New();
124   this->OutlinePolyData->SetPoints(this->Points);
125   this->OutlineMapper = vtkPolyDataMapper::New();
126   this->OutlineMapper->SetInputData(this->OutlinePolyData);
127   this->HexOutline = vtkActor::New();
128   this->HexOutline->SetMapper(this->OutlineMapper);
129   cells = vtkCellArray::New();
130   cells->AllocateEstimate(15, 2);
131   this->OutlinePolyData->SetLines(cells);
132   cells->Delete();
133 
134   // Set up the initial properties
135   this->CreateDefaultProperties();
136 
137   // Create the outline
138   this->GenerateOutline();
139 
140   // Create the handles
141   this->Handle = new vtkActor*[7];
142   this->HandleMapper = new vtkPolyDataMapper*[7];
143   this->HandleGeometry = new vtkSphereSource*[7];
144   for (i = 0; i < 7; i++)
145   {
146     this->HandleGeometry[i] = vtkSphereSource::New();
147     this->HandleGeometry[i]->SetThetaResolution(16);
148     this->HandleGeometry[i]->SetPhiResolution(8);
149     this->HandleMapper[i] = vtkPolyDataMapper::New();
150     this->HandleMapper[i]->SetInputConnection(this->HandleGeometry[i]->GetOutputPort());
151     this->Handle[i] = vtkActor::New();
152     this->Handle[i]->SetMapper(this->HandleMapper[i]);
153   }
154 
155   // Define the point coordinates
156   double bounds[6];
157   bounds[0] = -0.5;
158   bounds[1] = 0.5;
159   bounds[2] = -0.5;
160   bounds[3] = 0.5;
161   bounds[4] = -0.5;
162   bounds[5] = 0.5;
163   // Points 8-14 are down by PositionHandles();
164   this->PlaceWidget(bounds);
165 
166   // Manage the picking stuff
167   this->HandlePicker = vtkCellPicker::New();
168   this->HandlePicker->SetTolerance(0.001);
169   for (i = 0; i < 7; i++)
170   {
171     this->HandlePicker->AddPickList(this->Handle[i]);
172   }
173   this->HandlePicker->PickFromListOn();
174 
175   this->HexPicker = vtkCellPicker::New();
176   this->HexPicker->SetTolerance(0.001);
177   this->HexPicker->AddPickList(HexActor);
178   this->HexPicker->PickFromListOn();
179 
180   this->CurrentHandle = nullptr;
181 
182   this->Transform = vtkTransform::New();
183 }
184 
~vtkBoxWidget()185 vtkBoxWidget::~vtkBoxWidget()
186 {
187   this->HexActor->Delete();
188   this->HexMapper->Delete();
189   this->HexPolyData->Delete();
190   this->Points->Delete();
191 
192   this->HexFace->Delete();
193   this->HexFaceMapper->Delete();
194   this->HexFacePolyData->Delete();
195 
196   this->HexOutline->Delete();
197   this->OutlineMapper->Delete();
198   this->OutlinePolyData->Delete();
199 
200   for (int i = 0; i < 7; i++)
201   {
202     this->HandleGeometry[i]->Delete();
203     this->HandleMapper[i]->Delete();
204     this->Handle[i]->Delete();
205   }
206   delete[] this->Handle;
207   delete[] this->HandleMapper;
208   delete[] this->HandleGeometry;
209 
210   this->HandlePicker->Delete();
211   this->HexPicker->Delete();
212 
213   this->Transform->Delete();
214 
215   this->HandleProperty->Delete();
216   this->SelectedHandleProperty->Delete();
217   this->FaceProperty->Delete();
218   this->SelectedFaceProperty->Delete();
219   this->OutlineProperty->Delete();
220   this->SelectedOutlineProperty->Delete();
221 }
222 
SetEnabled(int enabling)223 void vtkBoxWidget::SetEnabled(int enabling)
224 {
225   if (!this->Interactor)
226   {
227     vtkErrorMacro(<< "The interactor must be set prior to enabling/disabling widget");
228     return;
229   }
230 
231   if (enabling) //------------------------------------------------------------
232   {
233     vtkDebugMacro(<< "Enabling widget");
234 
235     if (this->Enabled) // already enabled, just return
236     {
237       return;
238     }
239 
240     if (!this->CurrentRenderer)
241     {
242       this->SetCurrentRenderer(this->Interactor->FindPokedRenderer(
243         this->Interactor->GetLastEventPosition()[0], this->Interactor->GetLastEventPosition()[1]));
244       if (this->CurrentRenderer == nullptr)
245       {
246         return;
247       }
248     }
249 
250     this->Enabled = 1;
251 
252     // listen to the following events
253     vtkRenderWindowInteractor* i = this->Interactor;
254     i->AddObserver(vtkCommand::MouseMoveEvent, this->EventCallbackCommand, this->Priority);
255     i->AddObserver(vtkCommand::LeftButtonPressEvent, this->EventCallbackCommand, this->Priority);
256     i->AddObserver(vtkCommand::LeftButtonReleaseEvent, this->EventCallbackCommand, this->Priority);
257     i->AddObserver(vtkCommand::MiddleButtonPressEvent, this->EventCallbackCommand, this->Priority);
258     i->AddObserver(
259       vtkCommand::MiddleButtonReleaseEvent, this->EventCallbackCommand, this->Priority);
260     i->AddObserver(vtkCommand::RightButtonPressEvent, this->EventCallbackCommand, this->Priority);
261     i->AddObserver(vtkCommand::RightButtonReleaseEvent, this->EventCallbackCommand, this->Priority);
262 
263     // Add the various actors
264     // Add the outline
265     this->CurrentRenderer->AddActor(this->HexActor);
266     this->CurrentRenderer->AddActor(this->HexOutline);
267     this->HexActor->SetProperty(this->OutlineProperty);
268     this->HexOutline->SetProperty(this->OutlineProperty);
269 
270     // Add the hex face
271     this->CurrentRenderer->AddActor(this->HexFace);
272     this->HexFace->SetProperty(this->FaceProperty);
273 
274     // turn on the handles
275     for (int j = 0; j < 7; j++)
276     {
277       this->CurrentRenderer->AddActor(this->Handle[j]);
278       this->Handle[j]->SetProperty(this->HandleProperty);
279     }
280     this->RegisterPickers();
281 
282     this->InvokeEvent(vtkCommand::EnableEvent, nullptr);
283   }
284 
285   else // disabling-------------------------------------------------------------
286   {
287     vtkDebugMacro(<< "Disabling widget");
288 
289     if (!this->Enabled) // already disabled, just return
290     {
291       return;
292     }
293 
294     this->Enabled = 0;
295 
296     // don't listen for events any more
297     this->Interactor->RemoveObserver(this->EventCallbackCommand);
298 
299     // turn off the outline
300     this->CurrentRenderer->RemoveActor(this->HexActor);
301     this->CurrentRenderer->RemoveActor(this->HexOutline);
302 
303     // turn off the hex face
304     this->CurrentRenderer->RemoveActor(this->HexFace);
305 
306     // turn off the handles
307     for (int i = 0; i < 7; i++)
308     {
309       this->CurrentRenderer->RemoveActor(this->Handle[i]);
310     }
311 
312     this->CurrentHandle = nullptr;
313     this->InvokeEvent(vtkCommand::DisableEvent, nullptr);
314     this->SetCurrentRenderer(nullptr);
315     this->UnRegisterPickers();
316   }
317 
318   this->Interactor->Render();
319 }
320 
ProcessEvents(vtkObject * vtkNotUsed (object),unsigned long event,void * clientdata,void * vtkNotUsed (calldata))321 void vtkBoxWidget::ProcessEvents(
322   vtkObject* vtkNotUsed(object), unsigned long event, void* clientdata, void* vtkNotUsed(calldata))
323 {
324   vtkBoxWidget* self = reinterpret_cast<vtkBoxWidget*>(clientdata);
325 
326   // okay, let's do the right thing
327   switch (event)
328   {
329     case vtkCommand::LeftButtonPressEvent:
330       self->OnLeftButtonDown();
331       break;
332     case vtkCommand::LeftButtonReleaseEvent:
333       self->OnLeftButtonUp();
334       break;
335     case vtkCommand::MiddleButtonPressEvent:
336       self->OnMiddleButtonDown();
337       break;
338     case vtkCommand::MiddleButtonReleaseEvent:
339       self->OnMiddleButtonUp();
340       break;
341     case vtkCommand::RightButtonPressEvent:
342       self->OnRightButtonDown();
343       break;
344     case vtkCommand::RightButtonReleaseEvent:
345       self->OnRightButtonUp();
346       break;
347     case vtkCommand::MouseMoveEvent:
348       self->OnMouseMove();
349       break;
350   }
351 }
352 
PrintSelf(ostream & os,vtkIndent indent)353 void vtkBoxWidget::PrintSelf(ostream& os, vtkIndent indent)
354 {
355   this->Superclass::PrintSelf(os, indent);
356 
357   double* bounds = this->InitialBounds;
358   os << indent << "Initial Bounds: "
359      << "(" << bounds[0] << "," << bounds[1] << ") "
360      << "(" << bounds[2] << "," << bounds[3] << ") "
361      << "(" << bounds[4] << "," << bounds[5] << ")\n";
362 
363   if (this->HandleProperty)
364   {
365     os << indent << "Handle Property: " << this->HandleProperty << "\n";
366   }
367   else
368   {
369     os << indent << "Handle Property: (none)\n";
370   }
371   if (this->SelectedHandleProperty)
372   {
373     os << indent << "Selected Handle Property: " << this->SelectedHandleProperty << "\n";
374   }
375   else
376   {
377     os << indent << "SelectedHandle Property: (none)\n";
378   }
379 
380   if (this->FaceProperty)
381   {
382     os << indent << "Face Property: " << this->FaceProperty << "\n";
383   }
384   else
385   {
386     os << indent << "Face Property: (none)\n";
387   }
388   if (this->SelectedFaceProperty)
389   {
390     os << indent << "Selected Face Property: " << this->SelectedFaceProperty << "\n";
391   }
392   else
393   {
394     os << indent << "Selected Face 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   os << indent << "Outline Face Wires: " << (this->OutlineFaceWires ? "On\n" : "Off\n");
415   os << indent << "Outline Cursor Wires: " << (this->OutlineCursorWires ? "On\n" : "Off\n");
416   os << indent << "Inside Out: " << (this->InsideOut ? "On\n" : "Off\n");
417   os << indent << "Translation Enabled: " << (this->TranslationEnabled ? "On\n" : "Off\n");
418   os << indent << "Scaling Enabled: " << (this->ScalingEnabled ? "On\n" : "Off\n");
419   os << indent << "Rotation Enabled: " << (this->RotationEnabled ? "On\n" : "Off\n");
420 }
421 
422 #define VTK_AVERAGE(a, b, c)                                                                       \
423   c[0] = (a[0] + b[0]) / 2.0;                                                                      \
424   c[1] = (a[1] + b[1]) / 2.0;                                                                      \
425   c[2] = (a[2] + b[2]) / 2.0;
426 
PositionHandles()427 void vtkBoxWidget::PositionHandles()
428 {
429   double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
430   double* p0 = pts;
431   double* p1 = pts + 3 * 1;
432   double* p2 = pts + 3 * 2;
433   double* p3 = pts + 3 * 3;
434   // double *p4 = pts + 3*4;
435   double* p5 = pts + 3 * 5;
436   double* p6 = pts + 3 * 6;
437   double* p7 = pts + 3 * 7;
438   double x[3];
439 
440   VTK_AVERAGE(p0, p7, x);
441   this->Points->SetPoint(8, x);
442   VTK_AVERAGE(p1, p6, x);
443   this->Points->SetPoint(9, x);
444   VTK_AVERAGE(p0, p5, x);
445   this->Points->SetPoint(10, x);
446   VTK_AVERAGE(p2, p7, x);
447   this->Points->SetPoint(11, x);
448   VTK_AVERAGE(p1, p3, x);
449   this->Points->SetPoint(12, x);
450   VTK_AVERAGE(p5, p7, x);
451   this->Points->SetPoint(13, x);
452   VTK_AVERAGE(p0, p6, x);
453   this->Points->SetPoint(14, x);
454 
455   int i;
456   for (i = 0; i < 7; ++i)
457   {
458     this->HandleGeometry[i]->SetCenter(this->Points->GetPoint(8 + i));
459   }
460 
461   this->Points->GetData()->Modified();
462   this->HexFacePolyData->Modified();
463   this->HexPolyData->Modified();
464   this->GenerateOutline();
465 }
466 #undef VTK_AVERAGE
467 
HandlesOn()468 void vtkBoxWidget::HandlesOn()
469 {
470   for (int i = 0; i < 7; i++)
471   {
472     this->Handle[i]->VisibilityOn();
473   }
474 }
475 
HandlesOff()476 void vtkBoxWidget::HandlesOff()
477 {
478   for (int i = 0; i < 7; i++)
479   {
480     this->Handle[i]->VisibilityOff();
481   }
482 }
483 
SizeHandles()484 void vtkBoxWidget::SizeHandles()
485 {
486   double radius = this->vtk3DWidget::SizeHandles(1.5);
487   for (int i = 0; i < 7; i++)
488   {
489     this->HandleGeometry[i]->SetRadius(radius);
490   }
491 }
492 
HighlightHandle(vtkProp * prop)493 int vtkBoxWidget::HighlightHandle(vtkProp* prop)
494 {
495   // first unhighlight anything picked
496   this->HighlightOutline(0);
497   if (this->CurrentHandle)
498   {
499     this->CurrentHandle->SetProperty(this->HandleProperty);
500   }
501 
502   this->CurrentHandle = static_cast<vtkActor*>(prop);
503 
504   if (this->CurrentHandle)
505   {
506     this->CurrentHandle->SetProperty(this->SelectedHandleProperty);
507     for (int i = 0; i < 6; i++) // find attached face
508     {
509       if (this->CurrentHandle == this->Handle[i])
510       {
511         return i;
512       }
513     }
514   }
515 
516   if (this->CurrentHandle == this->Handle[6])
517   {
518     this->HighlightOutline(1);
519   }
520 
521   return -1;
522 }
523 
HighlightFace(int cellId)524 void vtkBoxWidget::HighlightFace(int cellId)
525 {
526   if (cellId >= 0)
527   {
528     vtkIdType npts;
529     const vtkIdType* pts;
530     vtkCellArray* cells = this->HexFacePolyData->GetPolys();
531     this->HexPolyData->GetCellPoints(cellId, npts, pts);
532     cells->ReplaceCellAtId(0, npts, pts);
533     cells->Modified();
534     this->CurrentHexFace = cellId;
535     this->HexFace->SetProperty(this->SelectedFaceProperty);
536     if (!this->CurrentHandle)
537     {
538       this->CurrentHandle = this->HexFace;
539     }
540   }
541   else
542   {
543     this->HexFace->SetProperty(this->FaceProperty);
544     this->CurrentHexFace = -1;
545   }
546 }
547 
HighlightOutline(int highlight)548 void vtkBoxWidget::HighlightOutline(int highlight)
549 {
550   if (highlight)
551   {
552     this->HexActor->SetProperty(this->SelectedOutlineProperty);
553     this->HexOutline->SetProperty(this->SelectedOutlineProperty);
554   }
555   else
556   {
557     this->HexActor->SetProperty(this->OutlineProperty);
558     this->HexOutline->SetProperty(this->OutlineProperty);
559   }
560 }
561 
OnLeftButtonDown()562 void vtkBoxWidget::OnLeftButtonDown()
563 {
564   int X = this->Interactor->GetEventPosition()[0];
565   int Y = this->Interactor->GetEventPosition()[1];
566 
567   // Okay, we can process this. Try to pick handles first;
568   // if no handles picked, then pick the bounding box.
569   if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y))
570   {
571     this->State = vtkBoxWidget::Outside;
572     return;
573   }
574 
575   vtkAssemblyPath* path = this->GetAssemblyPath(X, Y, 0., this->HandlePicker);
576 
577   if (path != nullptr)
578   {
579     this->State = vtkBoxWidget::Moving;
580     this->HighlightFace(this->HighlightHandle(path->GetFirstNode()->GetViewProp()));
581     this->HandlePicker->GetPickPosition(this->LastPickPosition);
582     this->ValidPick = 1;
583   }
584   else
585   {
586     path = this->GetAssemblyPath(X, Y, 0., this->HexPicker);
587 
588     if (path != nullptr)
589     {
590       this->State = vtkBoxWidget::Moving;
591       this->HexPicker->GetPickPosition(this->LastPickPosition);
592       this->ValidPick = 1;
593       if (!this->Interactor->GetShiftKey())
594       {
595         this->HighlightHandle(nullptr);
596         this->HighlightFace(this->HexPicker->GetCellId());
597       }
598       else
599       {
600         this->CurrentHandle = this->Handle[6];
601         this->HighlightOutline(1);
602       }
603     }
604     else
605     {
606       this->HighlightFace(this->HighlightHandle(nullptr));
607       this->State = vtkBoxWidget::Outside;
608       return;
609     }
610   }
611 
612   this->EventCallbackCommand->SetAbortFlag(1);
613   this->StartInteraction();
614   this->InvokeEvent(vtkCommand::StartInteractionEvent, nullptr);
615   this->Interactor->Render();
616 }
617 
OnLeftButtonUp()618 void vtkBoxWidget::OnLeftButtonUp()
619 {
620   if (this->State == vtkBoxWidget::Outside || this->State == vtkBoxWidget::Start)
621   {
622     return;
623   }
624 
625   this->State = vtkBoxWidget::Start;
626   this->HighlightFace(this->HighlightHandle(nullptr));
627   this->SizeHandles();
628 
629   this->EventCallbackCommand->SetAbortFlag(1);
630   this->EndInteraction();
631   this->InvokeEvent(vtkCommand::EndInteractionEvent, nullptr);
632   this->Interactor->Render();
633 }
634 
OnMiddleButtonDown()635 void vtkBoxWidget::OnMiddleButtonDown()
636 {
637   int X = this->Interactor->GetEventPosition()[0];
638   int Y = this->Interactor->GetEventPosition()[1];
639 
640   // Okay, we can process this. Try to pick handles first;
641   // if no handles picked, then pick the bounding box.
642   if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y))
643   {
644     this->State = vtkBoxWidget::Outside;
645     return;
646   }
647 
648   vtkAssemblyPath* path = this->GetAssemblyPath(X, Y, 0., this->HandlePicker);
649 
650   if (path != nullptr)
651   {
652     this->State = vtkBoxWidget::Moving;
653     this->CurrentHandle = this->Handle[6];
654     this->HighlightOutline(1);
655     this->HandlePicker->GetPickPosition(this->LastPickPosition);
656     this->ValidPick = 1;
657   }
658   else
659   {
660     path = this->GetAssemblyPath(X, Y, 0., this->HexPicker);
661 
662     if (path != nullptr)
663     {
664       this->State = vtkBoxWidget::Moving;
665       this->CurrentHandle = this->Handle[6];
666       this->HighlightOutline(1);
667       this->HexPicker->GetPickPosition(this->LastPickPosition);
668       this->ValidPick = 1;
669     }
670     else
671     {
672       this->HighlightFace(this->HighlightHandle(nullptr));
673       this->State = vtkBoxWidget::Outside;
674       return;
675     }
676   }
677 
678   this->EventCallbackCommand->SetAbortFlag(1);
679   this->StartInteraction();
680   this->InvokeEvent(vtkCommand::StartInteractionEvent, nullptr);
681   this->Interactor->Render();
682 }
683 
OnMiddleButtonUp()684 void vtkBoxWidget::OnMiddleButtonUp()
685 {
686   if (this->State == vtkBoxWidget::Outside || this->State == vtkBoxWidget::Start)
687   {
688     return;
689   }
690 
691   this->State = vtkBoxWidget::Start;
692   this->HighlightFace(this->HighlightHandle(nullptr));
693   this->SizeHandles();
694 
695   this->EventCallbackCommand->SetAbortFlag(1);
696   this->EndInteraction();
697   this->InvokeEvent(vtkCommand::EndInteractionEvent, nullptr);
698   this->Interactor->Render();
699 }
700 
OnRightButtonDown()701 void vtkBoxWidget::OnRightButtonDown()
702 {
703   int X = this->Interactor->GetEventPosition()[0];
704   int Y = this->Interactor->GetEventPosition()[1];
705 
706   // Okay, we can process this. Try to pick handles first;
707   // if no handles picked, then pick the bounding box.
708   if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y))
709   {
710     this->State = vtkBoxWidget::Outside;
711     return;
712   }
713 
714   vtkAssemblyPath* path = this->GetAssemblyPath(X, Y, 0., this->HandlePicker);
715 
716   if (path != nullptr)
717   {
718     this->State = vtkBoxWidget::Scaling;
719     this->HighlightOutline(1);
720     this->HandlePicker->GetPickPosition(this->LastPickPosition);
721     this->ValidPick = 1;
722   }
723   else
724   {
725     path = this->GetAssemblyPath(X, Y, 0., this->HexPicker);
726 
727     if (path != nullptr)
728     {
729       this->State = vtkBoxWidget::Scaling;
730       this->HighlightOutline(1);
731       this->HexPicker->GetPickPosition(this->LastPickPosition);
732       this->ValidPick = 1;
733     }
734     else
735     {
736       this->State = vtkBoxWidget::Outside;
737       return;
738     }
739   }
740 
741   this->EventCallbackCommand->SetAbortFlag(1);
742   this->StartInteraction();
743   this->InvokeEvent(vtkCommand::StartInteractionEvent, nullptr);
744   this->Interactor->Render();
745 }
746 
OnRightButtonUp()747 void vtkBoxWidget::OnRightButtonUp()
748 {
749   if (this->State == vtkBoxWidget::Outside)
750   {
751     return;
752   }
753 
754   this->State = vtkBoxWidget::Start;
755   this->HighlightOutline(0);
756   this->SizeHandles();
757 
758   this->EventCallbackCommand->SetAbortFlag(1);
759   this->EndInteraction();
760   this->InvokeEvent(vtkCommand::EndInteractionEvent, nullptr);
761   this->Interactor->Render();
762 }
763 
OnMouseMove()764 void vtkBoxWidget::OnMouseMove()
765 {
766   // See whether we're active
767   if (this->State == vtkBoxWidget::Outside || this->State == vtkBoxWidget::Start)
768   {
769     return;
770   }
771 
772   int X = this->Interactor->GetEventPosition()[0];
773   int Y = this->Interactor->GetEventPosition()[1];
774 
775   // Do different things depending on state
776   // Calculations everybody does
777   double focalPoint[4], pickPoint[4], prevPickPoint[4];
778   double z, vpn[3];
779 
780   vtkCamera* camera = this->CurrentRenderer->GetActiveCamera();
781   if (!camera)
782   {
783     return;
784   }
785 
786   // Compute the two points defining the motion vector
787   this->ComputeWorldToDisplay(
788     this->LastPickPosition[0], this->LastPickPosition[1], this->LastPickPosition[2], focalPoint);
789   z = focalPoint[2];
790   this->ComputeDisplayToWorld(double(this->Interactor->GetLastEventPosition()[0]),
791     double(this->Interactor->GetLastEventPosition()[1]), z, prevPickPoint);
792   this->ComputeDisplayToWorld(double(X), double(Y), z, pickPoint);
793 
794   // Process the motion
795   if (this->State == vtkBoxWidget::Moving)
796   {
797     // Okay to process
798     if (this->CurrentHandle)
799     {
800       if (this->RotationEnabled && this->CurrentHandle == this->HexFace)
801       {
802         camera->GetViewPlaneNormal(vpn);
803         this->Rotate(X, Y, prevPickPoint, pickPoint, vpn);
804       }
805       else if (this->TranslationEnabled && this->CurrentHandle == this->Handle[6])
806       {
807         this->Translate(prevPickPoint, pickPoint);
808       }
809       else if (this->TranslationEnabled && this->ScalingEnabled)
810       {
811         if (this->CurrentHandle == this->Handle[0])
812         {
813           this->MoveMinusXFace(prevPickPoint, pickPoint);
814         }
815         else if (this->CurrentHandle == this->Handle[1])
816         {
817           this->MovePlusXFace(prevPickPoint, pickPoint);
818         }
819         else if (this->CurrentHandle == this->Handle[2])
820         {
821           this->MoveMinusYFace(prevPickPoint, pickPoint);
822         }
823         else if (this->CurrentHandle == this->Handle[3])
824         {
825           this->MovePlusYFace(prevPickPoint, pickPoint);
826         }
827         else if (this->CurrentHandle == this->Handle[4])
828         {
829           this->MoveMinusZFace(prevPickPoint, pickPoint);
830         }
831         else if (this->CurrentHandle == this->Handle[5])
832         {
833           this->MovePlusZFace(prevPickPoint, pickPoint);
834         }
835       }
836     }
837   }
838   else if (this->ScalingEnabled && this->State == vtkBoxWidget::Scaling)
839   {
840     this->Scale(prevPickPoint, pickPoint, X, Y);
841   }
842 
843   // Interact, if desired
844   this->EventCallbackCommand->SetAbortFlag(1);
845   this->InvokeEvent(vtkCommand::InteractionEvent, nullptr);
846   this->Interactor->Render();
847 }
848 
MoveFace(double * p1,double * p2,double * dir,double * x1,double * x2,double * x3,double * x4,double * x5)849 void vtkBoxWidget::MoveFace(
850   double* p1, double* p2, double* dir, double* x1, double* x2, double* x3, double* x4, double* x5)
851 {
852   int i;
853   double v[3], v2[3];
854 
855   for (i = 0; i < 3; i++)
856   {
857     v[i] = p2[i] - p1[i];
858     v2[i] = dir[i];
859   }
860 
861   vtkMath::Normalize(v2);
862   double f = vtkMath::Dot(v, v2);
863 
864   for (i = 0; i < 3; i++)
865   {
866     v[i] = f * v2[i];
867 
868     x1[i] += v[i];
869     x2[i] += v[i];
870     x3[i] += v[i];
871     x4[i] += v[i];
872     x5[i] += v[i];
873   }
874   this->PositionHandles();
875 }
876 
GetDirection(const double Nx[3],const double Ny[3],const double Nz[3],double dir[3])877 void vtkBoxWidget::GetDirection(
878   const double Nx[3], const double Ny[3], const double Nz[3], double dir[3])
879 {
880   double dotNy, dotNz;
881   double y[3];
882 
883   if (vtkMath::Dot(Nx, Nx) != 0)
884   {
885     dir[0] = Nx[0];
886     dir[1] = Nx[1];
887     dir[2] = Nx[2];
888   }
889   else
890   {
891     dotNy = vtkMath::Dot(Ny, Ny);
892     dotNz = vtkMath::Dot(Nz, Nz);
893     if (dotNy != 0 && dotNz != 0)
894     {
895       vtkMath::Cross(Ny, Nz, dir);
896     }
897     else if (dotNy != 0)
898     {
899       // dir must have been initialized to the
900       // corresponding coordinate direction before calling
901       // this method
902       vtkMath::Cross(Ny, dir, y);
903       vtkMath::Cross(y, Ny, dir);
904     }
905     else if (dotNz != 0)
906     {
907       // dir must have been initialized to the
908       // corresponding coordinate direction before calling
909       // this method
910       vtkMath::Cross(Nz, dir, y);
911       vtkMath::Cross(y, Nz, dir);
912     }
913   }
914 }
MovePlusXFace(double * p1,double * p2)915 void vtkBoxWidget::MovePlusXFace(double* p1, double* p2)
916 {
917   double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
918 
919   double* h1 = pts + 3 * 9;
920 
921   double* x1 = pts + 3 * 1;
922   double* x2 = pts + 3 * 2;
923   double* x3 = pts + 3 * 5;
924   double* x4 = pts + 3 * 6;
925 
926   double dir[3] = { 1, 0, 0 };
927   this->ComputeNormals();
928   this->GetDirection(this->N[1], this->N[3], this->N[5], dir);
929   this->MoveFace(p1, p2, dir, x1, x2, x3, x4, h1);
930 }
931 
MoveMinusXFace(double * p1,double * p2)932 void vtkBoxWidget::MoveMinusXFace(double* p1, double* p2)
933 {
934   double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
935 
936   double* h1 = pts + 3 * 8;
937 
938   double* x1 = pts + 3 * 0;
939   double* x2 = pts + 3 * 3;
940   double* x3 = pts + 3 * 4;
941   double* x4 = pts + 3 * 7;
942 
943   double dir[3] = { -1, 0, 0 };
944   this->ComputeNormals();
945   this->GetDirection(this->N[0], this->N[4], this->N[2], dir);
946 
947   this->MoveFace(p1, p2, dir, x1, x2, x3, x4, h1);
948 }
949 
MovePlusYFace(double * p1,double * p2)950 void vtkBoxWidget::MovePlusYFace(double* p1, double* p2)
951 {
952   double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
953 
954   double* h1 = pts + 3 * 11;
955 
956   double* x1 = pts + 3 * 2;
957   double* x2 = pts + 3 * 3;
958   double* x3 = pts + 3 * 6;
959   double* x4 = pts + 3 * 7;
960 
961   double dir[3] = { 0, 1, 0 };
962   this->ComputeNormals();
963   this->GetDirection(this->N[3], this->N[5], this->N[1], dir);
964 
965   this->MoveFace(p1, p2, dir, x1, x2, x3, x4, h1);
966 }
967 
MoveMinusYFace(double * p1,double * p2)968 void vtkBoxWidget::MoveMinusYFace(double* p1, double* p2)
969 {
970   double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
971 
972   double* h1 = pts + 3 * 10;
973 
974   double* x1 = pts + 3 * 0;
975   double* x2 = pts + 3 * 1;
976   double* x3 = pts + 3 * 4;
977   double* x4 = pts + 3 * 5;
978 
979   double dir[3] = { 0, -1, 0 };
980   this->ComputeNormals();
981   this->GetDirection(this->N[2], this->N[0], this->N[4], dir);
982 
983   this->MoveFace(p1, p2, dir, x1, x2, x3, x4, h1);
984 }
985 
MovePlusZFace(double * p1,double * p2)986 void vtkBoxWidget::MovePlusZFace(double* p1, double* p2)
987 {
988   double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
989 
990   double* h1 = pts + 3 * 13;
991 
992   double* x1 = pts + 3 * 4;
993   double* x2 = pts + 3 * 5;
994   double* x3 = pts + 3 * 6;
995   double* x4 = pts + 3 * 7;
996 
997   double dir[3] = { 0, 0, 1 };
998   this->ComputeNormals();
999   this->GetDirection(this->N[5], this->N[1], this->N[3], dir);
1000 
1001   this->MoveFace(p1, p2, dir, x1, x2, x3, x4, h1);
1002 }
1003 
MoveMinusZFace(double * p1,double * p2)1004 void vtkBoxWidget::MoveMinusZFace(double* p1, double* p2)
1005 {
1006   double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
1007 
1008   double* h1 = pts + 3 * 12;
1009 
1010   double* x1 = pts + 3 * 0;
1011   double* x2 = pts + 3 * 1;
1012   double* x3 = pts + 3 * 2;
1013   double* x4 = pts + 3 * 3;
1014 
1015   double dir[3] = { 0, 0, -1 };
1016   this->ComputeNormals();
1017   this->GetDirection(this->N[4], this->N[2], this->N[0], dir);
1018 
1019   this->MoveFace(p1, p2, dir, x1, x2, x3, x4, h1);
1020 }
1021 
1022 // Loop through all points and translate them
Translate(double * p1,double * p2)1023 void vtkBoxWidget::Translate(double* p1, double* p2)
1024 {
1025   double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
1026   double v[3];
1027 
1028   v[0] = p2[0] - p1[0];
1029   v[1] = p2[1] - p1[1];
1030   v[2] = p2[2] - p1[2];
1031 
1032   // Move the corners
1033   for (int i = 0; i < 8; i++)
1034   {
1035     *pts++ += v[0];
1036     *pts++ += v[1];
1037     *pts++ += v[2];
1038   }
1039   this->PositionHandles();
1040 }
1041 
Scale(double * vtkNotUsed (p1),double * vtkNotUsed (p2),int vtkNotUsed (X),int Y)1042 void vtkBoxWidget::Scale(double* vtkNotUsed(p1), double* vtkNotUsed(p2), int vtkNotUsed(X), int Y)
1043 {
1044   double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
1045   double* center = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(3 * 14);
1046   double sf;
1047 
1048   if (Y > this->Interactor->GetLastEventPosition()[1])
1049   {
1050     sf = 1.03;
1051   }
1052   else
1053   {
1054     sf = 0.97;
1055   }
1056 
1057   // Move the corners
1058   for (int i = 0; i < 8; i++, pts += 3)
1059   {
1060     pts[0] = sf * (pts[0] - center[0]) + center[0];
1061     pts[1] = sf * (pts[1] - center[1]) + center[1];
1062     pts[2] = sf * (pts[2] - center[2]) + center[2];
1063   }
1064   this->PositionHandles();
1065 }
1066 
ComputeNormals()1067 void vtkBoxWidget::ComputeNormals()
1068 {
1069   double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
1070   double* p0 = pts;
1071   double* px = pts + 3 * 1;
1072   double* py = pts + 3 * 3;
1073   double* pz = pts + 3 * 4;
1074   int i;
1075 
1076   for (i = 0; i < 3; i++)
1077   {
1078     this->N[0][i] = p0[i] - px[i];
1079     this->N[2][i] = p0[i] - py[i];
1080     this->N[4][i] = p0[i] - pz[i];
1081   }
1082   vtkMath::Normalize(this->N[0]);
1083   vtkMath::Normalize(this->N[2]);
1084   vtkMath::Normalize(this->N[4]);
1085   for (i = 0; i < 3; i++)
1086   {
1087     this->N[1][i] = -this->N[0][i];
1088     this->N[3][i] = -this->N[2][i];
1089     this->N[5][i] = -this->N[4][i];
1090   }
1091 }
1092 
GetPlanes(vtkPlanes * planes)1093 void vtkBoxWidget::GetPlanes(vtkPlanes* planes)
1094 {
1095   if (!planes)
1096   {
1097     return;
1098   }
1099 
1100   this->ComputeNormals();
1101 
1102   vtkPoints* pts = vtkPoints::New(VTK_DOUBLE);
1103   pts->SetNumberOfPoints(6);
1104 
1105   vtkDoubleArray* normals = vtkDoubleArray::New();
1106   normals->SetNumberOfComponents(3);
1107   normals->SetNumberOfTuples(6);
1108 
1109   // Set the normals and coordinate values
1110   double factor = (this->InsideOut ? -1.0 : 1.0);
1111   for (int i = 0; i < 6; i++)
1112   {
1113     pts->SetPoint(i, this->Points->GetPoint(8 + i));
1114     normals->SetTuple3(i, factor * this->N[i][0], factor * this->N[i][1], factor * this->N[i][2]);
1115   }
1116 
1117   planes->SetPoints(pts);
1118   planes->SetNormals(normals);
1119 
1120   pts->Delete();
1121   normals->Delete();
1122 }
1123 
Rotate(int X,int Y,double * p1,double * p2,double * vpn)1124 void vtkBoxWidget::Rotate(int X, int Y, double* p1, double* p2, double* vpn)
1125 {
1126   double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
1127   double* center = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(3 * 14);
1128   double v[3];    // vector of motion
1129   double axis[3]; // axis of rotation
1130   double theta;   // rotation angle
1131   int i;
1132 
1133   v[0] = p2[0] - p1[0];
1134   v[1] = p2[1] - p1[1];
1135   v[2] = p2[2] - p1[2];
1136 
1137   // Create axis of rotation and angle of rotation
1138   vtkMath::Cross(vpn, v, axis);
1139   if (vtkMath::Normalize(axis) == 0.0)
1140   {
1141     return;
1142   }
1143   const int* size = this->CurrentRenderer->GetSize();
1144   double l2 = (X - this->Interactor->GetLastEventPosition()[0]) *
1145       (X - this->Interactor->GetLastEventPosition()[0]) +
1146     (Y - this->Interactor->GetLastEventPosition()[1]) *
1147       (Y - this->Interactor->GetLastEventPosition()[1]);
1148   theta = 360.0 * sqrt(l2 / (size[0] * size[0] + size[1] * size[1]));
1149 
1150   // Manipulate the transform to reflect the rotation
1151   this->Transform->Identity();
1152   this->Transform->Translate(center[0], center[1], center[2]);
1153   this->Transform->RotateWXYZ(theta, axis);
1154   this->Transform->Translate(-center[0], -center[1], -center[2]);
1155 
1156   // Set the corners
1157   vtkPoints* newPts = vtkPoints::New(VTK_DOUBLE);
1158   this->Transform->TransformPoints(this->Points, newPts);
1159 
1160   for (i = 0; i < 8; i++, pts += 3)
1161   {
1162     this->Points->SetPoint(i, newPts->GetPoint(i));
1163   }
1164 
1165   newPts->Delete();
1166   this->PositionHandles();
1167 }
1168 
CreateDefaultProperties()1169 void vtkBoxWidget::CreateDefaultProperties()
1170 {
1171   // Handle properties
1172   this->HandleProperty = vtkProperty::New();
1173   this->HandleProperty->SetColor(1, 1, 1);
1174 
1175   this->SelectedHandleProperty = vtkProperty::New();
1176   this->SelectedHandleProperty->SetColor(1, 0, 0);
1177 
1178   // Face properties
1179   this->FaceProperty = vtkProperty::New();
1180   this->FaceProperty->SetColor(1, 1, 1);
1181   this->FaceProperty->SetOpacity(0.0);
1182 
1183   this->SelectedFaceProperty = vtkProperty::New();
1184   this->SelectedFaceProperty->SetColor(1, 1, 0);
1185   this->SelectedFaceProperty->SetOpacity(0.25);
1186 
1187   // Outline properties
1188   this->OutlineProperty = vtkProperty::New();
1189   this->OutlineProperty->SetRepresentationToWireframe();
1190   this->OutlineProperty->SetAmbient(1.0);
1191   this->OutlineProperty->SetAmbientColor(1.0, 1.0, 1.0);
1192   this->OutlineProperty->SetLineWidth(2.0);
1193 
1194   this->SelectedOutlineProperty = vtkProperty::New();
1195   this->SelectedOutlineProperty->SetRepresentationToWireframe();
1196   this->SelectedOutlineProperty->SetAmbient(1.0);
1197   this->SelectedOutlineProperty->SetAmbientColor(0.0, 1.0, 0.0);
1198   this->SelectedOutlineProperty->SetLineWidth(2.0);
1199 }
1200 
PlaceWidget(double bds[6])1201 void vtkBoxWidget::PlaceWidget(double bds[6])
1202 {
1203   int i;
1204   double bounds[6], center[3];
1205 
1206   this->AdjustBounds(bds, bounds, center);
1207 
1208   this->Points->SetPoint(0, bounds[0], bounds[2], bounds[4]);
1209   this->Points->SetPoint(1, bounds[1], bounds[2], bounds[4]);
1210   this->Points->SetPoint(2, bounds[1], bounds[3], bounds[4]);
1211   this->Points->SetPoint(3, bounds[0], bounds[3], bounds[4]);
1212   this->Points->SetPoint(4, bounds[0], bounds[2], bounds[5]);
1213   this->Points->SetPoint(5, bounds[1], bounds[2], bounds[5]);
1214   this->Points->SetPoint(6, bounds[1], bounds[3], bounds[5]);
1215   this->Points->SetPoint(7, bounds[0], bounds[3], bounds[5]);
1216 
1217   for (i = 0; i < 6; i++)
1218   {
1219     this->InitialBounds[i] = bounds[i];
1220   }
1221   this->InitialLength = sqrt((bounds[1] - bounds[0]) * (bounds[1] - bounds[0]) +
1222     (bounds[3] - bounds[2]) * (bounds[3] - bounds[2]) +
1223     (bounds[5] - bounds[4]) * (bounds[5] - bounds[4]));
1224 
1225   this->PositionHandles();
1226   this->ComputeNormals();
1227   this->SizeHandles();
1228 }
1229 
GetTransform(vtkTransform * t)1230 void vtkBoxWidget::GetTransform(vtkTransform* t)
1231 {
1232   double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
1233   double* p0 = pts;
1234   double* p1 = pts + 3 * 1;
1235   double* p3 = pts + 3 * 3;
1236   double* p4 = pts + 3 * 4;
1237   double* p14 = pts + 3 * 14;
1238   double center[3], translate[3], scale[3], scaleVec[3][3];
1239   double InitialCenter[3];
1240   int i;
1241 
1242   // The transformation is relative to the initial bounds.
1243   // Initial bounds are set when PlaceWidget() is invoked.
1244   t->Identity();
1245 
1246   // Translation
1247   for (i = 0; i < 3; i++)
1248   {
1249     InitialCenter[i] = (this->InitialBounds[2 * i + 1] + this->InitialBounds[2 * i]) / 2.0;
1250     center[i] = p14[i] - InitialCenter[i];
1251   }
1252   translate[0] = center[0] + InitialCenter[0];
1253   translate[1] = center[1] + InitialCenter[1];
1254   translate[2] = center[2] + InitialCenter[2];
1255   t->Translate(translate[0], translate[1], translate[2]);
1256 
1257   // Orientation
1258   vtkMatrix4x4* matrix = vtkMatrix4x4::New();
1259   this->PositionHandles();
1260   this->ComputeNormals();
1261   for (i = 0; i < 3; i++)
1262   {
1263     matrix->SetElement(i, 0, this->N[1][i]);
1264     matrix->SetElement(i, 1, this->N[3][i]);
1265     matrix->SetElement(i, 2, this->N[5][i]);
1266   }
1267   t->Concatenate(matrix);
1268   matrix->Delete();
1269 
1270   // Scale
1271   for (i = 0; i < 3; i++)
1272   {
1273     scaleVec[0][i] = (p1[i] - p0[i]);
1274     scaleVec[1][i] = (p3[i] - p0[i]);
1275     scaleVec[2][i] = (p4[i] - p0[i]);
1276   }
1277 
1278   scale[0] = vtkMath::Norm(scaleVec[0]);
1279   if (this->InitialBounds[1] != this->InitialBounds[0])
1280   {
1281     scale[0] = scale[0] / (this->InitialBounds[1] - this->InitialBounds[0]);
1282   }
1283   scale[1] = vtkMath::Norm(scaleVec[1]);
1284   if (this->InitialBounds[3] != this->InitialBounds[2])
1285   {
1286     scale[1] = scale[1] / (this->InitialBounds[3] - this->InitialBounds[2]);
1287   }
1288   scale[2] = vtkMath::Norm(scaleVec[2]);
1289   if (this->InitialBounds[5] != this->InitialBounds[4])
1290   {
1291     scale[2] = scale[2] / (this->InitialBounds[5] - this->InitialBounds[4]);
1292   }
1293   t->Scale(scale[0], scale[1], scale[2]);
1294 
1295   // Add back in the contribution due to non-origin center
1296   t->Translate(-InitialCenter[0], -InitialCenter[1], -InitialCenter[2]);
1297 }
1298 
SetTransform(vtkTransform * t)1299 void vtkBoxWidget::SetTransform(vtkTransform* t)
1300 {
1301   if (!t)
1302   {
1303     vtkErrorMacro(<< "vtkTransform t must be non-nullptr");
1304     return;
1305   }
1306 
1307   double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
1308   double xIn[3];
1309   // make sure the transform is up-to-date before using it
1310   t->Update();
1311 
1312   // Position the eight points of the box and then update the
1313   // position of the other handles.
1314   double* bounds = this->InitialBounds;
1315 
1316   xIn[0] = bounds[0];
1317   xIn[1] = bounds[2];
1318   xIn[2] = bounds[4];
1319   t->InternalTransformPoint(xIn, pts);
1320 
1321   xIn[0] = bounds[1];
1322   xIn[1] = bounds[2];
1323   xIn[2] = bounds[4];
1324   t->InternalTransformPoint(xIn, pts + 3);
1325 
1326   xIn[0] = bounds[1];
1327   xIn[1] = bounds[3];
1328   xIn[2] = bounds[4];
1329   t->InternalTransformPoint(xIn, pts + 6);
1330 
1331   xIn[0] = bounds[0];
1332   xIn[1] = bounds[3];
1333   xIn[2] = bounds[4];
1334   t->InternalTransformPoint(xIn, pts + 9);
1335 
1336   xIn[0] = bounds[0];
1337   xIn[1] = bounds[2];
1338   xIn[2] = bounds[5];
1339   t->InternalTransformPoint(xIn, pts + 12);
1340 
1341   xIn[0] = bounds[1];
1342   xIn[1] = bounds[2];
1343   xIn[2] = bounds[5];
1344   t->InternalTransformPoint(xIn, pts + 15);
1345 
1346   xIn[0] = bounds[1];
1347   xIn[1] = bounds[3];
1348   xIn[2] = bounds[5];
1349   t->InternalTransformPoint(xIn, pts + 18);
1350 
1351   xIn[0] = bounds[0];
1352   xIn[1] = bounds[3];
1353   xIn[2] = bounds[5];
1354   t->InternalTransformPoint(xIn, pts + 21);
1355 
1356   this->PositionHandles();
1357 }
1358 
GetPolyData(vtkPolyData * pd)1359 void vtkBoxWidget::GetPolyData(vtkPolyData* pd)
1360 {
1361   pd->SetPoints(this->HexPolyData->GetPoints());
1362   pd->SetPolys(this->HexPolyData->GetPolys());
1363 }
1364 
SetOutlineFaceWires(int newValue)1365 void vtkBoxWidget::SetOutlineFaceWires(int newValue)
1366 {
1367   if (this->OutlineFaceWires != newValue)
1368   {
1369     this->OutlineFaceWires = newValue;
1370     this->Modified();
1371     // the outline is dependent on this value, so we have to regen
1372     this->GenerateOutline();
1373   }
1374 }
1375 
SetOutlineCursorWires(int newValue)1376 void vtkBoxWidget::SetOutlineCursorWires(int newValue)
1377 {
1378   if (this->OutlineCursorWires != newValue)
1379   {
1380     this->OutlineCursorWires = newValue;
1381     this->Modified();
1382     // the outline is dependent on this value, so we have to regen
1383     this->GenerateOutline();
1384   }
1385 }
1386 
GenerateOutline()1387 void vtkBoxWidget::GenerateOutline()
1388 {
1389   // Whatever the case may be, we have to reset the Lines of the
1390   // OutlinePolyData (i.e. nuke all current line data)
1391   vtkCellArray* cells = this->OutlinePolyData->GetLines();
1392   cells->Reset();
1393 
1394   // Now the outline lines
1395   if (!this->OutlineFaceWires && !this->OutlineCursorWires)
1396   {
1397     return;
1398   }
1399 
1400   vtkIdType pts[2];
1401 
1402   if (this->OutlineFaceWires)
1403   {
1404     pts[0] = 0;
1405     pts[1] = 7; // the -x face
1406     cells->InsertNextCell(2, pts);
1407     pts[0] = 3;
1408     pts[1] = 4;
1409     cells->InsertNextCell(2, pts);
1410     pts[0] = 1;
1411     pts[1] = 6; // the +x face
1412     cells->InsertNextCell(2, pts);
1413     pts[0] = 2;
1414     pts[1] = 5;
1415     cells->InsertNextCell(2, pts);
1416     pts[0] = 1;
1417     pts[1] = 4; // the -y face
1418     cells->InsertNextCell(2, pts);
1419     pts[0] = 0;
1420     pts[1] = 5;
1421     cells->InsertNextCell(2, pts);
1422     pts[0] = 3;
1423     pts[1] = 6; // the +y face
1424     cells->InsertNextCell(2, pts);
1425     pts[0] = 2;
1426     pts[1] = 7;
1427     cells->InsertNextCell(2, pts);
1428     pts[0] = 0;
1429     pts[1] = 2; // the -z face
1430     cells->InsertNextCell(2, pts);
1431     pts[0] = 1;
1432     pts[1] = 3;
1433     cells->InsertNextCell(2, pts);
1434     pts[0] = 4;
1435     pts[1] = 6; // the +Z face
1436     cells->InsertNextCell(2, pts);
1437     pts[0] = 5;
1438     pts[1] = 7;
1439     cells->InsertNextCell(2, pts);
1440   }
1441   if (this->OutlineCursorWires)
1442   {
1443     pts[0] = 8;
1444     pts[1] = 9; // the x cursor line
1445     cells->InsertNextCell(2, pts);
1446     pts[0] = 10;
1447     pts[1] = 11; // the y cursor line
1448     cells->InsertNextCell(2, pts);
1449     pts[0] = 12;
1450     pts[1] = 13; // the z cursor line
1451     cells->InsertNextCell(2, pts);
1452   }
1453   this->OutlinePolyData->Modified();
1454   if (this->OutlineProperty)
1455   {
1456     this->OutlineProperty->SetRepresentationToWireframe();
1457     this->SelectedOutlineProperty->SetRepresentationToWireframe();
1458   }
1459 }
1460 
1461 //------------------------------------------------------------------------------
RegisterPickers()1462 void vtkBoxWidget::RegisterPickers()
1463 {
1464   vtkPickingManager* pm = this->GetPickingManager();
1465   if (!pm)
1466   {
1467     return;
1468   }
1469   pm->AddPicker(this->HandlePicker, this);
1470   pm->AddPicker(this->HexPicker, this);
1471 }
1472