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 "vtkRenderWindow.h"
28 #include "vtkRenderWindowInteractor.h"
29 #include "vtkRenderer.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 const 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 const int* size = this->Interactor->GetRenderWindow()->GetSize();
92 unsigned char* pixels = this->PixelArray->GetPointer(0);
93 this->Interactor->GetRenderWindow()->SetRGBACharPixelData(
94 0, 0, size[0] - 1, size[1] - 1, pixels, 0);
95 this->Interactor->GetRenderWindow()->Frame();
96
97 unsigned int rect[5];
98 rect[0] = this->StartPosition[0];
99 rect[1] = this->StartPosition[1];
100 rect[2] = this->EndPosition[0];
101 rect[3] = this->EndPosition[1];
102 if (this->Interactor->GetShiftKey())
103 {
104 rect[4] = SELECT_UNION;
105 }
106 else
107 {
108 rect[4] = SELECT_NORMAL;
109 }
110 this->InvokeEvent(vtkCommand::SelectionChangedEvent, reinterpret_cast<void*>(rect));
111 this->InvokeEvent(vtkCommand::EndInteractionEvent);
112 }
113 else if (this->Interaction == PANNING)
114 {
115 this->Interaction = NONE;
116 this->InvokeEvent(vtkCommand::EndInteractionEvent);
117 }
118 }
119
120 //------------------------------------------------------------------------------
OnMiddleButtonDown()121 void vtkInteractorStyleRubberBand2D::OnMiddleButtonDown()
122 {
123 if (this->Interaction == NONE)
124 {
125 this->Interaction = PANNING;
126 this->FindPokedRenderer(
127 this->Interactor->GetEventPosition()[0], 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], this->Interactor->GetEventPosition()[1]);
150 this->InvokeEvent(vtkCommand::StartInteractionEvent);
151 }
152 }
153
154 //------------------------------------------------------------------------------
OnRightButtonUp()155 void vtkInteractorStyleRubberBand2D::OnRightButtonUp()
156 {
157 if (this->Interaction == ZOOMING)
158 {
159 this->Interaction = NONE;
160 this->InvokeEvent(vtkCommand::EndInteractionEvent);
161 }
162 }
163
164 //------------------------------------------------------------------------------
OnMouseMove()165 void vtkInteractorStyleRubberBand2D::OnMouseMove()
166 {
167 if (this->Interaction == PANNING || this->Interaction == ZOOMING)
168 {
169 vtkRenderWindowInteractor* rwi = this->GetInteractor();
170 int lastPt[] = { 0, 0 };
171 rwi->GetLastEventPosition(lastPt);
172 int curPt[] = { 0, 0 };
173 rwi->GetEventPosition(curPt);
174
175 vtkCamera* camera = this->CurrentRenderer->GetActiveCamera();
176 double lastScale = 2.0 * camera->GetParallelScale() / this->CurrentRenderer->GetSize()[1];
177 double lastFocalPt[] = { 0, 0, 0 };
178 camera->GetFocalPoint(lastFocalPt);
179 double lastPos[] = { 0, 0, 0 };
180 camera->GetPosition(lastPos);
181
182 if (this->Interaction == PANNING)
183 {
184 double delta[] = { 0, 0, 0 };
185 delta[0] = -lastScale * (curPt[0] - lastPt[0]);
186 delta[1] = -lastScale * (curPt[1] - lastPt[1]);
187 delta[2] = 0;
188 camera->SetFocalPoint(
189 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 const 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], this->Interactor->GetEventPosition()[1]);
239 vtkCamera* camera = this->CurrentRenderer->GetActiveCamera();
240 if (!camera)
241 {
242 return;
243 }
244 this->Interaction = ZOOMING;
245 double motion = 10.0;
246 double dyf = motion * 0.2;
247 double factor = pow(1.1, dyf);
248 camera->SetParallelScale(camera->GetParallelScale() / factor);
249 this->InvokeEvent(vtkCommand::InteractionEvent);
250 this->GetInteractor()->Render();
251 this->Interaction = NONE;
252 }
253
254 //------------------------------------------------------------------------------
OnMouseWheelBackward()255 void vtkInteractorStyleRubberBand2D::OnMouseWheelBackward()
256 {
257 this->FindPokedRenderer(
258 this->Interactor->GetEventPosition()[0], this->Interactor->GetEventPosition()[1]);
259 vtkCamera* camera = this->CurrentRenderer->GetActiveCamera();
260 if (!camera)
261 {
262 return;
263 }
264 this->Interaction = ZOOMING;
265 double motion = 10.0;
266 double dyf = motion * -0.2;
267 double factor = pow(1.1, dyf);
268 camera->SetParallelScale(camera->GetParallelScale() / factor);
269 this->InvokeEvent(vtkCommand::InteractionEvent);
270 this->GetInteractor()->Render();
271 this->Interaction = NONE;
272 }
273
274 //------------------------------------------------------------------------------
RedrawRubberBand()275 void vtkInteractorStyleRubberBand2D::RedrawRubberBand()
276 {
277 // Update the rubber band on the screen
278 const int* size = this->Interactor->GetRenderWindow()->GetSize();
279
280 vtkUnsignedCharArray* tmpPixelArray = vtkUnsignedCharArray::New();
281 tmpPixelArray->DeepCopy(this->PixelArray);
282 unsigned char* pixels = tmpPixelArray->GetPointer(0);
283
284 int min[2], max[2];
285
286 min[0] =
287 this->StartPosition[0] <= this->EndPosition[0] ? this->StartPosition[0] : this->EndPosition[0];
288 if (min[0] < 0)
289 {
290 min[0] = 0;
291 }
292 if (min[0] >= size[0])
293 {
294 min[0] = size[0] - 1;
295 }
296
297 min[1] =
298 this->StartPosition[1] <= this->EndPosition[1] ? this->StartPosition[1] : this->EndPosition[1];
299 if (min[1] < 0)
300 {
301 min[1] = 0;
302 }
303 if (min[1] >= size[1])
304 {
305 min[1] = size[1] - 1;
306 }
307
308 max[0] =
309 this->EndPosition[0] > this->StartPosition[0] ? this->EndPosition[0] : this->StartPosition[0];
310 if (max[0] < 0)
311 {
312 max[0] = 0;
313 }
314 if (max[0] >= size[0])
315 {
316 max[0] = size[0] - 1;
317 }
318
319 max[1] =
320 this->EndPosition[1] > this->StartPosition[1] ? this->EndPosition[1] : this->StartPosition[1];
321 if (max[1] < 0)
322 {
323 max[1] = 0;
324 }
325 if (max[1] >= size[1])
326 {
327 max[1] = size[1] - 1;
328 }
329
330 int i;
331 for (i = min[0]; i <= max[0]; i++)
332 {
333 pixels[4 * (min[1] * size[0] + i)] = 255 ^ pixels[4 * (min[1] * size[0] + i)];
334 pixels[4 * (min[1] * size[0] + i) + 1] = 255 ^ pixels[4 * (min[1] * size[0] + i) + 1];
335 pixels[4 * (min[1] * size[0] + i) + 2] = 255 ^ pixels[4 * (min[1] * size[0] + i) + 2];
336 pixels[4 * (max[1] * size[0] + i)] = 255 ^ pixels[4 * (max[1] * size[0] + i)];
337 pixels[4 * (max[1] * size[0] + i) + 1] = 255 ^ pixels[4 * (max[1] * size[0] + i) + 1];
338 pixels[4 * (max[1] * size[0] + i) + 2] = 255 ^ pixels[4 * (max[1] * size[0] + i) + 2];
339 }
340 for (i = min[1] + 1; i < max[1]; i++)
341 {
342 pixels[4 * (i * size[0] + min[0])] = 255 ^ pixels[4 * (i * size[0] + min[0])];
343 pixels[4 * (i * size[0] + min[0]) + 1] = 255 ^ pixels[4 * (i * size[0] + min[0]) + 1];
344 pixels[4 * (i * size[0] + min[0]) + 2] = 255 ^ pixels[4 * (i * size[0] + min[0]) + 2];
345 pixels[4 * (i * size[0] + max[0])] = 255 ^ pixels[4 * (i * size[0] + max[0])];
346 pixels[4 * (i * size[0] + max[0]) + 1] = 255 ^ pixels[4 * (i * size[0] + max[0]) + 1];
347 pixels[4 * (i * size[0] + max[0]) + 2] = 255 ^ pixels[4 * (i * size[0] + max[0]) + 2];
348 }
349
350 this->Interactor->GetRenderWindow()->SetRGBACharPixelData(
351 0, 0, size[0] - 1, size[1] - 1, pixels, 0);
352 this->Interactor->GetRenderWindow()->Frame();
353
354 tmpPixelArray->Delete();
355 }
356
357 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)358 void vtkInteractorStyleRubberBand2D::PrintSelf(ostream& os, vtkIndent indent)
359 {
360 this->Superclass::PrintSelf(os, indent);
361 os << indent << "Interaction: " << this->Interaction << endl;
362 os << indent << "RenderOnMouseMove: " << this->RenderOnMouseMove << endl;
363 os << indent << "StartPosition: " << this->StartPosition[0] << "," << this->StartPosition[1]
364 << endl;
365 os << indent << "EndPosition: " << this->EndPosition[0] << "," << this->EndPosition[1] << endl;
366 }
367