1 /*
2  * Software License Agreement (BSD License)
3  *
4  *  Point Cloud Library (PCL) - www.pointclouds.org
5  *  Copyright (c) 2010-2011, 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  * $Id$
38  *
39  */
40 
41 #pragma once
42 
43 #include <pcl/visualization/common/actor_map.h>
44 #include <pcl/visualization/common/ren_win_interact_map.h>
45 #include <pcl/visualization/keyboard_event.h>
46 #include <pcl/visualization/mouse_event.h>
47 #include <pcl/visualization/point_picking_event.h>
48 #include <pcl/visualization/area_picking_event.h>
49 #include <boost/signals2/signal.hpp>
50 #include <vtkInteractorStyleRubberBandPick.h>
51 #include <vtkRendererCollection.h>
52 #include <vtkRenderWindow.h>
53 
54 class vtkRendererCollection;
55 class vtkLegendScaleActor;
56 class vtkScalarBarActor;
57 class vtkPNGWriter;
58 class vtkWindowToImageFilter;
59 class vtkPointPicker;
60 
61 namespace pcl
62 {
63   namespace visualization
64   {
65 
66     /** \brief A list of potential keyboard modifiers for \ref pcl::visualization::PCLVisualizerInteractorStyle::PCLVisualizerInteractorStyle()
67       * Defaults to Alt.
68       */
69     enum InteractorKeyboardModifier
70     {
71       INTERACTOR_KB_MOD_ALT,
72       INTERACTOR_KB_MOD_CTRL,
73       INTERACTOR_KB_MOD_SHIFT
74     };
75 
76     /** \brief PCLVisualizerInteractorStyle defines an unique, custom VTK
77       * based interactory style for PCL Visualizer applications. Besides
78       * defining the rendering style, we also create a list of custom actions
79       * that are triggered on different keys being pressed:
80       *
81       * -        p, P   : switch to a point-based representation
82       * -        w, W   : switch to a wireframe-based representation (where available)
83       * -        s, S   : switch to a surface-based representation (where available)
84       * -        j, J   : take a .PNG snapshot of the current window view
85       * -        c, C   : display current camera/window parameters
86       * -        f, F   : fly to point mode
87       * -        e, E   : exit the interactor\
88       * -        q, Q   : stop and call VTK's TerminateApp
89       * -       + / -   : increment/decrement overall point size
90       * -        g, G   : display scale grid (on/off)
91       * -        u, U   : display lookup table (on/off)
92       * -  r, R [+ ALT] : reset camera [to viewpoint = {0, 0, 0} -> center_{x, y, z}]
93       * -  CTRL + s, S  : save camera parameters
94       * -  CTRL + r, R  : restore camera parameters
95       * -  ALT + s, S   : turn stereo mode on/off
96       * -  ALT + f, F   : switch between maximized window mode and original size
97       * -        l, L           : list all available geometric and color handlers for the current actor map
98       * -  ALT + 0..9 [+ CTRL]  : switch between different geometric handlers (where available)
99       * -        0..9 [+ CTRL]  : switch between different color handlers (where available)
100       * -
101       * -  SHIFT + left click   : select a point
102       * -        x, X   : toggle rubber band selection mode for left mouse button
103       *
104       * \author Radu B. Rusu
105       * \ingroup visualization
106       */
107     class PCL_EXPORTS PCLVisualizerInteractorStyle : public vtkInteractorStyleRubberBandPick
108     {
109       public:
110         using CloudActorMapPtr = pcl::visualization::CloudActorMapPtr;
111 
112         static PCLVisualizerInteractorStyle *New ();
113 
114         /** \brief Empty constructor. */
PCLVisualizerInteractorStyle()115         PCLVisualizerInteractorStyle () :
116           init_ (), win_height_ (), win_width_ (), win_pos_x_ (), win_pos_y_ (),
117           max_win_height_ (), max_win_width_ (), use_vbos_ (false), grid_enabled_ (), lut_enabled_ (),
118           stereo_anaglyph_mask_default_ (),
119           modifier_ (), camera_saved_ (), lut_actor_id_ ("")
120         {}
121 
122         /** \brief Empty destructor */
~PCLVisualizerInteractorStyle()123         ~PCLVisualizerInteractorStyle () {}
124 
125         // this macro defines Superclass, the isA functionality and the safe downcast method
126         vtkTypeMacro (PCLVisualizerInteractorStyle, vtkInteractorStyleRubberBandPick);
127 
128         /** \brief Initialization routine. Must be called before anything else. */
129         virtual void
130         Initialize ();
131 
132         /** \brief Pass a pointer to the cloud actor map
133           * \param[in] actors the actor map that will be used with this style
134           */
135         inline void
setCloudActorMap(const CloudActorMapPtr & actors)136         setCloudActorMap (const CloudActorMapPtr &actors) { cloud_actors_ = actors; }
137 
138         /** \brief Pass a pointer to the shape actor map
139           * \param[in] actors the actor map that will be used with this style
140           */
141         inline void
setShapeActorMap(const ShapeActorMapPtr & actors)142         setShapeActorMap (const ShapeActorMapPtr &actors) { shape_actors_ = actors; }
143 
144         /** \brief Get the cloud actor map pointer. */
145         inline CloudActorMapPtr
getCloudActorMap()146         getCloudActorMap () { return (cloud_actors_); }
147 
148         /** \brief Get the cloud actor map pointer. */
149         inline ShapeActorMapPtr
getShapeActorMap()150         getShapeActorMap () { return (shape_actors_); }
151 
152         /** \brief Pass a set of renderers to the interactor style.
153           * \param[in] rens the vtkRendererCollection to use
154           */
155         void
setRendererCollection(vtkSmartPointer<vtkRendererCollection> & rens)156         setRendererCollection (vtkSmartPointer<vtkRendererCollection> &rens) { rens_ = rens; }
157 
158         /** \brief Use Vertex Buffer Objects renderers.
159           * This is an optimization for the obsolete OpenGL backend. Modern OpenGL2 backend (VTK ≥ 6.3) uses vertex
160           * buffer objects by default, transparently for the user.
161           * \param[in] use_vbos set to true to use VBOs
162           */
163         inline void
setUseVbos(const bool use_vbos)164         setUseVbos (const bool use_vbos) { use_vbos_ = use_vbos; }
165 
166         /** \brief Register a callback function for mouse events
167           * \param[in] cb a std function that will be registered as a callback for a mouse event
168           * \return a connection object that allows to disconnect the callback function.
169           */
170         boost::signals2::connection
171         registerMouseCallback (std::function<void (const pcl::visualization::MouseEvent&)> cb);
172 
173         /** \brief Register a callback std::function for keyboard events
174           * \param[in] cb a std function that will be registered as a callback for a keyboard event
175           * \return a connection object that allows to disconnect the callback function.
176           */
177         boost::signals2::connection
178         registerKeyboardCallback (std::function<void (const pcl::visualization::KeyboardEvent&)> cb);
179 
180         /** \brief Register a callback function for point picking events
181           * \param[in] cb a std function that will be registered as a callback for a point picking event
182           * \return a connection object that allows to disconnect the callback function.
183           */
184         boost::signals2::connection
185         registerPointPickingCallback (std::function<void (const pcl::visualization::PointPickingEvent&)> cb);
186 
187         /** \brief Register a callback function for area picking events
188           * \param[in] cb a std function that will be registered as a callback for a area picking event
189           * \return a connection object that allows to disconnect the callback function.
190           */
191         boost::signals2::connection
192         registerAreaPickingCallback (std::function<void (const pcl::visualization::AreaPickingEvent&)> cb);
193 
194         /** \brief Save the current rendered image to disk, as a PNG screenshot.
195           * \param[in] file the name of the PNG file
196           */
197         void
198         saveScreenshot (const std::string &file);
199 
200         /** \brief Save the camera parameters to disk, as a .cam file.
201           * \param[in] file the name of the .cam file
202           */
203         bool
204         saveCameraParameters (const std::string &file);
205 
206         /** \brief Get camera parameters of a given viewport (0 means default viewport). */
207         void
208         getCameraParameters (Camera &camera, int viewport = 0) const;
209 
210         /** \brief Load camera parameters from a camera parameter file.
211           * \param[in] file the name of the camera parameter file
212           */
213         bool
214         loadCameraParameters (const std::string &file);
215 
216         /** \brief Set the camera parameters via an intrinsics and and extrinsics matrix
217           * \note This assumes that the pixels are square and that the center of the image is at the center of the sensor.
218           * \param[in] intrinsics the intrinsics that will be used to compute the VTK camera parameters
219           * \param[in] extrinsics the extrinsics that will be used to compute the VTK camera parameters
220           * \param[in] viewport the viewport to modify camera of (0 modifies all cameras)
221           */
222         void
223         setCameraParameters (const Eigen::Matrix3f &intrinsics, const Eigen::Matrix4f &extrinsics, int viewport = 0);
224 
225         /** \brief Set the camera parameters by given a full camera data structure.
226           * \param[in] camera camera structure containing all the camera parameters.
227           * \param[in] viewport the viewport to modify camera of (0 modifies all cameras)
228           */
229         void
230         setCameraParameters (const Camera &camera, int viewport = 0);
231 
232         /** \brief Set camera file for camera parameter saving/restoring.
233           * \param[in] file the name of the camera parameter file
234           */
235         void
setCameraFile(const std::string file)236         setCameraFile (const std::string file)
237         {
238           camera_file_ = file;
239         }
240 
241         /** \brief Get camera file for camera parameter saving/restoring. */
242         std::string
getCameraFile()243         getCameraFile () const
244         {
245           return (camera_file_);
246         }
247 
248         /** \brief Change the default keyboard modified from ALT to a different special key.
249           * Allowed values are:
250           * - INTERACTOR_KB_MOD_ALT
251           * - INTERACTOR_KB_MOD_CTRL
252           * - INTERACTOR_KB_MOD_SHIFT
253           * \param[in] modifier the new keyboard modifier
254           */
255         inline void
setKeyboardModifier(const InteractorKeyboardModifier & modifier)256         setKeyboardModifier (const InteractorKeyboardModifier &modifier)
257         {
258           modifier_ = modifier;
259         }
260 
261        protected:
262         /** \brief Set to true after initialization is complete. */
263         bool init_;
264 
265         /** \brief Collection of vtkRenderers stored internally. */
266         vtkSmartPointer<vtkRendererCollection> rens_;
267 
268         /** \brief Cloud actor map stored internally. */
269         CloudActorMapPtr cloud_actors_;
270 
271         /** \brief Shape map stored internally. */
272         ShapeActorMapPtr shape_actors_;
273 
274         /** \brief The current window width/height. */
275         int win_height_, win_width_;
276 
277         /** \brief The current window position x/y. */
278         int win_pos_x_, win_pos_y_;
279 
280         /** \brief The maximum resizeable window width/height. */
281         int max_win_height_, max_win_width_;
282 
283         /** \brief Boolean that holds whether or not to use the vtkVertexBufferObjectMapper*/
284         bool use_vbos_;
285 
286         /** \brief Set to true if the grid actor is enabled. */
287         bool grid_enabled_;
288         /** \brief Actor for 2D grid on screen. */
289         vtkSmartPointer<vtkLegendScaleActor> grid_actor_;
290 
291         /** \brief Set to true if the LUT actor is enabled. */
292         bool lut_enabled_;
293         /** \brief Actor for 2D lookup table on screen. */
294         vtkSmartPointer<vtkScalarBarActor> lut_actor_;
295 
296         /** \brief A PNG writer for screenshot captures. */
297         vtkSmartPointer<vtkPNGWriter> snapshot_writer_;
298         /** \brief Internal window to image filter. Needed by \a snapshot_writer_. */
299         vtkSmartPointer<vtkWindowToImageFilter> wif_;
300         /** \brief Stores the point picker when switching to an area picker. */
301         vtkSmartPointer<vtkPointPicker> point_picker_;
302 
303         boost::signals2::signal<void (const pcl::visualization::MouseEvent&)> mouse_signal_;
304         boost::signals2::signal<void (const pcl::visualization::KeyboardEvent&)> keyboard_signal_;
305         boost::signals2::signal<void (const pcl::visualization::PointPickingEvent&)> point_picking_signal_;
306         boost::signals2::signal<void (const pcl::visualization::AreaPickingEvent&)> area_picking_signal_;
307 
308         /** \brief Interactor style internal method. Gets called whenever a key is pressed. */
309         void
310         OnChar () override;
311 
312         // Keyboard events
313         void
314         OnKeyDown () override;
315         void
316         OnKeyUp () override;
317 
318         // mouse button events
319         void
320         OnMouseMove () override;
321         void
322         OnLeftButtonDown () override;
323         void
324         OnLeftButtonUp () override;
325         void
326         OnMiddleButtonDown () override;
327         void
328         OnMiddleButtonUp () override;
329         void
330         OnRightButtonDown () override;
331         void
332         OnRightButtonUp () override;
333         void
334         OnMouseWheelForward () override;
335         void
336         OnMouseWheelBackward () override;
337 
338         // mouse move event
339         /** \brief Interactor style internal method. Gets called periodically if a timer is set. */
340         void
341         OnTimer () override;
342 
343         /** \brief Interactor style internal method. Zoom in. */
344         void
345         zoomIn ();
346 
347         /** \brief Interactor style internal method. Zoom out. */
348         void
349         zoomOut ();
350 
351         /** \brief Get camera parameters from a string vector.
352           * \param[in] camera A string vector:
353           * Clipping Range, Focal Point, Position, ViewUp, Distance, Field of View Y, Window Size, Window Pos.
354           * Values in each string are separated by a ','
355           */
356         bool
357         getCameraParameters (const std::vector<std::string> &camera);
358 
359         /** \brief Set render window. */
360         void
setRenderWindow(const vtkSmartPointer<vtkRenderWindow> & win)361         setRenderWindow (const vtkSmartPointer<vtkRenderWindow> &win)
362         {
363           win_ = win;
364         }
365 
366         /** \brief True if we're using red-blue colors for anaglyphic stereo, false if magenta-green. */
367         bool stereo_anaglyph_mask_default_;
368 
369         /** \brief A VTK Mouse Callback object, used for point picking. */
370         vtkSmartPointer<PointPickingCallback> mouse_callback_;
371 
372         /** \brief The keyboard modifier to use. Default: Alt. */
373         InteractorKeyboardModifier modifier_;
374 
375         /** \brief Camera file for camera parameter saving/restoring. */
376         std::string camera_file_;
377         /** \brief A \ref pcl::visualization::Camera for camera parameter saving/restoring. */
378         Camera camera_;
379         /** \brief A \ref pcl::visualization::Camera is saved or not. */
380         bool camera_saved_;
381         /** \brief The render window.
382           * Only used when interactor maybe not available
383           */
384         vtkSmartPointer<vtkRenderWindow> win_;
385 
386         friend class PointPickingCallback;
387         friend class PCLVisualizer;
388 
389        private:
390         /** \brief ID used to fetch/display the look up table on the visualizer
391          * It should be set by PCLVisualizer \ref setLookUpTableID
392          * @note If empty, a random actor added to the interactor will be used */
393         std::string lut_actor_id_;
394 
395         /** \brief Add/remove the look up table displayed when 'u' is pressed, can also be used to update the current LUT displayed
396          * \ref lut_actor_id_ is used (if not empty) to chose which cloud/shape actor LUT will be updated (depending on what is available)
397          * If \ref lut_actor_id_ is empty the first actor with LUT support found will be used. */
398         void
399         updateLookUpTableDisplay (bool add_lut = false);
400     };
401 
402     /** \brief PCL histogram visualizer interactory style class.
403       * \author Radu B. Rusu
404       */
405     class PCLHistogramVisualizerInteractorStyle : public vtkInteractorStyleTrackballCamera
406     {
407       public:
408         static PCLHistogramVisualizerInteractorStyle *New ();
409 
410         /** \brief Empty constructor. */
PCLHistogramVisualizerInteractorStyle()411         PCLHistogramVisualizerInteractorStyle () : init_ (false) {}
412 
413         /** \brief Initialization routine. Must be called before anything else. */
414         void
415         Initialize ();
416 
417         /** \brief Pass a map of render/window/interactors to the interactor style.
418           * \param[in] wins the RenWinInteract map to use
419           */
420         void
setRenWinInteractMap(const RenWinInteractMap & wins)421         setRenWinInteractMap (const RenWinInteractMap &wins) { wins_ = wins; }
422 
423       private:
424         /** \brief A map of all windows on screen (with their renderers and interactors). */
425         RenWinInteractMap wins_;
426 
427         /** \brief Set to true after initialization is complete. */
428         bool init_;
429 
430         /** \brief Interactor style internal method. Gets called whenever a key is pressed. */
431         void OnKeyDown () override;
432 
433         /** \brief Interactor style internal method. Gets called periodically if a timer is set. */
434         void OnTimer () override;
435     };
436   }
437 }
438