Point Cloud Library (PCL)  1.7.0
/tmp/buildd/pcl-1.7-1.7.0/visualization/include/pcl/visualization/image_viewer.h
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Point Cloud Library (PCL) - www.pointclouds.org
00005  *  Copyright (c) 2010-2012, Willow Garage, Inc.
00006  *  Copyright (c) 2012-, Open Perception, Inc.
00007  *
00008  *  All rights reserved.
00009  *
00010  *  Redistribution and use in source and binary forms, with or without
00011  *  modification, are permitted provided that the following conditions
00012  *  are met:
00013  *
00014  *   * Redistributions of source code must retain the above copyright
00015  *     notice, this list of conditions and the following disclaimer.
00016  *   * Redistributions in binary form must reproduce the above
00017  *     copyright notice, this list of conditions and the following
00018  *     disclaimer in the documentation and/or other materials provided
00019  *     with the distribution.
00020  *   * Neither the name of the copyright holder(s) nor the names of its
00021  *     contributors may be used to endorse or promote products derived
00022  *     from this software without specific prior written permission.
00023  *
00024  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00025  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00026  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00027  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00028  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00029  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00030  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00031  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00032  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00033  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00034  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00035  *  POSSIBILITY OF SUCH DAMAGE.
00036  *
00037  */
00038 
00039 #ifndef PCL_VISUALIZATION_IMAGE_VISUALIZER_H__
00040 #define PCL_VISUALIZATION_IMAGE_VISUALIZER_H__
00041 
00042 #include <pcl/pcl_macros.h>
00043 #include <pcl/point_types.h>
00044 #include <pcl/console/print.h>
00045 #include <pcl/visualization/interactor.h>
00046 #include <pcl/visualization/interactor_style.h>
00047 #include <pcl/visualization/vtk/pcl_image_canvas_source_2d.h>
00048 #include <pcl/visualization/vtk/pcl_context_item.h>
00049 #include <pcl/geometry/planar_polygon.h>
00050 #include <pcl/correspondence.h>
00051 
00052 #include <boost/shared_array.hpp>
00053 
00054 #include <vtkInteractorStyleImage.h>
00055 
00056 class vtkImageSlice;
00057 class vtkContextActor;
00058 class vtkImageViewer;
00059 class vtkImageFlip;
00060 
00061 namespace pcl
00062 {
00063   namespace visualization
00064   {
00065     typedef Eigen::Array<unsigned char, 3, 1> Vector3ub;
00066     static const Vector3ub green_color (0, 255, 0);
00067     static const Vector3ub red_color (255, 0, 0);
00068     static const Vector3ub blue_color (0, 0, 255);
00069 
00070     /** \brief An image viewer interactor style, tailored for ImageViewer.
00071       * \author Radu B. Rusu
00072       * \ingroup visualization
00073       */
00074     class PCL_EXPORTS ImageViewerInteractorStyle : public vtkInteractorStyleImage
00075     {
00076       public:
00077         static ImageViewerInteractorStyle *New ();
00078         ImageViewerInteractorStyle ();
00079 
00080         virtual void OnMouseWheelForward () {}
00081         virtual void OnMouseWheelBackward () {}
00082         virtual void OnMiddleButtonDown () {}
00083         virtual void OnRightButtonDown () {}
00084         virtual void OnLeftButtonDown ();
00085 
00086         virtual void
00087         OnChar ();
00088 
00089         void
00090         adjustCamera (vtkImageData *image, vtkRenderer *ren);
00091 
00092         void
00093         adjustCamera (vtkRenderer *ren);
00094     };
00095 
00096     /** \brief ImageViewer is a class for 2D image visualization.
00097       *
00098       * Features include:
00099       *  - add and remove different layers with different opacity (transparency) values
00100       *  - add 2D geometric shapes (circles, boxes, etc) in separate layers
00101       *  - display RGB, monochrome, float, angle images
00102       *
00103       * Simple usage example:
00104       * \code
00105       * pcl::visualization::ImageViewer iv;
00106       * iv.addCircle (10, 10, 5, 1.0, 0.0, 0.0, "circles", 1.0);    // add a red, fully opaque circle with radius 5 pixels at (10,10) in layer "circles"
00107       * iv.addFilledRectangle (10, 20, 10, 20, 0.0, 1.0, 0.0, "boxes", 0.5);    // add a green, 50% transparent box at (10,10->20,20) in layer "boxes"
00108       * iv.addRGBImage<pcl::PointXYZRGBA> (cloud);                  // add a RGB image from a point cloud dataset in an "rgb_image" default layer
00109       * iv.spin ();                                                 // press 'q' to exit
00110       * iv.removeLayer ("circles");                                 // remove layer "circles"
00111       * iv.spin ();                                                 // press 'q' to exit
00112       * \endcode
00113       * 
00114       * \author Radu B. Rusu, Suat Gedikli
00115       * \ingroup visualization
00116       */
00117     class PCL_EXPORTS ImageViewer
00118     {
00119       public:
00120         typedef boost::shared_ptr<ImageViewer> Ptr;
00121 
00122         /** \brief Constructor.
00123           * \param[in] window_title the title of the window
00124           */
00125         ImageViewer (const std::string& window_title = "");
00126 
00127         /** \brief Destructor. */
00128         virtual ~ImageViewer ();
00129        
00130         /** \brief Show a monochrome 2D image on screen.
00131           * \param[in] data the input data representing the image
00132           * \param[in] width the width of the image
00133           * \param[in] height the height of the image
00134           * \param[in] layer_id the name of the layer (default: "image")
00135           * \param[in] opacity the opacity of the layer (default: 1.0)
00136           */
00137         void 
00138         showMonoImage (const unsigned char* data, unsigned width, unsigned height,
00139                        const std::string &layer_id = "mono_image", double opacity = 1.0);
00140 
00141         /** \brief Add a monochrome 2D image layer, but do not render it (use spin/spinOnce to update).
00142           * \param[in] data the input data representing the image
00143           * \param[in] width the width of the image
00144           * \param[in] height the height of the image
00145           * \param[in] layer_id the name of the layer (default: "image")
00146           * \param[in] opacity the opacity of the layer (default: 1.0)
00147           */
00148         void 
00149         addMonoImage (const unsigned char* data, unsigned width, unsigned height,
00150                       const std::string &layer_id = "mono_image", double opacity = 1.0);
00151 
00152         /** \brief Show a monochrome 2D image on screen.
00153           * \param[in] cloud the input data representing the grayscale point cloud
00154           * \param[in] layer_id the name of the layer (default: "image")
00155           * \param[in] opacity the opacity of the layer (default: 1.0)
00156           */
00157         inline void
00158         showMonoImage (const pcl::PointCloud<pcl::Intensity>::ConstPtr &cloud,
00159                       const std::string &layer_id = "mono_image", double opacity = 1.0)
00160         {
00161           return (showMonoImage (*cloud, layer_id, opacity));
00162         }
00163 
00164         /** \brief Add a monochrome 2D image layer, but do not render it (use spin/spinOnce to update).
00165           * \param[in] cloud the input data representing the grayscale point cloud
00166           * \param[in] layer_id the name of the layer (default: "image")
00167           * \param[in] opacity the opacity of the layer (default: 1.0)
00168           */
00169         inline void
00170         addMonoImage (const pcl::PointCloud<pcl::Intensity>::ConstPtr &cloud,
00171                      const std::string &layer_id = "mono_image", double opacity = 1.0)
00172         {
00173           return (addMonoImage (*cloud, layer_id, opacity));
00174         }
00175 
00176         /** \brief Show a monochrome 2D image on screen.
00177           * \param[in] cloud the input data representing the grayscale point cloud
00178           * \param[in] layer_id the name of the layer (default: "image")
00179           * \param[in] opacity the opacity of the layer (default: 1.0)
00180           */
00181         void
00182         showMonoImage (const pcl::PointCloud<pcl::Intensity> &cloud,
00183                       const std::string &layer_id = "mono_image", double opacity = 1.0);
00184 
00185         /** \brief Add a monochrome 2D image layer, but do not render it (use spin/spinOnce to update).
00186           * \param[in] cloud the input data representing the RGB point cloud
00187           * \param[in] layer_id the name of the layer (default: "image")
00188           * \param[in] opacity the opacity of the layer (default: 1.0)
00189           */
00190         void
00191         addMonoImage (const pcl::PointCloud<pcl::Intensity> &cloud,
00192                      const std::string &layer_id = "mono_image", double opacity = 1.0);
00193 
00194         /** \brief Show a monochrome 2D image on screen.
00195           * \param[in] cloud the input data representing the grayscale point cloud
00196           * \param[in] layer_id the name of the layer (default: "image")
00197           * \param[in] opacity the opacity of the layer (default: 1.0)
00198           */
00199         inline void
00200         showMonoImage (const pcl::PointCloud<pcl::Intensity8u>::ConstPtr &cloud,
00201                       const std::string &layer_id = "mono_image", double opacity = 1.0)
00202         {
00203           return (showMonoImage (*cloud, layer_id, opacity));
00204         }
00205 
00206         /** \brief Add a monochrome 2D image layer, but do not render it (use spin/spinOnce to update).
00207           * \param[in] cloud the input data representing the grayscale point cloud
00208           * \param[in] layer_id the name of the layer (default: "image")
00209           * \param[in] opacity the opacity of the layer (default: 1.0)
00210           */
00211         inline void
00212         addMonoImage (const pcl::PointCloud<pcl::Intensity8u>::ConstPtr &cloud,
00213                      const std::string &layer_id = "mono_image", double opacity = 1.0)
00214         {
00215           return (addMonoImage (*cloud, layer_id, opacity));
00216         }
00217 
00218         /** \brief Show a monochrome 2D image on screen.
00219           * \param[in] cloud the input data representing the grayscale point cloud
00220           * \param[in] layer_id the name of the layer (default: "image")
00221           * \param[in] opacity the opacity of the layer (default: 1.0)
00222           */
00223         void
00224         showMonoImage (const pcl::PointCloud<pcl::Intensity8u> &cloud,
00225                       const std::string &layer_id = "mono_image", double opacity = 1.0);
00226 
00227         /** \brief Add a monochrome 2D image layer, but do not render it (use spin/spinOnce to update).
00228           * \param[in] cloud the input data representing the RGB point cloud
00229           * \param[in] layer_id the name of the layer (default: "image")
00230           * \param[in] opacity the opacity of the layer (default: 1.0)
00231           */
00232         void
00233         addMonoImage (const pcl::PointCloud<pcl::Intensity8u> &cloud,
00234                      const std::string &layer_id = "mono_image", double opacity = 1.0);
00235 
00236         /** \brief Show a 2D RGB image on screen.
00237           * \param[in] data the input data representing the image
00238           * \param[in] width the width of the image
00239           * \param[in] height the height of the image
00240           * \param[in] layer_id the name of the layer (default: "image")
00241           * \param[in] opacity the opacity of the layer (default: 1.0)
00242           */
00243         void 
00244         showRGBImage (const unsigned char* data, unsigned width, unsigned height, 
00245                       const std::string &layer_id = "rgb_image", double opacity = 1.0);
00246 
00247         /** \brief Add an RGB 2D image layer, but do not render it (use spin/spinOnce to update).
00248           * \param[in] data the input data representing the image
00249           * \param[in] width the width of the image
00250           * \param[in] height the height of the image
00251           * \param[in] layer_id the name of the layer (default: "image")
00252           * \param[in] opacity the opacity of the layer (default: 1.0)
00253           */
00254         void 
00255         addRGBImage (const unsigned char* data, unsigned width, unsigned height, 
00256                      const std::string &layer_id = "rgb_image", double opacity = 1.0);
00257 
00258         /** \brief Show a 2D image on screen, obtained from the RGB channel of a point cloud.
00259           * \param[in] cloud the input data representing the RGB point cloud 
00260           * \param[in] layer_id the name of the layer (default: "image")
00261           * \param[in] opacity the opacity of the layer (default: 1.0)
00262           */
00263         template <typename T> inline void 
00264         showRGBImage (const typename pcl::PointCloud<T>::ConstPtr &cloud,
00265                       const std::string &layer_id = "rgb_image", double opacity = 1.0)
00266         {
00267           return (showRGBImage<T> (*cloud, layer_id, opacity));
00268         }
00269 
00270         /** \brief Add an RGB 2D image layer, but do not render it (use spin/spinOnce to update).
00271           * \param[in] cloud the input data representing the RGB point cloud 
00272           * \param[in] layer_id the name of the layer (default: "image")
00273           * \param[in] opacity the opacity of the layer (default: 1.0)
00274           */
00275         template <typename T> inline void 
00276         addRGBImage (const typename pcl::PointCloud<T>::ConstPtr &cloud,
00277                      const std::string &layer_id = "rgb_image", double opacity = 1.0)
00278         {
00279           return (addRGBImage<T> (*cloud, layer_id, opacity));
00280         }
00281 
00282         /** \brief Show a 2D image on screen, obtained from the RGB channel of a point cloud.
00283           * \param[in] cloud the input data representing the RGB point cloud 
00284           * \param[in] layer_id the name of the layer (default: "image")
00285           * \param[in] opacity the opacity of the layer (default: 1.0)
00286           */
00287         template <typename T> void 
00288         showRGBImage (const pcl::PointCloud<T> &cloud,
00289                       const std::string &layer_id = "rgb_image", double opacity = 1.0);
00290 
00291         /** \brief Add an RGB 2D image layer, but do not render it (use spin/spinOnce to update).
00292           * \param[in] cloud the input data representing the RGB point cloud 
00293           * \param[in] layer_id the name of the layer (default: "image")
00294           * \param[in] opacity the opacity of the layer (default: 1.0)
00295           */
00296         template <typename T> void 
00297         addRGBImage (const pcl::PointCloud<T> &cloud,
00298                      const std::string &layer_id = "rgb_image", double opacity = 1.0);
00299 
00300         /** \brief Show a 2D image (float) on screen.
00301           * \param[in] data the input data representing the image in float format
00302           * \param[in] width the width of the image
00303           * \param[in] height the height of the image
00304           * \param[in] min_value filter all values in the image to be larger than this minimum value
00305           * \param[in] max_value filter all values in the image to be smaller than this maximum value
00306           * \param[in] grayscale show data as grayscale (true) or not (false). Default: false
00307           * \param[in] layer_id the name of the layer (default: "image")
00308           * \param[in] opacity the opacity of the layer (default: 1.0)
00309           */
00310         void 
00311         showFloatImage (const float* data, unsigned int width, unsigned int height, 
00312                         float min_value = std::numeric_limits<float>::min (), 
00313                         float max_value = std::numeric_limits<float>::max (), bool grayscale = false,
00314                         const std::string &layer_id = "float_image", double opacity = 1.0);
00315 
00316         /** \brief Add a float 2D image layer, but do not render it (use spin/spinOnce to update).
00317           * \param[in] data the input data representing the image in float format
00318           * \param[in] width the width of the image
00319           * \param[in] height the height of the image
00320           * \param[in] min_value filter all values in the image to be larger than this minimum value
00321           * \param[in] max_value filter all values in the image to be smaller than this maximum value
00322           * \param[in] grayscale show data as grayscale (true) or not (false). Default: false
00323           * \param[in] layer_id the name of the layer (default: "image")
00324           * \param[in] opacity the opacity of the layer (default: 1.0)
00325           */
00326         void 
00327         addFloatImage (const float* data, unsigned int width, unsigned int height, 
00328                        float min_value = std::numeric_limits<float>::min (), 
00329                        float max_value = std::numeric_limits<float>::max (), bool grayscale = false,
00330                        const std::string &layer_id = "float_image", double opacity = 1.0);
00331         
00332         /** \brief Show a 2D image (unsigned short) on screen.
00333           * \param[in] short_image the input data representing the image in unsigned short format
00334           * \param[in] width the width of the image
00335           * \param[in] height the height of the image
00336           * \param[in] min_value filter all values in the image to be larger than this minimum value
00337           * \param[in] max_value filter all values in the image to be smaller than this maximum value
00338           * \param[in] grayscale show data as grayscale (true) or not (false). Default: false
00339           * \param[in] layer_id the name of the layer (default: "image")
00340           * \param[in] opacity the opacity of the layer (default: 1.0)
00341           */
00342         void
00343         showShortImage (const unsigned short* short_image, unsigned int width, unsigned int height, 
00344                         unsigned short min_value = std::numeric_limits<unsigned short>::min (), 
00345                         unsigned short max_value = std::numeric_limits<unsigned short>::max (), bool grayscale = false,
00346                         const std::string &layer_id = "short_image", double opacity = 1.0);
00347 
00348         /** \brief Add a short 2D image layer, but do not render it (use spin/spinOnce to update).
00349           * \param[in] short_image the input data representing the image in unsigned short format
00350           * \param[in] width the width of the image
00351           * \param[in] height the height of the image
00352           * \param[in] min_value filter all values in the image to be larger than this minimum value
00353           * \param[in] max_value filter all values in the image to be smaller than this maximum value
00354           * \param[in] grayscale show data as grayscale (true) or not (false). Default: false
00355           * \param[in] layer_id the name of the layer (default: "image")
00356           * \param[in] opacity the opacity of the layer (default: 1.0)
00357           */
00358         void
00359         addShortImage (const unsigned short* short_image, unsigned int width, unsigned int height, 
00360                        unsigned short min_value = std::numeric_limits<unsigned short>::min (), 
00361                        unsigned short max_value = std::numeric_limits<unsigned short>::max (), bool grayscale = false,
00362                        const std::string &layer_id = "short_image", double opacity = 1.0);
00363 
00364         /** \brief Show a 2D image on screen representing angle data.
00365           * \param[in] data the input data representing the image
00366           * \param[in] width the width of the image
00367           * \param[in] height the height of the image
00368           * \param[in] layer_id the name of the layer (default: "image")
00369           * \param[in] opacity the opacity of the layer (default: 1.0)
00370           */
00371         void 
00372         showAngleImage (const float* data, unsigned width, unsigned height,
00373                         const std::string &layer_id = "angle_image", double opacity = 1.0);
00374 
00375         /** \brief Add an angle 2D image layer, but do not render it (use spin/spinOnce to update).
00376           * \param[in] data the input data representing the image
00377           * \param[in] width the width of the image
00378           * \param[in] height the height of the image
00379           * \param[in] layer_id the name of the layer (default: "image")
00380           * \param[in] opacity the opacity of the layer (default: 1.0)
00381           */
00382         void 
00383         addAngleImage (const float* data, unsigned width, unsigned height,
00384                        const std::string &layer_id = "angle_image", double opacity = 1.0);
00385 
00386         /** \brief Show a 2D image on screen representing half angle data.
00387           * \param[in] data the input data representing the image
00388           * \param[in] width the width of the image
00389           * \param[in] height the height of the image
00390           * \param[in] layer_id the name of the layer (default: "image")
00391           * \param[in] opacity the opacity of the layer (default: 1.0)
00392           */
00393         void 
00394         showHalfAngleImage (const float* data, unsigned width, unsigned height,
00395                             const std::string &layer_id = "half_angle_image", double opacity = 1.0);
00396 
00397         /** \brief Add a half angle 2D image layer, but do not render it (use spin/spinOnce to update).
00398           * \param[in] data the input data representing the image
00399           * \param[in] width the width of the image
00400           * \param[in] height the height of the image
00401           * \param[in] layer_id the name of the layer (default: "image")
00402           * \param[in] opacity the opacity of the layer (default: 1.0)
00403           */
00404         void 
00405         addHalfAngleImage (const float* data, unsigned width, unsigned height,
00406                            const std::string &layer_id = "half_angle_image", double opacity = 1.0);
00407 
00408         /** \brief Sets the pixel at coordinates(u,v) to color while setting the neighborhood to another
00409           * \param[in] u the u/x coordinate of the pixel
00410           * \param[in] v the v/y coordinate of the pixel
00411           * \param[in] fg_color the pixel color
00412           * \param[in] bg_color the neighborhood color
00413           * \param[in] radius the circle radius around the pixel
00414           * \param[in] layer_id the name of the layer (default: "points")
00415           * \param[in] opacity the opacity of the layer (default: 1.0)
00416           */
00417         void
00418         markPoint (size_t u, size_t v, Vector3ub fg_color, Vector3ub bg_color = red_color, double radius = 3.0,
00419                    const std::string &layer_id = "points", double opacity = 1.0);
00420 
00421         /** \brief Set the window title name
00422           * \param[in] name the window title
00423           */
00424         void
00425         setWindowTitle (const std::string& name);
00426 
00427         /** \brief Spin method. Calls the interactor and runs an internal loop. */
00428         void 
00429         spin ();
00430         
00431         /** \brief Spin once method. Calls the interactor and updates the screen once. 
00432           * \param[in] time - How long (in ms) should the visualization loop be allowed to run.
00433           * \param[in] force_redraw - if false it might return without doing anything if the 
00434           * interactor's framerate does not require a redraw yet.
00435           */
00436         void 
00437         spinOnce (int time = 1, bool force_redraw = true);
00438         
00439         /** \brief Register a callback function for keyboard events
00440           * \param[in] callback  the function that will be registered as a callback for a keyboard event
00441           * \param[in] cookie    user data that is passed to the callback
00442           * \return a connection object that allows to disconnect the callback function.
00443           */
00444         boost::signals2::connection 
00445         registerKeyboardCallback (void (*callback) (const pcl::visualization::KeyboardEvent&, void*), 
00446                                   void* cookie = NULL)
00447         {
00448           return (registerKeyboardCallback (boost::bind (callback, _1, cookie)));
00449         }
00450         
00451         /** \brief Register a callback function for keyboard events
00452           * \param[in] callback  the member function that will be registered as a callback for a keyboard event
00453           * \param[in] instance  instance to the class that implements the callback function
00454           * \param[in] cookie    user data that is passed to the callback
00455           * \return a connection object that allows to disconnect the callback function.
00456           */
00457         template<typename T> boost::signals2::connection 
00458         registerKeyboardCallback (void (T::*callback) (const pcl::visualization::KeyboardEvent&, void*), 
00459                                   T& instance, void* cookie = NULL)
00460         {
00461           return (registerKeyboardCallback (boost::bind (callback,  boost::ref (instance), _1, cookie)));
00462         }
00463         
00464         /** \brief Register a callback boost::function for keyboard events
00465           * \param[in] cb the boost function that will be registered as a callback for a keyboard event
00466           * \return a connection object that allows to disconnect the callback function.
00467           */
00468         boost::signals2::connection 
00469         registerKeyboardCallback (boost::function<void (const pcl::visualization::KeyboardEvent&)> cb);
00470 
00471         /** \brief Register a callback boost::function for mouse events
00472           * \param[in] callback  the function that will be registered as a callback for a mouse event
00473           * \param[in] cookie    user data that is passed to the callback
00474           * \return a connection object that allows to disconnect the callback function.
00475           */
00476         boost::signals2::connection 
00477         registerMouseCallback (void (*callback) (const pcl::visualization::MouseEvent&, void*), 
00478                                void* cookie = NULL)
00479         {
00480           return (registerMouseCallback (boost::bind (callback, _1, cookie)));
00481         }
00482         
00483         /** \brief Register a callback function for mouse events
00484           * \param[in] callback  the member function that will be registered as a callback for a mouse event
00485           * \param[in] instance  instance to the class that implements the callback function
00486           * \param[in] cookie    user data that is passed to the callback
00487           * \return a connection object that allows to disconnect the callback function.
00488           */
00489         template<typename T> boost::signals2::connection 
00490         registerMouseCallback (void (T::*callback) (const pcl::visualization::MouseEvent&, void*), 
00491                                T& instance, void* cookie = NULL)
00492         {
00493           return (registerMouseCallback (boost::bind (callback, boost::ref (instance), _1, cookie)));
00494         }
00495 
00496         /** \brief Register a callback function for mouse events
00497           * \param[in] cb the boost function that will be registered as a callback for a mouse event
00498           * \return a connection object that allows to disconnect the callback function.
00499           */        
00500         boost::signals2::connection 
00501         registerMouseCallback (boost::function<void (const pcl::visualization::MouseEvent&)> cb);
00502         
00503         /** \brief Set the position in screen coordinates.
00504           * \param[in] x where to move the window to (X)
00505           * \param[in] y where to move the window to (Y)
00506           */
00507         void
00508         setPosition (int x, int y);
00509 
00510         /** \brief Set the window size in screen coordinates.
00511           * \param[in] xw window size in horizontal (pixels)
00512           * \param[in] yw window size in vertical (pixels)
00513           */
00514         void
00515         setSize (int xw, int yw);
00516 
00517         /** \brief Return the window size in pixels. */
00518         int*
00519         getSize ();
00520 
00521         /** \brief Returns true when the user tried to close the window */
00522         bool
00523         wasStopped () const { return (stopped_); }
00524 
00525         /** \brief Stop the interaction and close the visualizaton window. */
00526         void
00527         close ()
00528         {
00529           stopped_ = true;
00530           // This tends to close the window...
00531 #if ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION <= 4))
00532           interactor_->stopLoop ();
00533 #else
00534           interactor_->TerminateApp ();
00535 #endif
00536         }
00537 
00538         /** \brief Add a circle shape from a point and a radius
00539           * \param[in] x the x coordinate of the circle center
00540           * \param[in] y the y coordinate of the circle center
00541           * \param[in] radius the radius of the circle
00542           * \param[in] layer_id the 2D layer ID where we want the extra information to be drawn. 
00543           * \param[in] opacity the opacity of the layer: 0 for invisible, 1 for opaque. (default: 1.0)
00544           */
00545         bool
00546         addCircle (unsigned int x, unsigned int y, double radius, 
00547                    const std::string &layer_id = "circles", double opacity = 1.0);
00548 
00549         /** \brief Add a circle shape from a point and a radius
00550           * \param[in] x the x coordinate of the circle center
00551           * \param[in] y the y coordinate of the circle center
00552           * \param[in] radius the radius of the circle
00553           * \param[in] r the red channel of the color that the sphere should be rendered with (0.0 -> 1.0)
00554           * \param[in] g the green channel of the color that the sphere should be rendered with (0.0 -> 1.0)
00555           * \param[in] b the blue channel of the color that the sphere should be rendered with (0.0 -> 1.0)
00556           * \param[in] layer_id the 2D layer ID where we want the extra information to be drawn. 
00557           * \param[in] opacity the opacity of the layer: 0 for invisible, 1 for opaque. (default: 1.0)
00558           */
00559         bool
00560         addCircle (unsigned int x, unsigned int y, double radius, 
00561                    double r, double g, double b,
00562                    const std::string &layer_id = "circles", double opacity = 1.0);
00563 
00564         /** \brief Add a 2D box and color its edges with a given color
00565           * \param[in] min_pt the X,Y min coordinate
00566           * \param[in] max_pt the X,Y max coordinate
00567           * \param[in] layer_id the 2D layer ID where we want the extra information to be drawn. 
00568           * \param[in] opacity the opacity of the layer: 0 for invisible, 1 for opaque. (default: 1.0)
00569           */
00570         bool
00571         addRectangle (const pcl::PointXY &min_pt, const pcl::PointXY &max_pt,
00572                       const std::string &layer_id = "rectangles", double opacity = 1.0);
00573 
00574         /** \brief Add a 2D box and color its edges with a given color
00575           * \param[in] min_pt the X,Y min coordinate
00576           * \param[in] max_pt the X,Y max coordinate
00577           * \param[in] r the red channel of the color that the box should be rendered with (0.0 -> 1.0)
00578           * \param[in] g the green channel of the color that the box should be rendered with (0.0 -> 1.0)
00579           * \param[in] b the blue channel of the color that the box should be rendered with (0.0 -> 1.0)
00580           * \param[in] layer_id the 2D layer ID where we want the extra information to be drawn. 
00581           * \param[in] opacity the opacity of the layer: 0 for invisible, 1 for opaque. (default: 1.0)
00582           */
00583         bool
00584         addRectangle (const pcl::PointXY &min_pt, const pcl::PointXY &max_pt,
00585                       double r, double g, double b,
00586                       const std::string &layer_id = "rectangles", double opacity = 1.0);
00587 
00588         /** \brief Add a 2D box and color its edges with a given color
00589           * \param[in] x_min the X min coordinate
00590           * \param[in] x_max the X max coordinate
00591           * \param[in] y_min the Y min coordinate
00592           * \param[in] y_max the Y max coordinate 
00593           * \param[in] layer_id the 2D layer ID where we want the extra information to be drawn. 
00594           * \param[in] opacity the opacity of the layer: 0 for invisible, 1 for opaque. (default: 1.0)
00595           */
00596         bool
00597         addRectangle (unsigned int x_min, unsigned int x_max, unsigned int y_min, unsigned int y_max,  
00598                       const std::string &layer_id = "rectangles", double opacity = 1.0);
00599 
00600         /** \brief Add a 2D box and color its edges with a given color
00601           * \param[in] x_min the X min coordinate
00602           * \param[in] x_max the X max coordinate
00603           * \param[in] y_min the Y min coordinate
00604           * \param[in] y_max the Y max coordinate 
00605           * \param[in] r the red channel of the color that the box should be rendered with (0.0 -> 1.0)
00606           * \param[in] g the green channel of the color that the box should be rendered with (0.0 -> 1.0)
00607           * \param[in] b the blue channel of the color that the box should be rendered with (0.0 -> 1.0)
00608           * \param[in] layer_id the 2D layer ID where we want the extra information to be drawn. 
00609           * \param[in] opacity the opacity of the layer: 0 for invisible, 1 for opaque. (default: 1.0)
00610           */
00611         bool
00612         addRectangle (unsigned int x_min, unsigned int x_max, unsigned int y_min, unsigned int y_max,  
00613                       double r, double g, double b,
00614                       const std::string &layer_id = "rectangles", double opacity = 1.0);
00615 
00616         /** \brief Add a 2D box and color its edges with a given color
00617           * \param[in] image the organized point cloud dataset containing the image data
00618           * \param[in] min_pt the X,Y min coordinate
00619           * \param[in] max_pt the X,Y max coordinate
00620           * \param[in] layer_id the 2D layer ID where we want the extra information to be drawn. 
00621           * \param[in] opacity the opacity of the layer: 0 for invisible, 1 for opaque. (default: 1.0)
00622           */
00623         template <typename T> bool
00624         addRectangle (const typename pcl::PointCloud<T>::ConstPtr &image, 
00625                       const T &min_pt, const T &max_pt,
00626                       const std::string &layer_id = "rectangles", double opacity = 1.0);
00627 
00628         /** \brief Add a 2D box and color its edges with a given color
00629           * \param[in] image the organized point cloud dataset containing the image data
00630           * \param[in] min_pt the X,Y min coordinate
00631           * \param[in] max_pt the X,Y max coordinate
00632           * \param[in] r the red channel of the color that the box should be rendered with (0.0 -> 1.0)
00633           * \param[in] g the green channel of the color that the box should be rendered with (0.0 -> 1.0)
00634           * \param[in] b the blue channel of the color that the box should be rendered with (0.0 -> 1.0)
00635           * \param[in] layer_id the 2D layer ID where we want the extra information to be drawn. 
00636           * \param[in] opacity the opacity of the layer: 0 for invisible, 1 for opaque. (default: 1.0)
00637           */
00638         template <typename T> bool
00639         addRectangle (const typename pcl::PointCloud<T>::ConstPtr &image, 
00640                       const T &min_pt, const T &max_pt,
00641                       double r, double g, double b,
00642                       const std::string &layer_id = "rectangles", double opacity = 1.0);
00643 
00644         /** \brief Add a 2D box that contains a given image mask and color its edges
00645           * \param[in] image the organized point cloud dataset containing the image data
00646           * \param[in] mask the point data representing the mask that we want to draw
00647           * \param[in] r the red channel of the color that the mask should be rendered with 
00648           * \param[in] g the green channel of the color that the mask should be rendered with
00649           * \param[in] b the blue channel of the color that the mask should be rendered with
00650           * \param[in] layer_id the 2D layer ID where we want the extra information to be drawn.
00651           * \param[in] opacity the opacity of the layer: 0 for invisible, 1 for opaque. (default: 1.0)
00652           */
00653         template <typename T> bool
00654         addRectangle (const typename pcl::PointCloud<T>::ConstPtr &image, const pcl::PointCloud<T> &mask, 
00655                       double r, double g, double b, 
00656                       const std::string &layer_id = "rectangles", double opacity = 1.0);
00657 
00658         /** \brief Add a 2D box that contains a given image mask and color its edges in red
00659           * \param[in] image the organized point cloud dataset containing the image data
00660           * \param[in] mask the point data representing the mask that we want to draw
00661           * \param[in] layer_id the 2D layer ID where we want the extra information to be drawn.
00662           * \param[in] opacity the opacity of the layer: 0 for invisible, 1 for opaque. (default: 1.0)
00663           */
00664         template <typename T> bool
00665         addRectangle (const typename pcl::PointCloud<T>::ConstPtr &image, const pcl::PointCloud<T> &mask, 
00666                       const std::string &layer_id = "image_mask", double opacity = 1.0);
00667 
00668         /** \brief Add a 2D box and fill it in with a given color
00669           * \param[in] x_min the X min coordinate
00670           * \param[in] x_max the X max coordinate
00671           * \param[in] y_min the Y min coordinate
00672           * \param[in] y_max the Y max coordinate 
00673           * \param[in] layer_id the 2D layer ID where we want the extra information to be drawn. 
00674           * \param[in] opacity the opacity of the layer: 0 for invisible, 1 for opaque. (default: 0.5)
00675           */
00676         bool
00677         addFilledRectangle (unsigned int x_min, unsigned int x_max, unsigned int y_min, unsigned int y_max,  
00678                             const std::string &layer_id = "boxes", double opacity = 0.5);
00679 
00680         /** \brief Add a 2D box and fill it in with a given color
00681           * \param[in] x_min the X min coordinate
00682           * \param[in] x_max the X max coordinate
00683           * \param[in] y_min the Y min coordinate
00684           * \param[in] y_max the Y max coordinate 
00685           * \param[in] r the red channel of the color that the box should be rendered with (0.0 -> 1.0)
00686           * \param[in] g the green channel of the color that the box should be rendered with (0.0 -> 1.0)
00687           * \param[in] b the blue channel of the color that the box should be rendered with (0.0 -> 1.0)
00688           * \param[in] layer_id the 2D layer ID where we want the extra information to be drawn. 
00689           * \param[in] opacity the opacity of the layer: 0 for invisible, 1 for opaque. (default: 0.5)
00690           */
00691         bool
00692         addFilledRectangle (unsigned int x_min, unsigned int x_max, unsigned int y_min, unsigned int y_max,  
00693                             double r, double g, double b,
00694                             const std::string &layer_id = "boxes", double opacity = 0.5);
00695 
00696         /** \brief Add a 2D line with a given color
00697           * \param[in] x_min the X min coordinate
00698           * \param[in] y_min the Y min coordinate
00699           * \param[in] x_max the X max coordinate
00700           * \param[in] y_max the Y max coordinate 
00701           * \param[in] r the red channel of the color that the line should be rendered with (0.0 -> 1.0)
00702           * \param[in] g the green channel of the color that the line should be rendered with (0.0 -> 1.0)
00703           * \param[in] b the blue channel of the color that the line should be rendered with (0.0 -> 1.0)
00704           * \param[in] layer_id the 2D layer ID where we want the extra information to be drawn. 
00705           * \param[in] opacity the opacity of the layer: 0 for invisible, 1 for opaque. (default: 1.0)
00706           */
00707         bool
00708         addLine (unsigned int x_min, unsigned int y_min, unsigned int x_max, unsigned int y_max,
00709                  double r, double g, double b, 
00710                  const std::string &layer_id = "line", double opacity = 1.0);
00711 
00712         /** \brief Add a 2D line with a given color
00713           * \param[in] x_min the X min coordinate
00714           * \param[in] y_min the Y min coordinate
00715           * \param[in] x_max the X max coordinate
00716           * \param[in] y_max the Y max coordinate 
00717           * \param[in] layer_id the 2D layer ID where we want the extra information to be drawn. 
00718           * \param[in] opacity the opacity of the layer: 0 for invisible, 1 for opaque. (default: 1.0)
00719           */
00720         bool
00721         addLine (unsigned int x_min, unsigned int y_min, unsigned int x_max, unsigned int y_max,
00722                  const std::string &layer_id = "line", double opacity = 1.0);
00723 
00724 
00725         /** \brief Add a generic 2D mask to an image 
00726           * \param[in] image the organized point cloud dataset containing the image data
00727           * \param[in] mask the point data representing the mask that we want to draw
00728           * \param[in] r the red channel of the color that the mask should be rendered with 
00729           * \param[in] g the green channel of the color that the mask should be rendered with
00730           * \param[in] b the blue channel of the color that the mask should be rendered with
00731           * \param[in] layer_id the 2D layer ID where we want the extra information to be drawn.
00732           * \param[in] opacity the opacity of the layer: 0 for invisible, 1 for opaque. (default: 0.5)
00733           */
00734         template <typename T> bool
00735         addMask (const typename pcl::PointCloud<T>::ConstPtr &image, const pcl::PointCloud<T> &mask, 
00736                  double r, double g, double b, 
00737                  const std::string &layer_id = "image_mask", double opacity = 0.5);
00738 
00739         /** \brief Add a generic 2D mask to an image (colored in red)
00740           * \param[in] image the organized point cloud dataset containing the image data
00741           * \param[in] mask the point data representing the mask that we want to draw
00742           * \param[in] layer_id the 2D layer ID where we want the extra information to be drawn.
00743           * \param[in] opacity the opacity of the layer: 0 for invisible, 1 for opaque. (default: 0.5)
00744           */
00745         template <typename T> bool
00746         addMask (const typename pcl::PointCloud<T>::ConstPtr &image, const pcl::PointCloud<T> &mask, 
00747                  const std::string &layer_id = "image_mask", double opacity = 0.5);
00748 
00749         /** \brief Add a generic 2D planar polygon to an image 
00750           * \param[in] image the organized point cloud dataset containing the image data
00751           * \param[in] polygon the point data representing the polygon that we want to draw. 
00752           * A line will be drawn from each point to the next in the dataset.
00753           * \param[in] r the red channel of the color that the polygon should be rendered with 
00754           * \param[in] g the green channel of the color that the polygon should be rendered with
00755           * \param[in] b the blue channel of the color that the polygon should be rendered with
00756           * \param[in] layer_id the 2D layer ID where we want the extra information to be drawn.
00757           * \param[in] opacity the opacity of the layer: 0 for invisible, 1 for opaque. (default: 1.0)
00758           */
00759         template <typename T> bool
00760         addPlanarPolygon (const typename pcl::PointCloud<T>::ConstPtr &image, const pcl::PlanarPolygon<T> &polygon, 
00761                           double r, double g, double b, 
00762                           const std::string &layer_id = "planar_polygon", double opacity = 1.0);
00763 
00764         /** \brief Add a generic 2D planar polygon to an image 
00765           * \param[in] image the organized point cloud dataset containing the image data
00766           * \param[in] polygon the point data representing the polygon that we want to draw. 
00767           * A line will be drawn from each point to the next in the dataset.
00768           * \param[in] layer_id the 2D layer ID where we want the extra information to be drawn.
00769           * \param[in] opacity the opacity of the layer: 0 for invisible, 1 for opaque. (default: 1.0)
00770           */
00771         template <typename T> bool
00772         addPlanarPolygon (const typename pcl::PointCloud<T>::ConstPtr &image, const pcl::PlanarPolygon<T> &polygon, 
00773                           const std::string &layer_id = "planar_polygon", double opacity = 1.0);
00774 
00775         /** \brief Add a new 2D rendering layer to the viewer. 
00776           * \param[in] layer_id the name of the layer
00777           * \param[in] width the width of the layer
00778           * \param[in] height the height of the layer
00779           * \param[in] opacity the opacity of the layer: 0 for invisible, 1 for opaque. (default: 0.5)
00780           */
00781         bool
00782         addLayer (const std::string &layer_id, int width, int height, double opacity = 0.5);
00783 
00784         /** \brief Remove a 2D layer given by its ID.
00785           * \param[in] layer_id the name of the layer
00786           */
00787         void
00788         removeLayer (const std::string &layer_id);
00789 
00790         /** \brief Add the specified correspondences to the display.
00791           * \param[in] source_img The source RGB image
00792           * \param[in] target_img The target RGB image
00793           * \param[in] correspondences The list of correspondences to display.
00794           * \param[in] nth display only the Nth correspondence (e.g., skip the rest)
00795           * \param[in] layer_id the layer id (default: "correspondences")
00796           */
00797         template <typename PointT> bool
00798         showCorrespondences (const pcl::PointCloud<PointT> &source_img,
00799                              const pcl::PointCloud<PointT> &target_img,
00800                              const pcl::Correspondences &correspondences,
00801                              int nth = 1,
00802                              const std::string &layer_id = "correspondences");
00803 
00804       protected:
00805         /** \brief Trigger a render call. */
00806         void
00807         render ();
00808 
00809         /** \brief Convert the Intensity information in a PointCloud<Intensity> to an unsigned char array
00810           * \param[in] cloud the input cloud containing the grayscale intensity information
00811           * \param[out] data a boost shared array of unsigned char type
00812           * \note The method assumes that the data array has already been allocated and
00813           * contains enough space to copy all the data from cloud!
00814           */
00815         void
00816         convertIntensityCloudToUChar (const pcl::PointCloud<pcl::Intensity> &cloud,
00817                                 boost::shared_array<unsigned char> data);
00818 
00819         /** \brief Convert the Intensity8u information in a PointCloud<Intensity8u> to an unsigned char array
00820           * \param[in] cloud the input cloud containing the grayscale intensity information
00821           * \param[out] data a boost shared array of unsigned char type
00822           * \note The method assumes that the data array has already been allocated and
00823           * contains enough space to copy all the data from cloud!
00824           */
00825         void
00826         convertIntensityCloud8uToUChar (const pcl::PointCloud<pcl::Intensity8u> &cloud,
00827                                 boost::shared_array<unsigned char> data);
00828 
00829         /** \brief Convert the RGB information in a PointCloud<T> to an unsigned char array
00830           * \param[in] cloud the input cloud containing the RGB information
00831           * \param[out] data a boost shared array of unsigned char type
00832           * \note The method assumes that the data array has already been allocated and
00833           * contains enough space to copy all the data from cloud!
00834           */
00835         template <typename T> void
00836         convertRGBCloudToUChar (const pcl::PointCloud<T> &cloud,
00837                                 boost::shared_array<unsigned char> &data);
00838 
00839         /** \brief Set the stopped flag back to false */
00840         void
00841         resetStoppedFlag () { stopped_ = false; }
00842 
00843         /** \brief Fire up a mouse event with a specified event ID
00844           * \param[int] event_id the id of the event
00845           */
00846         void 
00847         emitMouseEvent (unsigned long event_id);
00848         
00849         /** \brief Fire up a keyboard event with a specified event ID
00850           * \param[int] event_id the id of the event
00851           */
00852         void 
00853         emitKeyboardEvent (unsigned long event_id);
00854         
00855         // Callbacks used to register for vtk command
00856         static void 
00857         MouseCallback (vtkObject*, unsigned long eid, void* clientdata, void *calldata);
00858         static void 
00859         KeyboardCallback (vtkObject*, unsigned long eid, void* clientdata, void *calldata);
00860         
00861       protected: // types
00862         struct ExitMainLoopTimerCallback : public vtkCommand
00863         {
00864           ExitMainLoopTimerCallback () : right_timer_id (), window () {}
00865 
00866           static ExitMainLoopTimerCallback* New ()
00867           {
00868             return (new ExitMainLoopTimerCallback);
00869           }
00870           virtual void 
00871           Execute (vtkObject* vtkNotUsed (caller), unsigned long event_id, void* call_data)
00872           {
00873             if (event_id != vtkCommand::TimerEvent)
00874               return;
00875             int timer_id = *static_cast<int*> (call_data);
00876             if (timer_id != right_timer_id)
00877               return;
00878 #if ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION <= 4))
00879             window->interactor_->stopLoop ();
00880 #else
00881             window->interactor_->TerminateApp ();
00882 #endif
00883           }
00884           int right_timer_id;
00885           ImageViewer* window;
00886         };
00887         struct ExitCallback : public vtkCommand
00888         {
00889           ExitCallback () : window () {}
00890 
00891           static ExitCallback* New ()
00892           {
00893             return (new ExitCallback);
00894           }
00895           virtual void 
00896           Execute (vtkObject*, unsigned long event_id, void*)
00897           {
00898             if (event_id != vtkCommand::ExitEvent)
00899               return;
00900             window->stopped_ = true;
00901 #if ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION <= 4))
00902             window->interactor_->stopLoop ();
00903 #else
00904             window->interactor_->TerminateApp ();
00905 #endif
00906           }
00907           ImageViewer* window;
00908         };
00909 
00910     private:
00911         /** \brief Internal structure describing a layer. */
00912         struct Layer
00913         {
00914           Layer () : actor (), layer_name () {}
00915           vtkSmartPointer<vtkContextActor> actor;
00916           std::string layer_name;
00917         };
00918 
00919         typedef std::vector<Layer> LayerMap;
00920 
00921         /** \brief Add a new 2D rendering layer to the viewer. 
00922           * \param[in] layer_id the name of the layer
00923           * \param[in] width the width of the layer
00924           * \param[in] height the height of the layer
00925           * \param[in] opacity the opacity of the layer: 0 for invisible, 1 for opaque. (default: 0.5)
00926           * \param[in] fill_box set to true to fill in the image with one black box before starting
00927           */
00928         LayerMap::iterator
00929         createLayer (const std::string &layer_id, int width, int height, double opacity = 0.5, bool fill_box = true);
00930 
00931         boost::signals2::signal<void (const pcl::visualization::MouseEvent&)> mouse_signal_;
00932         boost::signals2::signal<void (const pcl::visualization::KeyboardEvent&)> keyboard_signal_;
00933         
00934 #if ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION <= 4))
00935         vtkSmartPointer<PCLVisualizerInteractor> interactor_;
00936 #else
00937         vtkSmartPointer<vtkRenderWindowInteractor> interactor_;
00938 #endif
00939         vtkSmartPointer<vtkCallbackCommand> mouse_command_;
00940         vtkSmartPointer<vtkCallbackCommand> keyboard_command_;
00941 
00942         /** \brief Callback object enabling us to leave the main loop, when a timer fires. */
00943         vtkSmartPointer<ExitMainLoopTimerCallback> exit_main_loop_timer_callback_;
00944         vtkSmartPointer<ExitCallback> exit_callback_;
00945 
00946         /** \brief The ImageViewer widget. */
00947         vtkSmartPointer<vtkImageViewer> image_viewer_;
00948 
00949         /** \brief The render window. */
00950         vtkSmartPointer<vtkRenderWindow> win_;
00951 
00952         /** \brief The renderer. */
00953         vtkSmartPointer<vtkRenderer> ren_;
00954 
00955 #if ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION >= 10))
00956         /** \brief Global prop. This is the actual "actor". */
00957         vtkSmartPointer<vtkImageSlice> slice_;
00958 #endif
00959         /** \brief The interactor style. */
00960         vtkSmartPointer<ImageViewerInteractorStyle> interactor_style_;
00961 
00962         /** \brief The data array representing the image. Used internally. */
00963         boost::shared_array<unsigned char> data_;
00964   
00965         /** \brief The data array (representing the image) size. Used internally. */
00966         size_t data_size_;
00967 
00968         /** \brief Set to false if the interaction loop is running. */
00969         bool stopped_;
00970 
00971         /** \brief Global timer ID. Used in destructor only. */
00972         int timer_id_;
00973 
00974         // /** \brief Internal blender used to overlay 2D geometry over the image. */
00975         // vtkSmartPointer<vtkImageBlend> blend_;
00976  
00977         /** \brief Internal list with different 2D layers shapes. */
00978         LayerMap layer_map_;
00979 
00980         /** \brief Image reslice, used for flipping the image. */
00981         vtkSmartPointer<vtkImageFlip> algo_;
00982 
00983         /** \brief Internal data array. Used everytime add***Image is called. 
00984           * Cleared, everytime the render loop is executed. 
00985           */
00986         std::vector<unsigned char*> image_data_;
00987 
00988         struct LayerComparator
00989         {
00990           LayerComparator (const std::string &str) : str_ (str) {}
00991           const std::string &str_;
00992 
00993           bool
00994           operator () (const Layer &layer)
00995           {
00996             return (layer.layer_name == str_);
00997           }
00998         };        
00999         
01000       public:
01001         EIGEN_MAKE_ALIGNED_OPERATOR_NEW
01002     };
01003   }
01004 }
01005 
01006 #include <pcl/visualization/impl/image_viewer.hpp>
01007 
01008 #endif  /* __IMAGE_VISUALIZER_H__ */
01009