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