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