1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkBoxRepresentation.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
16 #include "vtkBoxRepresentation.h"
17
18 #include "vtkActor.h"
19 #include "vtkAssemblyPath.h"
20 #include "vtkBox.h"
21 #include "vtkCallbackCommand.h"
22 #include "vtkCamera.h"
23 #include "vtkCellArray.h"
24 #include "vtkCellPicker.h"
25 #include "vtkDoubleArray.h"
26 #include "vtkEventData.h"
27 #include "vtkInteractorObserver.h"
28 #include "vtkMath.h"
29 #include "vtkObjectFactory.h"
30 #include "vtkPickingManager.h"
31 #include "vtkPlane.h"
32 #include "vtkPlanes.h"
33 #include "vtkPolyData.h"
34 #include "vtkPolyDataMapper.h"
35 #include "vtkProperty.h"
36 #include "vtkQuaternion.h"
37 #include "vtkRenderWindow.h"
38 #include "vtkRenderWindowInteractor.h"
39 #include "vtkRenderer.h"
40 #include "vtkSphereSource.h"
41 #include "vtkTransform.h"
42 #include "vtkVectorOperators.h"
43 #include "vtkWindow.h"
44
45 #include <cassert>
46
47 vtkStandardNewMacro(vtkBoxRepresentation);
48
49 //------------------------------------------------------------------------------
vtkBoxRepresentation()50 vtkBoxRepresentation::vtkBoxRepresentation()
51 {
52 // The initial state
53 this->InteractionState = vtkBoxRepresentation::Outside;
54 this->TwoPlaneMode = false;
55 this->SnappedOrientation[0] = false;
56 this->SnappedOrientation[1] = false;
57 this->SnappedOrientation[2] = false;
58 this->SnapToAxes = false;
59
60 // Handle size is in pixels for this widget
61 this->HandleSize = 5.0;
62
63 // Control orientation of normals
64 this->InsideOut = 0;
65 this->OutlineFaceWires = 0;
66 this->OutlineCursorWires = 1;
67
68 for (int i = 0; i < 6; ++i)
69 {
70 this->Planes[i] = vtkPlane::New();
71 }
72
73 // Set up the initial properties
74 this->CreateDefaultProperties();
75
76 // Construct the poly data representing the hex
77 this->HexPolyData = vtkPolyData::New();
78 this->HexMapper = vtkPolyDataMapper::New();
79 this->HexMapper->SetInputData(HexPolyData);
80 this->HexActor = vtkActor::New();
81 this->HexActor->SetMapper(this->HexMapper);
82 this->HexActor->SetProperty(this->OutlineProperty);
83
84 // Construct initial points
85 this->Points = vtkPoints::New(VTK_DOUBLE);
86 this->Points->SetNumberOfPoints(15); // 8 corners; 6 faces; 1 center
87 this->HexPolyData->SetPoints(this->Points);
88
89 // Construct connectivity for the faces. These are used to perform
90 // the picking.
91 int i;
92 vtkIdType pts[4];
93 vtkCellArray* cells = vtkCellArray::New();
94 cells->AllocateEstimate(6, 4);
95 pts[0] = 3;
96 pts[1] = 0;
97 pts[2] = 4;
98 pts[3] = 7;
99 cells->InsertNextCell(4, pts);
100 pts[0] = 1;
101 pts[1] = 2;
102 pts[2] = 6;
103 pts[3] = 5;
104 cells->InsertNextCell(4, pts);
105 pts[0] = 0;
106 pts[1] = 1;
107 pts[2] = 5;
108 pts[3] = 4;
109 cells->InsertNextCell(4, pts);
110 pts[0] = 2;
111 pts[1] = 3;
112 pts[2] = 7;
113 pts[3] = 6;
114 cells->InsertNextCell(4, pts);
115 pts[0] = 0;
116 pts[1] = 3;
117 pts[2] = 2;
118 pts[3] = 1;
119 cells->InsertNextCell(4, pts);
120 pts[0] = 4;
121 pts[1] = 5;
122 pts[2] = 6;
123 pts[3] = 7;
124 cells->InsertNextCell(4, pts);
125 this->HexPolyData->SetPolys(cells);
126 cells->Delete();
127 this->HexPolyData->BuildCells();
128
129 // The face of the hexahedra
130 cells = vtkCellArray::New();
131 cells->AllocateEstimate(1, 4);
132 cells->InsertNextCell(4, pts); // temporary, replaced later
133 this->HexFacePolyData = vtkPolyData::New();
134 this->HexFacePolyData->SetPoints(this->Points);
135 this->HexFacePolyData->SetPolys(cells);
136 this->HexFaceMapper = vtkPolyDataMapper::New();
137 this->HexFaceMapper->SetInputData(HexFacePolyData);
138 this->HexFace = vtkActor::New();
139 this->HexFace->SetMapper(this->HexFaceMapper);
140 this->HexFace->SetProperty(this->FaceProperty);
141 cells->Delete();
142
143 // Create the outline for the hex
144 this->OutlinePolyData = vtkPolyData::New();
145 this->OutlinePolyData->SetPoints(this->Points);
146 this->OutlineMapper = vtkPolyDataMapper::New();
147 this->OutlineMapper->SetInputData(this->OutlinePolyData);
148 this->HexOutline = vtkActor::New();
149 this->HexOutline->SetMapper(this->OutlineMapper);
150 this->HexOutline->SetProperty(this->OutlineProperty);
151 cells = vtkCellArray::New();
152 cells->AllocateEstimate(15, 2);
153 this->OutlinePolyData->SetLines(cells);
154 cells->Delete();
155
156 // Create the outline
157 this->GenerateOutline();
158
159 // Create the handles
160 this->Handle = new vtkActor*[7];
161 this->HandleMapper = new vtkPolyDataMapper*[7];
162 this->HandleGeometry = new vtkSphereSource*[7];
163 for (i = 0; i < 7; i++)
164 {
165 this->HandleGeometry[i] = vtkSphereSource::New();
166 this->HandleGeometry[i]->SetOutputPointsPrecision(vtkAlgorithm::DOUBLE_PRECISION);
167 this->HandleGeometry[i]->SetThetaResolution(16);
168 this->HandleGeometry[i]->SetPhiResolution(8);
169 this->HandleMapper[i] = vtkPolyDataMapper::New();
170 this->HandleMapper[i]->SetInputConnection(this->HandleGeometry[i]->GetOutputPort());
171 this->Handle[i] = vtkActor::New();
172 this->Handle[i]->SetMapper(this->HandleMapper[i]);
173 this->Handle[i]->SetProperty(this->HandleProperty);
174 }
175
176 // Define the point coordinates
177 double bounds[6];
178 bounds[0] = -0.5;
179 bounds[1] = 0.5;
180 bounds[2] = -0.5;
181 bounds[3] = 0.5;
182 bounds[4] = -0.5;
183 bounds[5] = 0.5;
184 // Points 8-14 are down by PositionHandles();
185 this->BoundingBox = vtkBox::New();
186 this->PlaceWidget(bounds);
187
188 // Manage the picking stuff
189 this->HandlePicker = vtkCellPicker::New();
190 this->HandlePicker->SetTolerance(0.001);
191 for (i = 0; i < 7; i++)
192 {
193 this->HandlePicker->AddPickList(this->Handle[i]);
194 }
195 this->HandlePicker->PickFromListOn();
196
197 this->HexPicker = vtkCellPicker::New();
198 this->HexPicker->SetTolerance(0.001);
199 this->HexPicker->AddPickList(HexActor);
200 this->HexPicker->PickFromListOn();
201
202 this->CurrentHandle = nullptr;
203
204 // Internal data members for performance
205 this->Transform = vtkTransform::New();
206 this->PlanePoints = vtkPoints::New(VTK_DOUBLE);
207 this->PlanePoints->SetNumberOfPoints(6);
208 this->PlaneNormals = vtkDoubleArray::New();
209 this->PlaneNormals->SetNumberOfComponents(3);
210 this->PlaneNormals->SetNumberOfTuples(6);
211 this->Matrix = vtkMatrix4x4::New();
212
213 this->TranslationAxis = Axis::NONE;
214 }
215
216 //------------------------------------------------------------------------------
~vtkBoxRepresentation()217 vtkBoxRepresentation::~vtkBoxRepresentation()
218 {
219 this->HexActor->Delete();
220 this->HexMapper->Delete();
221 this->HexPolyData->Delete();
222 this->Points->Delete();
223
224 this->HexFace->Delete();
225 this->HexFaceMapper->Delete();
226 this->HexFacePolyData->Delete();
227
228 this->HexOutline->Delete();
229 this->OutlineMapper->Delete();
230 this->OutlinePolyData->Delete();
231
232 for (int i = 0; i < 7; i++)
233 {
234 this->HandleGeometry[i]->Delete();
235 this->HandleMapper[i]->Delete();
236 this->Handle[i]->Delete();
237 }
238 delete[] this->Handle;
239 delete[] this->HandleMapper;
240 delete[] this->HandleGeometry;
241
242 this->HandlePicker->Delete();
243 this->HexPicker->Delete();
244
245 this->Transform->Delete();
246 this->BoundingBox->Delete();
247 this->PlanePoints->Delete();
248 this->PlaneNormals->Delete();
249 this->Matrix->Delete();
250
251 this->HandleProperty->Delete();
252 this->SelectedHandleProperty->Delete();
253 this->FaceProperty->Delete();
254 this->SelectedFaceProperty->Delete();
255 this->OutlineProperty->Delete();
256 this->SelectedOutlineProperty->Delete();
257
258 for (int i = 0; i < 6; ++i)
259 {
260 this->Planes[i]->Delete();
261 }
262 }
263
264 //------------------------------------------------------------------------------
GetPolyData(vtkPolyData * pd)265 void vtkBoxRepresentation::GetPolyData(vtkPolyData* pd)
266 {
267 pd->SetPoints(this->HexPolyData->GetPoints());
268 pd->SetPolys(this->HexPolyData->GetPolys());
269 }
270
271 //------------------------------------------------------------------------------
StartWidgetInteraction(double e[2])272 void vtkBoxRepresentation::StartWidgetInteraction(double e[2])
273 {
274 // Store the start position
275 this->StartEventPosition[0] = e[0];
276 this->StartEventPosition[1] = e[1];
277 this->StartEventPosition[2] = 0.0;
278
279 // Store the start position
280 this->LastEventPosition[0] = e[0];
281 this->LastEventPosition[1] = e[1];
282 this->LastEventPosition[2] = 0.0;
283
284 this->ComputeInteractionState(static_cast<int>(e[0]), static_cast<int>(e[1]), 0);
285 }
286
StartComplexInteraction(vtkRenderWindowInteractor *,vtkAbstractWidget *,unsigned long,void * calldata)287 void vtkBoxRepresentation::StartComplexInteraction(
288 vtkRenderWindowInteractor*, vtkAbstractWidget*, unsigned long, void* calldata)
289 {
290 vtkEventData* edata = static_cast<vtkEventData*>(calldata);
291 vtkEventDataDevice3D* edd = edata->GetAsEventDataDevice3D();
292 if (edd)
293 {
294 edd->GetWorldPosition(this->StartEventPosition);
295 this->LastEventPosition[0] = this->StartEventPosition[0];
296 this->LastEventPosition[1] = this->StartEventPosition[1];
297 this->LastEventPosition[2] = this->StartEventPosition[2];
298 edd->GetWorldOrientation(this->StartEventOrientation);
299 std::copy(
300 this->StartEventOrientation, this->StartEventOrientation + 4, this->LastEventOrientation);
301 for (int i = 0; i < 3; ++i)
302 {
303 if (this->SnappedOrientation[i])
304 {
305 std::copy(this->StartEventOrientation, this->StartEventOrientation + 4,
306 this->SnappedEventOrientations[i]);
307 }
308 }
309 }
310 }
311
SetTwoPlaneMode(bool val)312 void vtkBoxRepresentation::SetTwoPlaneMode(bool val)
313 {
314 if (this->TwoPlaneMode == val)
315 {
316 return;
317 }
318
319 this->TwoPlaneMode = val;
320 if (this->TwoPlaneMode)
321 {
322 for (int i = 2; i < 6; i++)
323 {
324 this->HandlePicker->DeletePickList(this->Handle[i]);
325 this->Handle[i]->VisibilityOff();
326 }
327 }
328 else
329 {
330 for (int i = 2; i < 6; i++)
331 {
332 this->HandlePicker->AddPickList(this->Handle[i]);
333 this->Handle[i]->SetVisibility(this->Handle[0]->GetVisibility());
334 }
335 }
336 this->GenerateOutline();
337 this->Modified();
338 }
339 //------------------------------------------------------------------------------
WidgetInteraction(double e[2])340 void vtkBoxRepresentation::WidgetInteraction(double e[2])
341 {
342 // Convert events to appropriate coordinate systems
343 vtkCamera* camera = this->Renderer->GetActiveCamera();
344 if (!camera)
345 {
346 return;
347 }
348 double focalPoint[4], pickPoint[4], prevPickPoint[4];
349 double z, vpn[3];
350 camera->GetViewPlaneNormal(vpn);
351
352 // Compute the two points defining the motion vector
353 double pos[3];
354 if (this->LastPicker == this->HexPicker)
355 {
356 this->HexPicker->GetPickPosition(pos);
357 }
358 else
359 {
360 this->HandlePicker->GetPickPosition(pos);
361 }
362 vtkInteractorObserver::ComputeWorldToDisplay(this->Renderer, pos[0], pos[1], pos[2], focalPoint);
363 z = focalPoint[2];
364 vtkInteractorObserver::ComputeDisplayToWorld(
365 this->Renderer, this->LastEventPosition[0], this->LastEventPosition[1], z, prevPickPoint);
366 vtkInteractorObserver::ComputeDisplayToWorld(this->Renderer, e[0], e[1], z, pickPoint);
367
368 // Process the motion
369 if (this->InteractionState == vtkBoxRepresentation::MoveF0)
370 {
371 this->MoveMinusXFace(prevPickPoint, pickPoint);
372 }
373
374 else if (this->InteractionState == vtkBoxRepresentation::MoveF1)
375 {
376 this->MovePlusXFace(prevPickPoint, pickPoint);
377 }
378
379 else if (this->InteractionState == vtkBoxRepresentation::MoveF2)
380 {
381 this->MoveMinusYFace(prevPickPoint, pickPoint);
382 }
383
384 else if (this->InteractionState == vtkBoxRepresentation::MoveF3)
385 {
386 this->MovePlusYFace(prevPickPoint, pickPoint);
387 }
388
389 else if (this->InteractionState == vtkBoxRepresentation::MoveF4)
390 {
391 this->MoveMinusZFace(prevPickPoint, pickPoint);
392 }
393
394 else if (this->InteractionState == vtkBoxRepresentation::MoveF5)
395 {
396 this->MovePlusZFace(prevPickPoint, pickPoint);
397 }
398
399 else if (this->InteractionState == vtkBoxRepresentation::Translating)
400 {
401 this->Translate(prevPickPoint, pickPoint);
402 }
403
404 else if (this->InteractionState == vtkBoxRepresentation::Scaling)
405 {
406 this->Scale(prevPickPoint, pickPoint, static_cast<int>(e[0]), static_cast<int>(e[1]));
407 }
408
409 else if (this->InteractionState == vtkBoxRepresentation::Rotating)
410 {
411 this->Rotate(static_cast<int>(e[0]), static_cast<int>(e[1]), prevPickPoint, pickPoint, vpn);
412 }
413
414 // Store the start position
415 this->LastEventPosition[0] = e[0];
416 this->LastEventPosition[1] = e[1];
417 this->LastEventPosition[2] = 0.0;
418 }
419
ComplexInteraction(vtkRenderWindowInteractor *,vtkAbstractWidget *,unsigned long,void * calldata)420 void vtkBoxRepresentation::ComplexInteraction(
421 vtkRenderWindowInteractor*, vtkAbstractWidget*, unsigned long, void* calldata)
422 {
423 vtkEventData* edata = static_cast<vtkEventData*>(calldata);
424 vtkEventDataDevice3D* edd = edata->GetAsEventDataDevice3D();
425 if (edd)
426 {
427 // all others
428 double eventPos[3];
429 edd->GetWorldPosition(eventPos);
430 double eventDir[4];
431 edd->GetWorldOrientation(eventDir);
432
433 double* prevPickPoint = this->LastEventPosition;
434 double* pickPoint = eventPos;
435
436 if (this->InteractionState == vtkBoxRepresentation::MoveF0)
437 {
438 this->MoveMinusXFace(prevPickPoint, pickPoint);
439 }
440
441 else if (this->InteractionState == vtkBoxRepresentation::MoveF1)
442 {
443 this->MovePlusXFace(prevPickPoint, pickPoint);
444 }
445
446 else if (this->InteractionState == vtkBoxRepresentation::MoveF2)
447 {
448 this->MoveMinusYFace(prevPickPoint, pickPoint);
449 }
450
451 else if (this->InteractionState == vtkBoxRepresentation::MoveF3)
452 {
453 this->MovePlusYFace(prevPickPoint, pickPoint);
454 }
455
456 else if (this->InteractionState == vtkBoxRepresentation::MoveF4)
457 {
458 this->MoveMinusZFace(prevPickPoint, pickPoint);
459 }
460
461 else if (this->InteractionState == vtkBoxRepresentation::MoveF5)
462 {
463 this->MovePlusZFace(prevPickPoint, pickPoint);
464 }
465
466 else if (this->InteractionState == vtkBoxRepresentation::Translating)
467 {
468 this->UpdatePose(this->LastEventPosition, this->LastEventOrientation, eventPos, eventDir);
469 }
470
471 // Book keeping
472 std::copy(eventPos, eventPos + 3, this->LastEventPosition);
473 std::copy(eventDir, eventDir + 4, this->LastEventOrientation);
474 this->Modified();
475 }
476 }
477
StepForward()478 void vtkBoxRepresentation::StepForward()
479 {
480 double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
481 this->Translate(pts, pts + 3);
482 }
483
StepBackward()484 void vtkBoxRepresentation::StepBackward()
485 {
486 double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
487 this->Translate(pts + 3, pts);
488 }
489
EndComplexInteraction(vtkRenderWindowInteractor *,vtkAbstractWidget *,unsigned long,void *)490 void vtkBoxRepresentation::EndComplexInteraction(
491 vtkRenderWindowInteractor*, vtkAbstractWidget*, unsigned long, void*)
492 {
493 }
494
495 //------------------------------------------------------------------------------
MoveFace(const double * p1,const double * p2,const double * dir,double * x1,double * x2,double * x3,double * x4,double * x5)496 void vtkBoxRepresentation::MoveFace(const double* p1, const double* p2, const double* dir,
497 double* x1, double* x2, double* x3, double* x4, double* x5)
498 {
499 int i;
500 double v[3], v2[3];
501
502 for (i = 0; i < 3; i++)
503 {
504 v[i] = p2[i] - p1[i];
505 v2[i] = dir[i];
506 }
507
508 vtkMath::Normalize(v2);
509 double f = vtkMath::Dot(v, v2);
510
511 for (i = 0; i < 3; i++)
512 {
513 v[i] = f * v2[i];
514
515 x1[i] += v[i];
516 x2[i] += v[i];
517 x3[i] += v[i];
518 x4[i] += v[i];
519 x5[i] += v[i];
520 }
521 this->PositionHandles();
522 }
523
524 //------------------------------------------------------------------------------
GetDirection(const double Nx[3],const double Ny[3],const double Nz[3],double dir[3])525 void vtkBoxRepresentation::GetDirection(
526 const double Nx[3], const double Ny[3], const double Nz[3], double dir[3])
527 {
528 double dotNy, dotNz;
529 double y[3];
530
531 if (vtkMath::Dot(Nx, Nx) != 0)
532 {
533 dir[0] = Nx[0];
534 dir[1] = Nx[1];
535 dir[2] = Nx[2];
536 }
537 else
538 {
539 dotNy = vtkMath::Dot(Ny, Ny);
540 dotNz = vtkMath::Dot(Nz, Nz);
541 if (dotNy != 0 && dotNz != 0)
542 {
543 vtkMath::Cross(Ny, Nz, dir);
544 }
545 else if (dotNy != 0)
546 {
547 // dir must have been initialized to the
548 // corresponding coordinate direction before calling
549 // this method
550 vtkMath::Cross(Ny, dir, y);
551 vtkMath::Cross(y, Ny, dir);
552 }
553 else if (dotNz != 0)
554 {
555 // dir must have been initialized to the
556 // corresponding coordinate direction before calling
557 // this method
558 vtkMath::Cross(Nz, dir, y);
559 vtkMath::Cross(y, Nz, dir);
560 }
561 }
562 }
563
564 //------------------------------------------------------------------------------
MovePlusXFace(const double * p1,const double * p2)565 void vtkBoxRepresentation::MovePlusXFace(const double* p1, const double* p2)
566 {
567 double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
568
569 double* h1 = pts + 3 * 9;
570
571 double* x1 = pts + 3 * 1;
572 double* x2 = pts + 3 * 2;
573 double* x3 = pts + 3 * 5;
574 double* x4 = pts + 3 * 6;
575
576 double dir[3] = { 1, 0, 0 };
577 this->ComputeNormals();
578 this->GetDirection(this->N[1], this->N[3], this->N[5], dir);
579 this->MoveFace(p1, p2, dir, x1, x2, x3, x4, h1);
580 }
581
582 //------------------------------------------------------------------------------
MoveMinusXFace(const double * p1,const double * p2)583 void vtkBoxRepresentation::MoveMinusXFace(const double* p1, const double* p2)
584 {
585 double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
586
587 double* h1 = pts + 3 * 8;
588
589 double* x1 = pts + 3 * 0;
590 double* x2 = pts + 3 * 3;
591 double* x3 = pts + 3 * 4;
592 double* x4 = pts + 3 * 7;
593
594 double dir[3] = { -1, 0, 0 };
595 this->ComputeNormals();
596 this->GetDirection(this->N[0], this->N[4], this->N[2], dir);
597
598 this->MoveFace(p1, p2, dir, x1, x2, x3, x4, h1);
599 }
600
601 //------------------------------------------------------------------------------
MovePlusYFace(const double * p1,const double * p2)602 void vtkBoxRepresentation::MovePlusYFace(const double* p1, const double* p2)
603 {
604 double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
605
606 double* h1 = pts + 3 * 11;
607
608 double* x1 = pts + 3 * 2;
609 double* x2 = pts + 3 * 3;
610 double* x3 = pts + 3 * 6;
611 double* x4 = pts + 3 * 7;
612
613 double dir[3] = { 0, 1, 0 };
614 this->ComputeNormals();
615 this->GetDirection(this->N[3], this->N[5], this->N[1], dir);
616
617 this->MoveFace(p1, p2, dir, x1, x2, x3, x4, h1);
618 }
619
620 //------------------------------------------------------------------------------
MoveMinusYFace(const double * p1,const double * p2)621 void vtkBoxRepresentation::MoveMinusYFace(const double* p1, const double* p2)
622 {
623 double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
624
625 double* h1 = pts + 3 * 10;
626
627 double* x1 = pts + 3 * 0;
628 double* x2 = pts + 3 * 1;
629 double* x3 = pts + 3 * 4;
630 double* x4 = pts + 3 * 5;
631
632 double dir[3] = { 0, -1, 0 };
633 this->ComputeNormals();
634 this->GetDirection(this->N[2], this->N[0], this->N[4], dir);
635
636 this->MoveFace(p1, p2, dir, x1, x2, x3, x4, h1);
637 }
638
639 //------------------------------------------------------------------------------
MovePlusZFace(const double * p1,const double * p2)640 void vtkBoxRepresentation::MovePlusZFace(const double* p1, const double* p2)
641 {
642 double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
643
644 double* h1 = pts + 3 * 13;
645
646 double* x1 = pts + 3 * 4;
647 double* x2 = pts + 3 * 5;
648 double* x3 = pts + 3 * 6;
649 double* x4 = pts + 3 * 7;
650
651 double dir[3] = { 0, 0, 1 };
652 this->ComputeNormals();
653 this->GetDirection(this->N[5], this->N[1], this->N[3], dir);
654
655 this->MoveFace(p1, p2, dir, x1, x2, x3, x4, h1);
656 }
657
658 //------------------------------------------------------------------------------
MoveMinusZFace(const double * p1,const double * p2)659 void vtkBoxRepresentation::MoveMinusZFace(const double* p1, const double* p2)
660 {
661 double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
662
663 double* h1 = pts + 3 * 12;
664
665 double* x1 = pts + 3 * 0;
666 double* x2 = pts + 3 * 1;
667 double* x3 = pts + 3 * 2;
668 double* x4 = pts + 3 * 3;
669
670 double dir[3] = { 0, 0, -1 };
671 this->ComputeNormals();
672 this->GetDirection(this->N[4], this->N[2], this->N[0], dir);
673
674 this->MoveFace(p1, p2, dir, x1, x2, x3, x4, h1);
675 }
676
677 //------------------------------------------------------------------------------
678 // Loop through all points and translate them
Translate(const double * p1,const double * p2)679 void vtkBoxRepresentation::Translate(const double* p1, const double* p2)
680 {
681 double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
682 double v[3] = { 0, 0, 0 };
683
684 if (!this->IsTranslationConstrained())
685 {
686 v[0] = p2[0] - p1[0];
687 v[1] = p2[1] - p1[1];
688 v[2] = p2[2] - p1[2];
689 }
690 else
691 {
692 assert(this->TranslationAxis > -1 && this->TranslationAxis < 3 &&
693 "this->TranslationAxis out of bounds");
694 v[this->TranslationAxis] = p2[this->TranslationAxis] - p1[this->TranslationAxis];
695 }
696
697 // Move the corners
698 for (int i = 0; i < 8; i++)
699 {
700 *pts++ += v[0];
701 *pts++ += v[1];
702 *pts++ += v[2];
703 }
704 this->PositionHandles();
705 }
706
707 //------------------------------------------------------------------------------
Scale(const double * vtkNotUsed (p1),const double * vtkNotUsed (p2),int vtkNotUsed (X),int Y)708 void vtkBoxRepresentation::Scale(
709 const double* vtkNotUsed(p1), const double* vtkNotUsed(p2), int vtkNotUsed(X), int Y)
710 {
711 double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
712 double* center = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(3 * 14);
713 double sf;
714
715 if (Y > this->LastEventPosition[1])
716 {
717 sf = 1.03;
718 }
719 else
720 {
721 sf = 0.97;
722 }
723
724 // Move the corners
725 for (int i = 0; i < 8; i++, pts += 3)
726 {
727 pts[0] = sf * (pts[0] - center[0]) + center[0];
728 pts[1] = sf * (pts[1] - center[1]) + center[1];
729 pts[2] = sf * (pts[2] - center[2]) + center[2];
730 }
731 this->PositionHandles();
732 }
733
734 //------------------------------------------------------------------------------
ComputeNormals()735 void vtkBoxRepresentation::ComputeNormals()
736 {
737 double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
738 double* p0 = pts;
739 double* px = pts + 3 * 1;
740 double* py = pts + 3 * 3;
741 double* pz = pts + 3 * 4;
742 int i;
743
744 for (i = 0; i < 3; i++)
745 {
746 this->N[0][i] = p0[i] - px[i];
747 this->N[2][i] = p0[i] - py[i];
748 this->N[4][i] = p0[i] - pz[i];
749 }
750 vtkMath::Normalize(this->N[0]);
751 vtkMath::Normalize(this->N[2]);
752 vtkMath::Normalize(this->N[4]);
753 for (i = 0; i < 3; i++)
754 {
755 this->N[1][i] = -this->N[0][i];
756 this->N[3][i] = -this->N[2][i];
757 this->N[5][i] = -this->N[4][i];
758 }
759 }
760
761 //------------------------------------------------------------------------------
GetPlanes(vtkPlanes * planes)762 void vtkBoxRepresentation::GetPlanes(vtkPlanes* planes)
763 {
764 if (!planes)
765 {
766 return;
767 }
768
769 this->ComputeNormals();
770
771 // Set the normals and coordinate values
772 double factor = (this->InsideOut ? -1.0 : 1.0);
773 for (int i = 0; i < 6; i++)
774 {
775 this->PlanePoints->SetPoint(i, this->Points->GetPoint(8 + i));
776 this->PlaneNormals->SetTuple3(
777 i, factor * this->N[i][0], factor * this->N[i][1], factor * this->N[i][2]);
778 }
779
780 planes->SetPoints(this->PlanePoints);
781 planes->SetNormals(this->PlaneNormals);
782 planes->Modified();
783 }
784
785 //------------------------------------------------------------------------------
Rotate(int X,int Y,const double * p1,const double * p2,const double * vpn)786 void vtkBoxRepresentation::Rotate(
787 int X, int Y, const double* p1, const double* p2, const double* vpn)
788 {
789 double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
790 double* center = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(3 * 14);
791 double v[3]; // vector of motion
792 double axis[3]; // axis of rotation
793 double theta; // rotation angle
794 int i;
795
796 v[0] = p2[0] - p1[0];
797 v[1] = p2[1] - p1[1];
798 v[2] = p2[2] - p1[2];
799
800 // Create axis of rotation and angle of rotation
801 vtkMath::Cross(vpn, v, axis);
802 if (vtkMath::Normalize(axis) == 0.0)
803 {
804 return;
805 }
806 const int* size = this->Renderer->GetSize();
807 double l2 = (X - this->LastEventPosition[0]) * (X - this->LastEventPosition[0]) +
808 (Y - this->LastEventPosition[1]) * (Y - this->LastEventPosition[1]);
809 theta = 360.0 * sqrt(l2 / (size[0] * size[0] + size[1] * size[1]));
810
811 // Manipulate the transform to reflect the rotation
812 this->Transform->Identity();
813 this->Transform->Translate(center[0], center[1], center[2]);
814 this->Transform->RotateWXYZ(theta, axis);
815 this->Transform->Translate(-center[0], -center[1], -center[2]);
816
817 // Set the corners
818 vtkPoints* newPts = vtkPoints::New(VTK_DOUBLE);
819 this->Transform->TransformPoints(this->Points, newPts);
820
821 for (i = 0; i < 8; i++, pts += 3)
822 {
823 this->Points->SetPoint(i, newPts->GetPoint(i));
824 }
825
826 newPts->Delete();
827 this->PositionHandles();
828 }
829
830 namespace
831 {
snapToAxis(vtkVector3d & in,vtkVector3d & out,double snapAngle)832 bool snapToAxis(vtkVector3d& in, vtkVector3d& out, double snapAngle)
833 {
834 int largest = 0;
835 if (fabs(in[1]) > fabs(in[0]))
836 {
837 largest = 1;
838 }
839 if (fabs(in[2]) > fabs(in[largest]))
840 {
841 largest = 2;
842 }
843 vtkVector3d axis(0, 0, 0);
844 axis[largest] = 1.0;
845 // 3 degrees of sticky
846 if (fabs(in.Dot(axis)) > cos(vtkMath::Pi() * snapAngle / 180.0))
847 {
848 if (in.Dot(axis) < 0)
849 {
850 axis[largest] = -1;
851 }
852 out = axis;
853 return true;
854 }
855 return false;
856 }
857 }
858
UpdatePose(const double * pos1,const double * orient1,const double * pos2,const double * orient2)859 void vtkBoxRepresentation::UpdatePose(
860 const double* pos1, const double* orient1, const double* pos2, const double* orient2)
861 {
862
863 bool newSnap[3];
864 vtkVector3d basis[3];
865 double basisSize[3];
866
867 vtkQuaternion<double> q2;
868 q2.SetRotationAngleAndAxis(
869 vtkMath::RadiansFromDegrees(orient2[0]), orient2[1], orient2[2], orient2[3]);
870
871 for (int i = 0; i < 3; ++i)
872 {
873 newSnap[i] = false;
874 // compute the net rotation
875 vtkQuaternion<double> q1;
876 if (this->SnappedOrientation[i])
877 {
878 q1.SetRotationAngleAndAxis(vtkMath::RadiansFromDegrees(this->SnappedEventOrientations[i][0]),
879 this->SnappedEventOrientations[i][1], this->SnappedEventOrientations[i][2],
880 this->SnappedEventOrientations[i][3]);
881 }
882 else
883 {
884 q1.SetRotationAngleAndAxis(
885 vtkMath::RadiansFromDegrees(orient1[0]), orient1[1], orient1[2], orient1[3]);
886 }
887 q1.Conjugate();
888 vtkQuaternion<double> q3 = q2 * q1;
889 double axis[4];
890 axis[0] = vtkMath::DegreesFromRadians(q3.GetRotationAngleAndAxis(axis + 1));
891
892 // Manipulate the transform to reflect the rotation
893 this->Transform->Identity();
894 this->Transform->RotateWXYZ(axis[0], axis[1], axis[2], axis[3]);
895
896 // Set the corners
897 vtkPoints* newPts = vtkPoints::New(VTK_DOUBLE);
898 this->Transform->TransformPoints(this->Points, newPts);
899
900 vtkVector3d p0(newPts->GetPoint(0));
901 vtkVector3d p1(newPts->GetPoint((i > 0 ? i + 2 : 1)));
902 basis[i] = p1 - p0;
903 basisSize[i] = 0.5 * basis[i].Normalize();
904 if (this->SnapToAxes)
905 {
906 // 14 degrees to snap in, 16 to snap out
907 // avoids noise on the boundary
908 newSnap[i] = snapToAxis(basis[i], basis[i], (this->SnappedOrientation[i] ? 16 : 14));
909 }
910 newPts->Delete();
911 }
912
913 // orthogonalize the resulting basis
914 for (int i = 0; i < 3; ++i)
915 {
916 if (newSnap[i] || this->SnappedOrientation[i])
917 {
918 // orthogonalize the other axes
919 vtkVector3d& b0 = basis[i];
920 vtkVector3d& b1 = basis[(i + 1) % 3];
921 vtkVector3d& b2 = basis[(i + 2) % 3];
922
923 double val = b1.Dot(b0);
924 b1 = b1 - b0 * val;
925 b1.Normalize();
926 b2 = b0.Cross(b1);
927 b2.Normalize();
928
929 if (!this->SnappedOrientation[i])
930 {
931 std::copy(orient2, orient2 + 4, this->SnappedEventOrientations[i]);
932 }
933 }
934 this->SnappedOrientation[i] = newSnap[i];
935 }
936
937 // get the translation
938 vtkVector3d trans;
939 for (int i = 0; i < 3; i++)
940 {
941 trans[i] = pos2[i] - pos1[i];
942 }
943
944 vtkQuaternion<double> q1;
945 q1.SetRotationAngleAndAxis(
946 vtkMath::RadiansFromDegrees(orient1[0]), orient1[1], orient1[2], orient1[3]);
947 q1.Conjugate();
948 vtkQuaternion<double> q3 = q2 * q1;
949 double axis[4];
950 axis[0] = vtkMath::DegreesFromRadians(q3.GetRotationAngleAndAxis(axis + 1));
951
952 // compute the new center based on the rotation
953 // point of rotation and translation
954 vtkVector3d center(static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(3 * 14));
955
956 this->Transform->Identity();
957 this->Transform->Translate(pos1[0], pos1[1], pos1[2]);
958 this->Transform->RotateWXYZ(axis[0], axis[1], axis[2], axis[3]);
959 this->Transform->Translate(-(pos1[0]), -(pos1[1]), -(pos1[2]));
960 this->Transform->Translate(center[0], center[1], center[2]);
961
962 this->Transform->GetPosition(center.GetData());
963 center = center + trans;
964
965 // rebuild points based on basis vectors
966 this->Points->SetPoint(0,
967 (center - basis[0] * basisSize[0] - basis[1] * basisSize[1] - basis[2] * basisSize[2])
968 .GetData());
969 this->Points->SetPoint(1,
970 (center + basis[0] * basisSize[0] - basis[1] * basisSize[1] - basis[2] * basisSize[2])
971 .GetData());
972 this->Points->SetPoint(2,
973 (center + basis[0] * basisSize[0] + basis[1] * basisSize[1] - basis[2] * basisSize[2])
974 .GetData());
975 this->Points->SetPoint(3,
976 (center - basis[0] * basisSize[0] + basis[1] * basisSize[1] - basis[2] * basisSize[2])
977 .GetData());
978 this->Points->SetPoint(4,
979 (center - basis[0] * basisSize[0] - basis[1] * basisSize[1] + basis[2] * basisSize[2])
980 .GetData());
981 this->Points->SetPoint(5,
982 (center + basis[0] * basisSize[0] - basis[1] * basisSize[1] + basis[2] * basisSize[2])
983 .GetData());
984 this->Points->SetPoint(6,
985 (center + basis[0] * basisSize[0] + basis[1] * basisSize[1] + basis[2] * basisSize[2])
986 .GetData());
987 this->Points->SetPoint(7,
988 (center - basis[0] * basisSize[0] + basis[1] * basisSize[1] + basis[2] * basisSize[2])
989 .GetData());
990
991 this->PositionHandles();
992 }
993
994 //------------------------------------------------------------------------------
CreateDefaultProperties()995 void vtkBoxRepresentation::CreateDefaultProperties()
996 {
997 // Handle properties
998 this->HandleProperty = vtkProperty::New();
999 this->HandleProperty->SetColor(1, 1, 1);
1000
1001 this->SelectedHandleProperty = vtkProperty::New();
1002 this->SelectedHandleProperty->SetColor(1, 0, 0);
1003
1004 // Face properties
1005 this->FaceProperty = vtkProperty::New();
1006 this->FaceProperty->SetColor(1, 1, 1);
1007 this->FaceProperty->SetOpacity(0.0);
1008
1009 this->SelectedFaceProperty = vtkProperty::New();
1010 this->SelectedFaceProperty->SetColor(1, 1, 0);
1011 this->SelectedFaceProperty->SetOpacity(0.25);
1012
1013 // Outline properties
1014 this->OutlineProperty = vtkProperty::New();
1015 this->OutlineProperty->SetRepresentationToWireframe();
1016 this->OutlineProperty->SetAmbient(1.0);
1017 this->OutlineProperty->SetAmbientColor(1.0, 1.0, 1.0);
1018 this->OutlineProperty->SetLineWidth(2.0);
1019
1020 this->SelectedOutlineProperty = vtkProperty::New();
1021 this->SelectedOutlineProperty->SetRepresentationToWireframe();
1022 this->SelectedOutlineProperty->SetAmbient(1.0);
1023 this->SelectedOutlineProperty->SetAmbientColor(0.0, 1.0, 0.0);
1024 this->SelectedOutlineProperty->SetLineWidth(2.0);
1025 }
1026
1027 //------------------------------------------------------------------------------
PlaceWidget(double bds[6])1028 void vtkBoxRepresentation::PlaceWidget(double bds[6])
1029 {
1030 int i;
1031 double bounds[6], center[3];
1032
1033 this->AdjustBounds(bds, bounds, center);
1034
1035 this->Points->SetPoint(0, bounds[0], bounds[2], bounds[4]);
1036 this->Points->SetPoint(1, bounds[1], bounds[2], bounds[4]);
1037 this->Points->SetPoint(2, bounds[1], bounds[3], bounds[4]);
1038 this->Points->SetPoint(3, bounds[0], bounds[3], bounds[4]);
1039 this->Points->SetPoint(4, bounds[0], bounds[2], bounds[5]);
1040 this->Points->SetPoint(5, bounds[1], bounds[2], bounds[5]);
1041 this->Points->SetPoint(6, bounds[1], bounds[3], bounds[5]);
1042 this->Points->SetPoint(7, bounds[0], bounds[3], bounds[5]);
1043
1044 for (i = 0; i < 6; i++)
1045 {
1046 this->InitialBounds[i] = bounds[i];
1047 }
1048 this->InitialLength = sqrt((bounds[1] - bounds[0]) * (bounds[1] - bounds[0]) +
1049 (bounds[3] - bounds[2]) * (bounds[3] - bounds[2]) +
1050 (bounds[5] - bounds[4]) * (bounds[5] - bounds[4]));
1051
1052 this->PositionHandles();
1053 this->ComputeNormals();
1054 this->ValidPick = 1; // since we have set up widget
1055 this->SizeHandles();
1056 }
1057
1058 //------------------------------------------------------------------------------
GetTransform(vtkTransform * t)1059 void vtkBoxRepresentation::GetTransform(vtkTransform* t)
1060 {
1061 double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
1062 double* p0 = pts;
1063 double* p1 = pts + 3 * 1;
1064 double* p3 = pts + 3 * 3;
1065 double* p4 = pts + 3 * 4;
1066 double* p14 = pts + 3 * 14;
1067 double center[3], translate[3], scale[3], scaleVec[3][3];
1068 double InitialCenter[3];
1069 int i;
1070
1071 // The transformation is relative to the initial bounds.
1072 // Initial bounds are set when PlaceWidget() is invoked.
1073 t->Identity();
1074
1075 // Translation
1076 for (i = 0; i < 3; i++)
1077 {
1078 InitialCenter[i] = (this->InitialBounds[2 * i + 1] + this->InitialBounds[2 * i]) / 2.0;
1079 center[i] = p14[i] - InitialCenter[i];
1080 }
1081 translate[0] = center[0] + InitialCenter[0];
1082 translate[1] = center[1] + InitialCenter[1];
1083 translate[2] = center[2] + InitialCenter[2];
1084 t->Translate(translate[0], translate[1], translate[2]);
1085
1086 // Orientation
1087 this->Matrix->Identity();
1088 this->PositionHandles();
1089 this->ComputeNormals();
1090 for (i = 0; i < 3; i++)
1091 {
1092 this->Matrix->SetElement(i, 0, this->N[1][i]);
1093 this->Matrix->SetElement(i, 1, this->N[3][i]);
1094 this->Matrix->SetElement(i, 2, this->N[5][i]);
1095 }
1096 t->Concatenate(this->Matrix);
1097
1098 // Scale
1099 for (i = 0; i < 3; i++)
1100 {
1101 scaleVec[0][i] = (p1[i] - p0[i]);
1102 scaleVec[1][i] = (p3[i] - p0[i]);
1103 scaleVec[2][i] = (p4[i] - p0[i]);
1104 }
1105
1106 scale[0] = vtkMath::Norm(scaleVec[0]);
1107 if (this->InitialBounds[1] != this->InitialBounds[0])
1108 {
1109 scale[0] = scale[0] / (this->InitialBounds[1] - this->InitialBounds[0]);
1110 }
1111 scale[1] = vtkMath::Norm(scaleVec[1]);
1112 if (this->InitialBounds[3] != this->InitialBounds[2])
1113 {
1114 scale[1] = scale[1] / (this->InitialBounds[3] - this->InitialBounds[2]);
1115 }
1116 scale[2] = vtkMath::Norm(scaleVec[2]);
1117 if (this->InitialBounds[5] != this->InitialBounds[4])
1118 {
1119 scale[2] = scale[2] / (this->InitialBounds[5] - this->InitialBounds[4]);
1120 }
1121 t->Scale(scale[0], scale[1], scale[2]);
1122
1123 // Add back in the contribution due to non-origin center
1124 t->Translate(-InitialCenter[0], -InitialCenter[1], -InitialCenter[2]);
1125 }
1126
1127 //------------------------------------------------------------------------------
SetTransform(vtkTransform * t)1128 void vtkBoxRepresentation::SetTransform(vtkTransform* t)
1129 {
1130 if (!t)
1131 {
1132 vtkErrorMacro(<< "vtkTransform t must be non-nullptr");
1133 return;
1134 }
1135
1136 double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
1137 double xIn[3];
1138 // make sure the transform is up-to-date before using it
1139 t->Update();
1140
1141 // Position the eight points of the box and then update the
1142 // position of the other handles.
1143 double* bounds = this->InitialBounds;
1144
1145 xIn[0] = bounds[0];
1146 xIn[1] = bounds[2];
1147 xIn[2] = bounds[4];
1148 t->InternalTransformPoint(xIn, pts);
1149
1150 xIn[0] = bounds[1];
1151 xIn[1] = bounds[2];
1152 xIn[2] = bounds[4];
1153 t->InternalTransformPoint(xIn, pts + 3);
1154
1155 xIn[0] = bounds[1];
1156 xIn[1] = bounds[3];
1157 xIn[2] = bounds[4];
1158 t->InternalTransformPoint(xIn, pts + 6);
1159
1160 xIn[0] = bounds[0];
1161 xIn[1] = bounds[3];
1162 xIn[2] = bounds[4];
1163 t->InternalTransformPoint(xIn, pts + 9);
1164
1165 xIn[0] = bounds[0];
1166 xIn[1] = bounds[2];
1167 xIn[2] = bounds[5];
1168 t->InternalTransformPoint(xIn, pts + 12);
1169
1170 xIn[0] = bounds[1];
1171 xIn[1] = bounds[2];
1172 xIn[2] = bounds[5];
1173 t->InternalTransformPoint(xIn, pts + 15);
1174
1175 xIn[0] = bounds[1];
1176 xIn[1] = bounds[3];
1177 xIn[2] = bounds[5];
1178 t->InternalTransformPoint(xIn, pts + 18);
1179
1180 xIn[0] = bounds[0];
1181 xIn[1] = bounds[3];
1182 xIn[2] = bounds[5];
1183 t->InternalTransformPoint(xIn, pts + 21);
1184
1185 this->PositionHandles();
1186 }
1187
1188 //------------------------------------------------------------------------------
SetOutlineFaceWires(int newValue)1189 void vtkBoxRepresentation::SetOutlineFaceWires(int newValue)
1190 {
1191 if (this->OutlineFaceWires != newValue)
1192 {
1193 this->OutlineFaceWires = newValue;
1194 this->Modified();
1195 // the outline is dependent on this value, so we have to regen
1196 this->GenerateOutline();
1197 }
1198 }
1199
1200 //------------------------------------------------------------------------------
SetOutlineCursorWires(int newValue)1201 void vtkBoxRepresentation::SetOutlineCursorWires(int newValue)
1202 {
1203 if (this->OutlineCursorWires != newValue)
1204 {
1205 this->OutlineCursorWires = newValue;
1206 this->Modified();
1207 // the outline is dependent on this value, so we have to regen
1208 this->GenerateOutline();
1209 }
1210 }
1211
1212 //------------------------------------------------------------------------------
GenerateOutline()1213 void vtkBoxRepresentation::GenerateOutline()
1214 {
1215 // Whatever the case may be, we have to reset the Lines of the
1216 // OutlinePolyData (i.e. nuke all current line data)
1217 vtkCellArray* cells = this->OutlinePolyData->GetLines();
1218 cells->Reset();
1219 cells->Modified();
1220
1221 // Now the outline lines
1222 if (!this->OutlineFaceWires && !this->OutlineCursorWires)
1223 {
1224 return;
1225 }
1226
1227 vtkIdType pts[2];
1228
1229 if (this->OutlineFaceWires)
1230 {
1231 pts[0] = 0;
1232 pts[1] = 7; // the -x face
1233 cells->InsertNextCell(2, pts);
1234 pts[0] = 3;
1235 pts[1] = 4;
1236 cells->InsertNextCell(2, pts);
1237 pts[0] = 1;
1238 pts[1] = 6; // the +x face
1239 cells->InsertNextCell(2, pts);
1240 pts[0] = 2;
1241 pts[1] = 5;
1242 cells->InsertNextCell(2, pts);
1243 if (!this->TwoPlaneMode)
1244 {
1245 pts[0] = 1;
1246 pts[1] = 4; // the -y face
1247 cells->InsertNextCell(2, pts);
1248 pts[0] = 0;
1249 pts[1] = 5;
1250 cells->InsertNextCell(2, pts);
1251 pts[0] = 3;
1252 pts[1] = 6; // the +y face
1253 cells->InsertNextCell(2, pts);
1254 pts[0] = 2;
1255 pts[1] = 7;
1256 cells->InsertNextCell(2, pts);
1257 pts[0] = 0;
1258 pts[1] = 2; // the -z face
1259 cells->InsertNextCell(2, pts);
1260 pts[0] = 1;
1261 pts[1] = 3;
1262 cells->InsertNextCell(2, pts);
1263 pts[0] = 4;
1264 pts[1] = 6; // the +Z face
1265 cells->InsertNextCell(2, pts);
1266 pts[0] = 5;
1267 pts[1] = 7;
1268 cells->InsertNextCell(2, pts);
1269 }
1270 }
1271 if (this->OutlineCursorWires)
1272 {
1273 pts[0] = 8;
1274 pts[1] = 9; // the x cursor line
1275 cells->InsertNextCell(2, pts);
1276 if (!this->TwoPlaneMode)
1277 {
1278 pts[0] = 10;
1279 pts[1] = 11; // the y cursor line
1280 cells->InsertNextCell(2, pts);
1281 pts[0] = 12;
1282 pts[1] = 13; // the z cursor line
1283 cells->InsertNextCell(2, pts);
1284 }
1285 }
1286 this->OutlinePolyData->Modified();
1287 if (this->OutlineProperty)
1288 {
1289 this->OutlineProperty->SetRepresentationToWireframe();
1290 this->SelectedOutlineProperty->SetRepresentationToWireframe();
1291 }
1292 }
1293
1294 //------------------------------------------------------------------------------
ComputeInteractionState(int X,int Y,int modify)1295 int vtkBoxRepresentation::ComputeInteractionState(int X, int Y, int modify)
1296 {
1297 // Okay, we can process this. Try to pick handles first;
1298 // if no handles picked, then pick the bounding box.
1299 if (!this->Renderer || !this->Renderer->IsInViewport(X, Y))
1300 {
1301 this->InteractionState = vtkBoxRepresentation::Outside;
1302 return this->InteractionState;
1303 }
1304
1305 // Try and pick a handle first
1306 this->LastPicker = nullptr;
1307 this->CurrentHandle = nullptr;
1308
1309 vtkAssemblyPath* path = this->GetAssemblyPath(X, Y, 0., this->HandlePicker);
1310
1311 if (path != nullptr)
1312 {
1313 this->ValidPick = 1;
1314 this->LastPicker = this->HandlePicker;
1315 this->CurrentHandle = reinterpret_cast<vtkActor*>(path->GetFirstNode()->GetViewProp());
1316 if (this->CurrentHandle == this->Handle[0])
1317 {
1318 this->InteractionState = vtkBoxRepresentation::MoveF0;
1319 }
1320 else if (this->CurrentHandle == this->Handle[1])
1321 {
1322 this->InteractionState = vtkBoxRepresentation::MoveF1;
1323 }
1324 else if (this->CurrentHandle == this->Handle[2])
1325 {
1326 this->InteractionState = vtkBoxRepresentation::MoveF2;
1327 }
1328 else if (this->CurrentHandle == this->Handle[3])
1329 {
1330 this->InteractionState = vtkBoxRepresentation::MoveF3;
1331 }
1332 else if (this->CurrentHandle == this->Handle[4])
1333 {
1334 this->InteractionState = vtkBoxRepresentation::MoveF4;
1335 }
1336 else if (this->CurrentHandle == this->Handle[5])
1337 {
1338 this->InteractionState = vtkBoxRepresentation::MoveF5;
1339 }
1340 else if (this->CurrentHandle == this->Handle[6])
1341 {
1342 this->InteractionState = vtkBoxRepresentation::Translating;
1343 }
1344 }
1345 else // see if the hex is picked
1346 {
1347 path = this->GetAssemblyPath(X, Y, 0., this->HexPicker);
1348
1349 if (path != nullptr)
1350 {
1351 this->LastPicker = this->HexPicker;
1352 this->ValidPick = 1;
1353 if (!modify)
1354 {
1355 this->InteractionState = vtkBoxRepresentation::Rotating;
1356 }
1357 else
1358 {
1359 this->CurrentHandle = this->Handle[6];
1360 this->InteractionState = vtkBoxRepresentation::Translating;
1361 }
1362 }
1363 else
1364 {
1365 this->InteractionState = vtkBoxRepresentation::Outside;
1366 }
1367 }
1368
1369 return this->InteractionState;
1370 }
1371
ComputeComplexInteractionState(vtkRenderWindowInteractor *,vtkAbstractWidget *,unsigned long,void * calldata,int)1372 int vtkBoxRepresentation::ComputeComplexInteractionState(
1373 vtkRenderWindowInteractor*, vtkAbstractWidget*, unsigned long, void* calldata, int)
1374 {
1375 this->InteractionState = vtkBoxRepresentation::Outside;
1376
1377 vtkEventData* edata = static_cast<vtkEventData*>(calldata);
1378 vtkEventDataDevice3D* edd = edata->GetAsEventDataDevice3D();
1379 if (edd)
1380 {
1381 double pos[3];
1382 edd->GetWorldPosition(pos);
1383
1384 // Try and pick a handle first
1385 this->LastPicker = nullptr;
1386 this->CurrentHandle = nullptr;
1387
1388 vtkAssemblyPath* path = this->GetAssemblyPath3DPoint(pos, this->HandlePicker);
1389
1390 if (path != nullptr)
1391 {
1392 this->ValidPick = 1;
1393 this->LastPicker = this->HandlePicker;
1394 this->CurrentHandle = reinterpret_cast<vtkActor*>(path->GetFirstNode()->GetViewProp());
1395 if (this->CurrentHandle == this->Handle[0])
1396 {
1397 this->InteractionState = vtkBoxRepresentation::MoveF0;
1398 }
1399 else if (this->CurrentHandle == this->Handle[1])
1400 {
1401 this->InteractionState = vtkBoxRepresentation::MoveF1;
1402 }
1403 else if (this->CurrentHandle == this->Handle[2])
1404 {
1405 this->InteractionState = vtkBoxRepresentation::MoveF2;
1406 }
1407 else if (this->CurrentHandle == this->Handle[3])
1408 {
1409 this->InteractionState = vtkBoxRepresentation::MoveF3;
1410 }
1411 else if (this->CurrentHandle == this->Handle[4])
1412 {
1413 this->InteractionState = vtkBoxRepresentation::MoveF4;
1414 }
1415 else if (this->CurrentHandle == this->Handle[5])
1416 {
1417 this->InteractionState = vtkBoxRepresentation::MoveF5;
1418 }
1419 else if (this->CurrentHandle == this->Handle[6])
1420 {
1421 this->InteractionState = vtkBoxRepresentation::Translating;
1422 }
1423 }
1424 else // see if the hex is picked
1425 {
1426 path = this->GetAssemblyPath3DPoint(pos, this->HexPicker);
1427
1428 if (path != nullptr)
1429 {
1430 this->LastPicker = this->HexPicker;
1431 this->ValidPick = 1;
1432 this->CurrentHandle = this->Handle[6];
1433 this->InteractionState = vtkBoxRepresentation::Translating;
1434 }
1435 }
1436 }
1437
1438 return this->InteractionState;
1439 }
1440
1441 //------------------------------------------------------------------------------
SetInteractionState(int state)1442 void vtkBoxRepresentation::SetInteractionState(int state)
1443 {
1444 // Clamp to allowable values
1445 state = (state < vtkBoxRepresentation::Outside
1446 ? vtkBoxRepresentation::Outside
1447 : (state > vtkBoxRepresentation::Scaling ? vtkBoxRepresentation::Scaling : state));
1448
1449 // Depending on state, highlight appropriate parts of representation
1450 int handle;
1451 this->InteractionState = state;
1452 switch (state)
1453 {
1454 case vtkBoxRepresentation::MoveF0:
1455 case vtkBoxRepresentation::MoveF1:
1456 case vtkBoxRepresentation::MoveF2:
1457 case vtkBoxRepresentation::MoveF3:
1458 case vtkBoxRepresentation::MoveF4:
1459 case vtkBoxRepresentation::MoveF5:
1460 this->HighlightOutline(0);
1461 handle = this->HighlightHandle(this->CurrentHandle);
1462 this->HighlightFace(handle);
1463 break;
1464 case vtkBoxRepresentation::Rotating:
1465 this->HighlightOutline(0);
1466 this->HighlightHandle(nullptr);
1467 this->HighlightFace(this->HexPicker->GetCellId());
1468 break;
1469 case vtkBoxRepresentation::Translating:
1470 case vtkBoxRepresentation::Scaling:
1471 this->HighlightOutline(1);
1472 this->HighlightHandle(this->Handle[6]);
1473 this->HighlightFace(-1);
1474 break;
1475 default:
1476 this->HighlightOutline(0);
1477 this->HighlightHandle(nullptr);
1478 this->HighlightFace(-1);
1479 }
1480 }
1481
1482 //------------------------------------------------------------------------------
GetBounds()1483 double* vtkBoxRepresentation::GetBounds()
1484 {
1485 this->BuildRepresentation();
1486 this->BoundingBox->SetBounds(this->HexActor->GetBounds());
1487 return this->BoundingBox->GetBounds();
1488 }
1489
1490 //------------------------------------------------------------------------------
BuildRepresentation()1491 void vtkBoxRepresentation::BuildRepresentation()
1492 {
1493 // Rebuild only if necessary
1494 if (this->GetMTime() > this->BuildTime ||
1495 (this->Renderer && this->Renderer->GetVTKWindow() &&
1496 (this->Renderer->GetVTKWindow()->GetMTime() > this->BuildTime ||
1497 this->Renderer->GetActiveCamera()->GetMTime() > this->BuildTime)))
1498 {
1499 this->SizeHandles();
1500 this->BuildTime.Modified();
1501 }
1502 }
1503
1504 //------------------------------------------------------------------------------
ReleaseGraphicsResources(vtkWindow * w)1505 void vtkBoxRepresentation::ReleaseGraphicsResources(vtkWindow* w)
1506 {
1507 this->HexActor->ReleaseGraphicsResources(w);
1508 this->HexOutline->ReleaseGraphicsResources(w);
1509 this->HexFace->ReleaseGraphicsResources(w);
1510 // render the handles
1511 for (int j = 0; j < 7; j++)
1512 {
1513 this->Handle[j]->ReleaseGraphicsResources(w);
1514 }
1515 }
1516
1517 //------------------------------------------------------------------------------
RenderOpaqueGeometry(vtkViewport * v)1518 int vtkBoxRepresentation::RenderOpaqueGeometry(vtkViewport* v)
1519 {
1520 int count = 0;
1521 this->BuildRepresentation();
1522
1523 this->HexActor->SetPropertyKeys(this->GetPropertyKeys());
1524 this->HexOutline->SetPropertyKeys(this->GetPropertyKeys());
1525 this->HexFace->SetPropertyKeys(this->GetPropertyKeys());
1526
1527 count += this->HexActor->RenderOpaqueGeometry(v);
1528 count += this->HexOutline->RenderOpaqueGeometry(v);
1529 count += this->HexFace->RenderOpaqueGeometry(v);
1530 for (int j = 0; j < 7; j++)
1531 {
1532 if (this->Handle[j]->GetVisibility())
1533 {
1534 this->Handle[j]->SetPropertyKeys(this->GetPropertyKeys());
1535 count += this->Handle[j]->RenderOpaqueGeometry(v);
1536 }
1537 }
1538
1539 return count;
1540 }
1541
1542 //------------------------------------------------------------------------------
RenderTranslucentPolygonalGeometry(vtkViewport * v)1543 int vtkBoxRepresentation::RenderTranslucentPolygonalGeometry(vtkViewport* v)
1544 {
1545 int count = 0;
1546 this->BuildRepresentation();
1547
1548 this->HexActor->SetPropertyKeys(this->GetPropertyKeys());
1549 this->HexOutline->SetPropertyKeys(this->GetPropertyKeys());
1550 this->HexFace->SetPropertyKeys(this->GetPropertyKeys());
1551
1552 count += this->HexActor->RenderTranslucentPolygonalGeometry(v);
1553 count += this->HexOutline->RenderTranslucentPolygonalGeometry(v);
1554 count += this->HexFace->RenderTranslucentPolygonalGeometry(v);
1555 // render the handles
1556 for (int j = 0; j < 7; j++)
1557 {
1558 if (this->Handle[j]->GetVisibility())
1559 {
1560 this->Handle[j]->SetPropertyKeys(this->GetPropertyKeys());
1561 count += this->Handle[j]->RenderTranslucentPolygonalGeometry(v);
1562 }
1563 }
1564 return count;
1565 }
1566
1567 //------------------------------------------------------------------------------
HasTranslucentPolygonalGeometry()1568 vtkTypeBool vtkBoxRepresentation::HasTranslucentPolygonalGeometry()
1569 {
1570 int result = 0;
1571 this->BuildRepresentation();
1572
1573 result |= this->HexActor->HasTranslucentPolygonalGeometry();
1574 result |= this->HexOutline->HasTranslucentPolygonalGeometry();
1575
1576 // If the face is not selected, we are not really rendering translucent faces,
1577 // hence don't bother taking it's opacity into consideration.
1578 // Look at BUG #7301.
1579 if (this->HexFace->GetProperty() == this->SelectedFaceProperty)
1580 {
1581 result |= this->HexFace->HasTranslucentPolygonalGeometry();
1582 }
1583
1584 // render the handles
1585 for (int j = 0; j < 7; j++)
1586 {
1587 result |= this->Handle[j]->HasTranslucentPolygonalGeometry();
1588 }
1589
1590 return result;
1591 }
1592
1593 #define VTK_AVERAGE(a, b, c) \
1594 c[0] = (a[0] + b[0]) / 2.0; \
1595 c[1] = (a[1] + b[1]) / 2.0; \
1596 c[2] = (a[2] + b[2]) / 2.0;
1597
1598 //------------------------------------------------------------------------------
PositionHandles()1599 void vtkBoxRepresentation::PositionHandles()
1600 {
1601 double* pts = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(0);
1602 double* p0 = pts;
1603 double* p1 = pts + 3 * 1;
1604 double* p2 = pts + 3 * 2;
1605 double* p3 = pts + 3 * 3;
1606 // double *p4 = pts + 3*4;
1607 double* p5 = pts + 3 * 5;
1608 double* p6 = pts + 3 * 6;
1609 double* p7 = pts + 3 * 7;
1610 double x[3];
1611
1612 VTK_AVERAGE(p0, p7, x);
1613 this->Points->SetPoint(8, x);
1614 VTK_AVERAGE(p1, p6, x);
1615 this->Points->SetPoint(9, x);
1616 VTK_AVERAGE(p0, p5, x);
1617 this->Points->SetPoint(10, x);
1618 VTK_AVERAGE(p2, p7, x);
1619 this->Points->SetPoint(11, x);
1620 VTK_AVERAGE(p1, p3, x);
1621 this->Points->SetPoint(12, x);
1622 VTK_AVERAGE(p5, p7, x);
1623 this->Points->SetPoint(13, x);
1624 VTK_AVERAGE(p0, p6, x);
1625 this->Points->SetPoint(14, x);
1626
1627 for (int i = 0; i < 7; ++i)
1628 {
1629 this->HandleGeometry[i]->SetCenter(this->Points->GetPoint(8 + i));
1630 }
1631
1632 for (int i = 0; i < 6; ++i)
1633 {
1634 this->Planes[i]->SetOrigin(this->Points->GetPoint(8 + i));
1635 int mix = 2 * (i % 2);
1636 vtkVector3d pp1(this->Points->GetPoint(8 + i));
1637 vtkVector3d pp2(this->Points->GetPoint(9 + i - mix));
1638 pp2 = pp2 - pp1;
1639 pp2.Normalize();
1640 this->Planes[i]->SetNormal(pp2.GetData());
1641 }
1642
1643 this->Points->GetData()->Modified();
1644 this->HexFacePolyData->Modified();
1645 this->HexPolyData->Modified();
1646 this->GenerateOutline();
1647 }
1648 #undef VTK_AVERAGE
1649
1650 //------------------------------------------------------------------------------
HandlesOn()1651 void vtkBoxRepresentation::HandlesOn()
1652 {
1653 if (this->TwoPlaneMode)
1654 {
1655 this->Handle[0]->VisibilityOn();
1656 this->Handle[1]->VisibilityOn();
1657 this->Handle[6]->VisibilityOn();
1658 }
1659 else
1660 {
1661 for (int i = 0; i < 7; i++)
1662 {
1663 this->Handle[i]->VisibilityOn();
1664 }
1665 }
1666 }
1667
1668 //------------------------------------------------------------------------------
HandlesOff()1669 void vtkBoxRepresentation::HandlesOff()
1670 {
1671 for (int i = 0; i < 7; i++)
1672 {
1673 this->Handle[i]->VisibilityOff();
1674 }
1675 }
1676
1677 //------------------------------------------------------------------------------
SizeHandles()1678 void vtkBoxRepresentation::SizeHandles()
1679 {
1680 double* center = static_cast<vtkDoubleArray*>(this->Points->GetData())->GetPointer(3 * 14);
1681 double radius = this->vtkWidgetRepresentation::SizeHandlesInPixels(1.5, center);
1682 for (int i = 0; i < 7; i++)
1683 {
1684 this->HandleGeometry[i]->SetRadius(radius);
1685 }
1686 }
1687
1688 //------------------------------------------------------------------------------
HighlightHandle(vtkProp * prop)1689 int vtkBoxRepresentation::HighlightHandle(vtkProp* prop)
1690 {
1691 // first unhighlight anything picked
1692 this->HighlightOutline(0);
1693 if (this->CurrentHandle)
1694 {
1695 this->CurrentHandle->SetProperty(this->HandleProperty);
1696 }
1697
1698 this->CurrentHandle = static_cast<vtkActor*>(prop);
1699
1700 if (this->CurrentHandle)
1701 {
1702 this->CurrentHandle->SetProperty(this->SelectedHandleProperty);
1703 for (int i = 0; i < 6; i++) // find attached face
1704 {
1705 if (this->CurrentHandle == this->Handle[i])
1706 {
1707 return i;
1708 }
1709 }
1710 }
1711
1712 if (this->CurrentHandle == this->Handle[6])
1713 {
1714 this->HighlightOutline(1);
1715 return 6;
1716 }
1717
1718 return -1;
1719 }
1720
1721 //------------------------------------------------------------------------------
HighlightFace(int cellId)1722 void vtkBoxRepresentation::HighlightFace(int cellId)
1723 {
1724 if (cellId >= 0)
1725 {
1726 vtkIdType npts;
1727 const vtkIdType* pts;
1728 vtkCellArray* cells = this->HexFacePolyData->GetPolys();
1729 this->HexPolyData->GetCellPoints(cellId, npts, pts);
1730 this->HexFacePolyData->Modified();
1731 cells->ReplaceCellAtId(0, npts, pts);
1732 cells->Modified();
1733 this->CurrentHexFace = cellId;
1734 this->HexFace->SetProperty(this->SelectedFaceProperty);
1735 if (!this->CurrentHandle)
1736 {
1737 this->CurrentHandle = this->HexFace;
1738 }
1739 }
1740 else
1741 {
1742 this->HexFace->SetProperty(this->FaceProperty);
1743 this->CurrentHexFace = -1;
1744 }
1745 }
1746
1747 //------------------------------------------------------------------------------
HighlightOutline(int highlight)1748 void vtkBoxRepresentation::HighlightOutline(int highlight)
1749 {
1750 if (highlight)
1751 {
1752 this->HexActor->SetProperty(this->SelectedOutlineProperty);
1753 this->HexOutline->SetProperty(this->SelectedOutlineProperty);
1754 }
1755 else
1756 {
1757 this->HexActor->SetProperty(this->OutlineProperty);
1758 this->HexOutline->SetProperty(this->OutlineProperty);
1759 }
1760 }
1761
1762 //------------------------------------------------------------------------------
RegisterPickers()1763 void vtkBoxRepresentation::RegisterPickers()
1764 {
1765 vtkPickingManager* pm = this->GetPickingManager();
1766 if (!pm)
1767 {
1768 return;
1769 }
1770 pm->AddPicker(this->HandlePicker, this);
1771 pm->AddPicker(this->HexPicker, this);
1772 }
1773
1774 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)1775 void vtkBoxRepresentation::PrintSelf(ostream& os, vtkIndent indent)
1776 {
1777 this->Superclass::PrintSelf(os, indent);
1778
1779 double* bounds = this->InitialBounds;
1780 os << indent << "Initial Bounds: "
1781 << "(" << bounds[0] << "," << bounds[1] << ") "
1782 << "(" << bounds[2] << "," << bounds[3] << ") "
1783 << "(" << bounds[4] << "," << bounds[5] << ")\n";
1784
1785 if (this->HandleProperty)
1786 {
1787 os << indent << "Handle Property: " << this->HandleProperty << "\n";
1788 }
1789 else
1790 {
1791 os << indent << "Handle Property: (none)\n";
1792 }
1793 if (this->SelectedHandleProperty)
1794 {
1795 os << indent << "Selected Handle Property: " << this->SelectedHandleProperty << "\n";
1796 }
1797 else
1798 {
1799 os << indent << "SelectedHandle Property: (none)\n";
1800 }
1801
1802 if (this->FaceProperty)
1803 {
1804 os << indent << "Face Property: " << this->FaceProperty << "\n";
1805 }
1806 else
1807 {
1808 os << indent << "Face Property: (none)\n";
1809 }
1810 if (this->SelectedFaceProperty)
1811 {
1812 os << indent << "Selected Face Property: " << this->SelectedFaceProperty << "\n";
1813 }
1814 else
1815 {
1816 os << indent << "Selected Face Property: (none)\n";
1817 }
1818
1819 if (this->OutlineProperty)
1820 {
1821 os << indent << "Outline Property: " << this->OutlineProperty << "\n";
1822 }
1823 else
1824 {
1825 os << indent << "Outline Property: (none)\n";
1826 }
1827 if (this->SelectedOutlineProperty)
1828 {
1829 os << indent << "Selected Outline Property: " << this->SelectedOutlineProperty << "\n";
1830 }
1831 else
1832 {
1833 os << indent << "Selected Outline Property: (none)\n";
1834 }
1835
1836 os << indent << "Snap To Axes: " << (this->SnapToAxes ? "On\n" : "Off\n");
1837 os << indent << "Two Plane Mode: " << (this->TwoPlaneMode ? "On\n" : "Off\n");
1838
1839 os << indent << "Outline Face Wires: " << (this->OutlineFaceWires ? "On\n" : "Off\n");
1840 os << indent << "Outline Cursor Wires: " << (this->OutlineCursorWires ? "On\n" : "Off\n");
1841 os << indent << "Inside Out: " << (this->InsideOut ? "On\n" : "Off\n");
1842 }
1843