1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkInteractorStyleRubberBand3D.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   Copyright 2008 Sandia Corporation.
17   Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
18   the U.S. Government retains certain rights in this software.
19 -------------------------------------------------------------------------*/
20 
21 #include "vtkInteractorStyleRubberBand3D.h"
22 
23 #include "vtkActor.h"
24 #include "vtkCamera.h"
25 #include "vtkCommand.h"
26 #include "vtkObjectFactory.h"
27 #include "vtkRenderer.h"
28 #include "vtkRenderWindow.h"
29 #include "vtkRenderWindowInteractor.h"
30 #include "vtkUnsignedCharArray.h"
31 
32 vtkStandardNewMacro(vtkInteractorStyleRubberBand3D);
33 
34 //--------------------------------------------------------------------------
vtkInteractorStyleRubberBand3D()35 vtkInteractorStyleRubberBand3D::vtkInteractorStyleRubberBand3D()
36 {
37   this->PixelArray = vtkUnsignedCharArray::New();
38   this->Interaction = NONE;
39   this->RenderOnMouseMove = false;
40   this->StartPosition[0] = 0;
41   this->StartPosition[1] = 0;
42   this->EndPosition[0] = 0;
43   this->EndPosition[1] = 0;
44 }
45 
46 //--------------------------------------------------------------------------
~vtkInteractorStyleRubberBand3D()47 vtkInteractorStyleRubberBand3D::~vtkInteractorStyleRubberBand3D()
48 {
49   this->PixelArray->Delete();
50 }
51 
52 //--------------------------------------------------------------------------
OnLeftButtonDown()53 void vtkInteractorStyleRubberBand3D::OnLeftButtonDown()
54 {
55   if(this->Interaction == NONE)
56   {
57     this->Interaction = SELECTING;
58     vtkRenderWindow *renWin = this->Interactor->GetRenderWindow();
59 
60     this->StartPosition[0] = this->Interactor->GetEventPosition()[0];
61     this->StartPosition[1] = this->Interactor->GetEventPosition()[1];
62     this->EndPosition[0] = this->StartPosition[0];
63     this->EndPosition[1] = this->StartPosition[1];
64 
65     this->PixelArray->Initialize();
66     this->PixelArray->SetNumberOfComponents(4);
67     int *size = renWin->GetSize();
68     this->PixelArray->SetNumberOfTuples(size[0]*size[1]);
69 
70     renWin->GetRGBACharPixelData(0, 0, size[0]-1, size[1]-1, 1, this->PixelArray);
71     this->FindPokedRenderer(this->StartPosition[0], this->StartPosition[1]);
72     this->InvokeEvent(vtkCommand::StartInteractionEvent);
73   }
74 }
75 
76 //--------------------------------------------------------------------------
OnLeftButtonUp()77 void vtkInteractorStyleRubberBand3D::OnLeftButtonUp()
78 {
79   if(this->Interaction == SELECTING)
80   {
81     // Clear the rubber band
82     int* size = this->Interactor->GetRenderWindow()->GetSize();
83     unsigned char* pixels = this->PixelArray->GetPointer(0);
84     this->Interactor->GetRenderWindow()->SetRGBACharPixelData(0, 0, size[0]-1, size[1]-1, pixels, 0);
85     this->Interactor->GetRenderWindow()->Frame();
86 
87     unsigned int rect[5];
88     rect[0] = this->StartPosition[0];
89     rect[1] = this->StartPosition[1];
90     rect[2] = this->EndPosition[0];
91     rect[3] = this->EndPosition[1];
92     if (this->Interactor->GetShiftKey())
93     {
94       rect[4] = SELECT_UNION;
95     }
96     else
97     {
98       rect[4] = SELECT_NORMAL;
99     }
100     this->InvokeEvent(vtkCommand::SelectionChangedEvent, reinterpret_cast<void*>(rect));
101     this->InvokeEvent(vtkCommand::EndInteractionEvent);
102     this->Interaction = NONE;
103   }
104 }
105 
106 //--------------------------------------------------------------------------
OnMiddleButtonDown()107 void vtkInteractorStyleRubberBand3D::OnMiddleButtonDown()
108 {
109   if(this->Interaction == NONE)
110   {
111     this->Interaction = PANNING;
112     this->FindPokedRenderer(
113       this->Interactor->GetEventPosition()[0],
114       this->Interactor->GetEventPosition()[1]);
115     this->InvokeEvent(vtkCommand::StartInteractionEvent);
116   }
117 }
118 
119 //--------------------------------------------------------------------------
OnMiddleButtonUp()120 void vtkInteractorStyleRubberBand3D::OnMiddleButtonUp()
121 {
122   if(this->Interaction == PANNING)
123   {
124     this->InvokeEvent(vtkCommand::EndInteractionEvent);
125     this->Interaction = NONE;
126   }
127 }
128 
129 //--------------------------------------------------------------------------
OnRightButtonDown()130 void vtkInteractorStyleRubberBand3D::OnRightButtonDown()
131 {
132   if(this->Interaction == NONE)
133   {
134     if (this->Interactor->GetShiftKey())
135     {
136       this->Interaction = ZOOMING;
137     }
138     else
139     {
140       this->Interaction = ROTATING;
141     }
142     this->FindPokedRenderer(
143       this->Interactor->GetEventPosition()[0],
144       this->Interactor->GetEventPosition()[1]);
145     this->InvokeEvent(vtkCommand::StartInteractionEvent);
146   }
147 }
148 
149 //--------------------------------------------------------------------------
OnRightButtonUp()150 void vtkInteractorStyleRubberBand3D::OnRightButtonUp()
151 {
152   if(this->Interaction == ZOOMING || this->Interaction == ROTATING)
153   {
154     this->InvokeEvent(vtkCommand::EndInteractionEvent);
155     this->Interaction = NONE;
156   }
157 }
158 
159 //--------------------------------------------------------------------------
OnMouseMove()160 void vtkInteractorStyleRubberBand3D::OnMouseMove()
161 {
162   if (this->Interaction == PANNING)
163   {
164     this->Superclass::Pan();
165   }
166   else if (this->Interaction == ZOOMING)
167   {
168     this->Superclass::Dolly();
169   }
170   else if (this->Interaction == ROTATING)
171   {
172     this->Superclass::Rotate();
173   }
174   else if (this->Interaction == SELECTING)
175   {
176     this->EndPosition[0] = this->Interactor->GetEventPosition()[0];
177     this->EndPosition[1] = this->Interactor->GetEventPosition()[1];
178     int *size = this->Interactor->GetRenderWindow()->GetSize();
179     if (this->EndPosition[0] > (size[0]-1))
180     {
181       this->EndPosition[0] = size[0]-1;
182     }
183     if (this->EndPosition[0] < 0)
184     {
185       this->EndPosition[0] = 0;
186     }
187     if (this->EndPosition[1] > (size[1]-1))
188     {
189       this->EndPosition[1] = size[1]-1;
190     }
191     if (this->EndPosition[1] < 0)
192     {
193       this->EndPosition[1] = 0;
194     }
195     this->InvokeEvent(vtkCommand::InteractionEvent);
196     this->RedrawRubberBand();
197   }
198   else if (this->RenderOnMouseMove)
199   {
200     this->GetInteractor()->Render();
201   }
202 }
203 
204 //--------------------------------------------------------------------------
OnMouseWheelForward()205 void vtkInteractorStyleRubberBand3D::OnMouseWheelForward()
206 {
207   this->FindPokedRenderer(
208     this->Interactor->GetEventPosition()[0],
209     this->Interactor->GetEventPosition()[1]);
210   vtkCamera* camera = this->CurrentRenderer->GetActiveCamera();
211   if (!camera)
212   {
213     return;
214   }
215   this->Interaction = ZOOMING;
216   this->Superclass::OnMouseWheelForward();
217   this->Interaction = NONE;
218 }
219 
220 //--------------------------------------------------------------------------
OnMouseWheelBackward()221 void vtkInteractorStyleRubberBand3D::OnMouseWheelBackward()
222 {
223   this->FindPokedRenderer(
224     this->Interactor->GetEventPosition()[0],
225     this->Interactor->GetEventPosition()[1]);
226   vtkCamera* camera = this->CurrentRenderer->GetActiveCamera();
227   if (!camera)
228   {
229     return;
230   }
231   this->Interaction = ZOOMING;
232   this->Superclass::OnMouseWheelBackward();
233   this->Interaction = NONE;
234 }
235 
236 //--------------------------------------------------------------------------
RedrawRubberBand()237 void vtkInteractorStyleRubberBand3D::RedrawRubberBand()
238 {
239   // Update the rubber band on the screen
240   int *size = this->Interactor->GetRenderWindow()->GetSize();
241 
242   vtkUnsignedCharArray *tmpPixelArray = vtkUnsignedCharArray::New();
243   tmpPixelArray->DeepCopy(this->PixelArray);
244   unsigned char *pixels = tmpPixelArray->GetPointer(0);
245 
246   int min[2], max[2];
247 
248   min[0] = this->StartPosition[0] <= this->EndPosition[0] ?
249     this->StartPosition[0] : this->EndPosition[0];
250   if (min[0] < 0) { min[0] = 0; }
251   if (min[0] >= size[0]) { min[0] = size[0] - 1; }
252 
253   min[1] = this->StartPosition[1] <= this->EndPosition[1] ?
254     this->StartPosition[1] : this->EndPosition[1];
255   if (min[1] < 0) { min[1] = 0; }
256   if (min[1] >= size[1]) { min[1] = size[1] - 1; }
257 
258   max[0] = this->EndPosition[0] > this->StartPosition[0] ?
259     this->EndPosition[0] : this->StartPosition[0];
260   if (max[0] < 0) { max[0] = 0; }
261   if (max[0] >= size[0]) { max[0] = size[0] - 1; }
262 
263   max[1] = this->EndPosition[1] > this->StartPosition[1] ?
264     this->EndPosition[1] : this->StartPosition[1];
265   if (max[1] < 0) { max[1] = 0; }
266   if (max[1] >= size[1]) { max[1] = size[1] - 1; }
267 
268   int i;
269   for (i = min[0]; i <= max[0]; i++)
270   {
271     pixels[4*(min[1]*size[0]+i)] = 255 ^ pixels[4*(min[1]*size[0]+i)];
272     pixels[4*(min[1]*size[0]+i)+1] = 255 ^ pixels[4*(min[1]*size[0]+i)+1];
273     pixels[4*(min[1]*size[0]+i)+2] = 255 ^ pixels[4*(min[1]*size[0]+i)+2];
274     pixels[4*(max[1]*size[0]+i)] = 255 ^ pixels[4*(max[1]*size[0]+i)];
275     pixels[4*(max[1]*size[0]+i)+1] = 255 ^ pixels[4*(max[1]*size[0]+i)+1];
276     pixels[4*(max[1]*size[0]+i)+2] = 255 ^ pixels[4*(max[1]*size[0]+i)+2];
277   }
278   for (i = min[1]+1; i < max[1]; i++)
279   {
280     pixels[4*(i*size[0]+min[0])] = 255 ^ pixels[4*(i*size[0]+min[0])];
281     pixels[4*(i*size[0]+min[0])+1] = 255 ^ pixels[4*(i*size[0]+min[0])+1];
282     pixels[4*(i*size[0]+min[0])+2] = 255 ^ pixels[4*(i*size[0]+min[0])+2];
283     pixels[4*(i*size[0]+max[0])] = 255 ^ pixels[4*(i*size[0]+max[0])];
284     pixels[4*(i*size[0]+max[0])+1] = 255 ^ pixels[4*(i*size[0]+max[0])+1];
285     pixels[4*(i*size[0]+max[0])+2] = 255 ^ pixels[4*(i*size[0]+max[0])+2];
286   }
287 
288   this->Interactor->GetRenderWindow()->SetRGBACharPixelData(0, 0, size[0]-1, size[1]-1, pixels, 0);
289   this->Interactor->GetRenderWindow()->Frame();
290 
291   tmpPixelArray->Delete();
292 }
293 
294 //--------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)295 void vtkInteractorStyleRubberBand3D::PrintSelf(ostream& os, vtkIndent indent)
296 {
297   this->Superclass::PrintSelf(os, indent);
298   os << indent << "Interaction: " << this->Interaction << endl;
299   os << indent << "RenderOnMouseMove: " << this->RenderOnMouseMove << endl;
300   os << indent << "StartPosition: " << this->StartPosition[0] << "," << this->StartPosition[1] << endl;
301   os << indent << "EndPosition: " << this->EndPosition[0] << "," << this->EndPosition[1] << endl;
302 }
303