1 /*
2 * Software License Agreement (BSD License)
3 *
4 * Point Cloud Library (PCL) - www.pointclouds.org
5 * Copyright (c) 2009-2012, Willow Garage, Inc.
6 * Copyright (c) 2012-, Open Perception, Inc.
7 *
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 * * Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * * Redistributions in binary form must reproduce the above
17 * copyright notice, this list of conditions and the following
18 * disclaimer in the documentation and/or other materials provided
19 * with the distribution.
20 * * Neither the name of the copyright holder(s) nor the names of its
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 *
37 */
38
39 #include <vtkCallbackCommand.h>
40 #include <vtkCamera.h>
41 #include <vtkImageSlice.h>
42 #include <vtkImageSliceMapper.h>
43 #include <vtkImageViewer.h>
44 #include <vtkObjectFactory.h>
45 #include <vtkRenderer.h>
46 #include <vtkVersion.h>
47
48 #include <pcl/visualization/image_viewer.h>
49 #include <pcl/visualization/common/float_image_utils.h>
50 #include <pcl/visualization/keyboard_event.h>
51 #include <pcl/visualization/mouse_event.h>
52 #include <pcl/common/time.h>
53 #include <pcl/visualization/vtk/vtkRenderWindowInteractorFix.h>
54
55 //////////////////////////////////////////////////////////////////////////////////////////
ImageViewer(const std::string & window_title)56 pcl::visualization::ImageViewer::ImageViewer (const std::string& window_title)
57 : mouse_command_ (vtkSmartPointer<vtkCallbackCommand>::New ())
58 , keyboard_command_ (vtkSmartPointer<vtkCallbackCommand>::New ())
59 , win_ (vtkSmartPointer<vtkRenderWindow>::New ())
60 , ren_ (vtkSmartPointer<vtkRenderer>::New ())
61 , slice_ (vtkSmartPointer<vtkImageSlice>::New ())
62 , interactor_style_ (vtkSmartPointer<ImageViewerInteractorStyle>::New ())
63 , data_size_ (0)
64 , stopped_ ()
65 , timer_id_ ()
66 , algo_ (vtkSmartPointer<vtkImageFlip>::New ())
67 {
68 interactor_ = vtkSmartPointer <vtkRenderWindowInteractor>::Take (vtkRenderWindowInteractorFixNew ());
69
70 // Prepare for image flip
71 algo_->SetInterpolationModeToCubic ();
72 algo_->PreserveImageExtentOn ();
73 algo_->FlipAboutOriginOn ();
74 algo_->SetFilteredAxis (1);
75
76 // blend_->SetBlendModeToNormal ();
77 // blend_->SetNumberOfThreads (1);
78
79 // Set the mouse/keyboard callbacks
80 mouse_command_->SetClientData (this);
81 mouse_command_->SetCallback (ImageViewer::MouseCallback);
82
83 keyboard_command_->SetClientData (this);
84 keyboard_command_->SetCallback (ImageViewer::KeyboardCallback);
85
86 // Create our own interactor and set the window title
87 win_->SetSize (640, 480);
88 win_->AddRenderer (ren_);
89 win_->SetWindowName (window_title.c_str ());
90 interactor_->SetRenderWindow (win_);
91
92 vtkSmartPointer<vtkImageData> empty_image = vtkSmartPointer<vtkImageData>::New ();
93 vtkSmartPointer<vtkImageSliceMapper> map = vtkSmartPointer<vtkImageSliceMapper>::New ();
94 map->SetInputData (empty_image);
95 slice_->SetMapper (map);
96 ren_->AddViewProp (slice_);
97 ren_->GetActiveCamera ()->ParallelProjectionOn ();
98 interactor_->SetInteractorStyle (interactor_style_);
99
100 // Initialize and create timer
101 interactor_->Initialize ();
102 timer_id_ = interactor_->CreateRepeatingTimer (0);
103
104 // Set the exit callbacks
105 exit_main_loop_timer_callback_ = vtkSmartPointer<ExitMainLoopTimerCallback>::New ();
106 exit_main_loop_timer_callback_->window = this;
107 exit_main_loop_timer_callback_->right_timer_id = -1;
108 interactor_->AddObserver (vtkCommand::TimerEvent, exit_main_loop_timer_callback_);
109
110 exit_callback_ = vtkSmartPointer<ExitCallback>::New ();
111 exit_callback_->window = this;
112 interactor_->AddObserver (vtkCommand::ExitEvent, exit_callback_);
113
114 // Reset camera (flip it vertically)
115 resetStoppedFlag ();
116
117 PCL_DEBUG ("[pcl::visualization::ImageViewer] VTK version found: %d.%d\n", VTK_MAJOR_VERSION, VTK_MINOR_VERSION);
118 }
119
120 //////////////////////////////////////////////////////////////////////////////////////////
~ImageViewer()121 pcl::visualization::ImageViewer::~ImageViewer ()
122 {
123 interactor_->DestroyTimer (timer_id_);
124 }
125
126 //////////////////////////////////////////////////////////////////////////////////////////
127 void
addRGBImage(const unsigned char * rgb_data,unsigned width,unsigned height,const std::string & layer_id,double opacity,bool autoresize)128 pcl::visualization::ImageViewer::addRGBImage (
129 const unsigned char* rgb_data, unsigned width, unsigned height,
130 const std::string &layer_id, double opacity, bool autoresize)
131 {
132 if (autoresize &&
133 (unsigned (getSize ()[0]) != width ||
134 unsigned (getSize ()[1]) != height))
135 setSize (width, height);
136
137 // Check to see if this ID entry already exists (has it been already added to the visualizer?)
138 LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
139 if (am_it == layer_map_.end ())
140 {
141 PCL_DEBUG ("[pcl::visualization::ImageViewer::addRGBImage] No layer with ID='%s' found. Creating new one...\n", layer_id.c_str ());
142 am_it = createLayer (layer_id, width, height, opacity, false);
143 }
144
145 void* data = const_cast<void*> (reinterpret_cast<const void*> (rgb_data));
146
147 vtkSmartPointer<vtkImageData> image = vtkSmartPointer<vtkImageData>::New ();
148 image->SetExtent (0, width - 1, 0, height - 1, 0, 0);
149 image->AllocateScalars (VTK_UNSIGNED_CHAR, 3);
150 image->GetPointData ()->GetScalars ()->SetVoidArray (data, 3 * width * height, 1);
151 algo_->SetInputData (image);
152 algo_->Update ();
153 slice_->GetMapper ()->SetInputConnection (algo_->GetOutputPort ());
154 ren_->ResetCamera ();
155 ren_->GetActiveCamera ()->SetParallelScale (0.5 * win_->GetSize ()[1]);
156 }
157
158 //////////////////////////////////////////////////////////////////////////////////////////
159 void
showRGBImage(const unsigned char * rgb_data,unsigned width,unsigned height,const std::string & layer_id,double opacity)160 pcl::visualization::ImageViewer::showRGBImage (
161 const unsigned char* rgb_data, unsigned width, unsigned height,
162 const std::string &layer_id, double opacity)
163 {
164 addRGBImage (rgb_data, width, height, layer_id, opacity);
165 render ();
166 }
167
168 //////////////////////////////////////////////////////////////////////////////////////////
169 void
addMonoImage(const unsigned char * rgb_data,unsigned width,unsigned height,const std::string & layer_id,double opacity)170 pcl::visualization::ImageViewer::addMonoImage (
171 const unsigned char* rgb_data, unsigned width, unsigned height,
172 const std::string &layer_id, double opacity)
173 {
174 if (unsigned (getSize ()[0]) != width ||
175 unsigned (getSize ()[1]) != height)
176 setSize (width, height);
177
178 // Check to see if this ID entry already exists (has it been already added to the visualizer?)
179 LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
180 if (am_it == layer_map_.end ())
181 {
182 PCL_DEBUG ("[pcl::visualization::ImageViewer::showMonoImage] No layer with ID='%s' found. Creating new one...\n", layer_id.c_str ());
183 am_it = createLayer (layer_id, width, height, opacity, false);
184 }
185
186 void* data = const_cast<void*> (reinterpret_cast<const void*> (rgb_data));
187
188 vtkSmartPointer<vtkImageData> image = vtkSmartPointer<vtkImageData>::New ();
189 image->SetExtent (0, width - 1, 0, height - 1, 0, 0);
190 image->AllocateScalars (VTK_UNSIGNED_CHAR, 1);
191 image->GetPointData ()->GetScalars ()->SetVoidArray (data, width * height, 1);
192
193 algo_->SetInputData (image);
194 algo_->Update ();
195 slice_->GetMapper ()->SetInputConnection (algo_->GetOutputPort ());
196 ren_->ResetCamera ();
197 ren_->GetActiveCamera ()->SetParallelScale (0.5 * win_->GetSize ()[1]);
198 }
199
200
201 //////////////////////////////////////////////////////////////////////////////////////////
202 void
showMonoImage(const unsigned char * rgb_data,unsigned width,unsigned height,const std::string & layer_id,double opacity)203 pcl::visualization::ImageViewer::showMonoImage (
204 const unsigned char* rgb_data, unsigned width, unsigned height,
205 const std::string &layer_id, double opacity)
206 {
207 addMonoImage (rgb_data, width, height, layer_id, opacity);
208 render ();
209 }
210
211 //////////////////////////////////////////////////////////////////////////////////////////
212 void
addMonoImage(const pcl::PointCloud<pcl::Intensity> & cloud,const std::string & layer_id,double opacity)213 pcl::visualization::ImageViewer::addMonoImage (
214 const pcl::PointCloud<pcl::Intensity> &cloud,
215 const std::string &layer_id, double opacity)
216 {
217 if (data_size_ < cloud.width * cloud.height)
218 {
219 data_size_ = cloud.width * cloud.height * 3;
220 data_.reset (new unsigned char[data_size_]);
221 }
222
223 convertIntensityCloudToUChar (cloud, data_);
224
225 return (addMonoImage (data_.get (), cloud.width, cloud.height, layer_id, opacity));
226 }
227
228 //////////////////////////////////////////////////////////////////////////////////////////
229 void
showMonoImage(const pcl::PointCloud<pcl::Intensity> & cloud,const std::string & layer_id,double opacity)230 pcl::visualization::ImageViewer::showMonoImage (
231 const pcl::PointCloud<pcl::Intensity> &cloud,
232 const std::string &layer_id, double opacity)
233 {
234 addMonoImage (cloud, layer_id, opacity);
235 render ();
236 }
237
238 //////////////////////////////////////////////////////////////////////////////////////////
239 void
addMonoImage(const pcl::PointCloud<pcl::Intensity8u> & cloud,const std::string & layer_id,double opacity)240 pcl::visualization::ImageViewer::addMonoImage (
241 const pcl::PointCloud<pcl::Intensity8u> &cloud,
242 const std::string &layer_id, double opacity)
243 {
244 if (data_size_ < cloud.width * cloud.height)
245 {
246 data_size_ = cloud.width * cloud.height * 3;
247 data_.reset (new unsigned char[data_size_]);
248 }
249
250 convertIntensityCloud8uToUChar (cloud, data_);
251
252 return (addMonoImage (data_.get (), cloud.width, cloud.height, layer_id, opacity));
253 }
254
255 //////////////////////////////////////////////////////////////////////////////////////////
256 void
showMonoImage(const pcl::PointCloud<pcl::Intensity8u> & cloud,const std::string & layer_id,double opacity)257 pcl::visualization::ImageViewer::showMonoImage (
258 const pcl::PointCloud<pcl::Intensity8u> &cloud,
259 const std::string &layer_id, double opacity)
260 {
261 addMonoImage (cloud, layer_id, opacity);
262 render ();
263 }
264
265 //////////////////////////////////////////////////////////////////////////////////////////
266 void
addFloatImage(const float * float_image,unsigned int width,unsigned int height,float min_value,float max_value,bool grayscale,const std::string & layer_id,double opacity)267 pcl::visualization::ImageViewer::addFloatImage (
268 const float* float_image, unsigned int width, unsigned int height,
269 float min_value, float max_value, bool grayscale,
270 const std::string &layer_id, double opacity)
271 {
272 unsigned char* rgb_image = FloatImageUtils::getVisualImage (float_image, width, height,
273 min_value, max_value, grayscale);
274 addRGBImage (rgb_image, width, height, layer_id, opacity);
275 image_data_.push_back (rgb_image);
276 }
277
278 //////////////////////////////////////////////////////////////////////////////////////////
279 void
showFloatImage(const float * float_image,unsigned int width,unsigned int height,float min_value,float max_value,bool grayscale,const std::string & layer_id,double opacity)280 pcl::visualization::ImageViewer::showFloatImage (
281 const float* float_image, unsigned int width, unsigned int height,
282 float min_value, float max_value, bool grayscale,
283 const std::string &layer_id, double opacity)
284 {
285 addFloatImage (float_image, width, height, min_value, max_value, grayscale, layer_id, opacity);
286 render ();
287 }
288
289 //////////////////////////////////////////////////////////////////////////////////////////
290 void
addAngleImage(const float * angle_image,unsigned int width,unsigned int height,const std::string & layer_id,double opacity)291 pcl::visualization::ImageViewer::addAngleImage (
292 const float* angle_image, unsigned int width, unsigned int height,
293 const std::string &layer_id, double opacity)
294 {
295 unsigned char* rgb_image = FloatImageUtils::getVisualAngleImage (angle_image, width, height);
296 addRGBImage (rgb_image, width, height, layer_id, opacity);
297 image_data_.push_back (rgb_image);
298 }
299
300 //////////////////////////////////////////////////////////////////////////////////////////
301 void
showAngleImage(const float * angle_image,unsigned int width,unsigned int height,const std::string & layer_id,double opacity)302 pcl::visualization::ImageViewer::showAngleImage (
303 const float* angle_image, unsigned int width, unsigned int height,
304 const std::string &layer_id, double opacity)
305 {
306 addAngleImage (angle_image, width, height, layer_id, opacity);
307 render ();
308 }
309
310 //////////////////////////////////////////////////////////////////////////////////////////
311 void
addHalfAngleImage(const float * angle_image,unsigned int width,unsigned int height,const std::string & layer_id,double opacity)312 pcl::visualization::ImageViewer::addHalfAngleImage (
313 const float* angle_image, unsigned int width, unsigned int height,
314 const std::string &layer_id, double opacity)
315 {
316 unsigned char* rgb_image = FloatImageUtils::getVisualHalfAngleImage (angle_image, width, height);
317 addRGBImage (rgb_image, width, height, layer_id, opacity);
318 image_data_.push_back (rgb_image);
319 }
320
321 //////////////////////////////////////////////////////////////////////////////////////////
322 void
showHalfAngleImage(const float * angle_image,unsigned int width,unsigned int height,const std::string & layer_id,double opacity)323 pcl::visualization::ImageViewer::showHalfAngleImage (
324 const float* angle_image, unsigned int width, unsigned int height,
325 const std::string &layer_id, double opacity)
326 {
327 addHalfAngleImage (angle_image, width, height, layer_id, opacity);
328 render ();
329 }
330
331 //////////////////////////////////////////////////////////////////////////////////////////
332 void
addShortImage(const unsigned short * short_image,unsigned int width,unsigned int height,unsigned short min_value,unsigned short max_value,bool grayscale,const std::string & layer_id,double opacity)333 pcl::visualization::ImageViewer::addShortImage (
334 const unsigned short* short_image, unsigned int width, unsigned int height,
335 unsigned short min_value, unsigned short max_value, bool grayscale,
336 const std::string &layer_id, double opacity)
337 {
338 unsigned char* rgb_image = FloatImageUtils::getVisualImage (short_image, width, height,
339 min_value, max_value, grayscale);
340 addRGBImage (rgb_image, width, height, layer_id, opacity);
341 image_data_.push_back (rgb_image);
342 }
343
344 //////////////////////////////////////////////////////////////////////////////////////////
345 void
showShortImage(const unsigned short * short_image,unsigned int width,unsigned int height,unsigned short min_value,unsigned short max_value,bool grayscale,const std::string & layer_id,double opacity)346 pcl::visualization::ImageViewer::showShortImage (
347 const unsigned short* short_image, unsigned int width, unsigned int height,
348 unsigned short min_value, unsigned short max_value, bool grayscale,
349 const std::string &layer_id, double opacity)
350 {
351 addShortImage (short_image, width, height, min_value, max_value, grayscale, layer_id, opacity);
352 render ();
353 }
354
355 //////////////////////////////////////////////////////////////////////////////////////////
356 void
spin()357 pcl::visualization::ImageViewer::spin ()
358 {
359 render ();
360 resetStoppedFlag ();
361 // Render the window before we start the interactor
362 //interactor_->Render ();
363 interactor_->Start ();
364 }
365
366 //////////////////////////////////////////////////////////////////////////////////////////
367 void
spinOnce(int time,bool force_redraw)368 pcl::visualization::ImageViewer::spinOnce (int time, bool force_redraw)
369 {
370 if (force_redraw)
371 {
372 render ();
373 //interactor_->Render ();
374 }
375
376 if (time <= 0)
377 time = 1;
378
379 DO_EVERY (1.0 / interactor_->GetDesiredUpdateRate (),
380 exit_main_loop_timer_callback_->right_timer_id = interactor_->CreateRepeatingTimer (time);
381 interactor_->Start ();
382 interactor_->DestroyTimer (exit_main_loop_timer_callback_->right_timer_id);
383 );
384 for(auto &i : image_data_)
385 delete [] i;
386 image_data_.clear ();
387 }
388
389 //////////////////////////////////////////////////////////////////////////////////////////
390 boost::signals2::connection
registerMouseCallback(std::function<void (const pcl::visualization::MouseEvent &)> callback)391 pcl::visualization::ImageViewer::registerMouseCallback (
392 std::function<void (const pcl::visualization::MouseEvent&)> callback)
393 {
394 // just add observer at first time when a callback is registered
395 if (mouse_signal_.empty ())
396 {
397 interactor_->GetInteractorStyle ()->AddObserver (vtkCommand::MouseMoveEvent, mouse_command_);
398 interactor_->GetInteractorStyle ()->AddObserver (vtkCommand::MiddleButtonPressEvent, mouse_command_);
399 interactor_->GetInteractorStyle ()->AddObserver (vtkCommand::MiddleButtonReleaseEvent, mouse_command_);
400 interactor_->GetInteractorStyle ()->AddObserver (vtkCommand::MouseWheelBackwardEvent, mouse_command_);
401 interactor_->GetInteractorStyle ()->AddObserver (vtkCommand::MouseWheelForwardEvent, mouse_command_);
402 interactor_->GetInteractorStyle ()->AddObserver (vtkCommand::LeftButtonPressEvent, mouse_command_);
403 interactor_->GetInteractorStyle ()->AddObserver (vtkCommand::LeftButtonReleaseEvent, mouse_command_);
404 interactor_->GetInteractorStyle ()->AddObserver (vtkCommand::RightButtonPressEvent, mouse_command_);
405 interactor_->GetInteractorStyle ()->AddObserver (vtkCommand::RightButtonReleaseEvent, mouse_command_);
406 }
407 return (mouse_signal_.connect (callback));
408 }
409
410 //////////////////////////////////////////////////////////////////////////////////////////
411 boost::signals2::connection
registerKeyboardCallback(std::function<void (const pcl::visualization::KeyboardEvent &)> callback)412 pcl::visualization::ImageViewer::registerKeyboardCallback (
413 std::function<void (const pcl::visualization::KeyboardEvent&)> callback)
414 {
415 // just add observer at first time when a callback is registered
416 if (keyboard_signal_.empty ())
417 {
418 interactor_->AddObserver (vtkCommand::KeyPressEvent, keyboard_command_);
419 interactor_->AddObserver (vtkCommand::KeyReleaseEvent, keyboard_command_);
420 }
421
422 return (keyboard_signal_.connect (callback));
423 }
424
425 //////////////////////////////////////////////////////////////////////////////////////////
426 void
emitMouseEvent(unsigned long event_id)427 pcl::visualization::ImageViewer::emitMouseEvent (unsigned long event_id)
428 {
429 //interactor_->GetMousePosition (&x, &y);
430 int x = this->interactor_->GetEventPosition()[0];
431 int y = this->interactor_->GetEventPosition()[1];
432 MouseEvent event (MouseEvent::MouseMove, MouseEvent::NoButton, x, y,
433 interactor_->GetAltKey (),
434 interactor_->GetControlKey (),
435 interactor_->GetShiftKey ());
436 bool repeat = false;
437 switch (event_id)
438 {
439 case vtkCommand::MouseMoveEvent :
440 event.setType (MouseEvent::MouseMove);
441 break;
442
443 case vtkCommand::LeftButtonPressEvent :
444 event.setButton (MouseEvent::LeftButton);
445 if (interactor_->GetRepeatCount () == 0)
446 event.setType (MouseEvent::MouseButtonPress);
447 else
448 event.setType (MouseEvent::MouseDblClick);
449 break;
450
451 case vtkCommand::LeftButtonReleaseEvent :
452 event.setButton (MouseEvent::LeftButton);
453 event.setType (MouseEvent::MouseButtonRelease);
454 break;
455
456 case vtkCommand::RightButtonPressEvent :
457 event.setButton (MouseEvent::RightButton);
458 if (interactor_->GetRepeatCount () == 0)
459 event.setType (MouseEvent::MouseButtonPress);
460 else
461 event.setType (MouseEvent::MouseDblClick);
462 break;
463
464 case vtkCommand::RightButtonReleaseEvent :
465 event.setButton (MouseEvent::RightButton);
466 event.setType (MouseEvent::MouseButtonRelease);
467 break;
468
469 case vtkCommand::MiddleButtonPressEvent :
470 event.setButton (MouseEvent::MiddleButton);
471 if (interactor_->GetRepeatCount () == 0)
472 event.setType (MouseEvent::MouseButtonPress);
473 else
474 event.setType (MouseEvent::MouseDblClick);
475 break;
476
477 case vtkCommand::MiddleButtonReleaseEvent :
478 event.setButton (MouseEvent::MiddleButton);
479 event.setType (MouseEvent::MouseButtonRelease);
480 break;
481
482 case vtkCommand::MouseWheelBackwardEvent :
483 event.setButton (MouseEvent::VScroll);
484 event.setType (MouseEvent::MouseScrollDown);
485 if (interactor_->GetRepeatCount () != 0)
486 repeat = true;
487 break;
488
489 case vtkCommand::MouseWheelForwardEvent :
490 event.setButton (MouseEvent::VScroll);
491 event.setType (MouseEvent::MouseScrollUp);
492 if (interactor_->GetRepeatCount () != 0)
493 repeat = true;
494 break;
495 default:
496 return;
497 }
498
499 mouse_signal_ (event);
500 if (repeat)
501 mouse_signal_ (event);
502 }
503
504 //////////////////////////////////////////////////////////////////////////////////////////
505 void
emitKeyboardEvent(unsigned long event_id)506 pcl::visualization::ImageViewer::emitKeyboardEvent (unsigned long event_id)
507 {
508 KeyboardEvent event (bool(event_id == vtkCommand::KeyPressEvent), interactor_->GetKeySym (), interactor_->GetKeyCode (), interactor_->GetAltKey (), interactor_->GetControlKey (), interactor_->GetShiftKey ());
509 keyboard_signal_ (event);
510 }
511
512 //////////////////////////////////////////////////////////////////////////////////////////
513 void
MouseCallback(vtkObject *,unsigned long eid,void * clientdata,void *)514 pcl::visualization::ImageViewer::MouseCallback (vtkObject*, unsigned long eid, void* clientdata, void*)
515 {
516 ImageViewer* window = reinterpret_cast<ImageViewer*> (clientdata);
517 window->emitMouseEvent (eid);
518 }
519
520 //////////////////////////////////////////////////////////////////////////////////////////
521 void
KeyboardCallback(vtkObject *,unsigned long eid,void * clientdata,void *)522 pcl::visualization::ImageViewer::KeyboardCallback (vtkObject*, unsigned long eid, void* clientdata, void*)
523 {
524 ImageViewer* window = reinterpret_cast<ImageViewer*> (clientdata);
525 window->emitKeyboardEvent (eid);
526 }
527
528 //////////////////////////////////////////////////////////////////////////////////////////
529 pcl::visualization::ImageViewer::LayerMap::iterator
createLayer(const std::string & layer_id,int width,int height,double opacity,bool fill_box)530 pcl::visualization::ImageViewer::createLayer (
531 const std::string &layer_id, int width, int height, double opacity, bool fill_box)
532 {
533 Layer l;
534 l.layer_name = layer_id;
535 // Create a new layer
536 l.actor = vtkSmartPointer<vtkContextActor>::New ();
537 l.actor->PickableOff ();
538 l.actor->DragableOff ();
539 if (fill_box)
540 {
541 vtkSmartPointer<context_items::FilledRectangle> rect = vtkSmartPointer<context_items::FilledRectangle>::New ();
542 rect->setColors (0,0,0);
543 rect->setOpacity (opacity);
544 rect->set (0, 0, static_cast<float> (width), static_cast<float> (height));
545 l.actor->GetScene ()->AddItem (rect);
546 }
547 ren_->AddActor (l.actor);
548 // Add another element
549 layer_map_.push_back (l);
550
551 return (layer_map_.end () - 1);
552 }
553
554 //////////////////////////////////////////////////////////////////////////////////////////
555 bool
addLayer(const std::string & layer_id,int width,int height,double opacity)556 pcl::visualization::ImageViewer::addLayer (
557 const std::string &layer_id, int width, int height, double opacity)
558 {
559 // Check to see if this ID entry already exists (has it been already added to the visualizer?)
560 LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
561 if (am_it != layer_map_.end ())
562 {
563 PCL_DEBUG ("[pcl::visualization::ImageViewer::addLayer] Layer with ID='%s' already exists!\n", layer_id.c_str ());
564 return (false);
565 }
566
567 createLayer (layer_id, width, height, opacity, false);
568
569 return (true);
570 }
571
572 ///////////////////////////////////////////////////////////////////////////////////////////
573 void
removeLayer(const std::string & layer_id)574 pcl::visualization::ImageViewer::removeLayer (const std::string &layer_id)
575 {
576 // Check to see if this ID entry already exists (has it been already added to the visualizer?)
577 LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
578 if (am_it == layer_map_.end ())
579 {
580 PCL_DEBUG ("[pcl::visualization::ImageViewer::removeLayer] No layer with ID='%s' found.\n", layer_id.c_str ());
581 return;
582 }
583 ren_->RemoveActor (am_it->actor);
584 layer_map_.erase (am_it);
585 }
586
587 //////////////////////////////////////////////////////////////////////////////////////////
588 bool
addCircle(unsigned int x,unsigned int y,double radius,double r,double g,double b,const std::string & layer_id,double opacity)589 pcl::visualization::ImageViewer::addCircle (
590 unsigned int x, unsigned int y, double radius, double r, double g, double b,
591 const std::string &layer_id, double opacity)
592 {
593 // Check to see if this ID entry already exists (has it been already added to the visualizer?)
594 LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
595 if (am_it == layer_map_.end ())
596 {
597 PCL_DEBUG ("[pcl::visualization::ImageViewer::addCircle] No layer with ID='%s' found. Creating new one...\n", layer_id.c_str ());
598 am_it = createLayer (layer_id, getSize ()[0] - 1, getSize ()[1] - 1, opacity, false);
599 }
600
601 vtkSmartPointer<context_items::Circle> circle = vtkSmartPointer<context_items::Circle>::New ();
602 circle->setColors (static_cast<unsigned char> (255.0 * r),
603 static_cast<unsigned char> (255.0 * g),
604 static_cast<unsigned char> (255.0 * b));
605 circle->setOpacity (opacity);
606 circle->set (static_cast<float> (x), static_cast<float> (y), static_cast<float> (radius));
607 am_it->actor->GetScene ()->AddItem (circle);
608
609 return (true);
610 }
611
612 //////////////////////////////////////////////////////////////////////////////////////////
613 bool
addCircle(unsigned int x,unsigned int y,double radius,const std::string & layer_id,double opacity)614 pcl::visualization::ImageViewer::addCircle (unsigned int x, unsigned int y, double radius,
615 const std::string &layer_id, double opacity)
616 {
617 return (addCircle (x, y, radius, 0.0, 1.0, 0.0, layer_id, opacity));
618 }
619
620 //////////////////////////////////////////////////////////////////////////////////////////
621 bool
addFilledRectangle(unsigned int x_min,unsigned int x_max,unsigned int y_min,unsigned int y_max,double r,double g,double b,const std::string & layer_id,double opacity)622 pcl::visualization::ImageViewer::addFilledRectangle (
623 unsigned int x_min, unsigned int x_max, unsigned int y_min, unsigned int y_max,
624 double r, double g, double b, const std::string &layer_id, double opacity)
625 {
626 // Check to see if this ID entry already exists (has it been already added to the visualizer?)
627 LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
628 if (am_it == layer_map_.end ())
629 {
630 PCL_DEBUG ("[pcl::visualization::ImageViewer::addFilledRectangle] No layer with ID='%s' found. Creating new one...\n", layer_id.c_str ());
631 am_it = createLayer (layer_id, getSize ()[0] - 1, getSize ()[1] - 1, opacity, false);
632 }
633
634 vtkSmartPointer<context_items::FilledRectangle> rect = vtkSmartPointer<context_items::FilledRectangle>::New ();
635 rect->setColors (static_cast<unsigned char> (255.0 * r),
636 static_cast<unsigned char> (255.0 * g),
637 static_cast<unsigned char> (255.0 * b));
638 rect->setOpacity (opacity);
639 rect->set (static_cast<float> (x_min), static_cast<float> (y_min),
640 static_cast<float> (x_max - x_min), static_cast<float> (y_max - y_min));
641 am_it->actor->GetScene ()->AddItem (rect);
642
643 return (true);
644 }
645
646 //////////////////////////////////////////////////////////////////////////////////////////
647 bool
addFilledRectangle(unsigned int x_min,unsigned int x_max,unsigned int y_min,unsigned int y_max,const std::string & layer_id,double opacity)648 pcl::visualization::ImageViewer::addFilledRectangle (
649 unsigned int x_min, unsigned int x_max, unsigned int y_min, unsigned int y_max,
650 const std::string &layer_id, double opacity)
651 {
652 return (addFilledRectangle (x_min, x_max, y_min, y_max, 0.0, 1.0, 0.0, layer_id, opacity));
653 }
654
655 //////////////////////////////////////////////////////////////////////////////////////////
656 bool
addRectangle(unsigned int x_min,unsigned int x_max,unsigned int y_min,unsigned int y_max,double r,double g,double b,const std::string & layer_id,double opacity)657 pcl::visualization::ImageViewer::addRectangle (
658 unsigned int x_min, unsigned int x_max, unsigned int y_min, unsigned int y_max,
659 double r, double g, double b, const std::string &layer_id, double opacity)
660 {
661 // Check to see if this ID entry already exists (has it been already added to the visualizer?)
662 LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
663 if (am_it == layer_map_.end ())
664 {
665 PCL_DEBUG ("[pcl::visualization::ImageViewer::addRectangle] No layer with ID='%s' found. Creating new one...\n", layer_id.c_str ());
666 am_it = createLayer (layer_id, getSize ()[0] - 1, getSize ()[1] - 1, opacity, false);
667 }
668
669 vtkSmartPointer<context_items::Rectangle> rect = vtkSmartPointer<context_items::Rectangle>::New ();
670 rect->setColors (static_cast<unsigned char> (255.0 * r),
671 static_cast<unsigned char> (255.0 * g),
672 static_cast<unsigned char> (255.0 * b));
673 rect->setOpacity (opacity);
674 rect->set (static_cast<float> (x_min), static_cast<float> (y_min),
675 static_cast<float> (x_max), static_cast<float> (y_max));
676 am_it->actor->GetScene ()->AddItem (rect);
677
678 return (true);
679 }
680
681 //////////////////////////////////////////////////////////////////////////////////////////
682 bool
addRectangle(unsigned int x_min,unsigned int x_max,unsigned int y_min,unsigned int y_max,const std::string & layer_id,double opacity)683 pcl::visualization::ImageViewer::addRectangle (
684 unsigned int x_min, unsigned int x_max, unsigned int y_min, unsigned int y_max,
685 const std::string &layer_id, double opacity)
686 {
687 return (addRectangle (x_min, x_max, y_min, y_max, 0.0, 1.0, 0.0, layer_id, opacity));
688 }
689
690 //////////////////////////////////////////////////////////////////////////////////////////
691 bool
addRectangle(const pcl::PointXY & min_pt,const pcl::PointXY & max_pt,double r,double g,double b,const std::string & layer_id,double opacity)692 pcl::visualization::ImageViewer::addRectangle (
693 const pcl::PointXY &min_pt, const pcl::PointXY &max_pt,
694 double r, double g, double b, const std::string &layer_id, double opacity)
695 {
696 // Check to see if this ID entry already exists (has it been already added to the visualizer?)
697 LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
698 if (am_it == layer_map_.end ())
699 {
700 PCL_DEBUG ("[pcl::visualization::ImageViewer::addRectangle] No layer with ID='%s' found. Creating new one...\n", layer_id.c_str ());
701 am_it = createLayer (layer_id, getSize ()[0] - 1, getSize ()[1] - 1, opacity, false);
702 }
703
704 vtkSmartPointer<context_items::Rectangle> rect = vtkSmartPointer<context_items::Rectangle>::New ();
705 rect->setColors (static_cast<unsigned char> (255.0 * r),
706 static_cast<unsigned char> (255.0 * g),
707 static_cast<unsigned char> (255.0 * b));
708 rect->setOpacity (opacity);
709 rect->set (min_pt.x, min_pt.y, max_pt.x, max_pt.y);
710 am_it->actor->GetScene ()->AddItem (rect);
711
712 return (true);
713 }
714
715 //////////////////////////////////////////////////////////////////////////////////////////
716 bool
addRectangle(const pcl::PointXY & min_pt,const pcl::PointXY & max_pt,const std::string & layer_id,double opacity)717 pcl::visualization::ImageViewer::addRectangle (
718 const pcl::PointXY &min_pt, const pcl::PointXY &max_pt,
719 const std::string &layer_id, double opacity)
720 {
721 return (addRectangle (min_pt, max_pt, 0.0, 1.0, 0.0, layer_id, opacity));
722 }
723
724 //////////////////////////////////////////////////////////////////////////////////////////
725 bool
addLine(unsigned int x_min,unsigned int y_min,unsigned int x_max,unsigned int y_max,double r,double g,double b,const std::string & layer_id,double opacity)726 pcl::visualization::ImageViewer::addLine (unsigned int x_min, unsigned int y_min,
727 unsigned int x_max, unsigned int y_max,
728 double r, double g, double b,
729 const std::string &layer_id, double opacity)
730 {
731 // Check to see if this ID entry already exists (has it been already added to the visualizer?)
732 LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
733 if (am_it == layer_map_.end ())
734 {
735 PCL_DEBUG ("[pcl::visualization::ImageViewer::addLine] No layer with ID='%s' found. Creating new one...\n", layer_id.c_str ());
736 am_it = createLayer (layer_id, getSize ()[0] - 1, getSize ()[1] - 1, opacity, false);
737 }
738
739 vtkSmartPointer<context_items::Line> line = vtkSmartPointer<context_items::Line>::New ();
740 line->setColors (static_cast<unsigned char> (255.0 * r),
741 static_cast<unsigned char> (255.0 * g),
742 static_cast<unsigned char> (255.0 * b));
743 line->setOpacity (opacity);
744 line->set (static_cast<float> (x_min), static_cast<float> (y_min),
745 static_cast<float> (x_max), static_cast<float> (y_max));
746 am_it->actor->GetScene ()->AddItem (line);
747
748 return (true);
749 }
750
751 //////////////////////////////////////////////////////////////////////////////////////////
752 bool
addLine(unsigned int x_min,unsigned int y_min,unsigned int x_max,unsigned int y_max,const std::string & layer_id,double opacity)753 pcl::visualization::ImageViewer::addLine (unsigned int x_min, unsigned int y_min,
754 unsigned int x_max, unsigned int y_max,
755 const std::string &layer_id, double opacity)
756 {
757 return (addLine (x_min, y_min, x_max, y_max, 0.0, 1.0, 0.0, layer_id, opacity));
758 }
759
760 //////////////////////////////////////////////////////////////////////////////////////////
761 bool
addText(unsigned int x,unsigned int y,const std::string & text_string,double r,double g,double b,const std::string & layer_id,double opacity)762 pcl::visualization::ImageViewer::addText (unsigned int x, unsigned int y,
763 const std::string& text_string,
764 double r, double g, double b,
765 const std::string &layer_id, double opacity)
766 {
767 // Check to see if this ID entry already exists (has it been already added to the visualizer?)
768 LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
769 if (am_it == layer_map_.end ())
770 {
771 PCL_DEBUG ("[pcl::visualization::ImageViewer::addText] No layer with ID='%s' found. Creating new one...\n", layer_id.c_str ());
772 am_it = createLayer (layer_id, getSize ()[0] - 1, getSize ()[1] - 1, opacity, false);
773 }
774
775 vtkSmartPointer<context_items::Text> text = vtkSmartPointer<context_items::Text>::New ();
776 text->setColors (static_cast<unsigned char> (255.0 * r),
777 static_cast<unsigned char> (255.0 * g),
778 static_cast<unsigned char> (255.0 * b));
779 text->setOpacity (opacity);
780 text->set (static_cast<float> (x), static_cast<float> (y), text_string);
781 am_it->actor->GetScene ()->AddItem (text);
782
783 return (true);
784 }
785
786 //////////////////////////////////////////////////////////////////////////////////////////
787 bool
addText(unsigned int x,unsigned int y,const std::string & text,const std::string & layer_id,double opacity)788 pcl::visualization::ImageViewer::addText (unsigned int x, unsigned int y, const std::string& text,
789 const std::string &layer_id, double opacity)
790 {
791 return (addText (x, y, text, 0.0, 1.0, 0.0, layer_id, opacity));
792 }
793
794 //////////////////////////////////////////////////////////////////////////////////////////
795 void
markPoint(std::size_t u,std::size_t v,Vector3ub fg_color,Vector3ub bg_color,double radius,const std::string & layer_id,double opacity)796 pcl::visualization::ImageViewer::markPoint (
797 std::size_t u, std::size_t v, Vector3ub fg_color, Vector3ub bg_color, double radius,
798 const std::string &layer_id, double opacity)
799 {
800 // Check to see if this ID entry already exists (has it been already added to the visualizer?)
801 LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
802 if (am_it == layer_map_.end ())
803 {
804 PCL_DEBUG ("[pcl::visualization::ImageViewer::markPoint] No layer with ID='%s' found. Creating new one...\n", layer_id.c_str ());
805 am_it = createLayer (layer_id, getSize ()[0] - 1, getSize ()[1] - 1, opacity, false);
806 }
807
808 vtkSmartPointer<context_items::Point> point = vtkSmartPointer<context_items::Point>::New ();
809 point->setColors (fg_color[0], fg_color[1], fg_color[2]);
810 point->setOpacity (opacity);
811
812 vtkSmartPointer<context_items::Disk> disk = vtkSmartPointer<context_items::Disk>::New ();
813 disk->setColors (bg_color[0], bg_color[1], bg_color[2]);
814 disk->setOpacity (opacity);
815
816 point->set (static_cast<float> (u), static_cast<float> (v));
817 disk->set (static_cast<float> (u), static_cast<float> (v), static_cast<float> (radius));
818
819 am_it->actor->GetScene ()->AddItem (disk);
820 am_it->actor->GetScene ()->AddItem (point);
821 }
822
823 //////////////////////////////////////////////////////////////////////////////////////////
824 void
markPoints(const std::vector<int> & uv,Vector3ub fg_color,Vector3ub bg_color,double size,const std::string & layer_id,double opacity)825 pcl::visualization::ImageViewer::markPoints (
826 const std::vector<int>& uv, Vector3ub fg_color, Vector3ub bg_color, double size,
827 const std::string &layer_id, double opacity)
828 {
829 if (uv.empty ())
830 return;
831
832 std::vector<float> float_uv (uv.size ());
833 for (std::size_t i = 0; i < uv.size (); ++i)
834 float_uv[i] = static_cast<float> (uv[i]);
835 return (markPoints (float_uv, fg_color, bg_color, size, layer_id, opacity));
836 }
837
838 //////////////////////////////////////////////////////////////////////////////////////////
839 void
markPoints(const std::vector<float> & uv,Vector3ub fg_color,Vector3ub bg_color,double size,const std::string & layer_id,double opacity)840 pcl::visualization::ImageViewer::markPoints (
841 const std::vector<float>& uv, Vector3ub fg_color, Vector3ub bg_color, double size,
842 const std::string &layer_id, double opacity)
843 {
844 if (uv.empty ())
845 return;
846
847 // Check to see if this ID entry already exists (has it been already added to the visualizer?)
848 LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
849 if (am_it == layer_map_.end ())
850 {
851 PCL_DEBUG ("[pcl::visualization::ImageViewer::markPoint] No layer with ID='%s' found. Creating new one...\n", layer_id.c_str ());
852 am_it = createLayer (layer_id, getSize ()[0] - 1, getSize ()[1] - 1, opacity, false);
853 }
854
855 vtkSmartPointer<context_items::Markers> markers = vtkSmartPointer<context_items::Markers>::New ();
856 markers->setOpacity (opacity);
857 markers->set (uv);
858 markers->setSize (size);
859 markers->setColors (bg_color[0], bg_color[1], bg_color[2]);
860 markers->setPointColors (fg_color[0], fg_color[1], fg_color[2]);
861 am_it->actor->GetScene ()->AddItem (markers);
862 }
863
864 //////////////////////////////////////////////////////////////////////////////////////////
865 void
render()866 pcl::visualization::ImageViewer::render ()
867 {
868 win_->Render ();
869 for(auto &i : image_data_)
870 delete [] i;
871 image_data_.clear ();
872 }
873
874 //////////////////////////////////////////////////////////////////////////////////////////
875 void
convertIntensityCloudToUChar(const pcl::PointCloud<pcl::Intensity> & cloud,boost::shared_array<unsigned char> data)876 pcl::visualization::ImageViewer::convertIntensityCloudToUChar (
877 const pcl::PointCloud<pcl::Intensity> &cloud,
878 boost::shared_array<unsigned char> data)
879 {
880 int j = 0;
881 for (const auto &point : cloud.points)
882 {
883 data[j++] = static_cast <unsigned char> (point.intensity * 255);
884 }
885 }
886
887 //////////////////////////////////////////////////////////////////////////////////////////
888 void
convertIntensityCloud8uToUChar(const pcl::PointCloud<pcl::Intensity8u> & cloud,boost::shared_array<unsigned char> data)889 pcl::visualization::ImageViewer::convertIntensityCloud8uToUChar (
890 const pcl::PointCloud<pcl::Intensity8u> &cloud,
891 boost::shared_array<unsigned char> data)
892 {
893 int j = 0;
894 for (const auto &point : cloud.points)
895 data[j++] = static_cast<unsigned char> (point.intensity);
896 }
897
898 //////////////////////////////////////////////////////////////////////////////////////////
899 //////////////////////////////////////////////////////////////////////////////////////////
900 //////////////////////////////////////////////////////////////////////////////////////////
ImageViewerInteractorStyle()901 pcl::visualization::ImageViewerInteractorStyle::ImageViewerInteractorStyle ()
902 {
903 }
904
905 //////////////////////////////////////////////////////////////////////////////////////////
906 void
OnChar()907 pcl::visualization::ImageViewerInteractorStyle::OnChar ()
908 {
909 FindPokedRenderer (Interactor->GetEventPosition ()[0], Interactor->GetEventPosition ()[1]);
910
911 Superclass::OnChar();
912 }
913
914 //////////////////////////////////////////////////////////////////////////////////////////
915 void
adjustCamera(vtkImageData * image,vtkRenderer * ren)916 pcl::visualization::ImageViewerInteractorStyle::adjustCamera (
917 vtkImageData *image, vtkRenderer *ren)
918 {
919 // Set up the background camera to fill the renderer with the image
920 double origin[3], spacing[3];
921 int extent[6];
922 image->GetOrigin (origin);
923 image->GetSpacing (spacing);
924 image->GetExtent (extent);
925
926 vtkCamera* camera = ren->GetActiveCamera ();
927 double xc = origin[0] + 0.5 * (extent[0] + extent[1]) * spacing[0];
928 double yc = origin[1] + 0.5 * (extent[2] + extent[3]) * spacing[1];
929 double yd = (extent[3] - extent[2] + 1) * spacing[1];
930 double d = camera->GetDistance ();
931 camera->SetParallelScale (0.5 * yd);
932 camera->SetFocalPoint (xc, yc, 0.0);
933 camera->SetPosition (xc, yc, d);
934 }
935
936 //////////////////////////////////////////////////////////////////////////////////////////
937 void
adjustCamera(vtkRenderer * ren)938 pcl::visualization::ImageViewerInteractorStyle::adjustCamera (vtkRenderer *ren)
939 {
940 // Set up the background camera to fill the renderer with the image
941 vtkCamera* camera = ren->GetActiveCamera ();
942 int *wh = ren->GetRenderWindow ()->GetSize ();
943 double xc = static_cast<double> (wh[0]) / 2.0,
944 yc = static_cast<double> (wh[1]) / 2.0,
945 yd = static_cast<double> (wh[1]),
946 d = 3.346065;
947 camera->SetParallelScale (0.5 * yd);
948 camera->SetFocalPoint (xc, yc, 0.0);
949 camera->SetPosition (xc, yc, d);
950 }
951
952 //////////////////////////////////////////////////////////////////////////////////////////
953 void
OnLeftButtonDown()954 pcl::visualization::ImageViewerInteractorStyle::OnLeftButtonDown ()
955 {
956 int x = Interactor->GetEventPosition ()[0];
957 int y = Interactor->GetEventPosition ()[1];
958
959 FindPokedRenderer (x, y);
960 if (!CurrentRenderer)
961 return;
962
963 // Redefine this button to handle window/level
964 GrabFocus (this->EventCallbackCommand);
965 // If shift is held down, do nothing
966 if (!this->Interactor->GetShiftKey() && !this->Interactor->GetControlKey())
967 {
968 WindowLevelStartPosition[0] = x;
969 WindowLevelStartPosition[1] = y;
970 StartWindowLevel ();
971 }
972 else if (Interactor->GetShiftKey ())
973 return;
974 // If ctrl is held down in slicing mode, do nothing
975 else if (Interactor->GetControlKey ())
976 return;
977 // The rest of the button + key combinations remain the same
978 else
979 Superclass::OnLeftButtonDown ();
980 }
981
982 //////////////////////////////////////////////////////////////////////////////////////////
983 void
setWindowTitle(const std::string & name)984 pcl::visualization::ImageViewer::setWindowTitle (const std::string& name)
985 {
986 win_->SetWindowName (name.c_str ());
987 }
988
989 //////////////////////////////////////////////////////////////////////////////////////////
990 void
setPosition(int x,int y)991 pcl::visualization::ImageViewer::setPosition (int x, int y)
992 {
993 win_->SetPosition (x, y);
994 }
995
996 //////////////////////////////////////////////////////////////////////////////////////////
997 int*
getSize()998 pcl::visualization::ImageViewer::getSize ()
999 {
1000 return (win_->GetSize ());
1001 }
1002
1003 //////////////////////////////////////////////////////////////////////////////////////////
1004 void
setSize(int xw,int yw)1005 pcl::visualization::ImageViewer::setSize (int xw, int yw)
1006 {
1007 win_->SetSize (xw, yw);
1008 }
1009
1010 //////////////////////////////////////////////////////////////////////////////////////////
1011 namespace pcl
1012 {
1013 namespace visualization
1014 {
1015 vtkStandardNewMacro (ImageViewerInteractorStyle);
1016 }
1017 }
1018
1019