1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkInteractorStyleRubberBand2D.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 "vtkInteractorStyleRubberBand2D.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(vtkInteractorStyleRubberBand2D);
33
34 //--------------------------------------------------------------------------
vtkInteractorStyleRubberBand2D()35 vtkInteractorStyleRubberBand2D::vtkInteractorStyleRubberBand2D()
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 //--------------------------------------------------------------------------
~vtkInteractorStyleRubberBand2D()47 vtkInteractorStyleRubberBand2D::~vtkInteractorStyleRubberBand2D()
48 {
49 this->PixelArray->Delete();
50 }
51
52 //--------------------------------------------------------------------------
OnLeftButtonDown()53 void vtkInteractorStyleRubberBand2D::OnLeftButtonDown()
54 {
55 if(this->Interaction == NONE)
56 {
57 if (this->Interactor->GetAltKey())
58 {
59 this->Interaction = PANNING;
60 }
61 else
62 {
63 this->Interaction = SELECTING;
64 vtkRenderWindow *renWin = this->Interactor->GetRenderWindow();
65
66 this->StartPosition[0] = this->Interactor->GetEventPosition()[0];
67 this->StartPosition[1] = this->Interactor->GetEventPosition()[1];
68 this->EndPosition[0] = this->StartPosition[0];
69 this->EndPosition[1] = this->StartPosition[1];
70
71 this->PixelArray->Initialize();
72 this->PixelArray->SetNumberOfComponents(4);
73 int *size = renWin->GetSize();
74 this->PixelArray->SetNumberOfTuples(size[0]*size[1]);
75
76 renWin->GetRGBACharPixelData(0, 0, size[0]-1, size[1]-1, 1, this->PixelArray);
77 }
78 this->FindPokedRenderer(this->StartPosition[0], this->StartPosition[1]);
79 this->InvokeEvent(vtkCommand::StartInteractionEvent);
80 }
81 }
82
83 //--------------------------------------------------------------------------
OnLeftButtonUp()84 void vtkInteractorStyleRubberBand2D::OnLeftButtonUp()
85 {
86 if(this->Interaction == SELECTING)
87 {
88 this->Interaction = NONE;
89
90 // Clear the rubber band
91 int* size = this->Interactor->GetRenderWindow()->GetSize();
92 unsigned char* pixels = this->PixelArray->GetPointer(0);
93 this->Interactor->GetRenderWindow()->SetRGBACharPixelData(0, 0, size[0]-1, size[1]-1, pixels, 0);
94 this->Interactor->GetRenderWindow()->Frame();
95
96 unsigned int rect[5];
97 rect[0] = this->StartPosition[0];
98 rect[1] = this->StartPosition[1];
99 rect[2] = this->EndPosition[0];
100 rect[3] = this->EndPosition[1];
101 if (this->Interactor->GetShiftKey())
102 {
103 rect[4] = SELECT_UNION;
104 }
105 else
106 {
107 rect[4] = SELECT_NORMAL;
108 }
109 this->InvokeEvent(vtkCommand::SelectionChangedEvent, reinterpret_cast<void*>(rect));
110 this->InvokeEvent(vtkCommand::EndInteractionEvent);
111 }
112 else if(this->Interaction == PANNING)
113 {
114 this->Interaction = NONE;
115 this->InvokeEvent(vtkCommand::EndInteractionEvent);
116 }
117 }
118
119 //--------------------------------------------------------------------------
OnMiddleButtonDown()120 void vtkInteractorStyleRubberBand2D::OnMiddleButtonDown()
121 {
122 if(this->Interaction == NONE)
123 {
124 this->Interaction = PANNING;
125 this->FindPokedRenderer(
126 this->Interactor->GetEventPosition()[0],
127 this->Interactor->GetEventPosition()[1]);
128 this->InvokeEvent(vtkCommand::StartInteractionEvent);
129 }
130 }
131
132 //--------------------------------------------------------------------------
OnMiddleButtonUp()133 void vtkInteractorStyleRubberBand2D::OnMiddleButtonUp()
134 {
135 if(this->Interaction == PANNING)
136 {
137 this->Interaction = NONE;
138 this->InvokeEvent(vtkCommand::EndInteractionEvent);
139 }
140 }
141
142 //--------------------------------------------------------------------------
OnRightButtonDown()143 void vtkInteractorStyleRubberBand2D::OnRightButtonDown()
144 {
145 if(this->Interaction == NONE)
146 {
147 this->Interaction = ZOOMING;
148 this->FindPokedRenderer(
149 this->Interactor->GetEventPosition()[0],
150 this->Interactor->GetEventPosition()[1]);
151 this->InvokeEvent(vtkCommand::StartInteractionEvent);
152 }
153 }
154
155 //--------------------------------------------------------------------------
OnRightButtonUp()156 void vtkInteractorStyleRubberBand2D::OnRightButtonUp()
157 {
158 if(this->Interaction == ZOOMING)
159 {
160 this->Interaction = NONE;
161 this->InvokeEvent(vtkCommand::EndInteractionEvent);
162 }
163 }
164
165 //--------------------------------------------------------------------------
OnMouseMove()166 void vtkInteractorStyleRubberBand2D::OnMouseMove()
167 {
168 if (this->Interaction == PANNING || this->Interaction == ZOOMING)
169 {
170 vtkRenderWindowInteractor* rwi = this->GetInteractor();
171 int lastPt[] = {0, 0};
172 rwi->GetLastEventPosition(lastPt);
173 int curPt[] = {0, 0};
174 rwi->GetEventPosition(curPt);
175
176 vtkCamera* camera = this->CurrentRenderer->GetActiveCamera();
177 double lastScale = 2.0 * camera->GetParallelScale() / this->CurrentRenderer->GetSize()[1];
178 double lastFocalPt[] = {0, 0, 0};
179 camera->GetFocalPoint(lastFocalPt);
180 double lastPos[] = {0, 0, 0};
181 camera->GetPosition(lastPos);
182
183 if (this->Interaction == PANNING)
184 {
185 double delta[] = {0, 0, 0};
186 delta[0] = -lastScale*(curPt[0] - lastPt[0]);
187 delta[1] = -lastScale*(curPt[1] - lastPt[1]);
188 delta[2] = 0;
189 camera->SetFocalPoint(lastFocalPt[0] + delta[0], lastFocalPt[1] + delta[1], lastFocalPt[2] + delta[2]);
190 camera->SetPosition(lastPos[0] + delta[0], lastPos[1] + delta[1], lastPos[2] + delta[2]);
191 this->InvokeEvent(vtkCommand::InteractionEvent);
192 rwi->Render();
193 }
194 else if (this->Interaction == ZOOMING)
195 {
196 double motion = 10.0;
197 double dyf = motion*(curPt[1] - lastPt[1])/this->CurrentRenderer->GetCenter()[1];
198 double factor = pow(1.1, dyf);
199 camera->SetParallelScale(camera->GetParallelScale() / factor);
200 this->InvokeEvent(vtkCommand::InteractionEvent);
201 rwi->Render();
202 }
203 }
204 else if (this->Interaction == SELECTING)
205 {
206 this->EndPosition[0] = this->Interactor->GetEventPosition()[0];
207 this->EndPosition[1] = this->Interactor->GetEventPosition()[1];
208 int *size = this->Interactor->GetRenderWindow()->GetSize();
209 if (this->EndPosition[0] > (size[0]-1))
210 {
211 this->EndPosition[0] = size[0]-1;
212 }
213 if (this->EndPosition[0] < 0)
214 {
215 this->EndPosition[0] = 0;
216 }
217 if (this->EndPosition[1] > (size[1]-1))
218 {
219 this->EndPosition[1] = size[1]-1;
220 }
221 if (this->EndPosition[1] < 0)
222 {
223 this->EndPosition[1] = 0;
224 }
225 this->InvokeEvent(vtkCommand::InteractionEvent);
226 this->RedrawRubberBand();
227 }
228 else if (this->RenderOnMouseMove)
229 {
230 this->GetInteractor()->Render();
231 }
232 }
233
234 //--------------------------------------------------------------------------
OnMouseWheelForward()235 void vtkInteractorStyleRubberBand2D::OnMouseWheelForward()
236 {
237 this->FindPokedRenderer(
238 this->Interactor->GetEventPosition()[0],
239 this->Interactor->GetEventPosition()[1]);
240 vtkCamera* camera = this->CurrentRenderer->GetActiveCamera();
241 if (!camera)
242 {
243 return;
244 }
245 this->Interaction = ZOOMING;
246 double motion = 10.0;
247 double dyf = motion * 0.2;
248 double factor = pow(1.1, dyf);
249 camera->SetParallelScale(camera->GetParallelScale() / factor);
250 this->InvokeEvent(vtkCommand::InteractionEvent);
251 this->GetInteractor()->Render();
252 this->Interaction = NONE;
253 }
254
255 //--------------------------------------------------------------------------
OnMouseWheelBackward()256 void vtkInteractorStyleRubberBand2D::OnMouseWheelBackward()
257 {
258 this->FindPokedRenderer(
259 this->Interactor->GetEventPosition()[0],
260 this->Interactor->GetEventPosition()[1]);
261 vtkCamera* camera = this->CurrentRenderer->GetActiveCamera();
262 if (!camera)
263 {
264 return;
265 }
266 this->Interaction = ZOOMING;
267 double motion = 10.0;
268 double dyf = motion * -0.2;
269 double factor = pow(1.1, dyf);
270 camera->SetParallelScale(camera->GetParallelScale() / factor);
271 this->InvokeEvent(vtkCommand::InteractionEvent);
272 this->GetInteractor()->Render();
273 this->Interaction = NONE;
274 }
275
276 //--------------------------------------------------------------------------
RedrawRubberBand()277 void vtkInteractorStyleRubberBand2D::RedrawRubberBand()
278 {
279 // Update the rubber band on the screen
280 int *size = this->Interactor->GetRenderWindow()->GetSize();
281
282 vtkUnsignedCharArray *tmpPixelArray = vtkUnsignedCharArray::New();
283 tmpPixelArray->DeepCopy(this->PixelArray);
284 unsigned char *pixels = tmpPixelArray->GetPointer(0);
285
286 int min[2], max[2];
287
288 min[0] = this->StartPosition[0] <= this->EndPosition[0] ?
289 this->StartPosition[0] : this->EndPosition[0];
290 if (min[0] < 0) { min[0] = 0; }
291 if (min[0] >= size[0]) { min[0] = size[0] - 1; }
292
293 min[1] = this->StartPosition[1] <= this->EndPosition[1] ?
294 this->StartPosition[1] : this->EndPosition[1];
295 if (min[1] < 0) { min[1] = 0; }
296 if (min[1] >= size[1]) { min[1] = size[1] - 1; }
297
298 max[0] = this->EndPosition[0] > this->StartPosition[0] ?
299 this->EndPosition[0] : this->StartPosition[0];
300 if (max[0] < 0) { max[0] = 0; }
301 if (max[0] >= size[0]) { max[0] = size[0] - 1; }
302
303 max[1] = this->EndPosition[1] > this->StartPosition[1] ?
304 this->EndPosition[1] : this->StartPosition[1];
305 if (max[1] < 0) { max[1] = 0; }
306 if (max[1] >= size[1]) { max[1] = size[1] - 1; }
307
308 int i;
309 for (i = min[0]; i <= max[0]; i++)
310 {
311 pixels[4*(min[1]*size[0]+i)] = 255 ^ pixels[4*(min[1]*size[0]+i)];
312 pixels[4*(min[1]*size[0]+i)+1] = 255 ^ pixels[4*(min[1]*size[0]+i)+1];
313 pixels[4*(min[1]*size[0]+i)+2] = 255 ^ pixels[4*(min[1]*size[0]+i)+2];
314 pixels[4*(max[1]*size[0]+i)] = 255 ^ pixels[4*(max[1]*size[0]+i)];
315 pixels[4*(max[1]*size[0]+i)+1] = 255 ^ pixels[4*(max[1]*size[0]+i)+1];
316 pixels[4*(max[1]*size[0]+i)+2] = 255 ^ pixels[4*(max[1]*size[0]+i)+2];
317 }
318 for (i = min[1]+1; i < max[1]; i++)
319 {
320 pixels[4*(i*size[0]+min[0])] = 255 ^ pixels[4*(i*size[0]+min[0])];
321 pixels[4*(i*size[0]+min[0])+1] = 255 ^ pixels[4*(i*size[0]+min[0])+1];
322 pixels[4*(i*size[0]+min[0])+2] = 255 ^ pixels[4*(i*size[0]+min[0])+2];
323 pixels[4*(i*size[0]+max[0])] = 255 ^ pixels[4*(i*size[0]+max[0])];
324 pixels[4*(i*size[0]+max[0])+1] = 255 ^ pixels[4*(i*size[0]+max[0])+1];
325 pixels[4*(i*size[0]+max[0])+2] = 255 ^ pixels[4*(i*size[0]+max[0])+2];
326 }
327
328 this->Interactor->GetRenderWindow()->SetRGBACharPixelData(0, 0, size[0]-1, size[1]-1, pixels, 0);
329 this->Interactor->GetRenderWindow()->Frame();
330
331 tmpPixelArray->Delete();
332 }
333
334 //--------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)335 void vtkInteractorStyleRubberBand2D::PrintSelf(ostream& os, vtkIndent indent)
336 {
337 this->Superclass::PrintSelf(os, indent);
338 os << indent << "Interaction: " << this->Interaction << endl;
339 os << indent << "RenderOnMouseMove: " << this->RenderOnMouseMove << endl;
340 os << indent << "StartPosition: " << this->StartPosition[0] << "," << this->StartPosition[1] << endl;
341 os << indent << "EndPosition: " << this->EndPosition[0] << "," << this->EndPosition[1] << endl;
342 }
343