1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkLineWidget.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 "vtkLineWidget.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 "vtkCommand.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 "vtkPointWidget.h"
31 #include "vtkPolyData.h"
32 #include "vtkPolyDataMapper.h"
33 #include "vtkProperty.h"
34 #include "vtkRenderWindow.h"
35 #include "vtkRenderWindowInteractor.h"
36 #include "vtkRenderer.h"
37 #include "vtkSphereSource.h"
38
39 vtkStandardNewMacro(vtkLineWidget);
40
41 //------------------------------------------------------------------------------
42 // This class is used to coordinate the interaction between the point widget
43 // at the center of the line and the line widget. When the line is selected
44 // (as compared to the handles), a point widget appears at the selection
45 // point, which can be manipulated in the usual way.
46 class vtkPWCallback : public vtkCommand
47 {
48 public:
New()49 static vtkPWCallback* New() { return new vtkPWCallback; }
Execute(vtkObject * vtkNotUsed (caller),unsigned long,void *)50 void Execute(vtkObject* vtkNotUsed(caller), unsigned long, void*) override
51 {
52 double x[3];
53 this->PointWidget->GetPosition(x);
54 this->LineWidget->SetLinePosition(x);
55 }
vtkPWCallback()56 vtkPWCallback()
57 : LineWidget(nullptr)
58 , PointWidget(nullptr)
59 {
60 }
61 vtkLineWidget* LineWidget;
62 vtkPointWidget* PointWidget;
63 };
64
65 //------------------------------------------------------------------------------
66 // This class is used to coordinate the interaction between the point widget
67 // (point 1) and the line widget.
68 class vtkPW1Callback : public vtkCommand
69 {
70 public:
New()71 static vtkPW1Callback* New() { return new vtkPW1Callback; }
Execute(vtkObject * vtkNotUsed (caller),unsigned long,void *)72 void Execute(vtkObject* vtkNotUsed(caller), unsigned long, void*) override
73 {
74 double x[3];
75 this->PointWidget->GetPosition(x);
76 this->LineWidget->SetPoint1(x);
77 }
vtkPW1Callback()78 vtkPW1Callback()
79 : LineWidget(nullptr)
80 , PointWidget(nullptr)
81 {
82 }
83 vtkLineWidget* LineWidget;
84 vtkPointWidget* PointWidget;
85 };
86
87 //------------------------------------------------------------------------------
88 // This class is used to coordinate the interaction between the point widget
89 // (point 2) and the line widget.
90 class vtkPW2Callback : public vtkCommand
91 {
92 public:
New()93 static vtkPW2Callback* New() { return new vtkPW2Callback; }
Execute(vtkObject * vtkNotUsed (caller),unsigned long,void *)94 void Execute(vtkObject* vtkNotUsed(caller), unsigned long, void*) override
95 {
96 double x[3];
97 this->PointWidget->GetPosition(x);
98 this->LineWidget->SetPoint2(x);
99 }
vtkPW2Callback()100 vtkPW2Callback()
101 : LineWidget(nullptr)
102 , PointWidget(nullptr)
103 {
104 }
105 vtkLineWidget* LineWidget;
106 vtkPointWidget* PointWidget;
107 };
108
109 //------------------------------------------------------------------------------
110 // Begin the definition of the vtkLineWidget methods
111 //
vtkLineWidget()112 vtkLineWidget::vtkLineWidget()
113 {
114 this->State = vtkLineWidget::Start;
115 this->EventCallbackCommand->SetCallback(vtkLineWidget::ProcessEvents);
116
117 this->Align = vtkLineWidget::XAxis;
118
119 // Build the representation of the widget
120 int i;
121 // Represent the line
122 this->LineSource = vtkLineSource::New();
123 this->LineSource->SetResolution(5);
124 this->LineMapper = vtkPolyDataMapper::New();
125 this->LineMapper->SetInputConnection(this->LineSource->GetOutputPort());
126 this->LineActor = vtkActor::New();
127 this->LineActor->SetMapper(this->LineMapper);
128
129 // Create the handles
130 this->Handle = new vtkActor*[2];
131 this->HandleMapper = new vtkPolyDataMapper*[2];
132 this->HandleGeometry = new vtkSphereSource*[2];
133 for (i = 0; i < 2; i++)
134 {
135 this->HandleGeometry[i] = vtkSphereSource::New();
136 this->HandleGeometry[i]->SetThetaResolution(16);
137 this->HandleGeometry[i]->SetPhiResolution(8);
138 this->HandleMapper[i] = vtkPolyDataMapper::New();
139 this->HandleMapper[i]->SetInputConnection(this->HandleGeometry[i]->GetOutputPort());
140 this->Handle[i] = vtkActor::New();
141 this->Handle[i]->SetMapper(this->HandleMapper[i]);
142 }
143
144 // Define the point coordinates
145 double bounds[6];
146 bounds[0] = -0.5;
147 bounds[1] = 0.5;
148 bounds[2] = -0.5;
149 bounds[3] = 0.5;
150 bounds[4] = -0.5;
151 bounds[5] = 0.5;
152 this->PlaceFactor = 1.0; // overload parent's value
153
154 // Initial creation of the widget, serves to initialize it
155 this->PlaceWidget(bounds);
156 this->ClampToBounds = 0;
157
158 // Manage the picking stuff
159 this->HandlePicker = vtkCellPicker::New();
160 this->HandlePicker->SetTolerance(0.001);
161 for (i = 0; i < 2; i++)
162 {
163 this->HandlePicker->AddPickList(this->Handle[i]);
164 }
165 this->HandlePicker->PickFromListOn();
166
167 this->LinePicker = vtkCellPicker::New();
168 this->LinePicker->SetTolerance(0.005); // need some fluff
169 this->LinePicker->AddPickList(this->LineActor);
170 this->LinePicker->PickFromListOn();
171
172 this->CurrentHandle = nullptr;
173
174 // Set up the initial properties
175 this->CreateDefaultProperties();
176
177 // Create the point widgets and associated callbacks
178 this->PointWidget = vtkPointWidget::New();
179 this->PointWidget->AllOff();
180 this->PointWidget->SetHotSpotSize(0.5);
181
182 this->PointWidget1 = vtkPointWidget::New();
183 this->PointWidget1->AllOff();
184 this->PointWidget1->SetHotSpotSize(0.5);
185
186 this->PointWidget2 = vtkPointWidget::New();
187 this->PointWidget2->AllOff();
188 this->PointWidget2->SetHotSpotSize(0.5);
189
190 this->PWCallback = vtkPWCallback::New();
191 this->PWCallback->LineWidget = this;
192 this->PWCallback->PointWidget = this->PointWidget;
193 this->PW1Callback = vtkPW1Callback::New();
194 this->PW1Callback->LineWidget = this;
195 this->PW1Callback->PointWidget = this->PointWidget1;
196 this->PW2Callback = vtkPW2Callback::New();
197 this->PW2Callback->LineWidget = this;
198 this->PW2Callback->PointWidget = this->PointWidget2;
199
200 // Very tricky, the point widgets watch for their own
201 // interaction events.
202 this->PointWidget->AddObserver(vtkCommand::InteractionEvent, this->PWCallback, 0.0);
203 this->PointWidget1->AddObserver(vtkCommand::InteractionEvent, this->PW1Callback, 0.0);
204 this->PointWidget2->AddObserver(vtkCommand::InteractionEvent, this->PW2Callback, 0.0);
205 this->CurrentPointWidget = nullptr;
206 }
207
208 //------------------------------------------------------------------------------
~vtkLineWidget()209 vtkLineWidget::~vtkLineWidget()
210 {
211 this->LineActor->Delete();
212 this->LineMapper->Delete();
213 this->LineSource->Delete();
214
215 for (int i = 0; i < 2; i++)
216 {
217 this->HandleGeometry[i]->Delete();
218 this->HandleMapper[i]->Delete();
219 this->Handle[i]->Delete();
220 }
221 delete[] this->Handle;
222 delete[] this->HandleMapper;
223 delete[] this->HandleGeometry;
224
225 this->HandlePicker->Delete();
226 this->LinePicker->Delete();
227
228 this->HandleProperty->Delete();
229 this->SelectedHandleProperty->Delete();
230 this->LineProperty->Delete();
231 this->SelectedLineProperty->Delete();
232
233 this->PointWidget->RemoveObserver(this->PWCallback);
234 this->PointWidget1->RemoveObserver(this->PW1Callback);
235 this->PointWidget2->RemoveObserver(this->PW2Callback);
236 this->PointWidget->Delete();
237 this->PointWidget1->Delete();
238 this->PointWidget2->Delete();
239 this->PWCallback->Delete();
240 this->PW1Callback->Delete();
241 this->PW2Callback->Delete();
242 }
243
244 //------------------------------------------------------------------------------
SetEnabled(int enabling)245 void vtkLineWidget::SetEnabled(int enabling)
246 {
247 if (!this->Interactor)
248 {
249 vtkErrorMacro(<< "The interactor must be set prior to enabling/disabling widget");
250 return;
251 }
252
253 if (enabling) //-----------------------------------------------------------
254 {
255 vtkDebugMacro(<< "Enabling line widget");
256
257 if (this->Enabled) // already enabled, just return
258 {
259 return;
260 }
261
262 if (!this->CurrentRenderer)
263 {
264 this->SetCurrentRenderer(this->Interactor->FindPokedRenderer(
265 this->Interactor->GetLastEventPosition()[0], this->Interactor->GetLastEventPosition()[1]));
266 if (this->CurrentRenderer == nullptr)
267 {
268 return;
269 }
270 }
271
272 this->PointWidget->SetCurrentRenderer(this->CurrentRenderer);
273 this->PointWidget1->SetCurrentRenderer(this->CurrentRenderer);
274 this->PointWidget2->SetCurrentRenderer(this->CurrentRenderer);
275
276 this->Enabled = 1;
277
278 // listen for the following events
279 vtkRenderWindowInteractor* i = this->Interactor;
280 i->AddObserver(vtkCommand::MouseMoveEvent, this->EventCallbackCommand, this->Priority);
281 i->AddObserver(vtkCommand::LeftButtonPressEvent, this->EventCallbackCommand, this->Priority);
282 i->AddObserver(vtkCommand::LeftButtonReleaseEvent, this->EventCallbackCommand, this->Priority);
283 i->AddObserver(vtkCommand::MiddleButtonPressEvent, this->EventCallbackCommand, this->Priority);
284 i->AddObserver(
285 vtkCommand::MiddleButtonReleaseEvent, this->EventCallbackCommand, this->Priority);
286 i->AddObserver(vtkCommand::RightButtonPressEvent, this->EventCallbackCommand, this->Priority);
287 i->AddObserver(vtkCommand::RightButtonReleaseEvent, this->EventCallbackCommand, this->Priority);
288
289 // Add the line
290 this->CurrentRenderer->AddActor(this->LineActor);
291 this->LineActor->SetProperty(this->LineProperty);
292
293 // turn on the handles
294 for (int j = 0; j < 2; j++)
295 {
296 this->CurrentRenderer->AddActor(this->Handle[j]);
297 this->Handle[j]->SetProperty(this->HandleProperty);
298 }
299
300 this->BuildRepresentation();
301 this->SizeHandles();
302 this->RegisterPickers();
303
304 this->InvokeEvent(vtkCommand::EnableEvent, nullptr);
305 }
306
307 else // disabling----------------------------------------------------------
308 {
309 vtkDebugMacro(<< "Disabling line widget");
310
311 if (!this->Enabled) // already disabled, just return
312 {
313 return;
314 }
315
316 this->Enabled = 0;
317
318 // don't listen for events any more
319 this->Interactor->RemoveObserver(this->EventCallbackCommand);
320
321 // turn off the line
322 this->CurrentRenderer->RemoveActor(this->LineActor);
323
324 // turn off the handles
325 for (int i = 0; i < 2; i++)
326 {
327 this->CurrentRenderer->RemoveActor(this->Handle[i]);
328 }
329
330 if (this->CurrentPointWidget)
331 {
332 this->CurrentPointWidget->EnabledOff();
333 }
334
335 this->CurrentHandle = nullptr;
336 this->InvokeEvent(vtkCommand::DisableEvent, nullptr);
337 this->SetCurrentRenderer(nullptr);
338 this->UnRegisterPickers();
339 }
340
341 this->Interactor->Render();
342 }
343
344 //------------------------------------------------------------------------------
RegisterPickers()345 void vtkLineWidget::RegisterPickers()
346 {
347 vtkPickingManager* pm = this->GetPickingManager();
348 if (!pm)
349 {
350 return;
351 }
352 pm->AddPicker(this->HandlePicker, this);
353 pm->AddPicker(this->LinePicker, this);
354 }
355
356 //------------------------------------------------------------------------------
ProcessEvents(vtkObject * vtkNotUsed (object),unsigned long event,void * clientdata,void * vtkNotUsed (calldata))357 void vtkLineWidget::ProcessEvents(
358 vtkObject* vtkNotUsed(object), unsigned long event, void* clientdata, void* vtkNotUsed(calldata))
359 {
360 vtkLineWidget* self = reinterpret_cast<vtkLineWidget*>(clientdata);
361
362 // okay, let's do the right thing
363 switch (event)
364 {
365 case vtkCommand::LeftButtonPressEvent:
366 self->OnLeftButtonDown();
367 break;
368 case vtkCommand::LeftButtonReleaseEvent:
369 self->OnLeftButtonUp();
370 break;
371 case vtkCommand::MiddleButtonPressEvent:
372 self->OnMiddleButtonDown();
373 break;
374 case vtkCommand::MiddleButtonReleaseEvent:
375 self->OnMiddleButtonUp();
376 break;
377 case vtkCommand::RightButtonPressEvent:
378 self->OnRightButtonDown();
379 break;
380 case vtkCommand::RightButtonReleaseEvent:
381 self->OnRightButtonUp();
382 break;
383 case vtkCommand::MouseMoveEvent:
384 self->OnMouseMove();
385 break;
386 }
387 }
388
389 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)390 void vtkLineWidget::PrintSelf(ostream& os, vtkIndent indent)
391 {
392 this->Superclass::PrintSelf(os, indent);
393
394 if (this->HandleProperty)
395 {
396 os << indent << "Handle Property: " << this->HandleProperty << "\n";
397 }
398 else
399 {
400 os << indent << "Handle Property: (none)\n";
401 }
402 if (this->SelectedHandleProperty)
403 {
404 os << indent << "Selected Handle Property: " << this->SelectedHandleProperty << "\n";
405 }
406 else
407 {
408 os << indent << "Selected Handle Property: (none)\n";
409 }
410
411 if (this->LineProperty)
412 {
413 os << indent << "Line Property: " << this->LineProperty << "\n";
414 }
415 else
416 {
417 os << indent << "Line Property: (none)\n";
418 }
419 if (this->SelectedLineProperty)
420 {
421 os << indent << "Selected Line Property: " << this->SelectedLineProperty << "\n";
422 }
423 else
424 {
425 os << indent << "Selected Line Property: (none)\n";
426 }
427
428 os << indent << "Constrain To Bounds: " << (this->ClampToBounds ? "On\n" : "Off\n");
429
430 os << indent << "Align with: ";
431 switch (this->Align)
432 {
433 case XAxis:
434 os << "X Axis";
435 break;
436 case YAxis:
437 os << "Y Axis";
438 break;
439 case ZAxis:
440 os << "Z Axis";
441 break;
442 default:
443 os << "None";
444 }
445 int res = this->LineSource->GetResolution();
446 double* pt1 = this->LineSource->GetPoint1();
447 double* pt2 = this->LineSource->GetPoint2();
448
449 os << indent << "Resolution: " << res << "\n";
450 os << indent << "Point 1: (" << pt1[0] << ", " << pt1[1] << ", " << pt1[2] << ")\n";
451 os << indent << "Point 2: (" << pt2[0] << ", " << pt2[1] << ", " << pt2[2] << ")\n";
452 }
453
454 //------------------------------------------------------------------------------
BuildRepresentation()455 void vtkLineWidget::BuildRepresentation()
456 {
457 // int res = this->LineSource->GetResolution();
458 double* pt1 = this->LineSource->GetPoint1();
459 double* pt2 = this->LineSource->GetPoint2();
460
461 this->HandleGeometry[0]->SetCenter(pt1);
462 this->HandleGeometry[1]->SetCenter(pt2);
463 }
464
465 //------------------------------------------------------------------------------
SizeHandles()466 void vtkLineWidget::SizeHandles()
467 {
468 double radius = this->vtk3DWidget::SizeHandles(1.0);
469 this->HandleGeometry[0]->SetRadius(radius);
470 this->HandleGeometry[1]->SetRadius(radius);
471 }
472
473 //------------------------------------------------------------------------------
HighlightHandle(vtkProp * prop)474 int vtkLineWidget::HighlightHandle(vtkProp* prop)
475 {
476 // first unhighlight anything picked
477 if (this->CurrentHandle)
478 {
479 this->CurrentHandle->SetProperty(this->HandleProperty);
480 }
481
482 // set the current handle
483 this->CurrentHandle = static_cast<vtkActor*>(prop);
484
485 // find the current handle
486 if (this->CurrentHandle)
487 {
488 this->ValidPick = 1;
489 this->HandlePicker->GetPickPosition(this->LastPickPosition);
490 this->CurrentHandle->SetProperty(this->SelectedHandleProperty);
491 return (this->CurrentHandle == this->Handle[0] ? 0 : 1);
492 }
493 return -1;
494 }
495
496 //------------------------------------------------------------------------------
ForwardEvent(unsigned long event)497 int vtkLineWidget::ForwardEvent(unsigned long event)
498 {
499 if (!this->CurrentPointWidget)
500 {
501 return 0;
502 }
503
504 vtkPointWidget::ProcessEvents(this, event, this->CurrentPointWidget, nullptr);
505
506 return 1;
507 }
508
509 //------------------------------------------------------------------------------
510 // assumed current handle is set
EnablePointWidget()511 void vtkLineWidget::EnablePointWidget()
512 {
513 // Set up the point widgets
514 double x[3];
515 if (this->CurrentHandle) // picking the handles
516 {
517 if (this->CurrentHandle == this->Handle[0])
518 {
519 this->CurrentPointWidget = this->PointWidget1;
520 this->LineSource->GetPoint1(x);
521 }
522 else
523 {
524 this->CurrentPointWidget = this->PointWidget2;
525 this->LineSource->GetPoint2(x);
526 }
527 }
528 else // picking the line
529 {
530 this->CurrentPointWidget = this->PointWidget;
531 this->LinePicker->GetPickPosition(x);
532 this->LastPosition[0] = x[0];
533 this->LastPosition[1] = x[1];
534 this->LastPosition[2] = x[2];
535 }
536
537 double bounds[6];
538 for (int i = 0; i < 3; i++)
539 {
540 bounds[2 * i] = x[i] - 0.1 * this->InitialLength;
541 bounds[2 * i + 1] = x[i] + 0.1 * this->InitialLength;
542 }
543
544 // Note: translation mode is disabled and enabled to control
545 // the proper positioning of the bounding box.
546 this->CurrentPointWidget->SetInteractor(this->Interactor);
547 this->CurrentPointWidget->TranslationModeOff();
548 this->CurrentPointWidget->SetPlaceFactor(1.0);
549 this->CurrentPointWidget->PlaceWidget(bounds);
550 this->CurrentPointWidget->TranslationModeOn();
551 this->CurrentPointWidget->SetPosition(x);
552 this->CurrentPointWidget->SetCurrentRenderer(this->CurrentRenderer);
553 this->CurrentPointWidget->On();
554 }
555
556 //------------------------------------------------------------------------------
557 // assumed current handle is set
DisablePointWidget()558 void vtkLineWidget::DisablePointWidget()
559 {
560 if (this->CurrentPointWidget)
561 {
562 this->CurrentPointWidget->Off();
563 }
564 this->CurrentPointWidget = nullptr;
565 }
566
567 //------------------------------------------------------------------------------
HighlightHandles(int highlight)568 void vtkLineWidget::HighlightHandles(int highlight)
569 {
570 if (highlight)
571 {
572 this->ValidPick = 1;
573 this->HandlePicker->GetPickPosition(this->LastPickPosition);
574 this->Handle[0]->SetProperty(this->SelectedHandleProperty);
575 this->Handle[1]->SetProperty(this->SelectedHandleProperty);
576 }
577 else
578 {
579 this->Handle[0]->SetProperty(this->HandleProperty);
580 this->Handle[1]->SetProperty(this->HandleProperty);
581 }
582 }
583
584 //------------------------------------------------------------------------------
HighlightLine(int highlight)585 void vtkLineWidget::HighlightLine(int highlight)
586 {
587 if (highlight)
588 {
589 this->ValidPick = 1;
590 this->LinePicker->GetPickPosition(this->LastPickPosition);
591 this->LineActor->SetProperty(this->SelectedLineProperty);
592 }
593 else
594 {
595 this->LineActor->SetProperty(this->LineProperty);
596 }
597 }
598
599 //------------------------------------------------------------------------------
OnLeftButtonDown()600 void vtkLineWidget::OnLeftButtonDown()
601 {
602 int forward = 0;
603
604 int X = this->Interactor->GetEventPosition()[0];
605 int Y = this->Interactor->GetEventPosition()[1];
606
607 // Okay, make sure that the pick is in the current renderer
608 if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y))
609 {
610 this->State = vtkLineWidget::Outside;
611 return;
612 }
613
614 // Okay, we can process this. Try to pick handles first;
615 // if no handles picked, then try to pick the line.
616 vtkAssemblyPath* path = this->GetAssemblyPath(X, Y, 0., this->HandlePicker);
617
618 if (path != nullptr)
619 {
620 this->EventCallbackCommand->SetAbortFlag(1);
621 this->StartInteraction();
622 this->InvokeEvent(vtkCommand::StartInteractionEvent, nullptr);
623 this->State = vtkLineWidget::MovingHandle;
624 this->HighlightHandle(path->GetFirstNode()->GetViewProp());
625 this->EnablePointWidget();
626 forward = this->ForwardEvent(vtkCommand::LeftButtonPressEvent);
627 }
628 else
629 {
630 path = this->GetAssemblyPath(X, Y, 0., this->LinePicker);
631
632 if (path != nullptr)
633 {
634 this->EventCallbackCommand->SetAbortFlag(1);
635 this->StartInteraction();
636 this->InvokeEvent(vtkCommand::StartInteractionEvent, nullptr);
637 this->State = vtkLineWidget::MovingLine;
638 this->HighlightLine(1);
639 this->EnablePointWidget();
640 forward = this->ForwardEvent(vtkCommand::LeftButtonPressEvent);
641 }
642 else
643 {
644 this->State = vtkLineWidget::Outside;
645 this->HighlightHandle(nullptr);
646 return;
647 }
648 }
649
650 if (!forward)
651 {
652 this->Interactor->Render();
653 }
654 }
655
656 //------------------------------------------------------------------------------
OnLeftButtonUp()657 void vtkLineWidget::OnLeftButtonUp()
658 {
659 if (this->State == vtkLineWidget::Outside || this->State == vtkLineWidget::Start)
660 {
661 return;
662 }
663
664 this->State = vtkLineWidget::Start;
665 this->HighlightHandle(nullptr);
666 this->HighlightLine(0);
667
668 this->SizeHandles();
669
670 int forward = this->ForwardEvent(vtkCommand::LeftButtonReleaseEvent);
671 this->DisablePointWidget();
672
673 this->EventCallbackCommand->SetAbortFlag(1);
674 this->EndInteraction();
675 this->InvokeEvent(vtkCommand::EndInteractionEvent, nullptr);
676 if (!forward)
677 {
678 this->Interactor->Render();
679 }
680 }
681
682 //------------------------------------------------------------------------------
OnMiddleButtonDown()683 void vtkLineWidget::OnMiddleButtonDown()
684 {
685 int forward = 0;
686
687 int X = this->Interactor->GetEventPosition()[0];
688 int Y = this->Interactor->GetEventPosition()[1];
689
690 // Okay, make sure that the pick is in the current renderer
691 if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y))
692 {
693 this->State = vtkLineWidget::Outside;
694 return;
695 }
696
697 // Okay, we can process this. Try to pick handles first;
698 // if no handles picked, then pick the bounding box.
699 vtkAssemblyPath* path = this->GetAssemblyPath(X, Y, 0., this->HandlePicker);
700
701 if (path != nullptr)
702 {
703 this->EventCallbackCommand->SetAbortFlag(1);
704 this->StartInteraction();
705 this->InvokeEvent(vtkCommand::StartInteractionEvent, nullptr);
706 this->State = vtkLineWidget::MovingLine;
707 this->HighlightHandles(1);
708 this->HighlightLine(1);
709 this->EnablePointWidget();
710 forward = this->ForwardEvent(vtkCommand::LeftButtonPressEvent);
711 }
712 else
713 {
714 path = this->GetAssemblyPath(X, Y, 0., this->LinePicker);
715
716 if (path != nullptr)
717 {
718 this->EventCallbackCommand->SetAbortFlag(1);
719 this->StartInteraction();
720 this->InvokeEvent(vtkCommand::StartInteractionEvent, nullptr);
721 // The highlight methods set the LastPickPosition, so they are ordered
722 this->HighlightHandles(1);
723 this->HighlightLine(1);
724 this->State = vtkLineWidget::MovingLine;
725 this->EnablePointWidget();
726 forward = this->ForwardEvent(vtkCommand::LeftButtonPressEvent);
727 }
728 else
729 {
730 this->State = vtkLineWidget::Outside;
731 return;
732 }
733 }
734
735 if (!forward)
736 {
737 this->Interactor->Render();
738 }
739 }
740
741 //------------------------------------------------------------------------------
OnMiddleButtonUp()742 void vtkLineWidget::OnMiddleButtonUp()
743 {
744 if (this->State == vtkLineWidget::Outside || this->State == vtkLineWidget::Start)
745 {
746 return;
747 }
748
749 this->State = vtkLineWidget::Start;
750 this->HighlightLine(0);
751 this->HighlightHandles(0);
752
753 this->SizeHandles();
754
755 int forward = this->ForwardEvent(vtkCommand::LeftButtonReleaseEvent);
756 this->DisablePointWidget();
757
758 this->EventCallbackCommand->SetAbortFlag(1);
759 this->EndInteraction();
760 this->InvokeEvent(vtkCommand::EndInteractionEvent, nullptr);
761 if (!forward)
762 {
763 this->Interactor->Render();
764 }
765 }
766
767 //------------------------------------------------------------------------------
OnRightButtonDown()768 void vtkLineWidget::OnRightButtonDown()
769 {
770 int X = this->Interactor->GetEventPosition()[0];
771 int Y = this->Interactor->GetEventPosition()[1];
772
773 // Okay, make sure that the pick is in the current renderer
774 if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y))
775 {
776 this->State = vtkLineWidget::Outside;
777 return;
778 }
779
780 // Okay, we can process this. Try to pick handles first;
781 // if no handles picked, then pick the bounding box.
782 vtkAssemblyPath* path = this->GetAssemblyPath(X, Y, 0., this->HandlePicker);
783
784 if (path != nullptr)
785 {
786 this->HighlightLine(1);
787 this->HighlightHandles(1);
788 this->State = vtkLineWidget::Scaling;
789 }
790 else
791 {
792 path = this->GetAssemblyPath(X, Y, 0., this->LinePicker);
793
794 if (path != nullptr)
795 {
796 this->HighlightHandles(1);
797 this->HighlightLine(1);
798 this->State = vtkLineWidget::Scaling;
799 }
800 else
801 {
802 this->State = vtkLineWidget::Outside;
803 this->HighlightLine(0);
804 return;
805 }
806 }
807
808 this->EventCallbackCommand->SetAbortFlag(1);
809 this->StartInteraction();
810 this->InvokeEvent(vtkCommand::StartInteractionEvent, nullptr);
811 this->Interactor->Render();
812 }
813
814 //------------------------------------------------------------------------------
OnRightButtonUp()815 void vtkLineWidget::OnRightButtonUp()
816 {
817 if (this->State == vtkLineWidget::Outside || this->State == vtkLineWidget::Start)
818 {
819 return;
820 }
821
822 this->State = vtkLineWidget::Start;
823 this->HighlightLine(0);
824 this->HighlightHandles(0);
825
826 this->SizeHandles();
827
828 this->EventCallbackCommand->SetAbortFlag(1);
829 this->EndInteraction();
830 this->InvokeEvent(vtkCommand::EndInteractionEvent, nullptr);
831 this->Interactor->Render();
832 }
833
834 //------------------------------------------------------------------------------
OnMouseMove()835 void vtkLineWidget::OnMouseMove()
836 {
837 // See whether we're active
838 if (this->State == vtkLineWidget::Outside || this->State == vtkLineWidget::Start)
839 {
840 return;
841 }
842
843 int X = this->Interactor->GetEventPosition()[0];
844 int Y = this->Interactor->GetEventPosition()[1];
845
846 // Do different things depending on state
847 // Calculations everybody does
848 double focalPoint[4], pickPoint[4], prevPickPoint[4];
849 double z;
850
851 vtkCamera* camera = this->CurrentRenderer->GetActiveCamera();
852 if (!camera)
853 {
854 return;
855 }
856
857 // Compute the two points defining the motion vector
858 this->ComputeWorldToDisplay(
859 this->LastPickPosition[0], this->LastPickPosition[1], this->LastPickPosition[2], focalPoint);
860 z = focalPoint[2];
861 this->ComputeDisplayToWorld(double(this->Interactor->GetLastEventPosition()[0]),
862 double(this->Interactor->GetLastEventPosition()[1]), z, prevPickPoint);
863 this->ComputeDisplayToWorld(double(X), double(Y), z, pickPoint);
864
865 // Process the motion
866 int forward = 0;
867 if (this->State == vtkLineWidget::MovingHandle)
868 {
869 forward = this->ForwardEvent(vtkCommand::MouseMoveEvent);
870 }
871 else if (this->State == vtkLineWidget::MovingLine)
872 {
873 forward = this->ForwardEvent(vtkCommand::MouseMoveEvent);
874 }
875 else if (this->State == vtkLineWidget::Scaling)
876 {
877 this->Scale(prevPickPoint, pickPoint, X, Y);
878 }
879
880 // Interact, if desired
881 this->EventCallbackCommand->SetAbortFlag(1);
882 this->InvokeEvent(vtkCommand::InteractionEvent, nullptr);
883 if (!forward)
884 {
885 this->Interactor->Render();
886 }
887 }
888
889 //------------------------------------------------------------------------------
Scale(double * p1,double * p2,int vtkNotUsed (X),int Y)890 void vtkLineWidget::Scale(double* p1, double* p2, int vtkNotUsed(X), int Y)
891 {
892 // Get the motion vector
893 double v[3];
894 v[0] = p2[0] - p1[0];
895 v[1] = p2[1] - p1[1];
896 v[2] = p2[2] - p1[2];
897
898 // int res = this->LineSource->GetResolution();
899 double* pt1 = this->LineSource->GetPoint1();
900 double* pt2 = this->LineSource->GetPoint2();
901
902 double center[3];
903 center[0] = (pt1[0] + pt2[0]) / 2.0;
904 center[1] = (pt1[1] + pt2[1]) / 2.0;
905 center[2] = (pt1[2] + pt2[2]) / 2.0;
906
907 // Compute the scale factor
908 double sf = vtkMath::Norm(v) / sqrt(vtkMath::Distance2BetweenPoints(pt1, pt2));
909 if (Y > this->Interactor->GetLastEventPosition()[1])
910 {
911 sf = 1.0 + sf;
912 }
913 else
914 {
915 sf = 1.0 - sf;
916 }
917
918 // Move the end points
919 double point1[3], point2[3];
920 for (int i = 0; i < 3; i++)
921 {
922 point1[i] = sf * (pt1[i] - center[i]) + center[i];
923 point2[i] = sf * (pt2[i] - center[i]) + center[i];
924 }
925
926 this->LineSource->SetPoint1(point1);
927 this->LineSource->SetPoint2(point2);
928 this->LineSource->Update();
929
930 this->BuildRepresentation();
931 }
932
933 //------------------------------------------------------------------------------
CreateDefaultProperties()934 void vtkLineWidget::CreateDefaultProperties()
935 {
936 // Handle properties
937 this->HandleProperty = vtkProperty::New();
938 this->HandleProperty->SetColor(1, 1, 1);
939
940 this->SelectedHandleProperty = vtkProperty::New();
941 this->SelectedHandleProperty->SetColor(1, 0, 0);
942
943 // Line properties
944 this->LineProperty = vtkProperty::New();
945 this->LineProperty->SetRepresentationToWireframe();
946 this->LineProperty->SetAmbient(1.0);
947 this->LineProperty->SetAmbientColor(1.0, 1.0, 1.0);
948 this->LineProperty->SetLineWidth(2.0);
949
950 this->SelectedLineProperty = vtkProperty::New();
951 this->SelectedLineProperty->SetRepresentationToWireframe();
952 this->SelectedLineProperty->SetAmbient(1.0);
953 this->SelectedLineProperty->SetAmbientColor(0.0, 1.0, 0.0);
954 this->SelectedLineProperty->SetLineWidth(2.0);
955 }
956
957 //------------------------------------------------------------------------------
PlaceWidget(double bds[6])958 void vtkLineWidget::PlaceWidget(double bds[6])
959 {
960 int i;
961 double bounds[6], center[3];
962
963 this->AdjustBounds(bds, bounds, center);
964
965 if (this->Align == vtkLineWidget::YAxis)
966 {
967 this->LineSource->SetPoint1(center[0], bounds[2], center[2]);
968 this->LineSource->SetPoint2(center[0], bounds[3], center[2]);
969 }
970 else if (this->Align == vtkLineWidget::ZAxis)
971 {
972 this->LineSource->SetPoint1(center[0], center[1], bounds[4]);
973 this->LineSource->SetPoint2(center[0], center[1], bounds[5]);
974 }
975 else if (this->Align == vtkLineWidget::XAxis) // default or x-aligned
976 {
977 this->LineSource->SetPoint1(bounds[0], center[1], center[2]);
978 this->LineSource->SetPoint2(bounds[1], center[1], center[2]);
979 }
980 this->LineSource->Update();
981
982 for (i = 0; i < 6; i++)
983 {
984 this->InitialBounds[i] = bounds[i];
985 }
986 this->InitialLength = sqrt((bounds[1] - bounds[0]) * (bounds[1] - bounds[0]) +
987 (bounds[3] - bounds[2]) * (bounds[3] - bounds[2]) +
988 (bounds[5] - bounds[4]) * (bounds[5] - bounds[4]));
989
990 // Position the handles at the end of the lines
991 this->BuildRepresentation();
992 this->SizeHandles();
993 }
994
995 //------------------------------------------------------------------------------
SetPoint1(double x,double y,double z)996 void vtkLineWidget::SetPoint1(double x, double y, double z)
997 {
998 double xyz[3];
999 xyz[0] = x;
1000 xyz[1] = y;
1001 xyz[2] = z;
1002
1003 if (this->ClampToBounds)
1004 {
1005 this->ClampPosition(xyz);
1006 this->PointWidget1->SetPosition(xyz);
1007 }
1008 this->LineSource->SetPoint1(xyz);
1009 this->BuildRepresentation();
1010 }
1011
1012 //------------------------------------------------------------------------------
SetPoint2(double x,double y,double z)1013 void vtkLineWidget::SetPoint2(double x, double y, double z)
1014 {
1015 double xyz[3];
1016 xyz[0] = x;
1017 xyz[1] = y;
1018 xyz[2] = z;
1019
1020 if (this->ClampToBounds)
1021 {
1022 this->ClampPosition(xyz);
1023 this->PointWidget2->SetPosition(xyz);
1024 }
1025 this->LineSource->SetPoint2(xyz);
1026 this->BuildRepresentation();
1027 }
1028
1029 //------------------------------------------------------------------------------
SetLinePosition(double x[3])1030 void vtkLineWidget::SetLinePosition(double x[3])
1031 {
1032 double p1[3], p2[3], v[3];
1033
1034 // vector of motion
1035 v[0] = x[0] - this->LastPosition[0];
1036 v[1] = x[1] - this->LastPosition[1];
1037 v[2] = x[2] - this->LastPosition[2];
1038
1039 // update position
1040 this->GetPoint1(p1);
1041 this->GetPoint2(p2);
1042 for (int i = 0; i < 3; i++)
1043 {
1044 p1[i] += v[i];
1045 p2[i] += v[i];
1046 }
1047
1048 // See whether we can move
1049 if (this->ClampToBounds && (!this->InBounds(p1) || !this->InBounds(p2)))
1050 {
1051 this->PointWidget->SetPosition(this->LastPosition);
1052 return;
1053 }
1054
1055 this->SetPoint1(p1);
1056 this->SetPoint2(p2);
1057
1058 // remember last position
1059 this->LastPosition[0] = x[0];
1060 this->LastPosition[1] = x[1];
1061 this->LastPosition[2] = x[2];
1062 }
1063
1064 //------------------------------------------------------------------------------
ClampPosition(double x[3])1065 void vtkLineWidget::ClampPosition(double x[3])
1066 {
1067 for (int i = 0; i < 3; i++)
1068 {
1069 if (x[i] < this->InitialBounds[2 * i])
1070 {
1071 x[i] = this->InitialBounds[2 * i];
1072 }
1073 if (x[i] > this->InitialBounds[2 * i + 1])
1074 {
1075 x[i] = this->InitialBounds[2 * i + 1];
1076 }
1077 }
1078 }
1079
1080 //------------------------------------------------------------------------------
InBounds(double x[3])1081 int vtkLineWidget::InBounds(double x[3])
1082 {
1083 for (int i = 0; i < 3; i++)
1084 {
1085 if (x[i] < this->InitialBounds[2 * i] || x[i] > this->InitialBounds[2 * i + 1])
1086 {
1087 return 0;
1088 }
1089 }
1090 return 1;
1091 }
1092
1093 //------------------------------------------------------------------------------
GetPolyData(vtkPolyData * pd)1094 void vtkLineWidget::GetPolyData(vtkPolyData* pd)
1095 {
1096 pd->ShallowCopy(this->LineSource->GetOutput());
1097 }
1098