1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkSphereHandleRepresentation.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 "vtkSphereHandleRepresentation.h"
16 #include "vtkActor.h"
17 #include "vtkAssemblyPath.h"
18 #include "vtkCellPicker.h"
19 #include "vtkCoordinate.h"
20 #include "vtkInteractorObserver.h"
21 #include "vtkLine.h"
22 #include "vtkMath.h"
23 #include "vtkObjectFactory.h"
24 #include "vtkPickingManager.h"
25 #include "vtkPolyDataMapper.h"
26 #include "vtkProperty.h"
27 #include "vtkRenderWindow.h"
28 #include "vtkRenderWindowInteractor.h"
29 #include "vtkRenderer.h"
30 #include "vtkSphereSource.h"
31
32 vtkStandardNewMacro(vtkSphereHandleRepresentation);
33 vtkCxxSetObjectMacro(vtkSphereHandleRepresentation, SelectedProperty, vtkProperty);
34
35 //------------------------------------------------------------------------------
vtkSphereHandleRepresentation()36 vtkSphereHandleRepresentation::vtkSphereHandleRepresentation()
37 {
38 // Initialize state
39 this->InteractionState = vtkHandleRepresentation::Outside;
40
41 // Represent the line
42 this->Sphere = vtkSphereSource::New();
43 this->Sphere->SetThetaResolution(16);
44 this->Sphere->SetPhiResolution(8);
45
46 this->Mapper = vtkPolyDataMapper::New();
47 this->Mapper->SetInputConnection(this->Sphere->GetOutputPort());
48
49 // Set up the initial properties
50 this->CreateDefaultProperties();
51
52 this->Actor = vtkActor::New();
53 this->Actor->SetMapper(this->Mapper);
54 this->Actor->SetProperty(this->Property);
55
56 // Manage the picking stuff
57 this->CursorPicker = vtkCellPicker::New();
58 this->CursorPicker->PickFromListOn();
59 this->CursorPicker->AddPickList(this->Actor);
60 this->CursorPicker->SetTolerance(0.01); // need some fluff
61
62 // Override superclass'
63 this->PlaceFactor = 1.0;
64
65 // The size of the hot spot
66 this->HotSpotSize = 0.05;
67 this->WaitingForMotion = 0;
68
69 // Current handle size
70 this->HandleSize = 15.0; // in pixels
71 this->CurrentHandleSize = this->HandleSize;
72
73 // Translation control
74 this->TranslationMode = 1;
75 }
76
77 //------------------------------------------------------------------------------
~vtkSphereHandleRepresentation()78 vtkSphereHandleRepresentation::~vtkSphereHandleRepresentation()
79 {
80 this->Sphere->Delete();
81 this->CursorPicker->Delete();
82 this->Mapper->Delete();
83 this->Actor->Delete();
84 this->Property->Delete();
85 this->SelectedProperty->Delete();
86 }
87
88 //------------------------------------------------------------------------------
RegisterPickers()89 void vtkSphereHandleRepresentation::RegisterPickers()
90 {
91 vtkPickingManager* pm = this->GetPickingManager();
92 if (!pm)
93 {
94 return;
95 }
96 pm->AddPicker(this->CursorPicker, this);
97 }
98
99 //------------------------------------------------------------------------------
PlaceWidget(double bds[6])100 void vtkSphereHandleRepresentation::PlaceWidget(double bds[6])
101 {
102 int i;
103 double bounds[6], center[3];
104
105 this->AdjustBounds(bds, bounds, center);
106
107 // this->Sphere->SetModelBounds(bounds);
108 this->SetWorldPosition(center);
109
110 for (i = 0; i < 6; i++)
111 {
112 this->InitialBounds[i] = bounds[i];
113 }
114 this->InitialLength = sqrt((bounds[1] - bounds[0]) * (bounds[1] - bounds[0]) +
115 (bounds[3] - bounds[2]) * (bounds[3] - bounds[2]) +
116 (bounds[5] - bounds[4]) * (bounds[5] - bounds[4]));
117 }
118
119 //------------------------------------------------------------------------------
SetSphereRadius(double radius)120 void vtkSphereHandleRepresentation::SetSphereRadius(double radius)
121 {
122 if (radius == this->Sphere->GetRadius())
123 {
124 return;
125 }
126
127 this->Sphere->SetRadius(radius);
128 this->Modified();
129 }
130
131 //------------------------------------------------------------------------------
GetSphereRadius()132 double vtkSphereHandleRepresentation::GetSphereRadius()
133 {
134 return this->Sphere->GetRadius();
135 }
136
137 //------------------------------------------------------------------------------
GetBounds()138 double* vtkSphereHandleRepresentation::GetBounds()
139 {
140 static double bounds[6];
141 double center[3];
142 double radius = this->Sphere->GetRadius();
143 this->Sphere->GetCenter(center);
144
145 bounds[0] = this->PlaceFactor * (center[0] - radius);
146 bounds[1] = this->PlaceFactor * (center[0] + radius);
147 bounds[2] = this->PlaceFactor * (center[1] - radius);
148 bounds[3] = this->PlaceFactor * (center[1] + radius);
149 bounds[4] = this->PlaceFactor * (center[2] - radius);
150 bounds[5] = this->PlaceFactor * (center[2] + radius);
151
152 return bounds;
153 }
154
155 //------------------------------------------------------------------------------
SetWorldPosition(double p[3])156 void vtkSphereHandleRepresentation::SetWorldPosition(double p[3])
157 {
158 this->Sphere->SetCenter(p); // this may clamp the point
159 this->Superclass::SetWorldPosition(this->Sphere->GetCenter());
160 }
161
162 //------------------------------------------------------------------------------
SetDisplayPosition(double p[3])163 void vtkSphereHandleRepresentation::SetDisplayPosition(double p[3])
164 {
165 this->Superclass::SetDisplayPosition(p);
166 this->SetWorldPosition(this->WorldPosition->GetValue());
167 }
168
169 //------------------------------------------------------------------------------
SetHandleSize(double size)170 void vtkSphereHandleRepresentation::SetHandleSize(double size)
171 {
172 this->Superclass::SetHandleSize(size);
173 this->CurrentHandleSize = this->HandleSize;
174 }
175
176 //------------------------------------------------------------------------------
ComputeInteractionState(int X,int Y,int vtkNotUsed (modify))177 int vtkSphereHandleRepresentation::ComputeInteractionState(int X, int Y, int vtkNotUsed(modify))
178 {
179 this->VisibilityOn(); // actor must be on to be picked
180
181 vtkAssemblyPath* path = this->GetAssemblyPath(X, Y, 0., this->CursorPicker);
182
183 if (path != nullptr)
184 {
185 // this->InteractionState = vtkHandleRepresentation::Nearby;
186 this->InteractionState = vtkHandleRepresentation::Selecting;
187 }
188 else
189 {
190 this->InteractionState = vtkHandleRepresentation::Outside;
191 if (this->ActiveRepresentation)
192 {
193 this->VisibilityOff();
194 }
195 }
196
197 return this->InteractionState;
198 }
199
200 //------------------------------------------------------------------------------
201 // Record the current event position, and the rectilinear wipe position.
StartWidgetInteraction(double startEventPos[2])202 void vtkSphereHandleRepresentation::StartWidgetInteraction(double startEventPos[2])
203 {
204 this->StartEventPosition[0] = startEventPos[0];
205 this->StartEventPosition[1] = startEventPos[1];
206 this->StartEventPosition[2] = 0.0;
207
208 this->LastEventPosition[0] = startEventPos[0];
209 this->LastEventPosition[1] = startEventPos[1];
210
211 vtkAssemblyPath* path =
212 this->GetAssemblyPath(startEventPos[0], startEventPos[1], 0., this->CursorPicker);
213
214 if (path != nullptr)
215 {
216 // this->InteractionState = vtkHandleRepresentation::Nearby;
217 this->InteractionState = vtkHandleRepresentation::Selecting;
218 this->CursorPicker->GetPickPosition(this->LastPickPosition);
219 }
220 else
221 {
222 this->InteractionState = vtkHandleRepresentation::Outside;
223 this->ConstraintAxis = -1;
224 }
225 }
226
227 //------------------------------------------------------------------------------
228 // Based on the displacement vector (computed in display coordinates) and
229 // the cursor state (which corresponds to which part of the widget has been
230 // selected), the widget points are modified.
231 // First construct a local coordinate system based on the display coordinates
232 // of the widget.
WidgetInteraction(double eventPos[2])233 void vtkSphereHandleRepresentation::WidgetInteraction(double eventPos[2])
234 {
235 // Do different things depending on state
236 // Calculations everybody does
237 double focalPoint[4], pickPoint[4], prevPickPoint[4];
238 double z;
239
240 // Compute the two points defining the motion vector
241 vtkInteractorObserver::ComputeWorldToDisplay(this->Renderer, this->LastPickPosition[0],
242 this->LastPickPosition[1], this->LastPickPosition[2], focalPoint);
243 z = focalPoint[2];
244 vtkInteractorObserver::ComputeDisplayToWorld(
245 this->Renderer, this->LastEventPosition[0], this->LastEventPosition[1], z, prevPickPoint);
246 vtkInteractorObserver::ComputeDisplayToWorld(
247 this->Renderer, eventPos[0], eventPos[1], z, pickPoint);
248
249 // Process the motion
250 if (this->InteractionState == vtkHandleRepresentation::Selecting ||
251 this->InteractionState == vtkHandleRepresentation::Translating)
252 {
253 if (!this->WaitingForMotion || this->WaitCount++ > 3)
254 {
255 if (this->InteractionState == vtkHandleRepresentation::Selecting && !this->TranslationMode)
256 {
257 this->MoveFocus(prevPickPoint, pickPoint);
258 }
259 else
260 {
261 this->Translate(prevPickPoint, pickPoint);
262 }
263 }
264 }
265
266 else if (this->InteractionState == vtkHandleRepresentation::Scaling)
267 {
268 this->Scale(prevPickPoint, pickPoint, eventPos);
269 }
270
271 // Book keeping
272 this->LastEventPosition[0] = eventPos[0];
273 this->LastEventPosition[1] = eventPos[1];
274
275 this->Modified();
276 }
277 /*
278 //------------------------------------------------------------------------------
279 void vtkSphereHandleRepresentation::MoveFocus(const double *p1, const double *p2)
280 {
281 //Get the motion vector
282 double v[3];
283 v[0] = p2[0] - p1[0];
284 v[1] = p2[1] - p1[1];
285 v[2] = p2[2] - p1[2];
286
287 double focus[3];
288 this->Sphere->GetCenter(focus);
289 if ( this->ConstraintAxis >= 0 )
290 {
291 focus[this->ConstraintAxis] += v[this->ConstraintAxis];
292 }
293 else
294 {
295 focus[0] += v[0];
296 focus[1] += v[1];
297 focus[2] += v[2];
298 }
299
300 this->SetWorldPosition(focus);
301 }
302
303 //------------------------------------------------------------------------------
304 // Translate everything
305 void vtkSphereHandleRepresentation::Translate(const double *p1, const double *p2)
306 {
307 //Get the motion vector
308 double v[3];
309 v[0] = p2[0] - p1[0];
310 v[1] = p2[1] - p1[1];
311 v[2] = p2[2] - p1[2];
312
313 double *pos = this->Sphere->GetCenter();
314 double newFocus[3];
315
316 if ( this->ConstraintAxis >= 0 )
317 {//move along axis
318 for (int i=0; i<3; i++)
319 {
320 if ( i != this->ConstraintAxis )
321 {
322 v[i] = 0.0;
323 }
324 }
325 }
326
327 for (int i=0; i<3; i++)
328 {
329 newFocus[i] = pos[i] + v[i];
330 }
331 this->SetWorldPosition(newFocus);
332
333 double radius = this->SizeHandlesInPixels(1.0,newFocus);
334 radius *= this->CurrentHandleSize / this->HandleSize;
335
336 this->Sphere->SetRadius(radius);
337 }*/
338
339 //------------------------------------------------------------------------------
MoveFocus(const double * p1,const double * p2)340 void vtkSphereHandleRepresentation::MoveFocus(const double* p1, const double* p2)
341 {
342 Superclass::Translate(p1, p2);
343 }
344
345 //------------------------------------------------------------------------------
346 // Translate everything
Translate(const double * p1,const double * p2)347 void vtkSphereHandleRepresentation::Translate(const double* p1, const double* p2)
348 {
349 double v[3];
350 this->GetTranslationVector(p1, p2, v);
351 double* pos = this->Sphere->GetCenter();
352 double focus[3];
353 for (int i = 0; i < 3; i++)
354 {
355 focus[i] = pos[i] + v[i];
356 }
357 this->SetWorldPosition(focus);
358
359 double radius = this->SizeHandlesInPixels(1.0, focus);
360 radius *= this->CurrentHandleSize / this->HandleSize;
361
362 this->Sphere->SetRadius(radius);
363 }
364
365 //------------------------------------------------------------------------------
SizeBounds()366 void vtkSphereHandleRepresentation::SizeBounds()
367 {
368 double center[3];
369 this->Sphere->GetCenter(center);
370 double radius = this->SizeHandlesInPixels(1.0, center);
371 radius *= this->CurrentHandleSize / this->HandleSize;
372
373 this->Sphere->SetRadius(radius);
374 }
375
376 //------------------------------------------------------------------------------
Scale(const double * p1,const double * p2,const double eventPos[2])377 void vtkSphereHandleRepresentation::Scale(
378 const double* p1, const double* p2, const double eventPos[2])
379 {
380 // Get the motion vector
381 double v[3];
382 v[0] = p2[0] - p1[0];
383 v[1] = p2[1] - p1[1];
384 v[2] = p2[2] - p1[2];
385
386 const double* bounds = this->GetBounds();
387
388 // Compute the scale factor
389 double sf = vtkMath::Norm(v) /
390 sqrt((bounds[1] - bounds[0]) * (bounds[1] - bounds[0]) +
391 (bounds[3] - bounds[2]) * (bounds[3] - bounds[2]) +
392 (bounds[5] - bounds[4]) * (bounds[5] - bounds[4]));
393
394 if (eventPos[1] > this->LastEventPosition[1])
395 {
396 sf = 1.0 + sf;
397 }
398 else
399 {
400 sf = 1.0 - sf;
401 }
402
403 this->CurrentHandleSize *= sf;
404 this->CurrentHandleSize = (this->CurrentHandleSize < 0.001 ? 0.001 : this->CurrentHandleSize);
405
406 this->SizeBounds();
407 }
408
409 //------------------------------------------------------------------------------
Highlight(int highlight)410 void vtkSphereHandleRepresentation::Highlight(int highlight)
411 {
412 if (highlight)
413 {
414 this->Actor->SetProperty(this->SelectedProperty);
415 }
416 else
417 {
418 this->Actor->SetProperty(this->Property);
419 }
420 }
421
422 //------------------------------------------------------------------------------
CreateDefaultProperties()423 void vtkSphereHandleRepresentation::CreateDefaultProperties()
424 {
425 this->Property = vtkProperty::New();
426 this->Property->SetColor(1, 1, 1);
427
428 this->SelectedProperty = vtkProperty::New();
429 this->SelectedProperty->SetColor(0, 1, 0);
430 }
431
432 //------------------------------------------------------------------------------
BuildRepresentation()433 void vtkSphereHandleRepresentation::BuildRepresentation()
434 {
435 // The net effect is to resize the handle
436 if (this->GetMTime() > this->BuildTime ||
437 (this->Renderer && this->Renderer->GetVTKWindow() &&
438 this->Renderer->GetVTKWindow()->GetMTime() > this->BuildTime))
439 {
440 if (!this->Placed)
441 {
442 this->ValidPick = 1;
443 this->Placed = 1;
444 }
445
446 this->SizeBounds();
447 this->Sphere->Update();
448 this->BuildTime.Modified();
449 }
450 }
451
452 //------------------------------------------------------------------------------
ShallowCopy(vtkProp * prop)453 void vtkSphereHandleRepresentation::ShallowCopy(vtkProp* prop)
454 {
455 vtkSphereHandleRepresentation* rep = vtkSphereHandleRepresentation::SafeDownCast(prop);
456 if (rep)
457 {
458 this->SetTranslationMode(rep->GetTranslationMode());
459 this->SetProperty(rep->GetProperty());
460 this->SetSelectedProperty(rep->GetSelectedProperty());
461 this->SetHotSpotSize(rep->GetHotSpotSize());
462 }
463 this->Superclass::ShallowCopy(prop);
464 }
465
466 //------------------------------------------------------------------------------
DeepCopy(vtkProp * prop)467 void vtkSphereHandleRepresentation::DeepCopy(vtkProp* prop)
468 {
469 vtkSphereHandleRepresentation* rep = vtkSphereHandleRepresentation::SafeDownCast(prop);
470 if (rep)
471 {
472 this->SetTranslationMode(rep->GetTranslationMode());
473 this->Property->DeepCopy(rep->GetProperty());
474 this->SelectedProperty->DeepCopy(rep->GetSelectedProperty());
475 this->SetHotSpotSize(rep->GetHotSpotSize());
476 }
477 this->Superclass::DeepCopy(prop);
478 }
479
480 //------------------------------------------------------------------------------
GetActors(vtkPropCollection * pc)481 void vtkSphereHandleRepresentation::GetActors(vtkPropCollection* pc)
482 {
483 this->Actor->GetActors(pc);
484 }
485
486 //------------------------------------------------------------------------------
ReleaseGraphicsResources(vtkWindow * win)487 void vtkSphereHandleRepresentation::ReleaseGraphicsResources(vtkWindow* win)
488 {
489 this->Actor->ReleaseGraphicsResources(win);
490 }
491
492 //------------------------------------------------------------------------------
RenderOpaqueGeometry(vtkViewport * viewport)493 int vtkSphereHandleRepresentation::RenderOpaqueGeometry(vtkViewport* viewport)
494 {
495 this->BuildRepresentation();
496 return this->Actor->RenderOpaqueGeometry(viewport);
497 }
498
499 //------------------------------------------------------------------------------
RenderTranslucentPolygonalGeometry(vtkViewport * viewport)500 int vtkSphereHandleRepresentation ::RenderTranslucentPolygonalGeometry(vtkViewport* viewport)
501 {
502 this->BuildRepresentation();
503 return this->Actor->RenderTranslucentPolygonalGeometry(viewport);
504 }
505
506 //------------------------------------------------------------------------------
HasTranslucentPolygonalGeometry()507 vtkTypeBool vtkSphereHandleRepresentation::HasTranslucentPolygonalGeometry()
508 {
509 return 0; // this->Actor->HasTranslucentPolygonalGeometry();
510 }
511
512 //------------------------------------------------------------------------------
SetProperty(vtkProperty * p)513 void vtkSphereHandleRepresentation::SetProperty(vtkProperty* p)
514 {
515 vtkSetObjectBodyMacro(Property, vtkProperty, p);
516 if (p)
517 {
518 this->Actor->SetProperty(p);
519 }
520 }
521
522 //------------------------------------------------------------------------------
SetVisibility(vtkTypeBool visible)523 void vtkSphereHandleRepresentation::SetVisibility(vtkTypeBool visible)
524 {
525 this->Actor->SetVisibility(visible);
526 // Forward to superclass
527 this->Superclass::SetVisibility(visible);
528 }
529
530 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)531 void vtkSphereHandleRepresentation::PrintSelf(ostream& os, vtkIndent indent)
532 {
533 // Superclass typedef defined in vtkTypeMacro() found in vtkSetGet.h
534 this->Superclass::PrintSelf(os, indent);
535
536 os << indent << "Hot Spot Size: " << this->HotSpotSize << "\n";
537 if (this->Property)
538 {
539 os << indent << "Property: " << this->Property << "\n";
540 }
541 else
542 {
543 os << indent << "Property: (none)\n";
544 }
545 if (this->SelectedProperty)
546 {
547 os << indent << "Selected Property: " << this->SelectedProperty << "\n";
548 }
549 else
550 {
551 os << indent << "Selected Property: (none)\n";
552 }
553
554 os << indent << "Translation Mode: " << (this->TranslationMode ? "On\n" : "Off\n");
555 os << indent << "Sphere: " << this->Sphere << "\n";
556
557 this->Sphere->PrintSelf(os, indent.GetNextIndent());
558 }
559