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