Point Cloud Library (PCL)  1.5.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
point_cloud.h
Go to the documentation of this file.
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  *
00007  *  All rights reserved.
00008  *
00009  *  Redistribution and use in source and binary forms, with or without
00010  *  modification, are permitted provided that the following conditions
00011  *  are met:
00012  *
00013  *   * Redistributions of source code must retain the above copyright
00014  *     notice, this list of conditions and the following disclaimer.
00015  *   * Redistributions in binary form must reproduce the above
00016  *     copyright notice, this list of conditions and the following
00017  *     disclaimer in the documentation and/or other materials provided
00018  *     with the distribution.
00019  *   * Neither the name of Willow Garage, Inc. nor the names of its
00020  *     contributors may be used to endorse or promote products derived
00021  *     from this software without specific prior written permission.
00022  *
00023  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00026  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00027  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00028  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00029  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00032  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00033  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00034  *  POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  * $Id: point_cloud.h 4702 2012-02-23 09:39:33Z gedikli $
00037  *
00038  */
00039 
00040 #ifndef PCL_POINT_CLOUD_H_
00041 #define PCL_POINT_CLOUD_H_
00042 
00043 #include <Eigen/StdVector>
00044 #include <Eigen/Geometry>
00045 #include <cstddef>
00046 #include <std_msgs/Header.h>
00047 #include <pcl/pcl_macros.h>
00048 #include <pcl/exceptions.h>
00049 #include <pcl/cloud_properties.h>
00050 #include <pcl/channel_properties.h>
00051 #include <pcl/point_traits.h>
00052 #include <pcl/for_each_type.h>
00053 #include <boost/shared_ptr.hpp>
00054 #include <map>
00055 #include <boost/mpl/size.hpp>
00056 
00057 namespace pcl
00058 {
00059   namespace detail
00060   {
00061     struct FieldMapping
00062     {
00063       size_t serialized_offset;
00064       size_t struct_offset;
00065       size_t size;
00066     };
00067   } // namespace detail
00068 
00069   // Forward declarations
00070   template <typename PointT> class PointCloud;
00071   typedef std::vector<detail::FieldMapping> MsgFieldMap;
00072  
00074 
00075   template <typename PointOutT>
00076   struct NdCopyEigenPointFunctor
00077   {
00078     typedef typename traits::POD<PointOutT>::type Pod;
00079     
00084     NdCopyEigenPointFunctor (const Eigen::VectorXf &p1, PointOutT &p2)
00085       : p1_ (p1),
00086         p2_ (reinterpret_cast<Pod&>(p2)),
00087         f_idx_ (0) { }
00088 
00090     template<typename Key> inline void 
00091     operator() ()
00092     {
00093       //boost::fusion::at_key<Key> (p2_) = p1_[f_idx_++];
00094       typedef typename pcl::traits::datatype<PointOutT, Key>::type T;
00095       uint8_t* data_ptr = reinterpret_cast<uint8_t*>(&p2_) + pcl::traits::offset<PointOutT, Key>::value;
00096       *reinterpret_cast<T*>(data_ptr) = p1_[f_idx_++];
00097     }
00098 
00099     private:
00100       const Eigen::VectorXf &p1_;
00101       Pod &p2_;
00102       int f_idx_;
00103     public:
00104       EIGEN_MAKE_ALIGNED_OPERATOR_NEW
00105    };
00106 
00108 
00109   template <typename PointInT>
00110   struct NdCopyPointEigenFunctor
00111   {
00112     typedef typename traits::POD<PointInT>::type Pod;
00113     
00118      NdCopyPointEigenFunctor (const PointInT &p1, Eigen::VectorXf &p2)
00119       : p1_ (reinterpret_cast<const Pod&>(p1)), p2_ (p2), f_idx_ (0) { }
00120 
00122     template<typename Key> inline void 
00123     operator() ()
00124     {
00125       //p2_[f_idx_++] = boost::fusion::at_key<Key> (p1_);
00126       typedef typename pcl::traits::datatype<PointInT, Key>::type T;
00127       const uint8_t* data_ptr = reinterpret_cast<const uint8_t*>(&p1_) + pcl::traits::offset<PointInT, Key>::value;
00128       p2_[f_idx_++] = *reinterpret_cast<const T*>(data_ptr);
00129     }
00130 
00131     private:
00132       const Pod &p1_;
00133       Eigen::VectorXf &p2_;
00134       int f_idx_;
00135     public:
00136       EIGEN_MAKE_ALIGNED_OPERATOR_NEW
00137   };
00138 
00139   namespace detail
00140   {
00141     template <typename PointT> boost::shared_ptr<pcl::MsgFieldMap>&
00142     getMapping (pcl::PointCloud<PointT>& p);
00143   } // namespace detail
00144 
00178   template <typename PointT>
00179   class PointCloud
00180   {
00181     public:
00186       PointCloud () : 
00187         header (), width (0), height (0), is_dense (true),
00188         sensor_origin_ (Eigen::Vector4f::Zero ()), sensor_orientation_ (Eigen::Quaternionf::Identity ()),
00189         mapping_ ()
00190       {}
00191 
00195       PointCloud (PointCloud<PointT> &pc) : 
00196         header (), width (0), height (0), is_dense (true), 
00197         sensor_origin_ (Eigen::Vector4f::Zero ()), sensor_orientation_ (Eigen::Quaternionf::Identity ()),
00198         mapping_ ()
00199       {
00200         *this = pc;
00201       }
00202 
00206       PointCloud (const PointCloud<PointT> &pc) : 
00207         header (), width (0), height (0), is_dense (true), 
00208         sensor_origin_ (Eigen::Vector4f::Zero ()), sensor_orientation_ (Eigen::Quaternionf::Identity ()),
00209         mapping_ ()
00210       {
00211         *this = pc;
00212       }
00213 
00218       PointCloud (const PointCloud<PointT> &pc, 
00219                   const std::vector<int> &indices) :
00220         header (pc.header), points (indices.size ()), width (indices.size ()), height (1), is_dense (pc.is_dense),
00221         sensor_origin_ (pc.sensor_origin_), sensor_orientation_ (pc.sensor_orientation_),
00222         mapping_ ()
00223       {
00224         // Copy the obvious
00225         assert (indices.size () <= pc.size ());
00226         for (size_t i = 0; i < indices.size (); i++)
00227           points[i] = pc.points[indices[i]];
00228       }
00229 
00235       PointCloud (uint32_t width_, uint32_t height_, const PointT& value_ = PointT ())
00236         : header ()
00237         , points (width_ * height_, value_)
00238         , width (width_)
00239         , height (height_)
00240         , is_dense (true)
00241         , sensor_origin_ (Eigen::Vector4f::Zero ())
00242         , sensor_orientation_ (Eigen::Quaternionf::Identity ())
00243         , mapping_ ()
00244       {}
00245 
00247       virtual ~PointCloud () {}
00248 
00250 
00254       inline PointCloud&
00255       operator += (const PointCloud& rhs)
00256       {
00257         // Make the resultant point cloud take the newest stamp
00258         if (rhs.header.stamp > header.stamp)
00259           header.stamp = rhs.header.stamp;
00260 
00261         size_t nr_points = points.size ();
00262         points.resize (nr_points + rhs.points.size ());
00263         for (size_t i = nr_points; i < points.size (); ++i)
00264           points[i] = rhs.points[i - nr_points];
00265 
00266         width    = (uint32_t) points.size ();
00267         height   = 1;
00268         if (rhs.is_dense && is_dense)
00269           is_dense = true;
00270         else
00271           is_dense = false;
00272         return (*this);
00273       }
00274 
00276 
00280       inline const PointCloud
00281       operator + (const PointCloud& rhs)
00282       {
00283         return (PointCloud (*this) += rhs);
00284       }
00285       
00287 
00292       inline const PointT&
00293       at (int column, int row) const
00294       {
00295         if (this->height > 1)
00296           return (points.at (row * this->width + column));
00297         else
00298           throw IsNotDenseException ("Can't use 2D indexing with a unorganized point cloud");
00299       }
00300 
00306       inline PointT&
00307       at (int column, int row)
00308       {
00309         if (this->height > 1)
00310           return (points.at (row * this->width + column));
00311         else
00312           throw IsNotDenseException ("Can't use 2D indexing with a unorganized point cloud");
00313       }
00314 
00316 
00321       inline const PointT&
00322       operator () (size_t column, size_t row) const
00323       {
00324         return (points[row * this->width + column]);
00325       }
00326 
00332       inline PointT&
00333       operator () (size_t column, size_t row)
00334       {
00335         return (points[row * this->width + column]);
00336       }
00337 
00339 
00342       inline bool
00343       isOrganized () const
00344       {
00345         return (height != 1);
00346       }
00347       
00349 
00364       inline Eigen::Map<Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> > 
00365       getMatrixXfMap (int dim, int stride, int offset)
00366       {
00367         if (Eigen::MatrixXf::Flags & Eigen::RowMajorBit)
00368           return (Eigen::Map<Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> >((float*)(&points[0])+offset, points.size (), dim, Eigen::OuterStride<> (stride)));
00369         else
00370           return (Eigen::Map<Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> >((float*)(&points[0])+offset, dim, points.size (), Eigen::OuterStride<> (stride)));
00371       }
00372 
00388       inline const Eigen::Map<const Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> >
00389       getMatrixXfMap (int dim, int stride, int offset) const
00390       {
00391         if (Eigen::MatrixXf::Flags & Eigen::RowMajorBit)
00392           return (Eigen::Map<const Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> >((float*)(&points[0])+offset, points.size (), dim, Eigen::OuterStride<> (stride)));
00393         else
00394           return (Eigen::Map<const Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> >((float*)(&points[0])+offset, dim, points.size (), Eigen::OuterStride<> (stride)));                
00395       }
00396 
00398 
00403       inline Eigen::Map<Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> >
00404       getMatrixXfMap () 
00405       {
00406         return (getMatrixXfMap (sizeof (PointT) / sizeof (float),  sizeof (PointT) / sizeof (float), 0));
00407       }
00408 
00414       inline const Eigen::Map<const Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> >
00415       getMatrixXfMap () const
00416       {
00417         return (getMatrixXfMap (sizeof (PointT) / sizeof (float),  sizeof (PointT) / sizeof (float), 0));
00418       }
00419 
00421       std_msgs::Header header;
00422 
00424       std::vector<PointT, Eigen::aligned_allocator<PointT> > points;
00425 
00427       uint32_t width;
00429       uint32_t height;
00430 
00432       bool is_dense;
00433 
00435       Eigen::Vector4f    sensor_origin_;
00437       Eigen::Quaternionf sensor_orientation_;
00438 
00439       typedef PointT PointType;  // Make the template class available from the outside
00440       typedef std::vector<PointT, Eigen::aligned_allocator<PointT> > VectorType;
00441       typedef boost::shared_ptr<PointCloud<PointT> > Ptr;
00442       typedef boost::shared_ptr<const PointCloud<PointT> > ConstPtr;
00443 
00444       // iterators
00445       typedef typename VectorType::iterator iterator;
00446       typedef typename VectorType::const_iterator const_iterator;
00447       inline iterator begin () { return (points.begin ()); }
00448       inline iterator end ()   { return (points.end ()); }
00449       inline const_iterator begin () const { return (points.begin ()); }
00450       inline const_iterator end () const  { return (points.end ()); }
00451 
00452       //capacity
00453       inline size_t size () const { return (points.size ()); }
00454       inline void reserve (size_t n) { points.reserve (n); }
00455       inline void resize (size_t n) { points.resize (n); }
00456       inline bool empty () const { return points.empty (); }
00457 
00458       //element access
00459       inline const PointT& operator[] (size_t n) const { return points[n]; }
00460       inline PointT& operator[] (size_t n) { return points[n]; }
00461       inline const PointT& at (size_t n) const { return points.at (n); }
00462       inline PointT& at (size_t n) { return points.at (n); }
00463       inline const PointT& front () const { return points.front (); }
00464       inline PointT& front () { return points.front (); }
00465       inline const PointT& back () const { return points.back (); }
00466       inline PointT& back () { return points.back (); }
00467 
00472       inline void 
00473       push_back (const PointT& pt)
00474       {
00475         points.push_back (pt);
00476         width = points.size ();
00477         height = 1;
00478       }
00479 
00486       inline iterator 
00487       insert (iterator position, const PointT& pt)
00488       {
00489         iterator it = points.insert (position, pt);
00490         width = points.size ();
00491         height = 1;
00492         return (it);
00493       }
00494 
00501       inline void 
00502       insert (iterator position, size_t n, const PointT& pt)
00503       {
00504         points.insert (position, n, pt);
00505         width = points.size ();
00506         height = 1;
00507       }
00508 
00515       template <class InputIterator> inline void 
00516       insert (iterator position, InputIterator first, InputIterator last)
00517       {
00518         points.insert (position, first, last);
00519         width = points.size ();
00520         height = 1;
00521       }
00522 
00528       inline iterator 
00529       erase (iterator position)
00530       {
00531         iterator it = points.erase (position); 
00532         width = points.size ();
00533         height = 1;
00534         return (it);
00535       }
00536 
00543       inline iterator 
00544       erase (iterator first, iterator last)
00545       {
00546         iterator it = points.erase (first, last);
00547         width = points.size ();
00548         height = 1;
00549         return (it);
00550       }
00551 
00555       inline void 
00556       swap (PointCloud<PointT> &rhs)
00557       {
00558         this->points.swap (rhs.points);
00559         std::swap (width, rhs.width);
00560         std::swap (height, rhs.height);
00561         std::swap (is_dense, rhs.is_dense);
00562         std::swap (sensor_origin_, rhs.sensor_origin_);
00563         std::swap (sensor_orientation_, rhs.sensor_orientation_);
00564       }
00565 
00567       inline void 
00568       clear ()
00569       {
00570         points.clear ();
00571         width = 0;
00572         height = 0;
00573       }
00574 
00580       inline Ptr 
00581       makeShared () const { return Ptr (new PointCloud<PointT> (*this)); }
00582 
00583     protected:
00584       // This is motivated by ROS integration. Users should not need to access mapping_.
00585       boost::shared_ptr<MsgFieldMap> mapping_;
00586 
00587       friend boost::shared_ptr<MsgFieldMap>& detail::getMapping<PointT>(pcl::PointCloud<PointT> &p);
00588 
00589     public:
00590       EIGEN_MAKE_ALIGNED_OPERATOR_NEW
00591   };
00592 
00611   template <>
00612   class PointCloud<Eigen::MatrixXf> 
00613   {
00614     public:
00618       PointCloud () : 
00619         properties (), points (Eigen::MatrixXf (0, 0)), channels (), width (0), height (0), is_dense (true)
00620       {}
00621 
00625       PointCloud (PointCloud<Eigen::MatrixXf> &pc) :
00626         properties (), points (Eigen::MatrixXf (0, 0)), channels (), width (0), height (0), is_dense (true)
00627       {
00628         *this = pc;
00629       }
00630  
00634       template <typename PointT>
00635       PointCloud (PointCloud<PointT> &pc) :
00636         properties (), points (Eigen::MatrixXf (0, 0)), channels (), 
00637         width (pc.width), height (pc.height), is_dense (pc.is_dense)
00638       {
00639         // Copy the obvious
00640         properties.acquisition_time   = pc.header.stamp;
00641         properties.sensor_origin      = pc.sensor_origin_;//.head<3> ();
00642         properties.sensor_orientation = pc.sensor_orientation_;
00643 
00644         typedef typename pcl::traits::fieldList<PointT>::type FieldList;
00645         // Copy the fields
00646         pcl::for_each_type <FieldList> (CopyFieldsChannelProperties <PointT> (channels));
00647       
00648         // Resize the array
00649         points.resize (pc.points.size (), boost::mpl::size<FieldList>::value);
00650 
00651         for (size_t cp = 0; cp < pc.points.size (); ++cp)
00652           pcl::for_each_type <FieldList> (NdCopyPointEigenFunctor<PointT, Eigen::MatrixXf::RowXpr> (pc.points[cp], points.row (cp)));
00653       }
00654  
00658       PointCloud (const PointCloud<Eigen::MatrixXf> &pc) :
00659         properties (), points (Eigen::MatrixXf (0, 0)), channels (), width (0), height (0), is_dense (true)
00660       {
00661         *this = pc;
00662       }
00663 
00667       template <typename PointT>
00668       PointCloud (const PointCloud<PointT> &pc) :
00669         properties (), points (Eigen::MatrixXf (0, 0)), channels (), 
00670         width (pc.width), height (pc.height), is_dense (pc.is_dense)
00671       {
00672         // Copy the obvious
00673         properties.acquisition_time   = pc.header.stamp;
00674         properties.sensor_origin      = pc.sensor_origin_;//.head<3> ();
00675         properties.sensor_orientation = pc.sensor_orientation_;
00676 
00677         typedef typename pcl::traits::fieldList<PointT>::type FieldList;
00678 
00679         // Copy the fields
00680         pcl::for_each_type <FieldList> (CopyFieldsChannelProperties <PointT> (channels));
00681 
00682         // Resize the array
00683         points.resize (pc.points.size (), boost::mpl::size<FieldList>::value);
00684 
00685         for (size_t cp = 0; cp < pc.points.size (); ++cp)
00686           pcl::for_each_type <FieldList> (NdCopyPointEigenFunctor<PointT, Eigen::MatrixXf::RowXpr> (pc.points[cp], points.row (cp)));
00687       }
00688 
00693       PointCloud (const PointCloud &pc, 
00694                   const std::vector<int> &indices) :
00695         properties (pc.properties), 
00696         points (Eigen::MatrixXf (indices.size (), pc.points.cols ())), 
00697         channels (pc.channels), 
00698         width ((uint32_t) indices.size ()), height (1), is_dense (pc.is_dense)
00699       {
00700         // Copy the obvious
00701         assert ((int)indices.size () <= pc.points.rows ());
00702         for (size_t i = 0; i < indices.size (); i++)
00703           points.row (i) = pc.points.row (indices[i]);
00704       }
00705 
00711       inline PointCloud (uint32_t _width, uint32_t _height, uint32_t _dim)
00712         : properties ()
00713         , points (Eigen::MatrixXf (_width * _height, _dim))
00714         , channels ()
00715         , width (_width)
00716         , height (_height)
00717         , is_dense (true)
00718       {}
00719 
00724       inline PointCloud (uint32_t _num_points, uint32_t _dim)
00725         : properties ()
00726         , points (Eigen::MatrixXf (_num_points, _dim))
00727         , channels ()
00728         , width (_num_points)
00729         , height (1)
00730         , is_dense (true)
00731       {}
00732 
00734       virtual ~PointCloud () {}
00735 
00737 
00741       inline PointCloud&
00742       operator += (const PointCloud& rhs)
00743       {
00744         if (rhs.properties.acquisition_time > properties.acquisition_time)
00745           properties.acquisition_time = rhs.properties.acquisition_time;
00746 
00747         properties.sensor_origin = Eigen::Vector4f::Zero ();
00748         properties.sensor_orientation = Eigen::Quaternionf::Identity ();
00749 
00750         int nr_points = (int) points.rows ();
00751         points.resize (nr_points + rhs.points.rows (), points.cols ());
00752         for (int i = nr_points; i < points.rows (); ++i)
00753           points.row (i) = rhs.points.row (i - nr_points);
00754 
00755         channels = rhs.channels;
00756         width    = (uint32_t) points.rows ();
00757         height   = 1;
00758         if (rhs.is_dense && is_dense)
00759           is_dense = true;
00760         else
00761           is_dense = false;
00762         return (*this);
00763       }
00764       
00766 
00770       inline const PointCloud
00771       operator + (const PointCloud& rhs)
00772       {
00773         return (PointCloud (*this) += rhs);
00774       }
00775 
00777 
00782       inline Eigen::Map<Eigen::VectorXf>
00783       at (int column, int row)
00784       {
00785         if (height > 1)
00786           return (Eigen::VectorXf::Map (&points (row * width + column, 0), points.cols ()));
00787         else
00788           throw IsNotDenseException ("Can't use 2D indexing with a unorganized point cloud");
00789       }
00790 
00792 
00797       inline Eigen::Map<Eigen::VectorXf>
00798       operator () (int column, int row) 
00799       {
00800         return (Eigen::VectorXf::Map (&points (row * width + column, 0), points.cols ()));
00801       }
00802 
00804 
00807       inline bool
00808       isOrganized () const
00809       {
00810         return (height != 1);
00811       }
00812       
00814 
00815       inline bool 
00816       empty () const 
00817       { 
00818         return (points.rows () == 0); 
00819       }
00820 
00822       pcl::CloudProperties properties;
00823 
00825       Eigen::MatrixXf points;
00826 
00828       std::map<std::string, pcl::ChannelProperties> channels;
00829 
00831       uint32_t width;
00833       uint32_t height;
00834 
00836       bool is_dense;
00837 
00838       typedef boost::shared_ptr<PointCloud<Eigen::MatrixXf> > Ptr;
00839       typedef boost::shared_ptr<const PointCloud<Eigen::MatrixXf> > ConstPtr;
00840 
00841       inline size_t size () const { return (points.rows ()); }
00842 
00846       inline void 
00847       swap (PointCloud<Eigen::MatrixXf> &rhs)
00848       {
00849         std::swap (points, rhs.points);
00850         std::swap (width, rhs.width);
00851         std::swap (height, rhs.height);
00852         std::swap (is_dense, rhs.is_dense);
00853         std::swap (properties, rhs.properties);
00854         std::swap (channels, rhs.channels);
00855       }
00856 
00858       inline void 
00859       clear ()
00860       {
00861         points.resize (0, 0);
00862         width = 0;
00863         height = 0;
00864       }
00865 
00871       inline Ptr 
00872       makeShared () { return Ptr (new PointCloud<Eigen::MatrixXf> (*this)); }
00873 
00878       inline ConstPtr 
00879       makeShared () const { return ConstPtr (new PointCloud<Eigen::MatrixXf> (*this)); }
00880 
00881     public:
00882       EIGEN_MAKE_ALIGNED_OPERATOR_NEW
00883 
00884     private:
00886 
00887       template <typename PointOutT, typename PointInT>
00888       struct NdCopyEigenPointFunctor
00889       {
00890         typedef typename traits::POD<PointOutT>::type Pod;
00891         
00896         NdCopyEigenPointFunctor (const PointInT p1, PointOutT &p2)
00897           : p1_ (p1),
00898             p2_ (reinterpret_cast<Pod&>(p2)),
00899             f_idx_ (0) { }
00900 
00902         template<typename Key> inline void 
00903         operator() ()
00904         {
00905           //boost::fusion::at_key<Key> (p2_) = p1_[f_idx_++];
00906           typedef typename pcl::traits::datatype<PointOutT, Key>::type T;
00907           uint8_t* data_ptr = reinterpret_cast<uint8_t*>(&p2_) + pcl::traits::offset<PointOutT, Key>::value;
00908           *reinterpret_cast<T*>(data_ptr) = p1_[f_idx_++];
00909         }
00910 
00911         private:
00912           const PointInT p1_;
00913           Pod &p2_;
00914           int f_idx_;
00915         public:
00916           EIGEN_MAKE_ALIGNED_OPERATOR_NEW
00917        };
00918 
00920 
00921       template <typename PointInT, typename PointOutT>
00922       struct NdCopyPointEigenFunctor
00923       {
00924         typedef typename traits::POD<PointInT>::type Pod;
00925         
00930          NdCopyPointEigenFunctor (const PointInT &p1, PointOutT p2)
00931           : p1_ (reinterpret_cast<const Pod&>(p1)), p2_ (p2), f_idx_ (0) { }
00932 
00934         template<typename Key> inline void 
00935         operator() ()
00936         {
00937           //p2_[f_idx_++] = boost::fusion::at_key<Key> (p1_);
00938           typedef typename pcl::traits::datatype<PointInT, Key>::type T;
00939           const uint8_t* data_ptr = reinterpret_cast<const uint8_t*>(&p1_) + pcl::traits::offset<PointInT, Key>::value;
00940           p2_[f_idx_++] = *reinterpret_cast<const T*>(data_ptr);
00941         }
00942 
00943         private:
00944           const Pod &p1_;
00945           PointOutT p2_;
00946           int f_idx_;
00947         public:
00948           EIGEN_MAKE_ALIGNED_OPERATOR_NEW
00949       };
00950 
00952 
00953       template <typename T>
00954       struct CopyFieldsChannelProperties
00955       {
00959         CopyFieldsChannelProperties (std::map<std::string, pcl::ChannelProperties> &channels)
00960           : channels_ (channels) {}
00961 
00963         template<typename U> inline void 
00964         operator() ()
00965         {
00966           //boost::fusion::at_key<Key> (p2_) = p1_[f_idx_++];
00967           std::string name = pcl::traits::name<T, U>::value;
00968           channels_[name].name     = name;
00969           channels_[name].offset   = pcl::traits::offset<T, U>::value;
00970           int datatype = pcl::traits::datatype<T, U>::value;
00971           channels_[name].datatype = datatype;
00972           int count = pcl::traits::datatype<T, U>::size;
00973           channels_[name].count    = count;
00974           switch (datatype)
00975           {
00976             case sensor_msgs::PointField::INT8:
00977             case sensor_msgs::PointField::UINT8:
00978             {
00979               channels_[name].size = count;
00980               break;
00981             }
00982       
00983             case sensor_msgs::PointField::INT16:
00984             case sensor_msgs::PointField::UINT16:
00985             {
00986               channels_[name].size = count * 2;
00987               break;
00988             }
00989       
00990             case sensor_msgs::PointField::INT32:
00991             case sensor_msgs::PointField::UINT32:
00992             case sensor_msgs::PointField::FLOAT32:
00993             {
00994               channels_[name].size = count * 4;
00995               break;
00996             }
00997       
00998             case sensor_msgs::PointField::FLOAT64:
00999             {
01000               channels_[name].size = count * 8;
01001               break;
01002             }
01003           }
01004         }
01005 
01006         private:
01007           std::map<std::string, pcl::ChannelProperties> &channels_;
01008        };
01009   };
01010 
01012   namespace detail
01013   {
01014     template <typename PointT> boost::shared_ptr<pcl::MsgFieldMap>&
01015     getMapping (pcl::PointCloud<PointT>& p)
01016     {
01017       return (p.mapping_);
01018     }
01019   } // namespace detail
01020 
01021   template <typename PointT> std::ostream&
01022   operator << (std::ostream& s, const pcl::PointCloud<PointT> &p)
01023   {
01024     s << "points[]: " << p.points.size () << std::endl;
01025     s << "width: " << p.width << std::endl;
01026     s << "height: " << p.height << std::endl;
01027     s << "is_dense: " << p.is_dense << std::endl;
01028     return (s);
01029   }
01030 }
01031 
01032 #endif  //#ifndef PCL_POINT_CLOUD_H_