Point Cloud Library (PCL)  1.7.0
/tmp/buildd/pcl-1.7-1.7.0/io/include/pcl/io/ply_io.h
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Point Cloud Library (PCL) - www.pointclouds.org
00005  *  Copyright (c) 2010-2011, 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 the copyright holder(s) 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$
00037  *
00038  */
00039 
00040 #ifndef PCL_IO_PLY_IO_H_
00041 #define PCL_IO_PLY_IO_H_
00042 
00043 #include <pcl/io/boost.h>
00044 #include <pcl/io/file_io.h>
00045 #include <pcl/io/ply/ply_parser.h>
00046 #include <pcl/PolygonMesh.h>
00047 #include <sstream>
00048 
00049 namespace pcl
00050 {
00051   /** \brief Point Cloud Data (PLY) file format reader.
00052     *
00053     * The PLY data format is organized in the following way:
00054     * lines beginning with "comment" are treated as comments
00055     *   - ply
00056     *   - format [ascii|binary_little_endian|binary_big_endian] 1.0
00057     *   - element vertex COUNT
00058     *   - property float x 
00059     *   - property float y 
00060     *   - [property float z] 
00061     *   - [property float normal_x] 
00062     *   - [property float normal_y] 
00063     *   - [property float normal_z] 
00064     *   - [property uchar red] 
00065     *   - [property uchar green] 
00066     *   - [property uchar blue] ...
00067     *   - ascii/binary point coordinates
00068     *   - [element camera 1]
00069     *   - [property float view_px] ...
00070     *   - [element range_grid COUNT]
00071     *   - [property list uchar int vertex_indices]
00072     *   - end header
00073     *
00074     * \author Nizar Sallem
00075     * \ingroup io
00076     */
00077   class PCL_EXPORTS PLYReader : public FileReader
00078   {
00079     public:
00080       enum
00081       {
00082         PLY_V0 = 0,
00083         PLY_V1 = 1
00084       };
00085       
00086       PLYReader ()
00087         : FileReader ()
00088         , parser_ ()
00089         , origin_ (Eigen::Vector4f::Zero ())
00090         , orientation_ (Eigen::Matrix3f::Zero ())
00091         , cloud_ ()
00092         , vertex_count_ (0)
00093         , vertex_properties_counter_ (0)
00094         , vertex_offset_before_ (0)
00095         , range_grid_ (0)
00096         , range_count_ (0)
00097         , range_grid_vertex_indices_element_index_ (0)
00098         , rgb_offset_before_ (0)
00099         , do_resize_ (false)
00100       {}
00101 
00102       PLYReader (const PLYReader &p)
00103         : FileReader ()
00104         , parser_ ()
00105         , origin_ (Eigen::Vector4f::Zero ())
00106         , orientation_ (Eigen::Matrix3f::Zero ())
00107         , cloud_ ()
00108         , vertex_count_ (0)
00109         , vertex_properties_counter_ (0)
00110         , vertex_offset_before_ (0)
00111         , range_grid_ (0)
00112         , range_count_ (0)
00113         , range_grid_vertex_indices_element_index_ (0)
00114         , rgb_offset_before_ (0)
00115         , do_resize_ (false)
00116       {
00117         *this = p;
00118       }
00119 
00120       PLYReader&
00121       operator = (const PLYReader &p)
00122       {
00123         origin_ = p.origin_;
00124         orientation_ = p.orientation_;
00125         range_grid_ = p.range_grid_;
00126         return (*this);
00127       }
00128 
00129       ~PLYReader () { delete range_grid_; }
00130       /** \brief Read a point cloud data header from a PLY file.
00131         *
00132         * Load only the meta information (number of points, their types, etc),
00133         * and not the points themselves, from a given PLY file. Useful for fast
00134         * evaluation of the underlying data structure.
00135         *
00136         * Returns:
00137         *  * < 0 (-1) on error
00138         *  * > 0 on success
00139         * \param[in] file_name the name of the file to load
00140         * \param[out] cloud the resultant point cloud dataset (only the header will be filled)
00141         * \param[in] origin the sensor data acquisition origin (translation)
00142         * \param[in] orientation the sensor data acquisition origin (rotation)
00143         * \param[out] ply_version the PLY version read from the file
00144         * \param[out] data_type the type of PLY data stored in the file
00145         * \param[out] data_idx the data index
00146         * \param[in] offset the offset in the file where to expect the true header to begin.
00147         * One usage example for setting the offset parameter is for reading
00148         * data from a TAR "archive containing multiple files: TAR files always
00149         * add a 512 byte header in front of the actual file, so set the offset
00150         * to the next byte after the header (e.g., 513).
00151         */
00152       int 
00153       readHeader (const std::string &file_name, pcl::PCLPointCloud2 &cloud,
00154                   Eigen::Vector4f &origin, Eigen::Quaternionf &orientation,
00155                   int &ply_version, int &data_type, unsigned int &data_idx, const int offset = 0);
00156 
00157       /** \brief Read a point cloud data from a PLY file and store it into a pcl/PCLPointCloud2.
00158         * \param[in] file_name the name of the file containing the actual PointCloud data
00159         * \param[out] cloud the resultant PointCloud message read from disk
00160         * \param[in] origin the sensor data acquisition origin (translation)
00161         * \param[in] orientation the sensor data acquisition origin (rotation)
00162         * \param[out] ply_version the PLY version read from the file
00163         * \param[in] offset the offset in the file where to expect the true header to begin.
00164         * One usage example for setting the offset parameter is for reading
00165         * data from a TAR "archive containing multiple files: TAR files always
00166         * add a 512 byte header in front of the actual file, so set the offset
00167         * to the next byte after the header (e.g., 513).
00168         */
00169       int 
00170       read (const std::string &file_name, pcl::PCLPointCloud2 &cloud,
00171             Eigen::Vector4f &origin, Eigen::Quaternionf &orientation, int& ply_version, const int offset = 0);
00172 
00173       /** \brief Read a point cloud data from a PLY file (PLY_V6 only!) and store it into a pcl/PCLPointCloud2.
00174         *
00175         * \note This function is provided for backwards compatibility only and
00176         * it can only read PLY_V6 files correctly, as pcl::PCLPointCloud2
00177         * does not contain a sensor origin/orientation. Reading any file
00178         * > PLY_V6 will generate a warning.
00179         *
00180         * \param[in] file_name the name of the file containing the actual PointCloud data
00181         * \param[out] cloud the resultant PointCloud message read from disk
00182         * \param[in] offset the offset in the file where to expect the true header to begin.
00183         * One usage example for setting the offset parameter is for reading
00184         * data from a TAR "archive containing multiple files: TAR files always
00185         * add a 512 byte header in front of the actual file, so set the offset
00186         * to the next byte after the header (e.g., 513).
00187         */
00188       inline int 
00189       read (const std::string &file_name, pcl::PCLPointCloud2 &cloud, const int offset = 0)
00190       {
00191         Eigen::Vector4f origin;
00192         Eigen::Quaternionf orientation;
00193         int ply_version;
00194         return read (file_name, cloud, origin, orientation, ply_version, offset);
00195       }
00196 
00197       /** \brief Read a point cloud data from any PLY file, and convert it to the given template format.
00198         * \param[in] file_name the name of the file containing the actual PointCloud data
00199         * \param[out] cloud the resultant PointCloud message read from disk
00200         * \param[in] offset the offset in the file where to expect the true header to begin.
00201         * One usage example for setting the offset parameter is for reading
00202         * data from a TAR "archive containing multiple files: TAR files always
00203         * add a 512 byte header in front of the actual file, so set the offset
00204         * to the next byte after the header (e.g., 513).
00205         */
00206       template<typename PointT> inline int
00207       read (const std::string &file_name, pcl::PointCloud<PointT> &cloud, const int offset = 0)
00208       {
00209         pcl::PCLPointCloud2 blob;
00210         int ply_version;
00211         int res = read (file_name, blob, cloud.sensor_origin_, cloud.sensor_orientation_,
00212                         ply_version, offset);
00213 
00214         // Exit in case of error
00215         if (res < 0)
00216           return (res);
00217         pcl::fromPCLPointCloud2 (blob, cloud);
00218         return (0);
00219       }
00220       
00221     private:
00222       ::pcl::io::ply::ply_parser parser_;
00223 
00224       bool
00225       parse (const std::string& istream_filename);
00226 
00227       /** \brief Info callback function
00228         * \param[in] filename PLY file read
00229         * \param[in] line_number line triggering the callback
00230         * \param[in] message information message
00231         */
00232       void 
00233       infoCallback (const std::string& filename, std::size_t line_number, const std::string& message)
00234       {
00235         PCL_DEBUG ("[pcl::PLYReader] %s:%lu: %s\n", filename.c_str (), line_number, message.c_str ());
00236       }
00237       
00238       /** \brief Warning callback function
00239         * \param[in] filename PLY file read
00240         * \param[in] line_number line triggering the callback
00241         * \param[in] message warning message
00242         */
00243       void 
00244       warningCallback (const std::string& filename, std::size_t line_number, const std::string& message)
00245       {
00246         PCL_WARN ("[pcl::PLYReader] %s:%lu: %s\n", filename.c_str (), line_number, message.c_str ());
00247       }
00248       
00249       /** \brief Error callback function
00250         * \param[in] filename PLY file read
00251         * \param[in] line_number line triggering the callback
00252         * \param[in] message error message
00253         */
00254       void 
00255       errorCallback (const std::string& filename, std::size_t line_number, const std::string& message)
00256       {
00257         PCL_ERROR ("[pcl::PLYReader] %s:%lu: %s\n", filename.c_str (), line_number, message.c_str ());
00258       }
00259       
00260       /** \brief function called when the keyword element is parsed
00261         * \param[in] element_name element name
00262         * \param[in] count number of instances
00263         */
00264       boost::tuple<boost::function<void ()>, boost::function<void ()> > 
00265       elementDefinitionCallback (const std::string& element_name, std::size_t count);
00266       
00267       bool
00268       endHeaderCallback ();
00269 
00270       /** \brief function called when a scalar property is parsed
00271         * \param[in] element_name element name to which the property belongs
00272         * \param[in] property_name property name
00273         */
00274       template <typename ScalarType> boost::function<void (ScalarType)> 
00275       scalarPropertyDefinitionCallback (const std::string& element_name, const std::string& property_name);
00276 
00277       /** \brief function called when a list property is parsed
00278         * \param[in] element_name element name to which the property belongs
00279         * \param[in] property_name list property name
00280         */
00281       template <typename SizeType, typename ScalarType>
00282       boost::tuple<boost::function<void (SizeType)>, boost::function<void (ScalarType)>, boost::function<void ()> >
00283       listPropertyDefinitionCallback (const std::string& element_name, const std::string& property_name);
00284       
00285       /** \brief function called at the beginning of a list property parsing.
00286         * \param[in] size number of elements in the list
00287         */
00288       template <typename SizeType> void
00289       vertexListPropertyBeginCallback (const std::string& property_name, SizeType size);
00290 
00291       /** \brief function called when a list element is parsed.
00292         * \param[in] value the list's element value
00293         */
00294       template <typename ContentType> void
00295       vertexListPropertyContentCallback (ContentType value);
00296 
00297       /** \brief function called at the end of a list property parsing */
00298       inline void
00299       vertexListPropertyEndCallback ();
00300 
00301       /** Callback function for an anonymous vertex double property.
00302         * Writes down a double value in cloud data.
00303         * param[in] value double value parsed
00304         */
00305       inline void
00306       vertexDoublePropertyCallback (pcl::io::ply::float64 value);
00307 
00308       /** Callback function for an anonymous vertex float property.
00309         * Writes down a float value in cloud data.
00310         * param[in] value float value parsed
00311         */
00312       inline void
00313       vertexFloatPropertyCallback (pcl::io::ply::float32 value);
00314 
00315       /** Callback function for an anonymous vertex int property.
00316         * Writes down a int value in cloud data.
00317         * param[in] value int value parsed
00318         */
00319       inline void
00320       vertexIntPropertyCallback (pcl::io::ply::int32 value);
00321 
00322       /** Callback function for an anonymous vertex uint property.
00323         * Writes down a uint value in cloud data.
00324         * param[in] value uint value parsed
00325         */
00326       inline void
00327       vertexUnsignedIntPropertyCallback (pcl::io::ply::uint32 value);
00328 
00329       /** Callback function for an anonymous vertex short property.
00330         * Writes down a short value in cloud data.
00331         * param[in] value short value parsed
00332         */
00333       inline void
00334       vertexShortPropertyCallback (pcl::io::ply::int16 value);
00335 
00336       /** Callback function for an anonymous vertex ushort property.
00337         * Writes down a ushort value in cloud data.
00338         * param[in] value ushort value parsed
00339         */
00340       inline void
00341       vertexUnsignedShortPropertyCallback (pcl::io::ply::uint16 value);
00342 
00343       /** Callback function for an anonymous vertex char property.
00344         * Writes down a char value in cloud data.
00345         * param[in] value char value parsed
00346         */
00347       inline void
00348       vertexCharPropertyCallback (pcl::io::ply::int8 value);
00349 
00350       /** Callback function for an anonymous vertex uchar property.
00351         * Writes down a uchar value in cloud data.
00352         * param[in] value uchar value parsed
00353         */
00354       inline void
00355       vertexUnsignedCharPropertyCallback (pcl::io::ply::uint8 value);
00356 
00357       /** Callback function for vertex RGB color.
00358         * This callback is in charge of packing red green and blue in a single int
00359         * before writing it down in cloud data.
00360         * param[in] color_name color name in {red, green, blue}
00361         * param[in] color value of {red, green, blue} property
00362         */
00363       inline void
00364       vertexColorCallback (const std::string& color_name, pcl::io::ply::uint8 color);
00365 
00366       /** Callback function for vertex intensity.
00367         * converts intensity from int to float before writing it down in cloud data.
00368         * param[in] intensity
00369         */
00370       inline void
00371       vertexIntensityCallback (pcl::io::ply::uint8 intensity);
00372 
00373       /** Callback function for vertex alpha.
00374         * extracts RGB value, append alpha and put it back
00375         * param[in] alpha
00376         */
00377       inline void
00378       vertexAlphaCallback (pcl::io::ply::uint8 alpha);
00379       
00380       /** Callback function for origin x component.
00381         * param[in] value origin x value
00382         */
00383       inline void
00384       originXCallback (const float& value) { origin_[0] = value; }
00385       
00386       /** Callback function for origin y component.
00387         * param[in] value origin y value
00388         */
00389       inline void
00390       originYCallback (const float& value) { origin_[1] = value; }
00391 
00392       /** Callback function for origin z component.
00393         * param[in] value origin z value
00394         */      
00395       inline void
00396       originZCallback (const float& value) { origin_[2] = value; }
00397     
00398       /** Callback function for orientation x axis x component.
00399         * param[in] value orientation x axis x value
00400         */
00401       inline void
00402       orientationXaxisXCallback (const float& value) { orientation_ (0,0) = value; }
00403       
00404       /** Callback function for orientation x axis y component.
00405         * param[in] value orientation x axis y value
00406         */
00407       inline void
00408       orientationXaxisYCallback (const float& value) { orientation_ (0,1) = value; }
00409       
00410       /** Callback function for orientation x axis z component.
00411         * param[in] value orientation x axis z value
00412         */
00413       inline void
00414       orientationXaxisZCallback (const float& value) { orientation_ (0,2) = value; }
00415       
00416       /** Callback function for orientation y axis x component.
00417         * param[in] value orientation y axis x value
00418         */
00419       inline void
00420       orientationYaxisXCallback (const float& value) { orientation_ (1,0) = value; }
00421       
00422       /** Callback function for orientation y axis y component.
00423         * param[in] value orientation y axis y value
00424         */
00425       inline void
00426       orientationYaxisYCallback (const float& value) { orientation_ (1,1) = value; }
00427 
00428       /** Callback function for orientation y axis z component.
00429         * param[in] value orientation y axis z value
00430         */
00431       inline void
00432       orientationYaxisZCallback (const float& value) { orientation_ (1,2) = value; }
00433       
00434       /** Callback function for orientation z axis x component.
00435         * param[in] value orientation z axis x value
00436         */
00437       inline void
00438       orientationZaxisXCallback (const float& value) { orientation_ (2,0) = value; }
00439     
00440       /** Callback function for orientation z axis y component.
00441         * param[in] value orientation z axis y value
00442         */
00443       inline void
00444       orientationZaxisYCallback (const float& value) { orientation_ (2,1) = value; }
00445       
00446       /** Callback function for orientation z axis z component.
00447         * param[in] value orientation z axis z value
00448         */
00449       inline void
00450       orientationZaxisZCallback (const float& value) { orientation_ (2,2) = value; }
00451       
00452       /** Callback function to set the cloud height
00453         * param[in] height cloud height
00454         */
00455       inline void
00456       cloudHeightCallback (const int &height) { cloud_->height = height; }
00457 
00458       /** Callback function to set the cloud width
00459         * param[in] width cloud width
00460         */
00461       inline void
00462       cloudWidthCallback (const int &width) { cloud_->width = width; }
00463         
00464       /** Append a double property to the cloud fields.
00465         * param[in] name property name
00466         * param[in] count property count: 1 for scalar properties and higher for a
00467         * list property.
00468         */
00469       void
00470       appendDoubleProperty (const std::string& name, const size_t& count = 1);
00471 
00472       /** Append a float property to the cloud fields.
00473         * param[in] name property name
00474         * param[in] count property count: 1 for scalar properties and higher for a
00475         * list property.
00476         */
00477       void
00478       appendFloatProperty (const std::string& name, const size_t& count = 1);
00479 
00480       /** Append an unsigned int property to the cloud fields.
00481         * param[in] name property name
00482         * param[in] count property count: 1 for scalar properties and higher for a
00483         * list property.
00484         */
00485       void
00486       appendIntProperty (const std::string& name, const size_t& count = 1);
00487 
00488       /** Append an unsigned int property to the cloud fields.
00489         * param[in] name property name
00490         * param[in] count property count: 1 for scalar properties and higher for a
00491         * list property.
00492         */
00493       void
00494       appendUnsignedIntProperty (const std::string& name, const size_t& count = 1);
00495 
00496       /** Append a short property to the cloud fields.
00497         * param[in] name property name
00498         * param[in] count property count: 1 for scalar properties and higher for a
00499         * list property.
00500         */
00501       void
00502       appendShortProperty (const std::string& name, const size_t& count = 1);
00503 
00504       /** Append a short property to the cloud fields.
00505         * param[in] name property name
00506         * param[in] count property count: 1 for scalar properties and higher for a
00507         * list property.
00508         */
00509       void
00510       appendUnsignedShortProperty (const std::string& name, const size_t& count = 1);
00511 
00512       /** Append a char property to the cloud fields.
00513         * param[in] name property name
00514         * param[in] count property count: 1 for scalar properties and higher for a
00515         * list property.
00516         */
00517       void
00518       appendCharProperty (const std::string& name, const size_t& count = 1);
00519 
00520       /** Append a char property to the cloud fields.
00521         * param[in] name property name
00522         * param[in] count property count: 1 for scalar properties and higher for a
00523         * list property.
00524         */
00525       void
00526       appendUnsignedCharProperty (const std::string& name, const size_t& count = 1);
00527 
00528       /** Amend property from cloud fields identified by \a old_name renaming
00529         * it \a new_name.
00530         * param[in] old_name property old name
00531         * param[in] new_name property new name
00532         */
00533       void
00534       amendProperty (const std::string& old_name, const std::string& new_name, uint8_t datatype = 0);
00535 
00536       /** Callback function for the begin of vertex line */
00537       void
00538       vertexBeginCallback ();
00539 
00540       /** Callback function for the end of vertex line */
00541       void
00542       vertexEndCallback ();
00543 
00544       /** Callback function for the begin of range_grid line */
00545       void
00546       rangeGridBeginCallback ();
00547 
00548       /** Callback function for the begin of range_grid vertex_indices property 
00549         * param[in] size vertex_indices list size  
00550         */
00551       void
00552       rangeGridVertexIndicesBeginCallback (pcl::io::ply::uint8 size);
00553 
00554       /** Callback function for each range_grid vertex_indices element
00555         * param[in] vertex_index index of the vertex in vertex_indices
00556         */      
00557       void
00558       rangeGridVertexIndicesElementCallback (pcl::io::ply::int32 vertex_index);
00559 
00560       /** Callback function for the end of a range_grid vertex_indices property */
00561       void
00562       rangeGridVertexIndicesEndCallback ();
00563 
00564       /** Callback function for the end of a range_grid element end */
00565       void
00566       rangeGridEndCallback ();
00567 
00568       /** Callback function for obj_info */
00569       void
00570       objInfoCallback (const std::string& line);
00571 
00572       /// origin
00573       Eigen::Vector4f origin_;
00574 
00575       /// orientation
00576       Eigen::Matrix3f orientation_;
00577 
00578       //vertex element artifacts
00579       pcl::PCLPointCloud2 *cloud_;
00580       size_t vertex_count_, vertex_properties_counter_;
00581       int vertex_offset_before_;
00582       //range element artifacts
00583       std::vector<std::vector <int> > *range_grid_;
00584       size_t range_count_, range_grid_vertex_indices_element_index_;
00585       size_t rgb_offset_before_;
00586       bool do_resize_;
00587     public:
00588       EIGEN_MAKE_ALIGNED_OPERATOR_NEW
00589   };
00590 
00591   /** \brief Point Cloud Data (PLY) file format writer.
00592     * \author Nizar Sallem
00593     * \ingroup io
00594     */
00595   class PCL_EXPORTS PLYWriter : public FileWriter
00596   {
00597     public:
00598       ///Constructor
00599       PLYWriter () : FileWriter () {};
00600 
00601       ///Destructor
00602       ~PLYWriter () {};
00603 
00604       /** \brief Generate the header of a PLY v.7 file format
00605         * \param[in] cloud the point cloud data message
00606         * \param[in] origin the sensor data acquisition origin (translation)
00607         * \param[in] orientation the sensor data acquisition origin (rotation)
00608         * \param[in] valid_points number of valid points (finite ones for range_grid and
00609         * all of them for camer)
00610         * \param[in] use_camera if set to true then PLY file will use element camera else
00611         * element range_grid will be used.
00612         */
00613       inline std::string
00614       generateHeaderBinary (const pcl::PCLPointCloud2 &cloud,
00615                             const Eigen::Vector4f &origin, 
00616                             const Eigen::Quaternionf &orientation,
00617                             int valid_points,
00618                             bool use_camera = true)
00619       {
00620         return (generateHeader (cloud, origin, orientation, true, use_camera, valid_points));
00621       }
00622       
00623       /** \brief Generate the header of a PLY v.7 file format
00624         * \param[in] cloud the point cloud data message
00625         * \param[in] origin the sensor data acquisition origin (translation)
00626         * \param[in] orientation the sensor data acquisition origin (rotation)
00627         * \param[in] valid_points number of valid points (finite ones for range_grid and
00628         * all of them for camer)
00629         * \param[in] use_camera if set to true then PLY file will use element camera else
00630         * element range_grid will be used.
00631         */
00632       inline std::string
00633       generateHeaderASCII (const pcl::PCLPointCloud2 &cloud,
00634                            const Eigen::Vector4f &origin, 
00635                            const Eigen::Quaternionf &orientation,
00636                            int valid_points,
00637                            bool use_camera = true)
00638       {
00639         return (generateHeader (cloud, origin, orientation, false, use_camera, valid_points));
00640       }
00641 
00642       /** \brief Save point cloud data to a PLY file containing n-D points, in ASCII format
00643         * \param[in] file_name the output file name
00644         * \param[in] cloud the point cloud data message
00645         * \param[in] origin the sensor data acquisition origin (translation)
00646         * \param[in] orientation the sensor data acquisition origin (rotation)
00647         * \param[in] precision the specified output numeric stream precision (default: 8)
00648         * \param[in] use_camera if set to true then PLY file will use element camera else
00649         * element range_grid will be used.
00650         */
00651       int 
00652       writeASCII (const std::string &file_name, const pcl::PCLPointCloud2 &cloud,
00653                   const Eigen::Vector4f &origin = Eigen::Vector4f::Zero (), 
00654                   const Eigen::Quaternionf &orientation = Eigen::Quaternionf::Identity (),
00655                   int precision = 8,
00656                   bool use_camera = true);
00657 
00658       /** \brief Save point cloud data to a PLY file containing n-D points, in BINARY format
00659         * \param[in] file_name the output file name
00660         * \param[in] cloud the point cloud data message
00661         * \param[in] origin the sensor data acquisition origin (translation)
00662         * \param[in] orientation the sensor data acquisition origin (rotation)
00663         * \param[in] use_camera if set to true then PLY file will use element camera else
00664         * element range_grid will be used
00665         */
00666       int 
00667       writeBinary (const std::string &file_name, const pcl::PCLPointCloud2 &cloud,
00668                    const Eigen::Vector4f &origin = Eigen::Vector4f::Zero (), 
00669                    const Eigen::Quaternionf &orientation = Eigen::Quaternionf::Identity (),
00670                    bool use_camera = true);
00671 
00672       /** \brief Save point cloud data to a PLY file containing n-D points
00673         * \param[in] file_name the output file name
00674         * \param[in] cloud the point cloud data message
00675         * \param[in] origin the sensor acquisition origin
00676         * \param[in] orientation the sensor acquisition orientation
00677         * \param[in] binary set to true if the file is to be written in a binary
00678         * PLY format, false (default) for ASCII
00679         */
00680       inline int
00681       write (const std::string &file_name, const pcl::PCLPointCloud2 &cloud,
00682              const Eigen::Vector4f &origin = Eigen::Vector4f::Zero (), 
00683              const Eigen::Quaternionf &orientation = Eigen::Quaternionf::Identity (),
00684              const bool binary = false)
00685       {
00686         if (binary)
00687           return (this->writeBinary (file_name, cloud, origin, orientation, true));
00688         else
00689           return (this->writeASCII (file_name, cloud, origin, orientation, 8, true));
00690       }
00691 
00692       /** \brief Save point cloud data to a PLY file containing n-D points
00693         * \param[in] file_name the output file name
00694         * \param[in] cloud the point cloud data message
00695         * \param[in] origin the sensor acquisition origin
00696         * \param[in] orientation the sensor acquisition orientation
00697         * \param[in] binary set to true if the file is to be written in a binary
00698         * PLY format, false (default) for ASCII
00699         * \param[in] use_camera set to true to use camera element and false to
00700         * use range_grid element
00701         */
00702       inline int
00703       write (const std::string &file_name, const pcl::PCLPointCloud2 &cloud,
00704              const Eigen::Vector4f &origin = Eigen::Vector4f::Zero (), 
00705              const Eigen::Quaternionf &orientation = Eigen::Quaternionf::Identity (),
00706              bool binary = false,
00707              bool use_camera = true)
00708       {
00709         if (binary)
00710           return (this->writeBinary (file_name, cloud, origin, orientation, use_camera));
00711         else
00712           return (this->writeASCII (file_name, cloud, origin, orientation, 8, use_camera));
00713       }
00714 
00715       /** \brief Save point cloud data to a PLY file containing n-D points
00716         * \param[in] file_name the output file name
00717         * \param[in] cloud the point cloud data message (boost shared pointer)
00718         * \param[in] origin the sensor acquisition origin
00719         * \param[in] orientation the sensor acquisition orientation
00720         * \param[in] binary set to true if the file is to be written in a binary
00721         * PLY format, false (default) for ASCII
00722         * \param[in] use_camera set to true to use camera element and false to
00723         * use range_grid element
00724         */
00725       inline int
00726       write (const std::string &file_name, const pcl::PCLPointCloud2::ConstPtr &cloud,
00727              const Eigen::Vector4f &origin = Eigen::Vector4f::Zero (), 
00728              const Eigen::Quaternionf &orientation = Eigen::Quaternionf::Identity (),
00729              bool binary = false,
00730              bool use_camera = true)
00731       {
00732         return (write (file_name, *cloud, origin, orientation, binary, use_camera));
00733       }
00734 
00735       /** \brief Save point cloud data to a PLY file containing n-D points
00736         * \param[in] file_name the output file name
00737         * \param[in] cloud the pcl::PointCloud data
00738         * \param[in] binary set to true if the file is to be written in a binary
00739         * PLY format, false (default) for ASCII
00740         * \param[in] use_camera set to true to use camera element and false to
00741         * use range_grid element
00742         */
00743       template<typename PointT> inline int
00744       write (const std::string &file_name, 
00745              const pcl::PointCloud<PointT> &cloud, 
00746              bool binary = false,
00747              bool use_camera = true)
00748       {
00749         Eigen::Vector4f origin = cloud.sensor_origin_;
00750         Eigen::Quaternionf orientation = cloud.sensor_orientation_;
00751 
00752         pcl::PCLPointCloud2 blob;
00753         pcl::toPCLPointCloud2 (cloud, blob);
00754 
00755         // Save the data
00756         return (this->write (file_name, blob, origin, orientation, binary, use_camera));
00757       }
00758       
00759     private:
00760       /** \brief Generate a PLY header.
00761         * \param[in] cloud the input point cloud
00762         * \param[in] binary whether the PLY file should be saved as binary data (true) or ascii (false)
00763         */
00764       std::string
00765       generateHeader (const pcl::PCLPointCloud2 &cloud,
00766                       const Eigen::Vector4f &origin, 
00767                       const Eigen::Quaternionf &orientation,
00768                       bool binary, 
00769                       bool use_camera,
00770                       int valid_points);
00771       
00772       void
00773       writeContentWithCameraASCII (int nr_points, 
00774                                    int point_size,
00775                                    const pcl::PCLPointCloud2 &cloud,
00776                                    const Eigen::Vector4f &origin, 
00777                                    const Eigen::Quaternionf &orientation,
00778                                    std::ofstream& fs);
00779 
00780       void
00781       writeContentWithRangeGridASCII (int nr_points, 
00782                                       int point_size,
00783                                       const pcl::PCLPointCloud2 &cloud,
00784                                       std::ostringstream& fs,
00785                                       int& nb_valid_points);
00786   };
00787 
00788   namespace io
00789   {
00790     /** \brief Load a PLY v.6 file into a templated PointCloud type.
00791       *
00792       * Any PLY files containg sensor data will generate a warning as a
00793       * pcl/PCLPointCloud2 message cannot hold the sensor origin.
00794       *
00795       * \param[in] file_name the name of the file to load
00796       * \param[in] cloud the resultant templated point cloud
00797       * \ingroup io
00798       */
00799     inline int
00800     loadPLYFile (const std::string &file_name, pcl::PCLPointCloud2 &cloud)
00801     {
00802       pcl::PLYReader p;
00803       return (p.read (file_name, cloud));
00804     }
00805 
00806     /** \brief Load any PLY file into a templated PointCloud type.
00807       * \param[in] file_name the name of the file to load
00808       * \param[in] cloud the resultant templated point cloud
00809       * \param[in] origin the sensor acquisition origin (only for > PLY_V7 - null if not present)
00810       * \param[in] orientation the sensor acquisition orientation if availble, 
00811       * identity if not present
00812       * \ingroup io
00813       */
00814     inline int
00815     loadPLYFile (const std::string &file_name, pcl::PCLPointCloud2 &cloud,
00816                  Eigen::Vector4f &origin, Eigen::Quaternionf &orientation)
00817     {
00818       pcl::PLYReader p;
00819       int ply_version;
00820       return (p.read (file_name, cloud, origin, orientation, ply_version));
00821     }
00822 
00823     /** \brief Load any PLY file into a templated PointCloud type
00824       * \param[in] file_name the name of the file to load
00825       * \param[in] cloud the resultant templated point cloud
00826       * \ingroup io
00827       */
00828     template<typename PointT> inline int
00829     loadPLYFile (const std::string &file_name, pcl::PointCloud<PointT> &cloud)
00830     {
00831       pcl::PLYReader p;
00832       return (p.read (file_name, cloud));
00833     }
00834 
00835     /** \brief Save point cloud data to a PLY file containing n-D points
00836       * \param[in] file_name the output file name
00837       * \param[in] cloud the point cloud data message
00838       * \param[in] origin the sensor data acquisition origin (translation)
00839       * \param[in] orientation the sensor data acquisition origin (rotation)
00840       * \param[in] binary_mode true for binary mode, false (default) for ASCII
00841       * \ingroup io
00842       */
00843     inline int 
00844     savePLYFile (const std::string &file_name, const pcl::PCLPointCloud2 &cloud,
00845                  const Eigen::Vector4f &origin = Eigen::Vector4f::Zero (), 
00846                  const Eigen::Quaternionf &orientation = Eigen::Quaternionf::Identity (),
00847                  bool binary_mode = false, bool use_camera = true)
00848     {
00849       PLYWriter w;
00850       return (w.write (file_name, cloud, origin, orientation, binary_mode, use_camera));
00851     }
00852 
00853     /** \brief Templated version for saving point cloud data to a PLY file
00854       * containing a specific given cloud format
00855       * \param[in] file_name the output file name
00856       * \param[in] cloud the point cloud data message
00857       * \param[in] binary_mode true for binary mode, false (default) for ASCII
00858       * \ingroup io
00859       */
00860     template<typename PointT> inline int
00861     savePLYFile (const std::string &file_name, const pcl::PointCloud<PointT> &cloud, bool binary_mode = false)
00862     {
00863       PLYWriter w;
00864       return (w.write<PointT> (file_name, cloud, binary_mode));
00865     }
00866 
00867     /** \brief Templated version for saving point cloud data to a PLY file
00868       * containing a specific given cloud format.
00869       * \param[in] file_name the output file name
00870       * \param[in] cloud the point cloud data message
00871       * \ingroup io
00872       */
00873     template<typename PointT> inline int
00874     savePLYFileASCII (const std::string &file_name, const pcl::PointCloud<PointT> &cloud)
00875     {
00876       PLYWriter w;
00877       return (w.write<PointT> (file_name, cloud, false));
00878     }
00879 
00880     /** \brief Templated version for saving point cloud data to a PLY file containing a specific given cloud format.
00881       * \param[in] file_name the output file name
00882       * \param[in] cloud the point cloud data message
00883       * \ingroup io
00884       */
00885     template<typename PointT> inline int
00886     savePLYFileBinary (const std::string &file_name, const pcl::PointCloud<PointT> &cloud)
00887     {
00888       PLYWriter w;
00889       return (w.write<PointT> (file_name, cloud, true));
00890     }
00891 
00892     /** \brief Templated version for saving point cloud data to a PLY file containing a specific given cloud format
00893       * \param[in] file_name the output file name
00894       * \param[in] cloud the point cloud data message
00895       * \param[in] indices the set of indices to save
00896       * \param[in] binary_mode true for binary mode, false (default) for ASCII
00897       * \ingroup io
00898       */
00899     template<typename PointT> int
00900     savePLYFile (const std::string &file_name, const pcl::PointCloud<PointT> &cloud,
00901                  const std::vector<int> &indices, bool binary_mode = false)
00902     {
00903       // Copy indices to a new point cloud
00904       pcl::PointCloud<PointT> cloud_out;
00905       copyPointCloud (cloud, indices, cloud_out);
00906       // Save the data
00907       PLYWriter w;
00908       return (w.write<PointT> (file_name, cloud_out, binary_mode));
00909     }
00910 
00911     /** \brief Saves a PolygonMesh in ascii PLY format.
00912       * \param[in] file_name the name of the file to write to disk
00913       * \param[in] mesh the polygonal mesh to save
00914       * \param[in] precision the output ASCII precision default 5
00915       * \ingroup io
00916       */
00917     PCL_EXPORTS int
00918     savePLYFile (const std::string &file_name, const pcl::PolygonMesh &mesh, unsigned precision = 5);
00919     
00920     /** \brief Saves a PolygonMesh in binary PLY format.
00921       * \param[in] file_name the name of the file to write to disk
00922       * \param[in] mesh the polygonal mesh to save
00923       * \ingroup io
00924       */
00925     PCL_EXPORTS int
00926     savePLYFileBinary (const std::string &file_name, const pcl::PolygonMesh &mesh);
00927   }
00928 }
00929 
00930 #endif  //#ifndef PCL_IO_PLY_IO_H_