1 /*
2  * Software License Agreement (BSD License)
3  *
4  *  Point Cloud Library (PCL) - www.pointclouds.org
5  *  Copyright (c) 2010, 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 <fstream>
40 #include <list>
41 #include <pcl/common/angles.h>
42 #include <pcl/visualization/common/io.h>
43 #include <pcl/visualization/interactor_style.h>
44 #include <vtkVersion.h>
45 #include <vtkLODActor.h>
46 #include <vtkPolyData.h>
47 #include <vtkPolyDataMapper.h>
48 #include <vtkCellArray.h>
49 #include <vtkTextProperty.h>
50 #include <vtkAbstractPropPicker.h>
51 #include <vtkCamera.h>
52 #include <vtkRenderWindowInteractor.h>
53 #include <vtkScalarBarActor.h>
54 #include <vtkPNGWriter.h>
55 #include <vtkWindowToImageFilter.h>
56 #include <vtkRendererCollection.h>
57 #include <vtkActorCollection.h>
58 #include <vtkLegendScaleActor.h>
59 #include <vtkRenderer.h>
60 #include <vtkRenderWindow.h>
61 #include <vtkObjectFactory.h>
62 #include <vtkProperty.h>
63 #include <vtkPointData.h>
64 #include <vtkAssemblyPath.h>
65 #include <vtkAbstractPicker.h>
66 #include <vtkPointPicker.h>
67 #include <vtkAreaPicker.h>
68 
69 #include <boost/algorithm/string/classification.hpp> // for is_any_of
70 #include <boost/algorithm/string/split.hpp> // for split
71 #include <boost/filesystem.hpp> // for exists
72 
73 #if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
74 #include <pcl/visualization/vtk/vtkVertexBufferObjectMapper.h>
75 #endif
76 
77 #define ORIENT_MODE 0
78 #define SELECT_MODE 1
79 
80 //////////////////////////////////////////////////////////////////////////////////////////////
81 void
Initialize()82 pcl::visualization::PCLVisualizerInteractorStyle::Initialize ()
83 {
84   modifier_ = pcl::visualization::INTERACTOR_KB_MOD_ALT;
85   // Set windows size (width, height) to unknown (-1)
86   win_height_ = win_width_ = -1;
87   win_pos_x_ = win_pos_y_ = 0;
88   max_win_height_ = max_win_width_ = -1;
89 
90   // Grid is disabled by default
91   grid_enabled_ = false;
92   grid_actor_ = vtkSmartPointer<vtkLegendScaleActor>::New ();
93 
94   // LUT is disabled by default
95   lut_enabled_ = false;
96   lut_actor_ = vtkSmartPointer<vtkScalarBarActor>::New ();
97   lut_actor_->SetTitle ("");
98   lut_actor_->SetOrientationToHorizontal ();
99   lut_actor_->SetPosition (0.05, 0.01);
100   lut_actor_->SetWidth (0.9);
101   lut_actor_->SetHeight (0.1);
102   lut_actor_->SetNumberOfLabels (lut_actor_->GetNumberOfLabels () * 2);
103   vtkSmartPointer<vtkTextProperty> prop = lut_actor_->GetLabelTextProperty ();
104   prop->SetFontSize (10);
105   lut_actor_->SetLabelTextProperty (prop);
106   lut_actor_->SetTitleTextProperty (prop);
107 
108   // Create the image filter and PNG writer objects
109   wif_ = vtkSmartPointer<vtkWindowToImageFilter>::New ();
110   wif_->ReadFrontBufferOff ();
111   snapshot_writer_ = vtkSmartPointer<vtkPNGWriter>::New ();
112   snapshot_writer_->SetInputConnection (wif_->GetOutputPort ());
113 
114   init_ = true;
115 
116   stereo_anaglyph_mask_default_ = true;
117 
118   // Start in orient mode
119   Superclass::CurrentMode = ORIENT_MODE;
120 
121   // Add our own mouse callback before any user callback. Used for accurate point picking.
122   mouse_callback_ = vtkSmartPointer<pcl::visualization::PointPickingCallback>::New ();
123   AddObserver (vtkCommand::LeftButtonPressEvent, mouse_callback_);
124   AddObserver (vtkCommand::LeftButtonReleaseEvent, mouse_callback_);
125 }
126 
127 //////////////////////////////////////////////////////////////////////////////////////////////
128 void
saveScreenshot(const std::string & file)129 pcl::visualization::PCLVisualizerInteractorStyle::saveScreenshot (const std::string &file)
130 {
131   FindPokedRenderer (Interactor->GetEventPosition ()[0], Interactor->GetEventPosition ()[1]);
132   wif_->SetInput (Interactor->GetRenderWindow ());
133   wif_->Modified ();      // Update the WindowToImageFilter
134   snapshot_writer_->Modified ();
135   snapshot_writer_->SetFileName (file.c_str ());
136   snapshot_writer_->Write ();
137 }
138 
139 //////////////////////////////////////////////////////////////////////////////////////////////
140 bool
saveCameraParameters(const std::string & file)141 pcl::visualization::PCLVisualizerInteractorStyle::saveCameraParameters (const std::string &file)
142 {
143   FindPokedRenderer (Interactor->GetEventPosition ()[0], Interactor->GetEventPosition ()[1]);
144 
145   std::ofstream ofs_cam (file.c_str ());
146   if (!ofs_cam.is_open ())
147   {
148     return (false);
149   }
150 
151   vtkSmartPointer<vtkCamera> cam = Interactor->GetRenderWindow ()->GetRenderers ()->GetFirstRenderer ()->GetActiveCamera ();
152   double clip[2], focal[3], pos[3], view[3];
153   cam->GetClippingRange (clip);
154   cam->GetFocalPoint (focal);
155   cam->GetPosition (pos);
156   cam->GetViewUp (view);
157   int *win_pos = Interactor->GetRenderWindow ()->GetPosition ();
158   int *win_size = Interactor->GetRenderWindow ()->GetSize ();
159   ofs_cam << clip[0]  << "," << clip[1]  << "/" << focal[0] << "," << focal[1] << "," << focal[2] << "/" <<
160              pos[0]   << "," << pos[1]   << "," << pos[2]   << "/" << view[0]  << "," << view[1]  << "," << view[2] << "/" <<
161              cam->GetViewAngle () / 180.0 * M_PI  << "/" << win_size[0] << "," << win_size[1] << "/" << win_pos[0] << "," << win_pos[1]
162           << std::endl;
163   ofs_cam.close ();
164 
165   return (true);
166 }
167 
168 //////////////////////////////////////////////////////////////////////////////////////////////
169 void
getCameraParameters(pcl::visualization::Camera & camera,int viewport) const170 pcl::visualization::PCLVisualizerInteractorStyle::getCameraParameters (pcl::visualization::Camera &camera, int viewport) const
171 {
172   rens_->InitTraversal ();
173   vtkRenderer* renderer = nullptr;
174   int i = 0;
175   while ((renderer = rens_->GetNextItem ()))
176   {
177     if (viewport++ == i)
178     {
179       auto window = Interactor->GetRenderWindow ();
180       auto cam = renderer->GetActiveCamera ();
181       camera = Camera (*cam, *window);
182       break;
183     }
184   }
185 }
186 
187 //////////////////////////////////////////////////////////////////////////////////////////////
188 bool
loadCameraParameters(const std::string & file)189 pcl::visualization::PCLVisualizerInteractorStyle::loadCameraParameters (const std::string &file)
190 {
191   std::ifstream fs;
192   std::string line;
193   std::vector<std::string> camera;
194   bool ret;
195 
196   fs.open (file.c_str ());
197   if (!fs.is_open ())
198   {
199     return (false);
200   }
201   while (!fs.eof ())
202   {
203     getline (fs, line);
204     if (line.empty())
205       continue;
206 
207     boost::split (camera, line, boost::is_any_of ("/"), boost::token_compress_on);
208     break;
209   }
210   fs.close ();
211 
212   ret = getCameraParameters (camera);
213   if (ret)
214   {
215     camera_file_ = file;
216   }
217 
218   return (ret);
219 }
220 
221 /////////////////////////////////////////////////////////////////////////////////////////////
222 void
setCameraParameters(const Eigen::Matrix3f & intrinsics,const Eigen::Matrix4f & extrinsics,int viewport)223 pcl::visualization::PCLVisualizerInteractorStyle::setCameraParameters (const Eigen::Matrix3f &intrinsics,
224                                                                        const Eigen::Matrix4f &extrinsics,
225                                                                        int viewport)
226 {
227   // Position = extrinsic translation
228   Eigen::Vector3f pos_vec = extrinsics.block<3, 1> (0, 3);
229 
230   // Rotate the view vector
231   Eigen::Matrix3f rotation = extrinsics.block<3, 3> (0, 0);
232   Eigen::Vector3f y_axis (0.f, 1.f, 0.f);
233   Eigen::Vector3f up_vec (rotation * y_axis);
234 
235   // Compute the new focal point
236   Eigen::Vector3f z_axis (0.f, 0.f, 1.f);
237   Eigen::Vector3f focal_vec = pos_vec + rotation * z_axis;
238 
239   // Get the width and height of the image - assume the calibrated centers are at the center of the image
240   Eigen::Vector2i window_size;
241   window_size[0] = 2 * static_cast<int> (intrinsics (0, 2));
242   window_size[1] = 2 * static_cast<int> (intrinsics (1, 2));
243 
244   // Compute the vertical field of view based on the focal length and image height
245   double fovy = 2 * std::atan (window_size[1] / (2. * intrinsics (1, 1))) * 180.0 / M_PI;
246 
247 
248   rens_->InitTraversal ();
249   vtkRenderer* renderer = nullptr;
250   int i = 0;
251   while ((renderer = rens_->GetNextItem ()))
252   {
253     // Modify all renderer's cameras
254     if (viewport == 0 || viewport == i)
255     {
256       vtkSmartPointer<vtkCamera> cam = renderer->GetActiveCamera ();
257       cam->SetPosition (pos_vec[0], pos_vec[1], pos_vec[2]);
258       cam->SetFocalPoint (focal_vec[0], focal_vec[1], focal_vec[2]);
259       cam->SetViewUp (up_vec[0], up_vec[1], up_vec[2]);
260       cam->SetUseHorizontalViewAngle (0);
261       cam->SetViewAngle (fovy);
262       cam->SetClippingRange (0.01, 1000.01);
263       win_->SetSize (window_size[0], window_size[1]);
264     }
265     ++i;
266   }
267   win_->Render ();
268 }
269 
270 /////////////////////////////////////////////////////////////////////////////////////////////
271 void
setCameraParameters(const pcl::visualization::Camera & camera,int viewport)272 pcl::visualization::PCLVisualizerInteractorStyle::setCameraParameters (const pcl::visualization::Camera &camera, int viewport)
273 {
274   rens_->InitTraversal ();
275   vtkRenderer* renderer = nullptr;
276   int i = 0;
277   while ((renderer = rens_->GetNextItem ()))
278   {
279     // Modify all renderer's cameras
280     if (viewport == 0 || viewport == i)
281     {
282       vtkSmartPointer<vtkCamera> cam = renderer->GetActiveCamera ();
283       cam->SetPosition (camera.pos[0], camera.pos[1], camera.pos[2]);
284       cam->SetFocalPoint (camera.focal[0], camera.focal[1], camera.focal[2]);
285       cam->SetViewUp (camera.view[0], camera.view[1], camera.view[2]);
286       cam->SetClippingRange (camera.clip);
287       cam->SetUseHorizontalViewAngle (0);
288       cam->SetViewAngle (camera.fovy * 180.0 / M_PI);
289 
290       win_->SetSize (static_cast<int> (camera.window_size[0]),
291                      static_cast<int> (camera.window_size[1]));
292     }
293     ++i;
294   }
295 }
296 
297 //////////////////////////////////////////////////////////////////////////////////////////////
298 void
zoomIn()299 pcl::visualization::PCLVisualizerInteractorStyle::zoomIn ()
300 {
301   FindPokedRenderer (Interactor->GetEventPosition ()[0], Interactor->GetEventPosition ()[1]);
302   // Zoom in
303   StartDolly ();
304   double factor = 10.0 * 0.2 * .5;
305   Dolly (pow (1.1, factor));
306   EndDolly ();
307 }
308 
309 //////////////////////////////////////////////////////////////////////////////////////////////
310 void
zoomOut()311 pcl::visualization::PCLVisualizerInteractorStyle::zoomOut ()
312 {
313   FindPokedRenderer (Interactor->GetEventPosition ()[0], Interactor->GetEventPosition ()[1]);
314   // Zoom out
315   StartDolly ();
316   double factor = 10.0 * -0.2 * .5;
317   Dolly (pow (1.1, factor));
318   EndDolly ();
319 }
320 
321 //////////////////////////////////////////////////////////////////////////////////////////////
322 bool
getCameraParameters(const std::vector<std::string> & camera)323 pcl::visualization::PCLVisualizerInteractorStyle::getCameraParameters (const std::vector<std::string> &camera)
324 {
325   pcl::visualization::Camera camera_temp;
326 
327   // look for '/' as a separator
328   if (camera.size () != 7)
329   {
330     pcl::console::print_error ("[PCLVisualizer::getCameraParameters] Camera parameters given, but with an invalid number of options (%lu vs 7)!\n", static_cast<unsigned long> (camera.size ()));
331     return (false);
332   }
333 
334   std::string clip_str  = camera.at (0);
335   std::string focal_str = camera.at (1);
336   std::string pos_str   = camera.at (2);
337   std::string view_str  = camera.at (3);
338   std::string fovy_str  = camera.at (4);
339   std::string win_size_str = camera.at (5);
340   std::string win_pos_str  = camera.at (6);
341 
342   // Get each camera setting separately and parse for ','
343   std::vector<std::string> clip_st;
344   boost::split (clip_st, clip_str, boost::is_any_of (","), boost::token_compress_on);
345   if (clip_st.size () != 2)
346   {
347     pcl::console::print_error ("[PCLVisualizer::getCameraParameters] Invalid parameters given for camera clipping angle!\n");
348     return (false);
349   }
350   camera_temp.clip[0] = atof (clip_st.at (0).c_str ());
351   camera_temp.clip[1] = atof (clip_st.at (1).c_str ());
352 
353   std::vector<std::string> focal_st;
354   boost::split (focal_st, focal_str, boost::is_any_of (","), boost::token_compress_on);
355   if (focal_st.size () != 3)
356   {
357     pcl::console::print_error ("[PCLVisualizer::getCameraParameters] Invalid parameters given for camera focal point!\n");
358     return (false);
359   }
360   camera_temp.focal[0] = atof (focal_st.at (0).c_str ());
361   camera_temp.focal[1] = atof (focal_st.at (1).c_str ());
362   camera_temp.focal[2] = atof (focal_st.at (2).c_str ());
363 
364   std::vector<std::string> pos_st;
365   boost::split (pos_st, pos_str, boost::is_any_of (","), boost::token_compress_on);
366   if (pos_st.size () != 3)
367   {
368     pcl::console::print_error ("[PCLVisualizer::getCameraParameters] Invalid parameters given for camera position!\n");
369     return (false);
370   }
371   camera_temp.pos[0] = atof (pos_st.at (0).c_str ());
372   camera_temp.pos[1] = atof (pos_st.at (1).c_str ());
373   camera_temp.pos[2] = atof (pos_st.at (2).c_str ());
374 
375   std::vector<std::string> view_st;
376   boost::split (view_st, view_str, boost::is_any_of (","), boost::token_compress_on);
377   if (view_st.size () != 3)
378   {
379     pcl::console::print_error ("[PCLVisualizer::getCameraParameters] Invalid parameters given for camera viewup!\n");
380     return (false);
381   }
382   camera_temp.view[0] = atof (view_st.at (0).c_str ());
383   camera_temp.view[1] = atof (view_st.at (1).c_str ());
384   camera_temp.view[2] = atof (view_st.at (2).c_str ());
385 
386   std::vector<std::string> fovy_size_st;
387   boost::split (fovy_size_st, fovy_str, boost::is_any_of (","), boost::token_compress_on);
388   if (fovy_size_st.size () != 1)
389   {
390     pcl::console::print_error ("[PCLVisualizer::getCameraParameters] Invalid parameters given for field of view angle!\n");
391     return (false);
392   }
393   camera_temp.fovy = atof (fovy_size_st.at (0).c_str ());
394 
395   std::vector<std::string> win_size_st;
396   boost::split (win_size_st, win_size_str, boost::is_any_of (","), boost::token_compress_on);
397   if (win_size_st.size () != 2)
398   {
399     pcl::console::print_error ("[PCLVisualizer::getCameraParameters] Invalid parameters given for window size!\n");
400     return (false);
401   }
402   camera_temp.window_size[0] = atof (win_size_st.at (0).c_str ());
403   camera_temp.window_size[1] = atof (win_size_st.at (1).c_str ());
404 
405   std::vector<std::string> win_pos_st;
406   boost::split (win_pos_st, win_pos_str, boost::is_any_of (","), boost::token_compress_on);
407   if (win_pos_st.size () != 2)
408   {
409     pcl::console::print_error ("[PCLVisualizer::getCameraParameters] Invalid parameters given for window position!\n");
410     return (false);
411   }
412   camera_temp.window_pos[0] = atof (win_pos_st.at (0).c_str ());
413   camera_temp.window_pos[1] = atof (win_pos_st.at (1).c_str ());
414 
415   setCameraParameters (camera_temp);
416 
417   return (true);
418 }
419 
420 //////////////////////////////////////////////////////////////////////////////////////////////
421 void
OnChar()422 pcl::visualization::PCLVisualizerInteractorStyle::OnChar ()
423 {
424   // Make sure we ignore the same events we handle in OnKeyDown to avoid calling things twice
425   FindPokedRenderer (Interactor->GetEventPosition ()[0], Interactor->GetEventPosition ()[1]);
426   if (Interactor->GetKeyCode () >= '0' && Interactor->GetKeyCode () <= '9')
427     return;
428   std::string key (Interactor->GetKeySym ());
429   if (key.find ("XF86ZoomIn") != std::string::npos)
430     zoomIn ();
431   else if (key.find ("XF86ZoomOut") != std::string::npos)
432     zoomOut ();
433 
434   bool keymod = false;
435   switch (modifier_)
436   {
437     case INTERACTOR_KB_MOD_ALT:
438     {
439       keymod = Interactor->GetAltKey ();
440       break;
441     }
442     case INTERACTOR_KB_MOD_CTRL:
443     {
444       keymod = Interactor->GetControlKey ();
445       break;
446     }
447     case INTERACTOR_KB_MOD_SHIFT:
448     {
449       keymod = Interactor->GetShiftKey ();
450       break;
451     }
452   }
453 
454   switch (Interactor->GetKeyCode ())
455   {
456     // All of the options below simply exit
457     case 'h': case 'H':
458     case 'l': case 'L':
459     case 'p': case 'P':
460     case 'j': case 'J':
461     case 'c': case 'C':
462     case 43:        // KEY_PLUS
463     case 45:        // KEY_MINUS
464     case 'f': case 'F':
465     case 'g': case 'G':
466     case 'o': case 'O':
467     case 'u': case 'U':
468     case 'q': case 'Q':
469     case 'x': case 'X':
470     case 'r': case 'R':
471     {
472       break;
473     }
474     // S have special !ALT case
475     case 's': case 'S':
476     {
477       if (!keymod)
478         Superclass::OnChar ();
479       break;
480     }
481     default:
482     {
483       Superclass::OnChar ();
484       break;
485     }
486   }
487 }
488 
489 //////////////////////////////////////////////////////////////////////////////////////////////
490 boost::signals2::connection
registerMouseCallback(std::function<void (const pcl::visualization::MouseEvent &)> callback)491 pcl::visualization::PCLVisualizerInteractorStyle::registerMouseCallback (std::function<void (const pcl::visualization::MouseEvent&)> callback)
492 {
493   return (mouse_signal_.connect (callback));
494 }
495 
496 //////////////////////////////////////////////////////////////////////////////////////////////
497 boost::signals2::connection
registerKeyboardCallback(std::function<void (const pcl::visualization::KeyboardEvent &)> callback)498 pcl::visualization::PCLVisualizerInteractorStyle::registerKeyboardCallback (std::function<void (const pcl::visualization::KeyboardEvent&)> callback)
499 {
500   return (keyboard_signal_.connect (callback));
501 }
502 
503 //////////////////////////////////////////////////////////////////////////////////////////////
504 boost::signals2::connection
registerPointPickingCallback(std::function<void (const pcl::visualization::PointPickingEvent &)> callback)505 pcl::visualization::PCLVisualizerInteractorStyle::registerPointPickingCallback (std::function<void (const pcl::visualization::PointPickingEvent&)> callback)
506 {
507   return (point_picking_signal_.connect (callback));
508 }
509 
510 //////////////////////////////////////////////////////////////////////////////////////////////
511 boost::signals2::connection
registerAreaPickingCallback(std::function<void (const pcl::visualization::AreaPickingEvent &)> callback)512 pcl::visualization::PCLVisualizerInteractorStyle::registerAreaPickingCallback (std::function<void (const pcl::visualization::AreaPickingEvent&)> callback)
513 {
514   return (area_picking_signal_.connect (callback));
515 }
516 
517 //////////////////////////////////////////////////////////////////////////////////////////////
518 void
OnKeyDown()519 pcl::visualization::PCLVisualizerInteractorStyle::OnKeyDown ()
520 {
521   if (!init_)
522   {
523     pcl::console::print_error ("[PCLVisualizerInteractorStyle] Interactor style not initialized. Please call Initialize () before continuing.\n");
524     return;
525   }
526 
527   if (!rens_)
528   {
529     pcl::console::print_error ("[PCLVisualizerInteractorStyle] No renderer collection given! Use SetRendererCollection () before continuing.\n");
530     return;
531   }
532 
533   FindPokedRenderer (Interactor->GetEventPosition ()[0], Interactor->GetEventPosition ()[1]);
534 
535   if (!wif_->GetInput ())
536   {
537     wif_->SetInput (Interactor->GetRenderWindow ());
538     wif_->Modified ();
539     snapshot_writer_->Modified ();
540   }
541 
542   // Save the initial windows width/height
543   if (win_height_ == -1 || win_width_ == -1)
544   {
545     int *win_size = Interactor->GetRenderWindow ()->GetSize ();
546     win_height_ = win_size[0];
547     win_width_  = win_size[1];
548   }
549 
550   // Get the status of special keys (Cltr+Alt+Shift)
551   bool shift = Interactor->GetShiftKey   ();
552   bool ctrl  = Interactor->GetControlKey ();
553   bool alt   = Interactor->GetAltKey ();
554 
555   bool keymod = false;
556   switch (modifier_)
557   {
558     case INTERACTOR_KB_MOD_ALT:
559     {
560       keymod = alt;
561       break;
562     }
563     case INTERACTOR_KB_MOD_CTRL:
564     {
565       keymod = ctrl;
566       break;
567     }
568     case INTERACTOR_KB_MOD_SHIFT:
569     {
570       keymod = shift;
571       break;
572     }
573   }
574 
575   // ---[ Check the rest of the key codes
576 
577   // Save camera parameters
578   if ((Interactor->GetKeySym ()[0] == 'S' || Interactor->GetKeySym ()[0] == 's') && ctrl && !alt && !shift)
579   {
580     if (camera_file_.empty ())
581     {
582       getCameraParameters (camera_);
583       camera_saved_ = true;
584       pcl::console::print_info ("Camera parameters saved, you can press CTRL + R to restore.\n");
585     }
586     else
587     {
588       if (saveCameraParameters (camera_file_))
589       {
590         pcl::console::print_info ("Save camera parameters to %s, you can press CTRL + R to restore.\n", camera_file_.c_str ());
591       }
592       else
593       {
594         pcl::console::print_error ("[PCLVisualizerInteractorStyle] Can't save camera parameters to file: %s.\n", camera_file_.c_str ());
595       }
596     }
597   }
598 
599   // Restore camera parameters
600   if ((Interactor->GetKeySym ()[0] == 'R' || Interactor->GetKeySym ()[0] == 'r') && ctrl && !alt && !shift)
601   {
602     if (camera_file_.empty ())
603     {
604       if (camera_saved_)
605       {
606         setCameraParameters (camera_);
607         pcl::console::print_info ("Camera parameters restored.\n");
608       }
609       else
610       {
611         pcl::console::print_info ("No camera parameters saved for restoring.\n");
612       }
613     }
614     else
615     {
616       if (boost::filesystem::exists (camera_file_))
617       {
618         if (loadCameraParameters (camera_file_))
619         {
620           pcl::console::print_info ("Restore camera parameters from %s.\n", camera_file_.c_str ());
621         }
622         else
623         {
624           pcl::console::print_error ("Can't restore camera parameters from file: %s.\n", camera_file_.c_str ());
625         }
626       }
627       else
628       {
629         pcl::console::print_info ("No camera parameters saved in %s for restoring.\n", camera_file_.c_str ());
630       }
631     }
632   }
633 
634   // Switch between point color/geometry handlers
635   if (Interactor->GetKeySym () && Interactor->GetKeySym ()[0]  >= '0' && Interactor->GetKeySym ()[0] <= '9')
636   {
637     int index = Interactor->GetKeySym ()[0] - '0' - 1;
638     if (index == -1) index = 9;
639 
640     // Add 10 more for CTRL+0..9 keys
641     if (ctrl)
642       index += 10;
643 
644     // Geometry ?
645     if (keymod)
646     {
647       for (auto &actor : *cloud_actors_)
648       {
649         CloudActor &act = actor.second;
650         if (index >= static_cast<int> (act.geometry_handlers.size ()))
651           continue;
652 
653         // Save the geometry handler index for later usage
654         act.geometry_handler_index_ = index;
655 
656         // Create the new geometry
657         PointCloudGeometryHandler<pcl::PCLPointCloud2>::ConstPtr geometry_handler = act.geometry_handlers[index];
658 
659         // Use the handler to obtain the geometry
660         vtkSmartPointer<vtkPoints> points;
661         geometry_handler->getGeometry (points);
662 
663         // Set the vertices
664         vtkSmartPointer<vtkCellArray> vertices = vtkSmartPointer<vtkCellArray>::New ();
665         for (vtkIdType i = 0; i < static_cast<vtkIdType> (points->GetNumberOfPoints ()); ++i)
666           vertices->InsertNextCell (static_cast<vtkIdType>(1), &i);
667 
668         // Create the data
669         vtkSmartPointer<vtkPolyData> data = vtkSmartPointer<vtkPolyData>::New ();
670         data->SetPoints (points);
671         data->SetVerts (vertices);
672         // Modify the mapper
673 #if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
674         if (use_vbos_)
675         {
676           vtkVertexBufferObjectMapper* mapper = static_cast<vtkVertexBufferObjectMapper*>(act.actor->GetMapper ());
677           mapper->SetInput (data);
678           // Modify the actor
679           act.actor->SetMapper (mapper);
680         }
681         else
682 #endif
683         {
684           vtkPolyDataMapper* mapper = static_cast<vtkPolyDataMapper*>(act.actor->GetMapper ());
685           mapper->SetInputData (data);
686           // Modify the actor
687           act.actor->SetMapper (mapper);
688         }
689         act.actor->Modified ();
690       }
691     }
692     else
693     {
694       for (auto &actor : *cloud_actors_)
695       {
696         CloudActor &act = actor.second;
697         // Check for out of bounds
698         if (index >= static_cast<int> (act.color_handlers.size ()))
699           continue;
700 
701         // Save the color handler index for later usage
702         act.color_handler_index_ = index;
703 
704         // Get the new color
705         PointCloudColorHandler<pcl::PCLPointCloud2>::ConstPtr color_handler = act.color_handlers[index];
706 
707         auto scalars = color_handler->getColor ();
708         double minmax[2];
709         scalars->GetRange (minmax);
710         // Update the data
711         vtkPolyData *data = static_cast<vtkPolyData*>(act.actor->GetMapper ()->GetInput ());
712         data->GetPointData ()->SetScalars (scalars);
713         // Modify the mapper
714 #if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
715         if (use_vbos_)
716         {
717           vtkVertexBufferObjectMapper* mapper = static_cast<vtkVertexBufferObjectMapper*>(act.actor->GetMapper ());
718           mapper->SetScalarRange (minmax);
719           mapper->SetScalarModeToUsePointData ();
720           mapper->SetInput (data);
721           // Modify the actor
722           act.actor->SetMapper (mapper);
723         }
724         else
725 #endif
726         {
727           vtkPolyDataMapper* mapper = static_cast<vtkPolyDataMapper*>(act.actor->GetMapper ());
728           mapper->SetScalarRange (minmax);
729           mapper->SetScalarModeToUsePointData ();
730           mapper->SetInputData (data);
731           // Modify the actor
732           act.actor->SetMapper (mapper);
733         }
734         act.actor->Modified ();
735       }
736     }
737 
738     Interactor->Render ();
739     return;
740   }
741 
742   std::string key (Interactor->GetKeySym ());
743   if (key.find ("XF86ZoomIn") != std::string::npos)
744     zoomIn ();
745   else if (key.find ("XF86ZoomOut") != std::string::npos)
746     zoomOut ();
747 
748   switch (Interactor->GetKeyCode ())
749   {
750     case 'h': case 'H':
751     {
752       pcl::console::print_info ("| Help:\n"
753                   "-------\n"
754                   "          p, P   : switch to a point-based representation\n"
755                   "          w, W   : switch to a wireframe-based representation (where available)\n"
756                   "          s, S   : switch to a surface-based representation (where available)\n"
757                   "\n"
758                   "          j, J   : take a .PNG snapshot of the current window view\n"
759                   "          c, C   : display current camera/window parameters\n"
760                   "          f, F   : fly to point mode\n"
761                   "\n"
762                   "          e, E   : exit the interactor\n"
763                   "          q, Q   : stop and call VTK's TerminateApp\n"
764                   "\n"
765                   "           +/-   : increment/decrement overall point size\n"
766                   "     +/- [+ ALT] : zoom in/out \n"
767                   "\n"
768                   "          g, G   : display scale grid (on/off)\n"
769                   "          u, U   : display lookup table (on/off)\n"
770                   "\n"
771                   "    o, O         : switch between perspective/parallel projection (default = perspective)\n"
772                   "    r, R [+ ALT] : reset camera [to viewpoint = {0, 0, 0} -> center_{x, y, z}]\n"
773                   "    CTRL + s, S  : save camera parameters\n"
774                   "    CTRL + r, R  : restore camera parameters\n"
775                   "\n"
776                   "    ALT + s, S   : turn stereo mode on/off\n"
777                   "    ALT + f, F   : switch between maximized window mode and original size\n"
778                   "\n"
779                   "          l, L           : list all available geometric and color handlers for the current actor map\n"
780                   "    ALT + 0..9 [+ CTRL]  : switch between different geometric handlers (where available)\n"
781                   "          0..9 [+ CTRL]  : switch between different color handlers (where available)\n"
782                   "\n"
783                   "    SHIFT + left click   : select a point (start with -use_point_picking)\n"
784                   "\n"
785                   "          x, X   : toggle rubber band selection mode for left mouse button\n"
786           );
787       break;
788     }
789 
790     // Get the list of available handlers
791     case 'l': case 'L':
792     {
793       // Iterate over the entire actors list and extract the geomotry/color handlers list
794       for (auto &actor : *cloud_actors_)
795       {
796         std::list<std::string> geometry_handlers_list, color_handlers_list;
797         CloudActor *act = &actor.second;
798         for (auto &geometry_handler : act->geometry_handlers)
799           geometry_handlers_list.push_back (geometry_handler->getFieldName ());
800         for (auto &color_handler : act->color_handlers)
801           color_handlers_list.push_back (color_handler->getFieldName ());
802 
803         if (!geometry_handlers_list.empty ())
804         {
805           int i = 0;
806           pcl::console::print_info ("List of available geometry handlers for actor "); pcl::console::print_value ("%s: ", actor.first.c_str ());
807           for (auto &git : geometry_handlers_list)
808             pcl::console::print_value ("%s(%d) ", git.c_str (), ++i);
809           pcl::console::print_info ("\n");
810         }
811         if (!color_handlers_list.empty ())
812         {
813           int i = 0;
814           pcl::console::print_info ("List of available color handlers for actor "); pcl::console::print_value ("%s: ", actor.first.c_str ());
815           for (auto &cit : color_handlers_list)
816             pcl::console::print_value ("%s(%d) ", cit.c_str (), ++i);
817           pcl::console::print_info ("\n");
818         }
819       }
820 
821       break;
822     }
823 
824     // Switch representation to points
825     case 'p': case 'P':
826     {
827       vtkSmartPointer<vtkActorCollection> ac = CurrentRenderer->GetActors ();
828       vtkCollectionSimpleIterator ait;
829       for (ac->InitTraversal (ait); vtkActor* actor = ac->GetNextActor (ait); )
830       {
831         for (actor->InitPathTraversal (); vtkAssemblyPath* path = actor->GetNextPath (); )
832         {
833           vtkSmartPointer<vtkActor> apart = reinterpret_cast <vtkActor*> (path->GetLastNode ()->GetViewProp ());
834           apart->GetProperty ()->SetRepresentationToPoints ();
835         }
836       }
837       break;
838     }
839 
840     // Switch representation to wireframe (override default behavior)
841     case 'w': case 'W':
842     {
843       vtkSmartPointer<vtkActorCollection> ac = CurrentRenderer->GetActors ();
844       vtkCollectionSimpleIterator ait;
845       for (ac->InitTraversal (ait); vtkActor* actor = ac->GetNextActor (ait); )
846       {
847         for (actor->InitPathTraversal (); vtkAssemblyPath* path = actor->GetNextPath (); )
848         {
849           vtkSmartPointer<vtkActor> apart = reinterpret_cast <vtkActor*> (path->GetLastNode ()->GetViewProp ());
850           apart->GetProperty ()->SetRepresentationToWireframe ();
851           apart->GetProperty ()->SetLighting (false);
852         }
853       }
854       break;
855     }
856 
857     // Save a PNG snapshot with the current screen
858     case 'j': case 'J':
859     {
860       char cam_fn[80], snapshot_fn[80];
861       unsigned t = static_cast<unsigned> (time (nullptr));
862       sprintf (snapshot_fn, "screenshot-%d.png" , t);
863       saveScreenshot (snapshot_fn);
864 
865       sprintf (cam_fn, "screenshot-%d.cam", t);
866       saveCameraParameters (cam_fn);
867 
868       pcl::console::print_info ("Screenshot (%s) and camera information (%s) successfully captured.\n", snapshot_fn, cam_fn);
869       break;
870     }
871     // display current camera settings/parameters
872     case 'c': case 'C':
873     {
874       Camera cam (*CurrentRenderer->GetActiveCamera (), *Interactor->GetRenderWindow ());
875       std::cerr <<  "Clipping plane [near,far] "  << cam.clip[0] << ", " << cam.clip[1] << std::endl <<
876                     "Focal point [x,y,z] " << cam.focal[0] << ", " << cam.focal[1] << ", " << cam.focal[2] << std::endl <<
877                     "Position [x,y,z] " << cam.pos[0] << ", " << cam.pos[1] << ", " << cam.pos[2] << std::endl <<
878                     "View up [x,y,z] " << cam.view[0]  << ", " << cam.view[1]  << ", " << cam.view[2] << std::endl <<
879                     "Camera view angle [degrees] " << rad2deg (cam.fovy) << std::endl <<
880                     "Window size [x,y] " << cam.window_size[0] << ", " << cam.window_size[1] << std::endl <<
881                     "Window position [x,y] " << cam.window_pos[0] << ", " << cam.window_pos[1] << std::endl;
882       break;
883     }
884     case '=':
885     {
886       zoomIn();
887       break;
888     }
889     case 43:        // KEY_PLUS
890     {
891       if(alt)
892         zoomIn ();
893       else
894       {
895         vtkSmartPointer<vtkActorCollection> ac = CurrentRenderer->GetActors ();
896         vtkCollectionSimpleIterator ait;
897         for (ac->InitTraversal (ait); vtkActor* actor = ac->GetNextActor (ait); )
898         {
899           for (actor->InitPathTraversal (); vtkAssemblyPath* path = actor->GetNextPath (); )
900           {
901             vtkSmartPointer<vtkActor> apart = reinterpret_cast <vtkActor*> (path->GetLastNode ()->GetViewProp ());
902             float psize = apart->GetProperty ()->GetPointSize ();
903             if (psize < 63.0f)
904               apart->GetProperty ()->SetPointSize (psize + 1.0f);
905           }
906         }
907       }
908       break;
909     }
910     case 45:        // KEY_MINUS
911     {
912       if(alt)
913         zoomOut ();
914       else
915       {
916         vtkSmartPointer<vtkActorCollection> ac = CurrentRenderer->GetActors ();
917         vtkCollectionSimpleIterator ait;
918         for (ac->InitTraversal (ait); vtkActor* actor = ac->GetNextActor (ait); )
919         {
920           for (actor->InitPathTraversal (); vtkAssemblyPath* path = actor->GetNextPath (); )
921           {
922             vtkSmartPointer<vtkActor> apart = static_cast<vtkActor*> (path->GetLastNode ()->GetViewProp ());
923             float psize = apart->GetProperty ()->GetPointSize ();
924             if (psize > 1.0f)
925               apart->GetProperty ()->SetPointSize (psize - 1.0f);
926           }
927         }
928       }
929       break;
930     }
931     // Switch between maximize and original window size
932     case 'f': case 'F':
933     {
934       if (keymod)
935       {
936         // Get screen size
937         int *temp = Interactor->GetRenderWindow ()->GetScreenSize ();
938         int scr_size[2]; scr_size[0] = temp[0]; scr_size[1] = temp[1];
939 
940         // Get window size
941         temp = Interactor->GetRenderWindow ()->GetSize ();
942         int win_size[2]; win_size[0] = temp[0]; win_size[1] = temp[1];
943         // Is window size = max?
944         if (win_size[0] == max_win_height_ && win_size[1] == max_win_width_)
945         {
946           // Set the previously saved 'current' window size
947           Interactor->GetRenderWindow ()->SetSize (win_height_, win_width_);
948           // Set the previously saved window position
949           Interactor->GetRenderWindow ()->SetPosition (win_pos_x_, win_pos_y_);
950           Interactor->GetRenderWindow ()->Render ();
951           Interactor->Render ();
952         }
953         // Set to max
954         else
955         {
956           int *win_pos = Interactor->GetRenderWindow ()->GetPosition ();
957           // Save the current window position
958           win_pos_x_  = win_pos[0];
959           win_pos_y_  = win_pos[1];
960           // Save the current window size
961           win_height_ = win_size[0];
962           win_width_  = win_size[1];
963           // Set the maximum window size
964           Interactor->GetRenderWindow ()->SetSize (scr_size[0], scr_size[1]);
965           Interactor->GetRenderWindow ()->Render ();
966           Interactor->Render ();
967           int *win_size = Interactor->GetRenderWindow ()->GetSize ();
968           // Save the maximum window size
969           max_win_height_ = win_size[0];
970           max_win_width_  = win_size[1];
971         }
972       }
973       else
974       {
975         AnimState = VTKIS_ANIM_ON;
976         vtkAssemblyPath *path = nullptr;
977         Interactor->GetPicker ()->Pick (Interactor->GetEventPosition ()[0], Interactor->GetEventPosition ()[1], 0.0, CurrentRenderer);
978         vtkAbstractPropPicker *picker;
979         if ((picker = vtkAbstractPropPicker::SafeDownCast (Interactor->GetPicker ())))
980           path = picker->GetPath ();
981         if (path)
982           Interactor->FlyTo (CurrentRenderer, picker->GetPickPosition ());
983         AnimState = VTKIS_ANIM_OFF;
984       }
985       break;
986     }
987     // 's'/'S' w/out ALT
988     case 's': case 'S':
989     {
990       if (keymod)
991       {
992         int stereo_render = Interactor->GetRenderWindow ()->GetStereoRender ();
993         if (!stereo_render)
994         {
995           if (stereo_anaglyph_mask_default_)
996           {
997             Interactor->GetRenderWindow ()->SetAnaglyphColorMask (4, 3);
998             stereo_anaglyph_mask_default_ = false;
999           }
1000           else
1001           {
1002             Interactor->GetRenderWindow ()->SetAnaglyphColorMask (2, 5);
1003             stereo_anaglyph_mask_default_ = true;
1004           }
1005         }
1006         Interactor->GetRenderWindow ()->SetStereoRender (!stereo_render);
1007         Interactor->GetRenderWindow ()->Render ();
1008         Interactor->Render ();
1009       }
1010       else
1011       {
1012         Superclass::OnKeyDown();
1013         vtkSmartPointer<vtkActorCollection> ac = CurrentRenderer->GetActors();
1014         vtkCollectionSimpleIterator ait;
1015         for (ac->InitTraversal(ait); vtkActor* actor = ac->GetNextActor(ait);)
1016         {
1017           for (actor->InitPathTraversal(); vtkAssemblyPath* path = actor->GetNextPath();)
1018           {
1019             vtkSmartPointer<vtkActor> apart = reinterpret_cast<vtkActor*>(path->GetLastNode()->GetViewProp());
1020             apart->GetProperty()->SetRepresentationToSurface();
1021             apart->GetProperty()->SetLighting(true);
1022           }
1023         }
1024       }
1025       break;
1026     }
1027 
1028     // Display a grid/scale over the screen
1029     case 'g': case 'G':
1030     {
1031       if (!grid_enabled_)
1032       {
1033         grid_actor_->TopAxisVisibilityOn ();
1034         CurrentRenderer->AddViewProp (grid_actor_);
1035         grid_enabled_ = true;
1036       }
1037       else
1038       {
1039         CurrentRenderer->RemoveViewProp (grid_actor_);
1040         grid_enabled_ = false;
1041       }
1042       break;
1043     }
1044 
1045     case 'o': case 'O':
1046     {
1047       vtkSmartPointer<vtkCamera> cam = CurrentRenderer->GetActiveCamera ();
1048       int flag = cam->GetParallelProjection ();
1049       cam->SetParallelProjection (!flag);
1050 
1051       CurrentRenderer->SetActiveCamera (cam);
1052       CurrentRenderer->Render ();
1053       break;
1054     }
1055     // Display a LUT actor on screen
1056     case 'u': case 'U':
1057     {
1058       updateLookUpTableDisplay (true);
1059       break;
1060     }
1061 
1062     // Overwrite the camera reset
1063     case 'r': case 'R':
1064     {
1065       if (!keymod)
1066       {
1067         FindPokedRenderer(Interactor->GetEventPosition ()[0], Interactor->GetEventPosition ()[1]);
1068         if(CurrentRenderer)
1069           CurrentRenderer->ResetCamera ();
1070         else
1071           PCL_WARN ("no current renderer on the interactor style.\n");
1072 
1073         CurrentRenderer->Render ();
1074         break;
1075       }
1076 
1077       vtkSmartPointer<vtkCamera> cam = CurrentRenderer->GetActiveCamera ();
1078 
1079       static CloudActorMap::iterator it = cloud_actors_->begin ();
1080       // it might be that some actors don't have a valid transformation set -> we skip them to avoid a seg fault.
1081       bool found_transformation = false;
1082       for (unsigned idx = 0; idx < cloud_actors_->size (); ++idx, ++it)
1083       {
1084         if (it == cloud_actors_->end ())
1085           it = cloud_actors_->begin ();
1086 
1087         const CloudActor& actor = it->second;
1088         if (actor.viewpoint_transformation_.GetPointer ())
1089         {
1090           found_transformation = true;
1091           break;
1092         }
1093       }
1094 
1095       // if a valid transformation was found, use it otherwise fall back to default view point.
1096       if (found_transformation)
1097       {
1098         const CloudActor& actor = it->second;
1099         cam->SetPosition (actor.viewpoint_transformation_->GetElement (0, 3),
1100                           actor.viewpoint_transformation_->GetElement (1, 3),
1101                           actor.viewpoint_transformation_->GetElement (2, 3));
1102 
1103         cam->SetFocalPoint (actor.viewpoint_transformation_->GetElement (0, 3) - actor.viewpoint_transformation_->GetElement (0, 2),
1104                             actor.viewpoint_transformation_->GetElement (1, 3) - actor.viewpoint_transformation_->GetElement (1, 2),
1105                             actor.viewpoint_transformation_->GetElement (2, 3) - actor.viewpoint_transformation_->GetElement (2, 2));
1106 
1107         cam->SetViewUp (actor.viewpoint_transformation_->GetElement (0, 1),
1108                         actor.viewpoint_transformation_->GetElement (1, 1),
1109                         actor.viewpoint_transformation_->GetElement (2, 1));
1110       }
1111       else
1112       {
1113         cam->SetPosition (0, 0, 0);
1114         cam->SetFocalPoint (0, 0, 1);
1115         cam->SetViewUp (0, -1, 0);
1116       }
1117 
1118       // go to the next actor for the next key-press event.
1119       if (it != cloud_actors_->end ())
1120         ++it;
1121       else
1122         it = cloud_actors_->begin ();
1123 
1124       CurrentRenderer->SetActiveCamera (cam);
1125       CurrentRenderer->ResetCameraClippingRange ();
1126       CurrentRenderer->Render ();
1127       break;
1128     }
1129 
1130     case 'x' : case 'X' :
1131     {
1132       CurrentMode = (CurrentMode == ORIENT_MODE) ? SELECT_MODE : ORIENT_MODE;
1133       if (CurrentMode == SELECT_MODE)
1134       {
1135         // Save the point picker
1136         point_picker_ = static_cast<vtkPointPicker*> (Interactor->GetPicker ());
1137         // Switch for an area picker
1138         vtkSmartPointer<vtkAreaPicker> area_picker = vtkSmartPointer<vtkAreaPicker>::New ();
1139         Interactor->SetPicker (area_picker);
1140       }
1141       else
1142       {
1143         // Restore point picker
1144         Interactor->SetPicker (point_picker_);
1145       }
1146       break;
1147     }
1148 
1149     case 'q': case 'Q':
1150     {
1151       Interactor->ExitCallback ();
1152       return;
1153     }
1154     default:
1155     {
1156       Superclass::OnKeyDown ();
1157       break;
1158     }
1159   }
1160 
1161   KeyboardEvent event (true, Interactor->GetKeySym (), Interactor->GetKeyCode (), Interactor->GetAltKey (), Interactor->GetControlKey (), Interactor->GetShiftKey ());
1162   keyboard_signal_ (event);
1163 
1164   rens_->Render ();
1165   Interactor->Render ();
1166 }
1167 
1168 //////////////////////////////////////////////////////////////////////////////////////////////
1169 // Update the look up table displayed when 'u' is pressed
1170 void
updateLookUpTableDisplay(bool add_lut)1171 pcl::visualization::PCLVisualizerInteractorStyle::updateLookUpTableDisplay (bool add_lut)
1172 {
1173   bool actor_found = false;
1174 
1175   if (!lut_enabled_ && !add_lut)
1176     return;
1177 
1178   if (!lut_actor_id_.empty())  // Search if provided actor id is in CloudActorMap or ShapeActorMap
1179   {
1180     auto am_it = cloud_actors_->find (lut_actor_id_);
1181     if (am_it == cloud_actors_->end ())
1182     {
1183       auto sm_it = shape_actors_->find (lut_actor_id_);
1184       if (sm_it == shape_actors_->end ())
1185       {
1186         PCL_WARN ("[updateLookUpTableDisplay] Could not find any actor with id <%s>!\n", lut_actor_id_.c_str ());
1187         if (lut_enabled_)
1188         {  // Remove LUT and exit
1189           CurrentRenderer->RemoveActor (lut_actor_);
1190           lut_enabled_ = false;
1191         }
1192         return;
1193       }
1194 
1195       // ShapeActor found
1196       vtkSmartPointer<vtkProp> *act = & (*sm_it).second;
1197       vtkSmartPointer<vtkActor> actor = vtkActor::SafeDownCast (*act);
1198       if (!actor || !actor->GetMapper ()->GetInput ()->GetPointData ()->GetScalars ())
1199       {
1200         PCL_WARN ("[updateLookUpTableDisplay] id <%s> does not hold any color information!\n", lut_actor_id_.c_str ());
1201         if (lut_enabled_)
1202         {  // Remove LUT and exit
1203           CurrentRenderer->RemoveActor (lut_actor_);
1204           lut_enabled_ = false;
1205         }
1206         return;
1207       }
1208 
1209       lut_actor_->SetLookupTable (actor->GetMapper ()->GetLookupTable ());
1210       lut_actor_->Modified ();
1211       actor_found = true;
1212     }
1213     else
1214     {
1215       // CloudActor
1216       CloudActor *act = & (*am_it).second;
1217       if (!act->actor->GetMapper ()->GetLookupTable () && !act->actor->GetMapper ()->GetInput ()->GetPointData ()->GetScalars ())
1218       {
1219         PCL_WARN ("[updateLookUpTableDisplay] id <%s> does not hold any color information!\n", lut_actor_id_.c_str ());
1220         if (lut_enabled_)
1221         {  // Remove LUT and exit
1222           CurrentRenderer->RemoveActor (lut_actor_);
1223           lut_enabled_ = false;
1224         }
1225         return;
1226       }
1227 
1228       vtkScalarsToColors* lut = act->actor->GetMapper ()->GetLookupTable ();
1229       lut_actor_->SetLookupTable (lut);
1230       lut_actor_->Modified ();
1231       actor_found = true;
1232     }
1233   }
1234   else  // lut_actor_id_.empty(), the user did not specify which cloud/shape LUT should be displayed
1235   // Circling through all clouds/shapes and displaying first LUT found
1236   {
1237     for (const auto &actor : *cloud_actors_)
1238     {
1239       const auto &act = actor.second;
1240       if (!act.actor->GetMapper ()->GetLookupTable ())
1241         continue;
1242 
1243       if (!act.actor->GetMapper ()->GetInput ()->GetPointData ()->GetScalars ())
1244         continue;
1245 
1246       vtkScalarsToColors* lut = act.actor->GetMapper ()->GetLookupTable ();
1247       lut_actor_->SetLookupTable (lut);
1248       lut_actor_->Modified ();
1249       actor_found = true;
1250       break;
1251     }
1252 
1253     if (!actor_found)
1254     {
1255       for (const auto &shape_actor : *shape_actors_)
1256       {
1257         const vtkSmartPointer<vtkProp> *act = &shape_actor.second;
1258         const vtkSmartPointer<vtkActor> actor = vtkActor::SafeDownCast (*act);
1259         if (!actor)
1260           continue;
1261 
1262         if (!actor->GetMapper ()->GetInput ()->GetPointData ()->GetScalars ())  // Check if actor has scalars
1263           continue;
1264         lut_actor_->SetLookupTable (actor->GetMapper ()->GetLookupTable ());
1265         lut_actor_->Modified ();
1266         actor_found = true;
1267         break;
1268       }
1269     }
1270   }
1271 
1272   if ( (!actor_found && lut_enabled_) || (lut_enabled_ && add_lut))  // Remove actor
1273   {
1274     CurrentRenderer->RemoveActor (lut_actor_);
1275     lut_enabled_ = false;
1276   }
1277   else if (!lut_enabled_ && add_lut && actor_found)  // Add actor
1278   {
1279     CurrentRenderer->AddActor (lut_actor_);
1280     lut_actor_->SetVisibility (true);
1281     lut_enabled_ = true;
1282   }
1283   else if (lut_enabled_)  // Update actor (if displayed)
1284   {
1285     CurrentRenderer->RemoveActor (lut_actor_);
1286     CurrentRenderer->AddActor (lut_actor_);
1287   }
1288   else
1289     return;
1290 
1291   CurrentRenderer->Render ();
1292   return;
1293 }
1294 
1295 //////////////////////////////////////////////////////////////////////////////////////////////
1296 void
OnKeyUp()1297 pcl::visualization::PCLVisualizerInteractorStyle::OnKeyUp ()
1298 {
1299   KeyboardEvent event (false, Interactor->GetKeySym (), Interactor->GetKeyCode (), Interactor->GetAltKey (), Interactor->GetControlKey (), Interactor->GetShiftKey ());
1300   keyboard_signal_ (event);
1301   Superclass::OnKeyUp ();
1302 }
1303 
1304 //////////////////////////////////////////////////////////////////////////////////////////////
1305 void
OnMouseMove()1306 pcl::visualization::PCLVisualizerInteractorStyle::OnMouseMove ()
1307 {
1308   int x = this->Interactor->GetEventPosition()[0];
1309   int y = this->Interactor->GetEventPosition()[1];
1310   MouseEvent event (MouseEvent::MouseMove, MouseEvent::NoButton, x, y, Interactor->GetAltKey (), Interactor->GetControlKey (), Interactor->GetShiftKey (), Superclass::CurrentMode);
1311   mouse_signal_ (event);
1312   Superclass::OnMouseMove ();
1313 }
1314 
1315 //////////////////////////////////////////////////////////////////////////////////////////////
1316 void
OnLeftButtonDown()1317 pcl::visualization::PCLVisualizerInteractorStyle::OnLeftButtonDown ()
1318 {
1319 
1320   int x = this->Interactor->GetEventPosition()[0];
1321   int y = this->Interactor->GetEventPosition()[1];
1322 
1323   if (Interactor->GetRepeatCount () == 0)
1324   {
1325     MouseEvent event (MouseEvent::MouseButtonPress, MouseEvent::LeftButton, x, y, Interactor->GetAltKey (), Interactor->GetControlKey (), Interactor->GetShiftKey (), Superclass::CurrentMode);
1326     mouse_signal_ (event);
1327   }
1328   else
1329   {
1330     MouseEvent event (MouseEvent::MouseDblClick, MouseEvent::LeftButton, x, y, Interactor->GetAltKey (), Interactor->GetControlKey (), Interactor->GetShiftKey (), Superclass::CurrentMode);
1331     mouse_signal_ (event);
1332   }
1333   Superclass::OnLeftButtonDown ();
1334 }
1335 
1336 //////////////////////////////////////////////////////////////////////////////////////////////
1337 void
OnLeftButtonUp()1338 pcl::visualization::PCLVisualizerInteractorStyle::OnLeftButtonUp ()
1339 {
1340   int x = this->Interactor->GetEventPosition()[0];
1341   int y = this->Interactor->GetEventPosition()[1];
1342   MouseEvent event (MouseEvent::MouseButtonRelease, MouseEvent::LeftButton, x, y, Interactor->GetAltKey (), Interactor->GetControlKey (), Interactor->GetShiftKey (), Superclass::CurrentMode);
1343   mouse_signal_ (event);
1344   Superclass::OnLeftButtonUp ();
1345 }
1346 
1347 //////////////////////////////////////////////////////////////////////////////////////////////
1348 void
OnMiddleButtonDown()1349 pcl::visualization::PCLVisualizerInteractorStyle::OnMiddleButtonDown ()
1350 {
1351   int x = this->Interactor->GetEventPosition()[0];
1352   int y = this->Interactor->GetEventPosition()[1];
1353   if (Interactor->GetRepeatCount () == 0)
1354   {
1355     MouseEvent event (MouseEvent::MouseButtonPress, MouseEvent::MiddleButton, x, y, Interactor->GetAltKey (), Interactor->GetControlKey (), Interactor->GetShiftKey (), Superclass::CurrentMode);
1356     mouse_signal_ (event);
1357   }
1358   else
1359   {
1360     MouseEvent event (MouseEvent::MouseDblClick, MouseEvent::MiddleButton, x, y, Interactor->GetAltKey (), Interactor->GetControlKey (), Interactor->GetShiftKey (), Superclass::CurrentMode);
1361     mouse_signal_ (event);
1362   }
1363   Superclass::OnMiddleButtonDown ();
1364 }
1365 
1366 //////////////////////////////////////////////////////////////////////////////////////////////
1367 void
OnMiddleButtonUp()1368 pcl::visualization::PCLVisualizerInteractorStyle::OnMiddleButtonUp ()
1369 {
1370   int x = this->Interactor->GetEventPosition()[0];
1371   int y = this->Interactor->GetEventPosition()[1];
1372   MouseEvent event (MouseEvent::MouseButtonRelease, MouseEvent::MiddleButton, x, y, Interactor->GetAltKey (), Interactor->GetControlKey (), Interactor->GetShiftKey (), Superclass::CurrentMode);
1373   mouse_signal_ (event);
1374   Superclass::OnMiddleButtonUp ();
1375 }
1376 
1377 //////////////////////////////////////////////////////////////////////////////////////////////
1378 void
OnRightButtonDown()1379 pcl::visualization::PCLVisualizerInteractorStyle::OnRightButtonDown ()
1380 {
1381   int x = this->Interactor->GetEventPosition()[0];
1382   int y = this->Interactor->GetEventPosition()[1];
1383   if (Interactor->GetRepeatCount () == 0)
1384   {
1385     MouseEvent event (MouseEvent::MouseButtonPress, MouseEvent::RightButton, x, y, Interactor->GetAltKey (), Interactor->GetControlKey (), Interactor->GetShiftKey (), Superclass::CurrentMode);
1386     mouse_signal_ (event);
1387   }
1388   else
1389   {
1390     MouseEvent event (MouseEvent::MouseDblClick, MouseEvent::RightButton, x, y, Interactor->GetAltKey (), Interactor->GetControlKey (), Interactor->GetShiftKey (), Superclass::CurrentMode);
1391     mouse_signal_ (event);
1392   }
1393   Superclass::OnRightButtonDown ();
1394 }
1395 
1396 //////////////////////////////////////////////////////////////////////////////////////////////
1397 void
OnRightButtonUp()1398 pcl::visualization::PCLVisualizerInteractorStyle::OnRightButtonUp ()
1399 {
1400   int x = this->Interactor->GetEventPosition()[0];
1401   int y = this->Interactor->GetEventPosition()[1];
1402   MouseEvent event (MouseEvent::MouseButtonRelease, MouseEvent::RightButton, x, y, Interactor->GetAltKey (), Interactor->GetControlKey (), Interactor->GetShiftKey (), Superclass::CurrentMode);
1403   mouse_signal_ (event);
1404   Superclass::OnRightButtonUp ();
1405 }
1406 
1407 //////////////////////////////////////////////////////////////////////////////////////////////
1408 void
OnMouseWheelForward()1409 pcl::visualization::PCLVisualizerInteractorStyle::OnMouseWheelForward ()
1410 {
1411   int x = this->Interactor->GetEventPosition()[0];
1412   int y = this->Interactor->GetEventPosition()[1];
1413   MouseEvent event (MouseEvent::MouseScrollUp, MouseEvent::VScroll, x, y, Interactor->GetAltKey (), Interactor->GetControlKey (), Interactor->GetShiftKey (), Superclass::CurrentMode);
1414   mouse_signal_ (event);
1415   if (Interactor->GetRepeatCount ())
1416     mouse_signal_ (event);
1417 
1418   if (Interactor->GetAltKey ())
1419   {
1420     // zoom
1421     vtkSmartPointer<vtkCamera> cam = CurrentRenderer->GetActiveCamera ();
1422     double opening_angle = cam->GetViewAngle ();
1423     if (opening_angle > 15.0)
1424       opening_angle -= 1.0;
1425 
1426     cam->SetViewAngle (opening_angle);
1427     cam->Modified ();
1428     CurrentRenderer->SetActiveCamera (cam);
1429     CurrentRenderer->ResetCameraClippingRange ();
1430     CurrentRenderer->Modified ();
1431     CurrentRenderer->Render ();
1432     rens_->Render ();
1433     Interactor->Render ();
1434   }
1435   else
1436   Superclass::OnMouseWheelForward ();
1437 }
1438 
1439 //////////////////////////////////////////////////////////////////////////////////////////////
1440 void
OnMouseWheelBackward()1441 pcl::visualization::PCLVisualizerInteractorStyle::OnMouseWheelBackward ()
1442 {
1443   int x = this->Interactor->GetEventPosition()[0];
1444   int y = this->Interactor->GetEventPosition()[1];
1445   MouseEvent event (MouseEvent::MouseScrollDown, MouseEvent::VScroll, x, y, Interactor->GetAltKey (), Interactor->GetControlKey (), Interactor->GetShiftKey (), Superclass::CurrentMode);
1446   mouse_signal_ (event);
1447   if (Interactor->GetRepeatCount ())
1448     mouse_signal_ (event);
1449 
1450   if (Interactor->GetAltKey ())
1451   {
1452     // zoom
1453     vtkSmartPointer<vtkCamera> cam = CurrentRenderer->GetActiveCamera ();
1454     double opening_angle = cam->GetViewAngle ();
1455     if (opening_angle < 170.0)
1456       opening_angle += 1.0;
1457 
1458     cam->SetViewAngle (opening_angle);
1459     cam->Modified ();
1460     CurrentRenderer->SetActiveCamera (cam);
1461     CurrentRenderer->ResetCameraClippingRange ();
1462     CurrentRenderer->Modified ();
1463     CurrentRenderer->Render ();
1464     rens_->Render ();
1465     Interactor->Render ();
1466   }
1467   else
1468     Superclass::OnMouseWheelBackward ();
1469 }
1470 
1471 //////////////////////////////////////////////////////////////////////////////////////////////
1472 void
OnTimer()1473 pcl::visualization::PCLVisualizerInteractorStyle::OnTimer ()
1474 {
1475   if (!init_)
1476   {
1477     pcl::console::print_error ("[PCLVisualizerInteractorStyle] Interactor style not initialized. Please call Initialize () before continuing.\n");
1478     return;
1479   }
1480 
1481   if (!rens_)
1482   {
1483     pcl::console::print_error ("[PCLVisualizerInteractorStyle] No renderer collection given! Use SetRendererCollection () before continuing.\n");
1484     return;
1485   }
1486   rens_->Render ();
1487   Interactor->Render ();
1488 }
1489 
1490 //////////////////////////////////////////////////////////////////////////////////////////////
1491 //////////////////////////////////////////////////////////////////////////////////////////////
1492 void
Initialize()1493 pcl::visualization::PCLHistogramVisualizerInteractorStyle::Initialize ()
1494 {
1495   init_ = true;
1496 }
1497 
1498 //////////////////////////////////////////////////////////////////////////////////////////////
1499 void
OnKeyDown()1500 pcl::visualization::PCLHistogramVisualizerInteractorStyle::OnKeyDown ()
1501 {
1502   if (!init_)
1503   {
1504     pcl::console::print_error ("[PCLHistogramVisualizerInteractorStyle] Interactor style not initialized. Please call Initialize () before continuing.\n");
1505     return;
1506   }
1507 
1508   FindPokedRenderer (Interactor->GetEventPosition ()[0], Interactor->GetEventPosition ()[1]);
1509 
1510   //fprintf (stderr, "Key sym: %s\n", Interactor->GetKeySym ());
1511   // ---[ Check the rest of the key codes
1512   switch (Interactor->GetKeyCode ())
1513   {
1514     case 'q': case 'Q':
1515     {
1516       Interactor->ExitCallback ();
1517       return;
1518     }
1519     // Switch representation to wireframe
1520     default:
1521     {
1522       Superclass::OnKeyDown ();
1523     }
1524   }
1525   Interactor->Render ();
1526 }
1527 
1528 //////////////////////////////////////////////////////////////////////////////////////////////
1529 void
OnTimer()1530 pcl::visualization::PCLHistogramVisualizerInteractorStyle::OnTimer ()
1531 {
1532   if (!init_)
1533   {
1534     pcl::console::print_error ("[PCLHistogramVisualizerInteractorStyle] Interactor style not initialized. Please call Initialize () before continuing.\n");
1535     return;
1536   }
1537 
1538   for (auto &win : wins_)
1539     win.second.ren_->Render ();
1540 }
1541 
1542 namespace pcl
1543 {
1544   namespace visualization
1545   {
1546     // Standard VTK macro for *New ()
1547     vtkStandardNewMacro (PCLVisualizerInteractorStyle);
1548     vtkStandardNewMacro (PCLHistogramVisualizerInteractorStyle);
1549   }
1550 }
1551 
1552