LVRInteractorStylePolygonPick.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Visualization Toolkit
4  Module: LVRInteractorStylePolygonPick.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 =========================================================================*/
16 
17 #include <vtkAbstractPropPicker.h>
18 #include <vtkNew.h>
19 #include <vtkAreaPicker.h>
20 #include <vtkAssemblyPath.h>
21 #include <vtkObjectFactory.h>
22 #include <vtkRenderWindow.h>
23 #include <vtkRenderWindowInteractor.h>
24 #include <vtkRenderer.h>
25 #include <vtkUnsignedCharArray.h>
26 #include <vtkVectorOperators.h>
27 #include <vtkCommand.h>
28 #include <algorithm>
29 
31 
32 #define VTKISRBP_ORIENT 0
33 #define VTKISRBP_SELECT 1
34 
35 //-----------------------------------------------------------------------------
37 {
38 public:
39  std::vector<vtkVector2i> points;
40 
41  void PopPoint()
42  {
43  this->points.pop_back();
44  }
45 
46  void AddPoint(const vtkVector2i& point) { this->points.push_back(point); }
47 
48  void AddPoint(int x, int y) { this->AddPoint(vtkVector2i(x, y)); }
49 
50  void RemoveLastPoint(){this->points.pop_back();}
51  vtkVector2i GetPoint(vtkIdType index) const { return this->points[index]; }
52 
53  vtkIdType GetNumberOfPoints() const { return static_cast<vtkIdType>(this->points.size()); }
54 
55  void Clear() { this->points.clear(); }
56 
57  void DrawPixels(
58  const vtkVector2i& StartPos, const vtkVector2i& EndPos, unsigned char* pixels, int* size)
59  {
60  int x1 = StartPos.GetX(), x2 = EndPos.GetX();
61  int y1 = StartPos.GetY(), y2 = EndPos.GetY();
62 
63  double x = x2 - x1;
64  double y = y2 - y1;
65  double length = sqrt(x * x + y * y);
66  if (length == 0)
67  {
68  return;
69  }
70  double addx = x / length;
71  double addy = y / length;
72 
73  x = x1;
74  y = y1;
75  int row, col;
76  for (double i = 0; i < length; i += 1)
77  {
78  col = (int)x;
79  row = (int)y;
80  pixels[3 * (row * size[0] + col)] = 255 ^ pixels[3 * (row * size[0] + col)];
81  pixels[3 * (row * size[0] + col) + 1] = 255 ^ pixels[3 * (row * size[0] + col) + 1];
82  pixels[3 * (row * size[0] + col) + 2] = 255 ^ pixels[3 * (row * size[0] + col) + 2];
83  x += addx;
84  y += addy;
85  }
86  }
87 };
88 
89 //--------------------------------------------------------------------------
91 {
92  this->Internal = new vtkInternal();
94  this->StartPosition[0] = this->StartPosition[1] = 0;
95  this->EndPosition[0] = this->EndPosition[1] = 0;
96  this->Moving = 0;
97  this->DrawPolygonPixels = true;
98  this->PixelArray = vtkUnsignedCharArray::New();
99 }
100 
101 //--------------------------------------------------------------------------
103 {
104  this->PixelArray->Delete();
105  delete this->Internal;
106 }
107 
108 //--------------------------------------------------------------------------
110 {
112 }
113 
114 //----------------------------------------------------------------------------
116 {
117  return this->Internal->points;
118 }
119 
120 //--------------------------------------------------------------------------
122 {
123  switch (this->Interactor->GetKeyCode())
124  {
125  case 'l':
126  case 'L':
127  // r toggles the rubber band selection mode for mouse button 1
128  if (this->CurrentMode == VTKISRBP_ORIENT)
129  {
131  }
132  else
133  {
135  }
136  break;
137  case 'p':
138  case 'P':
139  {
140  vtkRenderWindowInteractor* rwi = this->Interactor;
141  int* eventPos = rwi->GetEventPosition();
142  this->FindPokedRenderer(eventPos[0], eventPos[1]);
143  this->StartPosition[0] = eventPos[0];
144  this->StartPosition[1] = eventPos[1];
145  this->EndPosition[0] = eventPos[0];
146  this->EndPosition[1] = eventPos[1];
147  this->Pick();
148  break;
149  }
150  default:
151  this->Superclass::OnChar();
152  }
153 }
154 
155 //--------------------------------------------------------------------------
157 {
158 
159  if (this->CurrentMode != VTKISRBP_SELECT)
160  {
161  // if not in rubber band mode, let the parent class handle it
162  this->Superclass::OnLeftButtonDown();
163  return;
164  }
165 
166  if (!this->Interactor)
167  {
168  return;
169  }
170 
171  // otherwise record the rubber band starting coordinate
172 
173  this->Moving = 1;
174  if (!lassoToolSelected)
175  {
176  if (!firstPoint)
177  {
178  return;
179  }
180  firstPoint = false;
181  }
182 
183 
184  vtkRenderWindow* renWin = this->Interactor->GetRenderWindow();
185 
186  this->StartPosition[0] = this->Interactor->GetEventPosition()[0];
187  this->StartPosition[1] = this->Interactor->GetEventPosition()[1];
188  this->EndPosition[0] = this->StartPosition[0];
189  this->EndPosition[1] = this->StartPosition[1];
190 
191  this->PixelArray->Initialize();
192  this->PixelArray->SetNumberOfComponents(3);
193  int* size = renWin->GetSize();
194  this->PixelArray->SetNumberOfTuples(size[0] * size[1]);
195 
196  renWin->GetPixelData(0, 0, size[0] - 1, size[1] - 1, 1, this->PixelArray);
197  this->Internal->Clear();
198  this->Internal->AddPoint(this->StartPosition[0], this->StartPosition[1]);
199  this->InvokeEvent(vtkCommand::StartInteractionEvent);
200 
201  //renWin->GetRGBACharPixelData(0, 0, size[0] - 1, size[1] - 1, 1, this->PixelArray);
202  this->FindPokedRenderer(this->StartPosition[0], this->StartPosition[1]);
203 }
204 
205 //--------------------------------------------------------------------------
207 {
208  if (this->CurrentMode != VTKISRBP_SELECT)
209  {
210  // if not in rubber band mode, let the parent class handle it
211  this->Superclass::OnMouseMove();
212  return;
213  }
214 
215  if (!this->Interactor || !this->Moving)
216  {
217  return;
218  }
219 
220  this->EndPosition[0] = this->Interactor->GetEventPosition()[0];
221  this->EndPosition[1] = this->Interactor->GetEventPosition()[1];
222  int* size = this->Interactor->GetRenderWindow()->GetSize();
223  if (this->EndPosition[0] > (size[0] - 1))
224  {
225  this->EndPosition[0] = size[0] - 1;
226  }
227  if (this->EndPosition[0] < 0)
228  {
229  this->EndPosition[0] = 0;
230  }
231  if (this->EndPosition[1] > (size[1] - 1))
232  {
233  this->EndPosition[1] = size[1] - 1;
234  }
235  if (this->EndPosition[1] < 0)
236  {
237  this->EndPosition[1] = 0;
238  }
239 
240  vtkVector2i lastPoint = this->Internal->GetPoint(this->Internal->GetNumberOfPoints() - 1);
241  vtkVector2i newPoint(this->EndPosition[0], this->EndPosition[1]);
242  if ((lastPoint - newPoint).SquaredNorm() > 100)
243  {
244  if (!lassoToolSelected && this->Internal->GetNumberOfPoints() > 2)
245  {
246  this->Internal->RemoveLastPoint();
247  }
248  this->Internal->AddPoint(newPoint);
249  if (this->DrawPolygonPixels)
250  {
251  this->DrawPolygon();
252  }
253  }
254 }
255 
256 //--------------------------------------------------------------------------
258 {
259  if (this->CurrentMode != VTKISRBP_SELECT)
260  {
261  // if not in rubber band mode, let the parent class handle it
262  this->Superclass::OnLeftButtonUp();
263  return;
264  }
265 
266  if (!this->Interactor || !this->Moving)
267  {
268  return;
269  }
270 
271  if (!lassoToolSelected)
272  {
273 
274  vtkVector2i newPoint(this->Interactor->GetEventPosition()[0], this->Interactor->GetEventPosition()[1]);
275  this->Internal->AddPoint(newPoint);
276  if (this->DrawPolygonPixels)
277  {
278  this->DrawPolygon();
279  }
280  this->Moving = 0;
281  return;
282  }
283 
284  // otherwise record the rubber band end coordinate and then fire off a pick
285  if ((this->StartPosition[0] != this->EndPosition[0]) ||
286  (this->StartPosition[1] != this->EndPosition[1]))
287  {
288  this->Pick();
289  }
290  this->Moving = 0;
291  // this->CurrentMode = VTKISRBP_ORIENT;
292 }
293 
294 
295 
296 inline bool compareX(vtkVector2i i, vtkVector2i j) {return (i[0] < j[0]);};
297 inline bool compareY(vtkVector2i i, vtkVector2i j) {return (i[1] < j[1]);};
298 //--------------------------------------------------------------------------
300 {
301  // calculate binding box
302  std::vector<vtkVector2i> polygonPoints = this->GetPolygonPoints();
303  double rbcenter[3];
304  int* size = this->Interactor->GetRenderWindow()->GetSize();
305  int min[2], max[2];
306 
307  min[0] = std::min_element(polygonPoints.begin(), polygonPoints.end(), compareX)->GetX();
308  min[1] = std::min_element(polygonPoints.begin(), polygonPoints.end(), compareY)->GetY();
309 
310  max[0] = std::max_element(polygonPoints.begin(), polygonPoints.end(), compareX)->GetX();
311  max[1] = std::max_element(polygonPoints.begin(), polygonPoints.end(), compareY)->GetY();
312  //std::cout << "Minimum : " << min[0] << " " << min[1] << std::endl;
313  //std::cout << "Maximum : " << max[0] << " " << max[1] << std::endl;
314  //std::cout << "Count: " << polygonPoints.size() << std::endl;
315 
316  rbcenter[0] = (min[0] + max[0]) / 2.0;
317  rbcenter[1] = (min[1] + max[1]) / 2.0;
318  rbcenter[2] = 0;
319 
320  if (this->State == VTKIS_NONE)
321  {
322  // tell the RenderWindowInteractor's picker to make it happen
323  vtkRenderWindowInteractor* rwi = this->Interactor;
324 
325  vtkAssemblyPath* path = nullptr;
326  rwi->StartPickCallback();
327  vtkAbstractPropPicker* picker = vtkAbstractPropPicker::SafeDownCast(rwi->GetPicker());
328  if (picker != nullptr)
329  {
330  vtkAreaPicker* areaPicker = vtkAreaPicker::SafeDownCast(picker);
331  if (areaPicker != nullptr)
332  {
333  areaPicker->AreaPick(min[0], min[1], max[0], max[1], this->CurrentRenderer);
334  }
335  else
336  {
337  picker->Pick(rbcenter[0], rbcenter[1], 0.0, this->CurrentRenderer);
338  }
339  path = picker->GetPath();
340  }
341  if (path == nullptr)
342  {
343  this->HighlightProp(nullptr);
344  this->PropPicked = 0;
345  }
346  else
347  {
348  // highlight the one prop that the picker saved in the path
349  // this->HighlightProp(path->GetFirstNode()->GetViewProp());
350  this->PropPicked = 1;
351  }
352  rwi->EndPickCallback();
353  }
354 
355  this->Interactor->Render();
356 }
357 
358 //--------------------------------------------------------------------------
360 {
361  vtkNew<vtkUnsignedCharArray> tmpPixelArray;
362  tmpPixelArray->DeepCopy(this->PixelArray);
363  unsigned char* pixels = tmpPixelArray->GetPointer(0);
364  int* size = this->Interactor->GetRenderWindow()->GetSize();
365 
366  // draw each line segment
367  for (vtkIdType i = 0; i < this->Internal->GetNumberOfPoints() - 1; i++)
368  {
369  const vtkVector2i& a = this->Internal->GetPoint(i);
370  const vtkVector2i& b = this->Internal->GetPoint(i + 1);
371 
372  this->Internal->DrawPixels(a, b, pixels, size);
373  }
374 
375  // draw a line from the end to the start
376  if (this->Internal->GetNumberOfPoints() >= 3)
377  {
378  const vtkVector2i& start = this->Internal->GetPoint(0);
379  const vtkVector2i& end = this->Internal->GetPoint(this->Internal->GetNumberOfPoints() - 1);
380 
381  this->Internal->DrawPixels(start, end, pixels, size);
382  }
383 
384  this->Interactor->GetRenderWindow()->SetPixelData(0, 0, size[0] - 1, size[1] - 1, pixels, 0);
385  this->Interactor->GetRenderWindow()->Frame();
386 }
387 
388 //--------------------------------------------------------------------------
389 void LVRInteractorStylePolygonPick::PrintSelf(ostream& os, vtkIndent indent)
390 {
391  this->Superclass::PrintSelf(os, indent);
392 }
393 
395 {
396  std::cout << "lasso" << std::endl;
397  lassoToolSelected = false;
398 }
399 
401 {
402  std::cout << "no lasso" << std::endl;
403 
404  lassoToolSelected = true;
405 }
407 {
408  if (!lassoToolSelected)// && "Return" == this->Interactor->GetKeySym())
409  {
410  if (this->CurrentMode != VTKISRBP_SELECT)
411  {
412  // if not in rubber band mode, let the parent class handle it
413  // this->Superclass::OnKeyDown();
414  // return;
415  }
416 
417  // otherwise record the rubber band end coordinate and then fire off a pick
418  if ((this->StartPosition[0] != this->EndPosition[0]) ||
419  (this->StartPosition[1] != this->EndPosition[1]))
420  {
421  std::cout << "did this " << std::endl;
422  this->Pick();
423  firstPoint = true;
424  }
425  this->Moving = 0;
426  }
427 }
bool compareY(vtkVector2i i, vtkVector2i j)
void PrintSelf(ostream &os, vtkIndent indent) override
#define VTKISRBP_SELECT
#define VTKISRBP_ORIENT
Like TrackBallCamera, but this can pick props underneath a rubber band selection rectangle.
void DrawPixels(const vtkVector2i &StartPos, const vtkVector2i &EndPos, unsigned char *pixels, int *size)
vtkStandardNewMacro(LVRInteractorStylePolygonPick)
bool compareX(vtkVector2i i, vtkVector2i j)
std::vector< vtkVector2i > GetPolygonPoints()


lvr2
Author(s): Thomas Wiemann , Sebastian Pütz , Alexander Mock , Lars Kiesow , Lukas Kalbertodt , Tristan Igelbrink , Johan M. von Behren , Dominik Feldschnieders , Alexander Löhr
autogenerated on Mon Feb 28 2022 22:46:08