Point Cloud Library (PCL)  1.7.0
ply_io.h
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2010-2011, Willow Garage, Inc.
6  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  * * Neither the name of the copyright holder(s) nor the names of its
20  * contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  * $Id$
37  *
38  */
39 
40 #ifndef PCL_IO_PLY_IO_H_
41 #define PCL_IO_PLY_IO_H_
42 
43 #include <pcl/io/boost.h>
44 #include <pcl/io/file_io.h>
45 #include <pcl/io/ply/ply_parser.h>
46 #include <pcl/PolygonMesh.h>
47 #include <sstream>
48 
49 namespace pcl
50 {
51  /** \brief Point Cloud Data (PLY) file format reader.
52  *
53  * The PLY data format is organized in the following way:
54  * lines beginning with "comment" are treated as comments
55  * - ply
56  * - format [ascii|binary_little_endian|binary_big_endian] 1.0
57  * - element vertex COUNT
58  * - property float x
59  * - property float y
60  * - [property float z]
61  * - [property float normal_x]
62  * - [property float normal_y]
63  * - [property float normal_z]
64  * - [property uchar red]
65  * - [property uchar green]
66  * - [property uchar blue] ...
67  * - ascii/binary point coordinates
68  * - [element camera 1]
69  * - [property float view_px] ...
70  * - [element range_grid COUNT]
71  * - [property list uchar int vertex_indices]
72  * - end header
73  *
74  * \author Nizar Sallem
75  * \ingroup io
76  */
77  class PCL_EXPORTS PLYReader : public FileReader
78  {
79  public:
80  enum
81  {
82  PLY_V0 = 0,
83  PLY_V1 = 1
84  };
85 
87  : FileReader ()
88  , parser_ ()
89  , origin_ (Eigen::Vector4f::Zero ())
90  , orientation_ (Eigen::Matrix3f::Zero ())
91  , cloud_ ()
92  , vertex_count_ (0)
93  , vertex_properties_counter_ (0)
94  , vertex_offset_before_ (0)
95  , range_grid_ (0)
96  , range_count_ (0)
97  , range_grid_vertex_indices_element_index_ (0)
98  , rgb_offset_before_ (0)
99  , do_resize_ (false)
100  {}
101 
102  PLYReader (const PLYReader &p)
103  : FileReader ()
104  , parser_ ()
105  , origin_ (Eigen::Vector4f::Zero ())
106  , orientation_ (Eigen::Matrix3f::Zero ())
107  , cloud_ ()
108  , vertex_count_ (0)
109  , vertex_properties_counter_ (0)
110  , vertex_offset_before_ (0)
111  , range_grid_ (0)
112  , range_count_ (0)
113  , range_grid_vertex_indices_element_index_ (0)
114  , rgb_offset_before_ (0)
115  , do_resize_ (false)
116  {
117  *this = p;
118  }
119 
120  PLYReader&
121  operator = (const PLYReader &p)
122  {
123  origin_ = p.origin_;
124  orientation_ = p.orientation_;
125  range_grid_ = p.range_grid_;
126  return (*this);
127  }
128 
129  ~PLYReader () { delete range_grid_; }
130  /** \brief Read a point cloud data header from a PLY file.
131  *
132  * Load only the meta information (number of points, their types, etc),
133  * and not the points themselves, from a given PLY file. Useful for fast
134  * evaluation of the underlying data structure.
135  *
136  * Returns:
137  * * < 0 (-1) on error
138  * * > 0 on success
139  * \param[in] file_name the name of the file to load
140  * \param[out] cloud the resultant point cloud dataset (only the header will be filled)
141  * \param[in] origin the sensor data acquisition origin (translation)
142  * \param[in] orientation the sensor data acquisition origin (rotation)
143  * \param[out] ply_version the PLY version read from the file
144  * \param[out] data_type the type of PLY data stored in the file
145  * \param[out] data_idx the data index
146  * \param[in] offset the offset in the file where to expect the true header to begin.
147  * One usage example for setting the offset parameter is for reading
148  * data from a TAR "archive containing multiple files: TAR files always
149  * add a 512 byte header in front of the actual file, so set the offset
150  * to the next byte after the header (e.g., 513).
151  */
152  int
153  readHeader (const std::string &file_name, pcl::PCLPointCloud2 &cloud,
154  Eigen::Vector4f &origin, Eigen::Quaternionf &orientation,
155  int &ply_version, int &data_type, unsigned int &data_idx, const int offset = 0);
156 
157  /** \brief Read a point cloud data from a PLY file and store it into a pcl/PCLPointCloud2.
158  * \param[in] file_name the name of the file containing the actual PointCloud data
159  * \param[out] cloud the resultant PointCloud message read from disk
160  * \param[in] origin the sensor data acquisition origin (translation)
161  * \param[in] orientation the sensor data acquisition origin (rotation)
162  * \param[out] ply_version the PLY version read from the file
163  * \param[in] offset the offset in the file where to expect the true header to begin.
164  * One usage example for setting the offset parameter is for reading
165  * data from a TAR "archive containing multiple files: TAR files always
166  * add a 512 byte header in front of the actual file, so set the offset
167  * to the next byte after the header (e.g., 513).
168  */
169  int
170  read (const std::string &file_name, pcl::PCLPointCloud2 &cloud,
171  Eigen::Vector4f &origin, Eigen::Quaternionf &orientation, int& ply_version, const int offset = 0);
172 
173  /** \brief Read a point cloud data from a PLY file (PLY_V6 only!) and store it into a pcl/PCLPointCloud2.
174  *
175  * \note This function is provided for backwards compatibility only and
176  * it can only read PLY_V6 files correctly, as pcl::PCLPointCloud2
177  * does not contain a sensor origin/orientation. Reading any file
178  * > PLY_V6 will generate a warning.
179  *
180  * \param[in] file_name the name of the file containing the actual PointCloud data
181  * \param[out] cloud the resultant PointCloud message read from disk
182  * \param[in] offset the offset in the file where to expect the true header to begin.
183  * One usage example for setting the offset parameter is for reading
184  * data from a TAR "archive containing multiple files: TAR files always
185  * add a 512 byte header in front of the actual file, so set the offset
186  * to the next byte after the header (e.g., 513).
187  */
188  inline int
189  read (const std::string &file_name, pcl::PCLPointCloud2 &cloud, const int offset = 0)
190  {
191  Eigen::Vector4f origin;
192  Eigen::Quaternionf orientation;
193  int ply_version;
194  return read (file_name, cloud, origin, orientation, ply_version, offset);
195  }
196 
197  /** \brief Read a point cloud data from any PLY file, and convert it to the given template format.
198  * \param[in] file_name the name of the file containing the actual PointCloud data
199  * \param[out] cloud the resultant PointCloud message read from disk
200  * \param[in] offset the offset in the file where to expect the true header to begin.
201  * One usage example for setting the offset parameter is for reading
202  * data from a TAR "archive containing multiple files: TAR files always
203  * add a 512 byte header in front of the actual file, so set the offset
204  * to the next byte after the header (e.g., 513).
205  */
206  template<typename PointT> inline int
207  read (const std::string &file_name, pcl::PointCloud<PointT> &cloud, const int offset = 0)
208  {
209  pcl::PCLPointCloud2 blob;
210  int ply_version;
211  int res = read (file_name, blob, cloud.sensor_origin_, cloud.sensor_orientation_,
212  ply_version, offset);
213 
214  // Exit in case of error
215  if (res < 0)
216  return (res);
217  pcl::fromPCLPointCloud2 (blob, cloud);
218  return (0);
219  }
220 
221  private:
223 
224  bool
225  parse (const std::string& istream_filename);
226 
227  /** \brief Info callback function
228  * \param[in] filename PLY file read
229  * \param[in] line_number line triggering the callback
230  * \param[in] message information message
231  */
232  void
233  infoCallback (const std::string& filename, std::size_t line_number, const std::string& message)
234  {
235  PCL_DEBUG ("[pcl::PLYReader] %s:%lu: %s\n", filename.c_str (), line_number, message.c_str ());
236  }
237 
238  /** \brief Warning callback function
239  * \param[in] filename PLY file read
240  * \param[in] line_number line triggering the callback
241  * \param[in] message warning message
242  */
243  void
244  warningCallback (const std::string& filename, std::size_t line_number, const std::string& message)
245  {
246  PCL_WARN ("[pcl::PLYReader] %s:%lu: %s\n", filename.c_str (), line_number, message.c_str ());
247  }
248 
249  /** \brief Error callback function
250  * \param[in] filename PLY file read
251  * \param[in] line_number line triggering the callback
252  * \param[in] message error message
253  */
254  void
255  errorCallback (const std::string& filename, std::size_t line_number, const std::string& message)
256  {
257  PCL_ERROR ("[pcl::PLYReader] %s:%lu: %s\n", filename.c_str (), line_number, message.c_str ());
258  }
259 
260  /** \brief function called when the keyword element is parsed
261  * \param[in] element_name element name
262  * \param[in] count number of instances
263  */
264  boost::tuple<boost::function<void ()>, boost::function<void ()> >
265  elementDefinitionCallback (const std::string& element_name, std::size_t count);
266 
267  bool
268  endHeaderCallback ();
269 
270  /** \brief function called when a scalar property is parsed
271  * \param[in] element_name element name to which the property belongs
272  * \param[in] property_name property name
273  */
274  template <typename ScalarType> boost::function<void (ScalarType)>
275  scalarPropertyDefinitionCallback (const std::string& element_name, const std::string& property_name);
276 
277  /** \brief function called when a list property is parsed
278  * \param[in] element_name element name to which the property belongs
279  * \param[in] property_name list property name
280  */
281  template <typename SizeType, typename ScalarType>
282  boost::tuple<boost::function<void (SizeType)>, boost::function<void (ScalarType)>, boost::function<void ()> >
283  listPropertyDefinitionCallback (const std::string& element_name, const std::string& property_name);
284 
285  /** \brief function called at the beginning of a list property parsing.
286  * \param[in] size number of elements in the list
287  */
288  template <typename SizeType> void
289  vertexListPropertyBeginCallback (const std::string& property_name, SizeType size);
290 
291  /** \brief function called when a list element is parsed.
292  * \param[in] value the list's element value
293  */
294  template <typename ContentType> void
295  vertexListPropertyContentCallback (ContentType value);
296 
297  /** \brief function called at the end of a list property parsing */
298  inline void
299  vertexListPropertyEndCallback ();
300 
301  /** Callback function for an anonymous vertex double property.
302  * Writes down a double value in cloud data.
303  * param[in] value double value parsed
304  */
305  inline void
306  vertexDoublePropertyCallback (pcl::io::ply::float64 value);
307 
308  /** Callback function for an anonymous vertex float property.
309  * Writes down a float value in cloud data.
310  * param[in] value float value parsed
311  */
312  inline void
313  vertexFloatPropertyCallback (pcl::io::ply::float32 value);
314 
315  /** Callback function for an anonymous vertex int property.
316  * Writes down a int value in cloud data.
317  * param[in] value int value parsed
318  */
319  inline void
320  vertexIntPropertyCallback (pcl::io::ply::int32 value);
321 
322  /** Callback function for an anonymous vertex uint property.
323  * Writes down a uint value in cloud data.
324  * param[in] value uint value parsed
325  */
326  inline void
327  vertexUnsignedIntPropertyCallback (pcl::io::ply::uint32 value);
328 
329  /** Callback function for an anonymous vertex short property.
330  * Writes down a short value in cloud data.
331  * param[in] value short value parsed
332  */
333  inline void
334  vertexShortPropertyCallback (pcl::io::ply::int16 value);
335 
336  /** Callback function for an anonymous vertex ushort property.
337  * Writes down a ushort value in cloud data.
338  * param[in] value ushort value parsed
339  */
340  inline void
341  vertexUnsignedShortPropertyCallback (pcl::io::ply::uint16 value);
342 
343  /** Callback function for an anonymous vertex char property.
344  * Writes down a char value in cloud data.
345  * param[in] value char value parsed
346  */
347  inline void
348  vertexCharPropertyCallback (pcl::io::ply::int8 value);
349 
350  /** Callback function for an anonymous vertex uchar property.
351  * Writes down a uchar value in cloud data.
352  * param[in] value uchar value parsed
353  */
354  inline void
355  vertexUnsignedCharPropertyCallback (pcl::io::ply::uint8 value);
356 
357  /** Callback function for vertex RGB color.
358  * This callback is in charge of packing red green and blue in a single int
359  * before writing it down in cloud data.
360  * param[in] color_name color name in {red, green, blue}
361  * param[in] color value of {red, green, blue} property
362  */
363  inline void
364  vertexColorCallback (const std::string& color_name, pcl::io::ply::uint8 color);
365 
366  /** Callback function for vertex intensity.
367  * converts intensity from int to float before writing it down in cloud data.
368  * param[in] intensity
369  */
370  inline void
371  vertexIntensityCallback (pcl::io::ply::uint8 intensity);
372 
373  /** Callback function for vertex alpha.
374  * extracts RGB value, append alpha and put it back
375  * param[in] alpha
376  */
377  inline void
378  vertexAlphaCallback (pcl::io::ply::uint8 alpha);
379 
380  /** Callback function for origin x component.
381  * param[in] value origin x value
382  */
383  inline void
384  originXCallback (const float& value) { origin_[0] = value; }
385 
386  /** Callback function for origin y component.
387  * param[in] value origin y value
388  */
389  inline void
390  originYCallback (const float& value) { origin_[1] = value; }
391 
392  /** Callback function for origin z component.
393  * param[in] value origin z value
394  */
395  inline void
396  originZCallback (const float& value) { origin_[2] = value; }
397 
398  /** Callback function for orientation x axis x component.
399  * param[in] value orientation x axis x value
400  */
401  inline void
402  orientationXaxisXCallback (const float& value) { orientation_ (0,0) = value; }
403 
404  /** Callback function for orientation x axis y component.
405  * param[in] value orientation x axis y value
406  */
407  inline void
408  orientationXaxisYCallback (const float& value) { orientation_ (0,1) = value; }
409 
410  /** Callback function for orientation x axis z component.
411  * param[in] value orientation x axis z value
412  */
413  inline void
414  orientationXaxisZCallback (const float& value) { orientation_ (0,2) = value; }
415 
416  /** Callback function for orientation y axis x component.
417  * param[in] value orientation y axis x value
418  */
419  inline void
420  orientationYaxisXCallback (const float& value) { orientation_ (1,0) = value; }
421 
422  /** Callback function for orientation y axis y component.
423  * param[in] value orientation y axis y value
424  */
425  inline void
426  orientationYaxisYCallback (const float& value) { orientation_ (1,1) = value; }
427 
428  /** Callback function for orientation y axis z component.
429  * param[in] value orientation y axis z value
430  */
431  inline void
432  orientationYaxisZCallback (const float& value) { orientation_ (1,2) = value; }
433 
434  /** Callback function for orientation z axis x component.
435  * param[in] value orientation z axis x value
436  */
437  inline void
438  orientationZaxisXCallback (const float& value) { orientation_ (2,0) = value; }
439 
440  /** Callback function for orientation z axis y component.
441  * param[in] value orientation z axis y value
442  */
443  inline void
444  orientationZaxisYCallback (const float& value) { orientation_ (2,1) = value; }
445 
446  /** Callback function for orientation z axis z component.
447  * param[in] value orientation z axis z value
448  */
449  inline void
450  orientationZaxisZCallback (const float& value) { orientation_ (2,2) = value; }
451 
452  /** Callback function to set the cloud height
453  * param[in] height cloud height
454  */
455  inline void
456  cloudHeightCallback (const int &height) { cloud_->height = height; }
457 
458  /** Callback function to set the cloud width
459  * param[in] width cloud width
460  */
461  inline void
462  cloudWidthCallback (const int &width) { cloud_->width = width; }
463 
464  /** Append a double property to the cloud fields.
465  * param[in] name property name
466  * param[in] count property count: 1 for scalar properties and higher for a
467  * list property.
468  */
469  void
470  appendDoubleProperty (const std::string& name, const size_t& count = 1);
471 
472  /** Append a float property to the cloud fields.
473  * param[in] name property name
474  * param[in] count property count: 1 for scalar properties and higher for a
475  * list property.
476  */
477  void
478  appendFloatProperty (const std::string& name, const size_t& count = 1);
479 
480  /** Append an unsigned int property to the cloud fields.
481  * param[in] name property name
482  * param[in] count property count: 1 for scalar properties and higher for a
483  * list property.
484  */
485  void
486  appendIntProperty (const std::string& name, const size_t& count = 1);
487 
488  /** Append an unsigned int property to the cloud fields.
489  * param[in] name property name
490  * param[in] count property count: 1 for scalar properties and higher for a
491  * list property.
492  */
493  void
494  appendUnsignedIntProperty (const std::string& name, const size_t& count = 1);
495 
496  /** Append a short property to the cloud fields.
497  * param[in] name property name
498  * param[in] count property count: 1 for scalar properties and higher for a
499  * list property.
500  */
501  void
502  appendShortProperty (const std::string& name, const size_t& count = 1);
503 
504  /** Append a short property to the cloud fields.
505  * param[in] name property name
506  * param[in] count property count: 1 for scalar properties and higher for a
507  * list property.
508  */
509  void
510  appendUnsignedShortProperty (const std::string& name, const size_t& count = 1);
511 
512  /** Append a char property to the cloud fields.
513  * param[in] name property name
514  * param[in] count property count: 1 for scalar properties and higher for a
515  * list property.
516  */
517  void
518  appendCharProperty (const std::string& name, const size_t& count = 1);
519 
520  /** Append a char property to the cloud fields.
521  * param[in] name property name
522  * param[in] count property count: 1 for scalar properties and higher for a
523  * list property.
524  */
525  void
526  appendUnsignedCharProperty (const std::string& name, const size_t& count = 1);
527 
528  /** Amend property from cloud fields identified by \a old_name renaming
529  * it \a new_name.
530  * param[in] old_name property old name
531  * param[in] new_name property new name
532  */
533  void
534  amendProperty (const std::string& old_name, const std::string& new_name, uint8_t datatype = 0);
535 
536  /** Callback function for the begin of vertex line */
537  void
538  vertexBeginCallback ();
539 
540  /** Callback function for the end of vertex line */
541  void
542  vertexEndCallback ();
543 
544  /** Callback function for the begin of range_grid line */
545  void
546  rangeGridBeginCallback ();
547 
548  /** Callback function for the begin of range_grid vertex_indices property
549  * param[in] size vertex_indices list size
550  */
551  void
552  rangeGridVertexIndicesBeginCallback (pcl::io::ply::uint8 size);
553 
554  /** Callback function for each range_grid vertex_indices element
555  * param[in] vertex_index index of the vertex in vertex_indices
556  */
557  void
558  rangeGridVertexIndicesElementCallback (pcl::io::ply::int32 vertex_index);
559 
560  /** Callback function for the end of a range_grid vertex_indices property */
561  void
562  rangeGridVertexIndicesEndCallback ();
563 
564  /** Callback function for the end of a range_grid element end */
565  void
566  rangeGridEndCallback ();
567 
568  /** Callback function for obj_info */
569  void
570  objInfoCallback (const std::string& line);
571 
572  /// origin
573  Eigen::Vector4f origin_;
574 
575  /// orientation
576  Eigen::Matrix3f orientation_;
577 
578  //vertex element artifacts
579  pcl::PCLPointCloud2 *cloud_;
580  size_t vertex_count_, vertex_properties_counter_;
581  int vertex_offset_before_;
582  //range element artifacts
583  std::vector<std::vector <int> > *range_grid_;
584  size_t range_count_, range_grid_vertex_indices_element_index_;
585  size_t rgb_offset_before_;
586  bool do_resize_;
587  public:
588  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
589  };
590 
591  /** \brief Point Cloud Data (PLY) file format writer.
592  * \author Nizar Sallem
593  * \ingroup io
594  */
595  class PCL_EXPORTS PLYWriter : public FileWriter
596  {
597  public:
598  ///Constructor
599  PLYWriter () : FileWriter () {};
600 
601  ///Destructor
602  ~PLYWriter () {};
603 
604  /** \brief Generate the header of a PLY v.7 file format
605  * \param[in] cloud the point cloud data message
606  * \param[in] origin the sensor data acquisition origin (translation)
607  * \param[in] orientation the sensor data acquisition origin (rotation)
608  * \param[in] valid_points number of valid points (finite ones for range_grid and
609  * all of them for camer)
610  * \param[in] use_camera if set to true then PLY file will use element camera else
611  * element range_grid will be used.
612  */
613  inline std::string
615  const Eigen::Vector4f &origin,
616  const Eigen::Quaternionf &orientation,
617  int valid_points,
618  bool use_camera = true)
619  {
620  return (generateHeader (cloud, origin, orientation, true, use_camera, valid_points));
621  }
622 
623  /** \brief Generate the header of a PLY v.7 file format
624  * \param[in] cloud the point cloud data message
625  * \param[in] origin the sensor data acquisition origin (translation)
626  * \param[in] orientation the sensor data acquisition origin (rotation)
627  * \param[in] valid_points number of valid points (finite ones for range_grid and
628  * all of them for camer)
629  * \param[in] use_camera if set to true then PLY file will use element camera else
630  * element range_grid will be used.
631  */
632  inline std::string
634  const Eigen::Vector4f &origin,
635  const Eigen::Quaternionf &orientation,
636  int valid_points,
637  bool use_camera = true)
638  {
639  return (generateHeader (cloud, origin, orientation, false, use_camera, valid_points));
640  }
641 
642  /** \brief Save point cloud data to a PLY file containing n-D points, in ASCII format
643  * \param[in] file_name the output file name
644  * \param[in] cloud the point cloud data message
645  * \param[in] origin the sensor data acquisition origin (translation)
646  * \param[in] orientation the sensor data acquisition origin (rotation)
647  * \param[in] precision the specified output numeric stream precision (default: 8)
648  * \param[in] use_camera if set to true then PLY file will use element camera else
649  * element range_grid will be used.
650  */
651  int
652  writeASCII (const std::string &file_name, const pcl::PCLPointCloud2 &cloud,
653  const Eigen::Vector4f &origin = Eigen::Vector4f::Zero (),
654  const Eigen::Quaternionf &orientation = Eigen::Quaternionf::Identity (),
655  int precision = 8,
656  bool use_camera = true);
657 
658  /** \brief Save point cloud data to a PLY file containing n-D points, in BINARY format
659  * \param[in] file_name the output file name
660  * \param[in] cloud the point cloud data message
661  * \param[in] origin the sensor data acquisition origin (translation)
662  * \param[in] orientation the sensor data acquisition origin (rotation)
663  * \param[in] use_camera if set to true then PLY file will use element camera else
664  * element range_grid will be used
665  */
666  int
667  writeBinary (const std::string &file_name, const pcl::PCLPointCloud2 &cloud,
668  const Eigen::Vector4f &origin = Eigen::Vector4f::Zero (),
669  const Eigen::Quaternionf &orientation = Eigen::Quaternionf::Identity (),
670  bool use_camera = true);
671 
672  /** \brief Save point cloud data to a PLY file containing n-D points
673  * \param[in] file_name the output file name
674  * \param[in] cloud the point cloud data message
675  * \param[in] origin the sensor acquisition origin
676  * \param[in] orientation the sensor acquisition orientation
677  * \param[in] binary set to true if the file is to be written in a binary
678  * PLY format, false (default) for ASCII
679  */
680  inline int
681  write (const std::string &file_name, const pcl::PCLPointCloud2 &cloud,
682  const Eigen::Vector4f &origin = Eigen::Vector4f::Zero (),
683  const Eigen::Quaternionf &orientation = Eigen::Quaternionf::Identity (),
684  const bool binary = false)
685  {
686  if (binary)
687  return (this->writeBinary (file_name, cloud, origin, orientation, true));
688  else
689  return (this->writeASCII (file_name, cloud, origin, orientation, 8, true));
690  }
691 
692  /** \brief Save point cloud data to a PLY file containing n-D points
693  * \param[in] file_name the output file name
694  * \param[in] cloud the point cloud data message
695  * \param[in] origin the sensor acquisition origin
696  * \param[in] orientation the sensor acquisition orientation
697  * \param[in] binary set to true if the file is to be written in a binary
698  * PLY format, false (default) for ASCII
699  * \param[in] use_camera set to true to use camera element and false to
700  * use range_grid element
701  */
702  inline int
703  write (const std::string &file_name, const pcl::PCLPointCloud2 &cloud,
704  const Eigen::Vector4f &origin = Eigen::Vector4f::Zero (),
705  const Eigen::Quaternionf &orientation = Eigen::Quaternionf::Identity (),
706  bool binary = false,
707  bool use_camera = true)
708  {
709  if (binary)
710  return (this->writeBinary (file_name, cloud, origin, orientation, use_camera));
711  else
712  return (this->writeASCII (file_name, cloud, origin, orientation, 8, use_camera));
713  }
714 
715  /** \brief Save point cloud data to a PLY file containing n-D points
716  * \param[in] file_name the output file name
717  * \param[in] cloud the point cloud data message (boost shared pointer)
718  * \param[in] origin the sensor acquisition origin
719  * \param[in] orientation the sensor acquisition orientation
720  * \param[in] binary set to true if the file is to be written in a binary
721  * PLY format, false (default) for ASCII
722  * \param[in] use_camera set to true to use camera element and false to
723  * use range_grid element
724  */
725  inline int
726  write (const std::string &file_name, const pcl::PCLPointCloud2::ConstPtr &cloud,
727  const Eigen::Vector4f &origin = Eigen::Vector4f::Zero (),
728  const Eigen::Quaternionf &orientation = Eigen::Quaternionf::Identity (),
729  bool binary = false,
730  bool use_camera = true)
731  {
732  return (write (file_name, *cloud, origin, orientation, binary, use_camera));
733  }
734 
735  /** \brief Save point cloud data to a PLY file containing n-D points
736  * \param[in] file_name the output file name
737  * \param[in] cloud the pcl::PointCloud data
738  * \param[in] binary set to true if the file is to be written in a binary
739  * PLY format, false (default) for ASCII
740  * \param[in] use_camera set to true to use camera element and false to
741  * use range_grid element
742  */
743  template<typename PointT> inline int
744  write (const std::string &file_name,
745  const pcl::PointCloud<PointT> &cloud,
746  bool binary = false,
747  bool use_camera = true)
748  {
749  Eigen::Vector4f origin = cloud.sensor_origin_;
750  Eigen::Quaternionf orientation = cloud.sensor_orientation_;
751 
752  pcl::PCLPointCloud2 blob;
753  pcl::toPCLPointCloud2 (cloud, blob);
754 
755  // Save the data
756  return (this->write (file_name, blob, origin, orientation, binary, use_camera));
757  }
758 
759  private:
760  /** \brief Generate a PLY header.
761  * \param[in] cloud the input point cloud
762  * \param[in] binary whether the PLY file should be saved as binary data (true) or ascii (false)
763  */
764  std::string
765  generateHeader (const pcl::PCLPointCloud2 &cloud,
766  const Eigen::Vector4f &origin,
767  const Eigen::Quaternionf &orientation,
768  bool binary,
769  bool use_camera,
770  int valid_points);
771 
772  void
773  writeContentWithCameraASCII (int nr_points,
774  int point_size,
775  const pcl::PCLPointCloud2 &cloud,
776  const Eigen::Vector4f &origin,
777  const Eigen::Quaternionf &orientation,
778  std::ofstream& fs);
779 
780  void
781  writeContentWithRangeGridASCII (int nr_points,
782  int point_size,
783  const pcl::PCLPointCloud2 &cloud,
784  std::ostringstream& fs,
785  int& nb_valid_points);
786  };
787 
788  namespace io
789  {
790  /** \brief Load a PLY v.6 file into a templated PointCloud type.
791  *
792  * Any PLY files containg sensor data will generate a warning as a
793  * pcl/PCLPointCloud2 message cannot hold the sensor origin.
794  *
795  * \param[in] file_name the name of the file to load
796  * \param[in] cloud the resultant templated point cloud
797  * \ingroup io
798  */
799  inline int
800  loadPLYFile (const std::string &file_name, pcl::PCLPointCloud2 &cloud)
801  {
802  pcl::PLYReader p;
803  return (p.read (file_name, cloud));
804  }
805 
806  /** \brief Load any PLY file into a templated PointCloud type.
807  * \param[in] file_name the name of the file to load
808  * \param[in] cloud the resultant templated point cloud
809  * \param[in] origin the sensor acquisition origin (only for > PLY_V7 - null if not present)
810  * \param[in] orientation the sensor acquisition orientation if availble,
811  * identity if not present
812  * \ingroup io
813  */
814  inline int
815  loadPLYFile (const std::string &file_name, pcl::PCLPointCloud2 &cloud,
816  Eigen::Vector4f &origin, Eigen::Quaternionf &orientation)
817  {
818  pcl::PLYReader p;
819  int ply_version;
820  return (p.read (file_name, cloud, origin, orientation, ply_version));
821  }
822 
823  /** \brief Load any PLY file into a templated PointCloud type
824  * \param[in] file_name the name of the file to load
825  * \param[in] cloud the resultant templated point cloud
826  * \ingroup io
827  */
828  template<typename PointT> inline int
829  loadPLYFile (const std::string &file_name, pcl::PointCloud<PointT> &cloud)
830  {
831  pcl::PLYReader p;
832  return (p.read (file_name, cloud));
833  }
834 
835  /** \brief Save point cloud data to a PLY file containing n-D points
836  * \param[in] file_name the output file name
837  * \param[in] cloud the point cloud data message
838  * \param[in] origin the sensor data acquisition origin (translation)
839  * \param[in] orientation the sensor data acquisition origin (rotation)
840  * \param[in] binary_mode true for binary mode, false (default) for ASCII
841  * \ingroup io
842  */
843  inline int
844  savePLYFile (const std::string &file_name, const pcl::PCLPointCloud2 &cloud,
845  const Eigen::Vector4f &origin = Eigen::Vector4f::Zero (),
846  const Eigen::Quaternionf &orientation = Eigen::Quaternionf::Identity (),
847  bool binary_mode = false, bool use_camera = true)
848  {
849  PLYWriter w;
850  return (w.write (file_name, cloud, origin, orientation, binary_mode, use_camera));
851  }
852 
853  /** \brief Templated version for saving point cloud data to a PLY file
854  * containing a specific given cloud format
855  * \param[in] file_name the output file name
856  * \param[in] cloud the point cloud data message
857  * \param[in] binary_mode true for binary mode, false (default) for ASCII
858  * \ingroup io
859  */
860  template<typename PointT> inline int
861  savePLYFile (const std::string &file_name, const pcl::PointCloud<PointT> &cloud, bool binary_mode = false)
862  {
863  PLYWriter w;
864  return (w.write<PointT> (file_name, cloud, binary_mode));
865  }
866 
867  /** \brief Templated version for saving point cloud data to a PLY file
868  * containing a specific given cloud format.
869  * \param[in] file_name the output file name
870  * \param[in] cloud the point cloud data message
871  * \ingroup io
872  */
873  template<typename PointT> inline int
874  savePLYFileASCII (const std::string &file_name, const pcl::PointCloud<PointT> &cloud)
875  {
876  PLYWriter w;
877  return (w.write<PointT> (file_name, cloud, false));
878  }
879 
880  /** \brief Templated version for saving point cloud data to a PLY file containing a specific given cloud format.
881  * \param[in] file_name the output file name
882  * \param[in] cloud the point cloud data message
883  * \ingroup io
884  */
885  template<typename PointT> inline int
886  savePLYFileBinary (const std::string &file_name, const pcl::PointCloud<PointT> &cloud)
887  {
888  PLYWriter w;
889  return (w.write<PointT> (file_name, cloud, true));
890  }
891 
892  /** \brief Templated version for saving point cloud data to a PLY file containing a specific given cloud format
893  * \param[in] file_name the output file name
894  * \param[in] cloud the point cloud data message
895  * \param[in] indices the set of indices to save
896  * \param[in] binary_mode true for binary mode, false (default) for ASCII
897  * \ingroup io
898  */
899  template<typename PointT> int
900  savePLYFile (const std::string &file_name, const pcl::PointCloud<PointT> &cloud,
901  const std::vector<int> &indices, bool binary_mode = false)
902  {
903  // Copy indices to a new point cloud
904  pcl::PointCloud<PointT> cloud_out;
905  copyPointCloud (cloud, indices, cloud_out);
906  // Save the data
907  PLYWriter w;
908  return (w.write<PointT> (file_name, cloud_out, binary_mode));
909  }
910 
911  /** \brief Saves a PolygonMesh in ascii PLY format.
912  * \param[in] file_name the name of the file to write to disk
913  * \param[in] mesh the polygonal mesh to save
914  * \param[in] precision the output ASCII precision default 5
915  * \ingroup io
916  */
917  PCL_EXPORTS int
918  savePLYFile (const std::string &file_name, const pcl::PolygonMesh &mesh, unsigned precision = 5);
919 
920  /** \brief Saves a PolygonMesh in binary PLY format.
921  * \param[in] file_name the name of the file to write to disk
922  * \param[in] mesh the polygonal mesh to save
923  * \ingroup io
924  */
925  PCL_EXPORTS int
926  savePLYFileBinary (const std::string &file_name, const pcl::PolygonMesh &mesh);
927  }
928 }
929 
930 #endif //#ifndef PCL_IO_PLY_IO_H_