1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkPointHandleRepresentation3D.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 "vtkPointHandleRepresentation3D.h"
16 #include "vtkActor.h"
17 #include "vtkAssemblyPath.h"
18 #include "vtkCamera.h"
19 #include "vtkCellPicker.h"
20 #include "vtkCoordinate.h"
21 #include "vtkCursor3D.h"
22 #include "vtkEventData.h"
23 #include "vtkFocalPlanePointPlacer.h"
24 #include "vtkInteractorObserver.h"
25 #include "vtkLine.h"
26 #include "vtkMath.h"
27 #include "vtkObjectFactory.h"
28 #include "vtkPickingManager.h"
29 #include "vtkPolyDataMapper.h"
30 #include "vtkProperty.h"
31 #include "vtkRenderWindow.h"
32 #include "vtkRenderWindowInteractor.h"
33 #include "vtkRenderer.h"
34
35 #include <cassert>
36
37 vtkStandardNewMacro(vtkPointHandleRepresentation3D);
38
39 vtkCxxSetObjectMacro(vtkPointHandleRepresentation3D, Property, vtkProperty);
40 vtkCxxSetObjectMacro(vtkPointHandleRepresentation3D, SelectedProperty, vtkProperty);
41
42 //------------------------------------------------------------------------------
vtkPointHandleRepresentation3D()43 vtkPointHandleRepresentation3D::vtkPointHandleRepresentation3D()
44 {
45 // Initialize state
46 this->InteractionState = vtkHandleRepresentation::Outside;
47
48 // Represent the line
49 this->Cursor3D = vtkCursor3D::New();
50 this->Cursor3D->AllOff();
51 this->Cursor3D->AxesOn();
52 this->Cursor3D->TranslationModeOn();
53
54 this->Mapper = vtkPolyDataMapper::New();
55 this->Mapper->SetInputConnection(this->Cursor3D->GetOutputPort());
56
57 // Set up the initial properties
58 this->CreateDefaultProperties();
59
60 this->Actor = vtkActor::New();
61 this->Actor->SetMapper(this->Mapper);
62 this->Actor->SetProperty(this->Property);
63
64 // Manage the picking stuff
65 this->CursorPicker = vtkCellPicker::New();
66 this->CursorPicker->PickFromListOn();
67 this->CursorPicker->AddPickList(this->Actor);
68 this->CursorPicker->SetTolerance(0.01); // need some fluff
69
70 // Override superclass'
71 this->PlaceFactor = 1.0;
72
73 // The size of the hot spot
74 this->HotSpotSize = 0.05;
75 this->WaitingForMotion = 0;
76 this->ConstraintAxis = -1;
77
78 // Current handle size
79 this->HandleSize = 15.0; // in pixels
80 this->CurrentHandleSize = this->HandleSize;
81
82 // Translation control
83 this->TranslationMode = 1;
84
85 vtkFocalPlanePointPlacer* pointPlacer = vtkFocalPlanePointPlacer::New();
86 this->SetPointPlacer(pointPlacer);
87 pointPlacer->Delete();
88
89 // Continuous moves
90 this->SmoothMotion = 1;
91 }
92
93 //------------------------------------------------------------------------------
~vtkPointHandleRepresentation3D()94 vtkPointHandleRepresentation3D::~vtkPointHandleRepresentation3D()
95 {
96 this->Cursor3D->Delete();
97 this->CursorPicker->Delete();
98 this->Mapper->Delete();
99 this->Actor->Delete();
100 this->Property->Delete();
101 this->SelectedProperty->Delete();
102 }
103
104 //------------------------------------------------------------------------------
RegisterPickers()105 void vtkPointHandleRepresentation3D::RegisterPickers()
106 {
107 vtkPickingManager* pm = this->GetPickingManager();
108 if (!pm)
109 {
110 return;
111 }
112 pm->AddPicker(this->CursorPicker, this);
113 }
114
115 //------------------------------------------------------------------------------
PlaceWidget(double bds[6])116 void vtkPointHandleRepresentation3D::PlaceWidget(double bds[6])
117 {
118 int i;
119 double bounds[6], center[3];
120
121 this->AdjustBounds(bds, bounds, center);
122
123 this->Cursor3D->SetModelBounds(bounds);
124 this->SetWorldPosition(center);
125
126 for (i = 0; i < 6; i++)
127 {
128 this->InitialBounds[i] = bounds[i];
129 }
130 this->InitialLength = sqrt((bounds[1] - bounds[0]) * (bounds[1] - bounds[0]) +
131 (bounds[3] - bounds[2]) * (bounds[3] - bounds[2]) +
132 (bounds[5] - bounds[4]) * (bounds[5] - bounds[4]));
133 }
134
135 //------------------------------------------------------------------------------
GetBounds()136 double* vtkPointHandleRepresentation3D::GetBounds()
137 {
138 return this->Cursor3D->GetModelBounds();
139 }
140
141 //------------------------------------------------------------------------------
SetWorldPosition(double p[3])142 void vtkPointHandleRepresentation3D::SetWorldPosition(double p[3])
143 {
144 if (this->Renderer && this->PointPlacer)
145 {
146 if (this->PointPlacer->ValidateWorldPosition(p))
147 {
148 this->Cursor3D->SetFocalPoint(p); // this may clamp the point
149 this->WorldPosition->SetValue(this->Cursor3D->GetFocalPoint());
150 this->WorldPositionTime.Modified();
151 }
152 }
153 else
154 {
155 this->Cursor3D->SetFocalPoint(p); // this may clamp the point
156 this->WorldPosition->SetValue(this->Cursor3D->GetFocalPoint());
157 this->WorldPositionTime.Modified();
158 }
159 }
160
161 //------------------------------------------------------------------------------
SetDisplayPosition(double p[3])162 void vtkPointHandleRepresentation3D::SetDisplayPosition(double p[3])
163 {
164 if (this->Renderer && this->PointPlacer)
165 {
166 if (this->PointPlacer->ValidateDisplayPosition(this->Renderer, p))
167 {
168 double worldPos[3], worldOrient[9];
169 if (this->PointPlacer->ComputeWorldPosition(this->Renderer, p, worldPos, worldOrient))
170 {
171 this->DisplayPosition->SetValue(p);
172 this->WorldPosition->SetValue(worldPos);
173 this->DisplayPositionTime.Modified();
174 this->SetWorldPosition(this->WorldPosition->GetValue());
175 }
176 }
177 }
178 else
179 {
180 this->DisplayPosition->SetValue(p);
181 this->DisplayPositionTime.Modified();
182 }
183 }
184
185 //------------------------------------------------------------------------------
SetHandleSize(double size)186 void vtkPointHandleRepresentation3D::SetHandleSize(double size)
187 {
188 this->Superclass::SetHandleSize(size);
189 this->CurrentHandleSize = this->HandleSize;
190 }
191
192 //------------------------------------------------------------------------------
ComputeInteractionState(int X,int Y,int vtkNotUsed (modify))193 int vtkPointHandleRepresentation3D ::ComputeInteractionState(int X, int Y, int vtkNotUsed(modify))
194 {
195 this->VisibilityOn(); // actor must be on to be picked
196
197 // First make sure that the cursor is within the bounding sphere of the
198 // representation in display space.
199 double d[3], bounds[6];
200 this->Cursor3D->GetModelBounds(bounds);
201 this->GetDisplayPosition(d);
202
203 if (!this->NearbyEvent(X, Y, bounds))
204 {
205 this->InteractionState = vtkHandleRepresentation::Outside;
206 return this->InteractionState;
207 }
208
209 // Now see if anything is picked
210 vtkAssemblyPath* path = this->GetAssemblyPath(X, Y, 0., this->CursorPicker);
211
212 if (path != nullptr)
213 {
214 this->InteractionState = vtkHandleRepresentation::Nearby;
215 }
216 else
217 {
218 this->InteractionState = vtkHandleRepresentation::Outside;
219 if (this->ActiveRepresentation)
220 {
221 this->VisibilityOff();
222 }
223 }
224
225 return this->InteractionState;
226 }
227
228 //------------------------------------------------------------------------------
ComputeComplexInteractionState(vtkRenderWindowInteractor *,vtkAbstractWidget *,unsigned long,void * calldata,int)229 int vtkPointHandleRepresentation3D::ComputeComplexInteractionState(
230 vtkRenderWindowInteractor*, vtkAbstractWidget*, unsigned long, void* calldata, int)
231 {
232 this->VisibilityOn(); // actor must be on to be picked
233
234 vtkEventData* edata = static_cast<vtkEventData*>(calldata);
235 vtkEventDataDevice3D* edd = edata->GetAsEventDataDevice3D();
236 if (edd)
237 {
238 double pos[3];
239 edd->GetWorldPosition(pos);
240 vtkAssemblyPath* path = this->GetAssemblyPath3DPoint(pos, this->CursorPicker);
241 double focus[3];
242 this->Cursor3D->GetFocalPoint(focus);
243 double d[3];
244 this->GetDisplayPosition(d);
245
246 if (path != nullptr)
247 {
248 this->InteractionState = vtkHandleRepresentation::Nearby;
249 }
250 else
251 {
252 this->InteractionState = vtkHandleRepresentation::Outside;
253 if (this->ActiveRepresentation)
254 {
255 this->VisibilityOff();
256 }
257 }
258 }
259
260 return this->InteractionState;
261 }
262
263 //------------------------------------------------------------------------------
DetermineConstraintAxis(int constraint,double * x,double * startPickPoint)264 int vtkPointHandleRepresentation3D::DetermineConstraintAxis(
265 int constraint, double* x, double* startPickPoint)
266 {
267 // Look for trivial cases
268 if (!this->Constrained)
269 {
270 return -1;
271 }
272 else if (constraint >= 0 && constraint < 3)
273 {
274 return constraint;
275 }
276
277 // Okay, figure out constraint. First see if the choice is
278 // outside the hot spot
279 if (!x)
280 {
281 double p[3], d2, tol;
282 this->CursorPicker->GetPickPosition(p);
283 d2 = vtkMath::Distance2BetweenPoints(p, this->LastPickPosition);
284 tol = this->HotSpotSize * this->InitialLength;
285 if (d2 > (tol * tol))
286 {
287 this->WaitingForMotion = 0;
288 return this->CursorPicker->GetCellId();
289 }
290 else
291 {
292 this->WaitingForMotion = 1;
293 this->WaitCount = 0;
294 return -1;
295 }
296 }
297 else if (x)
298 {
299 this->WaitingForMotion = 0;
300 double v[3];
301 v[0] = fabs(x[0] - startPickPoint[0]);
302 v[1] = fabs(x[1] - startPickPoint[1]);
303 v[2] = fabs(x[2] - startPickPoint[2]);
304 return (v[0] > v[1] ? (v[0] > v[2] ? 0 : 2) : (v[1] > v[2] ? 1 : 2));
305 }
306 else
307 {
308 return -1;
309 }
310 }
311
312 //------------------------------------------------------------------------------
313 // Record the current event position, and the translation state
StartWidgetInteraction(double startEventPos[2])314 void vtkPointHandleRepresentation3D::StartWidgetInteraction(double startEventPos[2])
315 {
316 this->StartEventPosition[0] = startEventPos[0];
317 this->StartEventPosition[1] = startEventPos[1];
318 this->StartEventPosition[2] = 0.0;
319
320 this->LastEventPosition[0] = startEventPos[0];
321 this->LastEventPosition[1] = startEventPos[1];
322
323 // Make sure events are close to widget and something is picked
324 double bounds[6];
325 this->Cursor3D->GetModelBounds(bounds);
326 bool nearby = this->NearbyEvent(startEventPos[0], startEventPos[1], bounds);
327 vtkAssemblyPath* path =
328 this->GetAssemblyPath(startEventPos[0], startEventPos[1], 0., this->CursorPicker);
329
330 if (nearby && path != nullptr)
331 {
332 this->InteractionState = vtkHandleRepresentation::Nearby;
333 this->ConstraintAxis = -1;
334 this->CursorPicker->GetPickPosition(this->LastPickPosition);
335 }
336 else
337 {
338 this->InteractionState = vtkHandleRepresentation::Outside;
339 this->ConstraintAxis = -1;
340 }
341 this->Cursor3D->SetTranslationMode(this->TranslationMode);
342 this->WaitCount = 0;
343 }
344
345 //------------------------------------------------------------------------------
StartComplexInteraction(vtkRenderWindowInteractor *,vtkAbstractWidget *,unsigned long,void * calldata)346 void vtkPointHandleRepresentation3D::StartComplexInteraction(
347 vtkRenderWindowInteractor*, vtkAbstractWidget*, unsigned long, void* calldata)
348 {
349 vtkEventData* edata = static_cast<vtkEventData*>(calldata);
350 vtkEventDataDevice3D* edd = edata->GetAsEventDataDevice3D();
351 if (edd)
352 {
353 edd->GetWorldPosition(this->StartEventPosition);
354 this->LastEventPosition[0] = this->StartEventPosition[0];
355 this->LastEventPosition[1] = this->StartEventPosition[1];
356 this->LastEventPosition[2] = this->StartEventPosition[2];
357
358 double bounds[6];
359 this->Cursor3D->GetModelBounds(bounds);
360 bool nearby =
361 this->NearbyEvent(this->StartEventPosition[0], this->StartEventPosition[1], bounds);
362 vtkAssemblyPath* path =
363 this->GetAssemblyPath3DPoint(this->StartEventPosition, this->CursorPicker);
364
365 if (nearby && path != nullptr)
366 {
367 this->InteractionState = vtkHandleRepresentation::Nearby;
368 this->ConstraintAxis = -1;
369 this->CursorPicker->GetPickPosition(this->LastPickPosition);
370 }
371 else
372 {
373 this->InteractionState = vtkHandleRepresentation::Outside;
374 this->ConstraintAxis = -1;
375 }
376 this->Cursor3D->SetTranslationMode(this->TranslationMode);
377 this->WaitCount = 0;
378 }
379 }
380
381 //------------------------------------------------------------------------------
382 // Based on the displacement vector (computed in display coordinates) and
383 // the cursor state (which corresponds to which part of the widget has been
384 // selected), the widget points are modified.
385 // First construct a local coordinate system based on the display coordinates
386 // of the widget.
WidgetInteraction(double eventPos[2])387 void vtkPointHandleRepresentation3D::WidgetInteraction(double eventPos[2])
388 {
389 // Do different things depending on state
390 // Calculations everybody does
391 double focalPoint[4], pickPoint[4], prevPickPoint[4], startPickPoint[4], z;
392
393 // Compute the two points defining the motion vector
394 vtkInteractorObserver::ComputeWorldToDisplay(this->Renderer, this->LastPickPosition[0],
395 this->LastPickPosition[1], this->LastPickPosition[2], focalPoint);
396 z = focalPoint[2];
397 vtkInteractorObserver::ComputeDisplayToWorld(
398 this->Renderer, this->LastEventPosition[0], this->LastEventPosition[1], z, prevPickPoint);
399 vtkInteractorObserver::ComputeDisplayToWorld(
400 this->Renderer, eventPos[0], eventPos[1], z, pickPoint);
401
402 // Process the motion
403 if (this->InteractionState == vtkHandleRepresentation::Selecting ||
404 this->InteractionState == vtkHandleRepresentation::Translating)
405 {
406 this->WaitCount++;
407
408 if (this->WaitCount > 3 || !this->Constrained)
409 {
410 vtkInteractorObserver::ComputeDisplayToWorld(this->Renderer, this->StartEventPosition[0],
411 this->StartEventPosition[1], z, startPickPoint);
412
413 this->ConstraintAxis =
414 this->DetermineConstraintAxis(this->ConstraintAxis, pickPoint, startPickPoint);
415
416 if (this->InteractionState == vtkHandleRepresentation::Selecting && !this->TranslationMode)
417 {
418 vtkDebugMacro(<< "Processing widget interaction for Select mode");
419
420 // If we are doing axis constrained motion, ignore the placer.
421 // Can't have both the placer and an axis constraint dictating
422 // handle placement.
423 if (this->ConstraintAxis >= 0 || this->Constrained || !this->PointPlacer)
424 {
425 this->MoveFocus(prevPickPoint, pickPoint);
426 }
427 else
428 {
429 double newCenterPointRequested[3]; // displayPosition
430 double newCenterPoint[3], worldOrient[9];
431
432 // Make a request for the new position.
433 this->MoveFocusRequest(prevPickPoint, pickPoint, eventPos, newCenterPointRequested);
434
435 vtkFocalPlanePointPlacer* fPlacer =
436 vtkFocalPlanePointPlacer::SafeDownCast(this->PointPlacer);
437 if (fPlacer)
438 {
439 // Offset the placer plane to one that passes through the current
440 // world position and is parallel to the focal plane. Offset =
441 // the distance currentWorldPos is from the focal plane
442 //
443 double currentWorldPos[3], projDir[3], fp[3];
444 this->GetWorldPosition(currentWorldPos);
445 this->Renderer->GetActiveCamera()->GetFocalPoint(fp);
446 double vec[3] = { currentWorldPos[0] - fp[0], currentWorldPos[1] - fp[1],
447 currentWorldPos[2] - fp[2] };
448 this->Renderer->GetActiveCamera()->GetDirectionOfProjection(projDir);
449 fPlacer->SetOffset(vtkMath::Dot(vec, projDir));
450 }
451
452 vtkDebugMacro(<< "Request for computing world position at "
453 << "display position of " << newCenterPointRequested[0] << ","
454 << newCenterPointRequested[1]);
455
456 // See what the placer says.
457 if (this->PointPlacer->ComputeWorldPosition(
458 this->Renderer, newCenterPointRequested, newCenterPoint, worldOrient))
459 {
460 // Once the placer has validated us, update the handle position
461 this->SetWorldPosition(newCenterPoint);
462 }
463 }
464 }
465 else
466 {
467 vtkDebugMacro(<< "Processing widget interaction for translate");
468
469 // If we are doing axis constrained motion, ignore the placer.
470 // Can't have both the placer and the axis constraint dictating
471 // handle placement.
472 if (this->ConstraintAxis >= 0 || this->Constrained || !this->PointPlacer)
473 {
474 this->Translate(prevPickPoint, pickPoint);
475 }
476 else
477 {
478 double newCenterPointRequested[3]; // displayPosition
479 double newCenterPoint[3], worldOrient[9];
480
481 // Make a request for the new position.
482 this->MoveFocusRequest(prevPickPoint, pickPoint, eventPos, newCenterPointRequested);
483
484 vtkFocalPlanePointPlacer* fPlacer =
485 vtkFocalPlanePointPlacer::SafeDownCast(this->PointPlacer);
486 if (fPlacer)
487 {
488 // Offset the placer plane to one that passes through the current
489 // world position and is parallel to the focal plane. Offset =
490 // the distance currentWorldPos is from the focal plane
491 //
492 double currentWorldPos[3], projDir[3], fp[3];
493 this->GetWorldPosition(currentWorldPos);
494 this->Renderer->GetActiveCamera()->GetFocalPoint(fp);
495 double vec[3] = { currentWorldPos[0] - fp[0], currentWorldPos[1] - fp[1],
496 currentWorldPos[2] - fp[2] };
497 this->Renderer->GetActiveCamera()->GetDirectionOfProjection(projDir);
498 fPlacer->SetOffset(vtkMath::Dot(vec, projDir));
499 }
500
501 vtkDebugMacro(<< "Request for computing world position at "
502 << "display position of " << newCenterPointRequested[0] << ","
503 << newCenterPointRequested[1]);
504
505 // See what the placer says.
506 if (this->PointPlacer->ComputeWorldPosition(
507 this->Renderer, newCenterPointRequested, newCenterPoint, worldOrient))
508 {
509
510 // Once the placer has validated us, update the handle
511 // position and its bounds.
512 double* p = this->GetWorldPosition();
513
514 // Get the motion vector
515 double v[3] = { newCenterPoint[0] - p[0], newCenterPoint[1] - p[1],
516 newCenterPoint[2] - p[2] };
517 double *bounds = this->Cursor3D->GetModelBounds(), newBounds[6];
518 for (int i = 0; i < 3; i++)
519 {
520 newBounds[2 * i] = bounds[2 * i] + v[i];
521 newBounds[2 * i + 1] = bounds[2 * i + 1] + v[i];
522 }
523
524 this->Cursor3D->SetModelBounds(newBounds);
525 this->SetWorldPosition(newCenterPoint);
526 }
527 }
528 }
529 }
530 }
531
532 else if (this->InteractionState == vtkHandleRepresentation::Scaling)
533 {
534 // Scaling does not change the position of the handle, we needn't
535 // ask the placer..
536 this->Scale(prevPickPoint, pickPoint, eventPos);
537 }
538
539 // Book keeping
540 this->LastEventPosition[0] = eventPos[0];
541 this->LastEventPosition[1] = eventPos[1];
542
543 this->Modified();
544 }
545
ComplexInteraction(vtkRenderWindowInteractor *,vtkAbstractWidget *,unsigned long,void * calldata)546 void vtkPointHandleRepresentation3D::ComplexInteraction(
547 vtkRenderWindowInteractor*, vtkAbstractWidget*, unsigned long, void* calldata)
548 {
549 vtkEventData* edata = static_cast<vtkEventData*>(calldata);
550 vtkEventDataDevice3D* edd = edata->GetAsEventDataDevice3D();
551 if (edd)
552 {
553 double eventPos[3];
554 edd->GetWorldPosition(eventPos);
555 // Process the motion
556 if (this->InteractionState == vtkHandleRepresentation::Selecting ||
557 this->InteractionState == vtkHandleRepresentation::Translating)
558 {
559 this->WaitCount++;
560
561 if (this->WaitCount > 3 || !this->Constrained)
562 {
563 this->ConstraintAxis =
564 this->DetermineConstraintAxis(this->ConstraintAxis, eventPos, this->StartEventPosition);
565
566 if (this->InteractionState == vtkHandleRepresentation::Selecting && !this->TranslationMode)
567 {
568 vtkDebugMacro(<< "Processing widget interaction for Select mode");
569
570 this->MoveFocus(this->LastEventPosition, eventPos);
571 }
572 else
573 {
574 vtkDebugMacro(<< "Processing widget interaction for translate");
575 this->Translate(this->LastEventPosition, eventPos);
576 }
577 }
578 }
579
580 // Book keeping
581 this->LastEventPosition[0] = eventPos[0];
582 this->LastEventPosition[1] = eventPos[1];
583 this->LastEventPosition[2] = eventPos[2];
584
585 this->Modified();
586 }
587 }
588
589 //------------------------------------------------------------------------------
MoveFocusRequest(const double * p1,const double * p2,const double eventPos[2],double center[3])590 void vtkPointHandleRepresentation3D ::MoveFocusRequest(
591 const double* p1, const double* p2, const double eventPos[2], double center[3])
592 {
593 if (this->SmoothMotion)
594 {
595 double focus[4], v[3];
596 this->Cursor3D->GetFocalPoint(focus);
597 this->GetTranslationVector(p1, p2, v);
598
599 // Move the center of the handle along the motion vector
600 focus[0] += v[0];
601 focus[1] += v[1];
602 focus[2] += v[2];
603 focus[3] = 1.0;
604
605 // Get the display position that this center would fall on.
606 this->Renderer->SetWorldPoint(focus);
607 this->Renderer->WorldToDisplay();
608 this->Renderer->GetDisplayPoint(center);
609 }
610 else
611 {
612 center[0] = eventPos[0];
613 center[1] = eventPos[1];
614 center[2] = 1.0;
615 }
616 }
617
618 //------------------------------------------------------------------------------
MoveFocus(const double * p1,const double * p2)619 void vtkPointHandleRepresentation3D::MoveFocus(const double* p1, const double* p2)
620 {
621 this->Translate(p1, p2);
622 }
623
624 //------------------------------------------------------------------------------
SetTranslationMode(vtkTypeBool mode)625 void vtkPointHandleRepresentation3D::SetTranslationMode(vtkTypeBool mode)
626 {
627 if (this->TranslationMode != mode)
628 {
629 this->TranslationMode = mode;
630 // Pass new setting to Cursor3D, otherwise PlaceWidget will not work
631 // as it should when TranslationMode is off.
632 this->Cursor3D->SetTranslationMode(mode);
633 this->Modified();
634 }
635 }
636
637 //------------------------------------------------------------------------------
638 // Translate everything
Translate(const double * p1,const double * p2)639 void vtkPointHandleRepresentation3D::Translate(const double* p1, const double* p2)
640 {
641 double v[3] = { 0, 0, 0 };
642 vtkHandleRepresentation::Translate(p1, p2);
643 this->GetTranslationVector(p1, p2, v);
644
645 double* bounds = this->Cursor3D->GetModelBounds();
646 double* pos = this->Cursor3D->GetFocalPoint();
647 double newBounds[6], newFocus[3];
648 int i;
649
650 if (this->ConstraintAxis >= 0)
651 { // move along axis
652 for (i = 0; i < 3; i++)
653 {
654 if (i != this->ConstraintAxis)
655 {
656 v[i] = 0.0;
657 }
658 }
659 }
660
661 for (i = 0; i < 3; i++)
662 {
663 newBounds[2 * i] = bounds[2 * i] + v[i];
664 newBounds[2 * i + 1] = bounds[2 * i + 1] + v[i];
665 newFocus[i] = pos[i] + v[i];
666 }
667
668 this->Cursor3D->SetModelBounds(newBounds);
669 this->Cursor3D->SetFocalPoint(newFocus);
670 }
671
672 //------------------------------------------------------------------------------
SizeBounds()673 void vtkPointHandleRepresentation3D::SizeBounds()
674 {
675 // Only change the size of the bounding box if translation mode is on.
676 if (this->TranslationMode)
677 {
678 double center[3], bounds[6];
679 this->Cursor3D->GetFocalPoint(center);
680 double radius = this->SizeHandlesInPixels(1.0, center);
681 radius *= this->CurrentHandleSize / this->HandleSize;
682
683 for (int i = 0; i < 3; i++)
684 {
685 bounds[2 * i] = center[i] - radius;
686 bounds[2 * i + 1] = center[i] + radius;
687 }
688 this->Cursor3D->SetModelBounds(bounds);
689 }
690 }
691
692 //------------------------------------------------------------------------------
Scale(const double * p1,const double * p2,const double eventPos[2])693 void vtkPointHandleRepresentation3D::Scale(
694 const double* p1, const double* p2, const double eventPos[2])
695 {
696 // Get the motion vector
697 double v[3];
698 v[0] = p2[0] - p1[0];
699 v[1] = p2[1] - p1[1];
700 v[2] = p2[2] - p1[2];
701
702 double* bounds = this->Cursor3D->GetModelBounds();
703
704 // Compute the scale factor
705 double sf = vtkMath::Norm(v) /
706 sqrt((bounds[1] - bounds[0]) * (bounds[1] - bounds[0]) +
707 (bounds[3] - bounds[2]) * (bounds[3] - bounds[2]) +
708 (bounds[5] - bounds[4]) * (bounds[5] - bounds[4]));
709
710 if (eventPos[1] > this->LastEventPosition[1])
711 {
712 sf = 1.0 + sf;
713 }
714 else
715 {
716 sf = 1.0 - sf;
717 }
718
719 this->CurrentHandleSize *= sf;
720 this->CurrentHandleSize = (this->CurrentHandleSize < 0.001 ? 0.001 : this->CurrentHandleSize);
721
722 this->SizeBounds();
723 }
724
725 //------------------------------------------------------------------------------
Highlight(int highlight)726 void vtkPointHandleRepresentation3D::Highlight(int highlight)
727 {
728 if (highlight)
729 {
730 this->Actor->SetProperty(this->SelectedProperty);
731 }
732 else
733 {
734 this->Actor->SetProperty(this->Property);
735 }
736 }
737
738 //------------------------------------------------------------------------------
CreateDefaultProperties()739 void vtkPointHandleRepresentation3D::CreateDefaultProperties()
740 {
741 this->Property = vtkProperty::New();
742 this->Property->SetAmbient(1.0);
743 this->Property->SetAmbientColor(1.0, 1.0, 1.0);
744 this->Property->SetLineWidth(0.5);
745
746 this->SelectedProperty = vtkProperty::New();
747 this->SelectedProperty->SetAmbient(1.0);
748 this->SelectedProperty->SetAmbientColor(0.0, 1.0, 0.0);
749 this->SelectedProperty->SetLineWidth(2.0);
750 }
751
752 //------------------------------------------------------------------------------
SetVisibility(vtkTypeBool visible)753 void vtkPointHandleRepresentation3D::SetVisibility(vtkTypeBool visible)
754 {
755 this->Actor->SetVisibility(visible);
756 // Forward to superclass
757 this->Superclass::SetVisibility(visible);
758 }
759
760 //------------------------------------------------------------------------------
BuildRepresentation()761 void vtkPointHandleRepresentation3D::BuildRepresentation()
762 {
763 // The net effect is to resize the handle
764 if (this->GetMTime() > this->BuildTime ||
765 (this->Renderer && this->Renderer->GetVTKWindow() &&
766 this->Renderer->GetVTKWindow()->GetMTime() > this->BuildTime))
767 {
768 if (!this->Placed)
769 {
770 this->ValidPick = 1;
771 this->Placed = 1;
772 }
773
774 this->SizeBounds();
775 this->Cursor3D->Update();
776 this->BuildTime.Modified();
777 }
778 }
779
780 //------------------------------------------------------------------------------
ShallowCopy(vtkProp * prop)781 void vtkPointHandleRepresentation3D::ShallowCopy(vtkProp* prop)
782 {
783 vtkPointHandleRepresentation3D* rep = vtkPointHandleRepresentation3D::SafeDownCast(prop);
784 if (rep)
785 {
786 this->SetOutline(rep->GetOutline());
787 this->SetXShadows(rep->GetXShadows());
788 this->SetYShadows(rep->GetYShadows());
789 this->SetZShadows(rep->GetZShadows());
790 this->SetTranslationMode(rep->GetTranslationMode());
791 this->SetProperty(rep->GetProperty());
792 this->Actor->SetProperty(rep->GetProperty());
793 this->SetSelectedProperty(rep->GetSelectedProperty());
794 this->SetHotSpotSize(rep->GetHotSpotSize());
795 }
796 this->Superclass::ShallowCopy(prop);
797 }
798
799 //------------------------------------------------------------------------------
DeepCopy(vtkProp * prop)800 void vtkPointHandleRepresentation3D::DeepCopy(vtkProp* prop)
801 {
802 vtkPointHandleRepresentation3D* rep = vtkPointHandleRepresentation3D::SafeDownCast(prop);
803 if (rep)
804 {
805 this->SetOutline(rep->GetOutline());
806 this->SetXShadows(rep->GetXShadows());
807 this->SetYShadows(rep->GetYShadows());
808 this->SetZShadows(rep->GetZShadows());
809 this->SetTranslationMode(rep->GetTranslationMode());
810 this->SetProperty(rep->GetProperty());
811 this->Actor->SetProperty(rep->GetProperty());
812 this->SetSelectedProperty(rep->GetSelectedProperty());
813 this->SetHotSpotSize(rep->GetHotSpotSize());
814 }
815 this->Superclass::DeepCopy(prop);
816 }
817
818 //------------------------------------------------------------------------------
GetActors(vtkPropCollection * pc)819 void vtkPointHandleRepresentation3D::GetActors(vtkPropCollection* pc)
820 {
821 this->Actor->GetActors(pc);
822 }
823
824 //------------------------------------------------------------------------------
ReleaseGraphicsResources(vtkWindow * win)825 void vtkPointHandleRepresentation3D::ReleaseGraphicsResources(vtkWindow* win)
826 {
827 this->Actor->ReleaseGraphicsResources(win);
828 }
829
830 //------------------------------------------------------------------------------
RenderOpaqueGeometry(vtkViewport * viewport)831 int vtkPointHandleRepresentation3D::RenderOpaqueGeometry(vtkViewport* viewport)
832 {
833 this->BuildRepresentation();
834
835 // Sanity check
836 double worldPos[3];
837 this->GetWorldPosition(worldPos);
838 if (worldPos[0] == VTK_DOUBLE_MAX)
839 {
840 return 0;
841 }
842
843 return this->Actor->RenderOpaqueGeometry(viewport);
844 }
845
846 //------------------------------------------------------------------------------
RenderTranslucentPolygonalGeometry(vtkViewport * viewport)847 int vtkPointHandleRepresentation3D::RenderTranslucentPolygonalGeometry(vtkViewport* viewport)
848 {
849 this->BuildRepresentation();
850
851 // Sanity check
852 double worldPos[3];
853 this->GetWorldPosition(worldPos);
854 if (worldPos[0] == VTK_DOUBLE_MAX)
855 {
856 return 0;
857 }
858
859 return this->Actor->RenderTranslucentPolygonalGeometry(viewport);
860 }
861 //------------------------------------------------------------------------------
HasTranslucentPolygonalGeometry()862 vtkTypeBool vtkPointHandleRepresentation3D::HasTranslucentPolygonalGeometry()
863 {
864 this->BuildRepresentation();
865 return this->Actor->HasTranslucentPolygonalGeometry();
866 }
867
868 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)869 void vtkPointHandleRepresentation3D::PrintSelf(ostream& os, vtkIndent indent)
870 {
871 // Superclass typedef defined in vtkTypeMacro() found in vtkSetGet.h
872 this->Superclass::PrintSelf(os, indent);
873
874 os << indent << "Hot Spot Size: " << this->HotSpotSize << "\n";
875 if (this->Property)
876 {
877 os << indent << "Property: " << this->Property << "\n";
878 }
879 else
880 {
881 os << indent << "Property: (none)\n";
882 }
883 if (this->SelectedProperty)
884 {
885 os << indent << "Selected Property: " << this->SelectedProperty << "\n";
886 }
887 else
888 {
889 os << indent << "Selected Property: (none)\n";
890 }
891
892 os << indent << "Outline: " << (this->GetOutline() ? "On\n" : "Off\n");
893 os << indent << "XShadows: " << (this->GetXShadows() ? "On\n" : "Off\n");
894 os << indent << "YShadows: " << (this->GetYShadows() ? "On\n" : "Off\n");
895 os << indent << "ZShadows: " << (this->GetZShadows() ? "On\n" : "Off\n");
896
897 os << indent << "Translation Mode: " << (this->TranslationMode ? "On\n" : "Off\n");
898 os << indent << "SmoothMotion: " << this->SmoothMotion << endl;
899 }
900