Point Cloud Library (PCL)  1.9.1-dev
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 #pragma once
41 
42 #include <pcl/io/boost.h>
43 #include <pcl/io/file_io.h>
44 #include <pcl/io/ply/ply_parser.h>
45 #include <pcl/PolygonMesh.h>
46 #include <sstream>
47 
48 namespace pcl
49 {
50  /** \brief Point Cloud Data (PLY) file format reader.
51  *
52  * The PLY data format is organized in the following way:
53  * lines beginning with "comment" are treated as comments
54  * - ply
55  * - format [ascii|binary_little_endian|binary_big_endian] 1.0
56  * - element vertex COUNT
57  * - property float x
58  * - property float y
59  * - [property float z]
60  * - [property float normal_x]
61  * - [property float normal_y]
62  * - [property float normal_z]
63  * - [property uchar red]
64  * - [property uchar green]
65  * - [property uchar blue] ...
66  * - ascii/binary point coordinates
67  * - [element camera 1]
68  * - [property float view_px] ...
69  * - [element range_grid COUNT]
70  * - [property list uchar int vertex_indices]
71  * - end header
72  *
73  * \author Nizar Sallem
74  * \ingroup io
75  */
76  class PCL_EXPORTS PLYReader : public FileReader
77  {
78  public:
79  enum
80  {
81  PLY_V0 = 0,
82  PLY_V1 = 1
83  };
84 
86  : origin_ (Eigen::Vector4f::Zero ())
87  , orientation_ (Eigen::Matrix3f::Zero ())
88  , cloud_ ()
89  , vertex_count_ (0)
90  , vertex_offset_before_ (0)
91  , range_grid_ (nullptr)
92  , rgb_offset_before_ (0)
93  , do_resize_ (false)
94  , polygons_ (nullptr)
95  , r_(0), g_(0), b_(0)
96  , a_(0), rgba_(0)
97  {}
98 
99  PLYReader (const PLYReader &p)
100  : origin_ (Eigen::Vector4f::Zero ())
101  , orientation_ (Eigen::Matrix3f::Zero ())
102  , cloud_ ()
103  , vertex_count_ (0)
104  , vertex_offset_before_ (0)
105  , range_grid_ (nullptr)
106  , rgb_offset_before_ (0)
107  , do_resize_ (false)
108  , polygons_ (nullptr)
109  , r_(0), g_(0), b_(0)
110  , a_(0), rgba_(0)
111  {
112  *this = p;
113  }
114 
115  PLYReader&
116  operator = (const PLYReader &p)
117  {
118  origin_ = p.origin_;
119  orientation_ = p.orientation_;
120  range_grid_ = p.range_grid_;
121  polygons_ = p.polygons_;
122  return (*this);
123  }
124 
125  ~PLYReader () { delete range_grid_; }
126  /** \brief Read a point cloud data header from a PLY file.
127  *
128  * Load only the meta information (number of points, their types, etc),
129  * and not the points themselves, from a given PLY file. Useful for fast
130  * evaluation of the underlying data structure.
131  *
132  * Returns:
133  * * < 0 (-1) on error
134  * * > 0 on success
135  * \param[in] file_name the name of the file to load
136  * \param[out] cloud the resultant point cloud dataset (only the header will be filled)
137  * \param[in] origin the sensor data acquisition origin (translation)
138  * \param[in] orientation the sensor data acquisition origin (rotation)
139  * \param[out] ply_version the PLY version read from the file
140  * \param[out] data_type the type of PLY data stored in the file
141  * \param[out] data_idx the data index
142  * \param[in] offset the offset in the file where to expect the true header to begin.
143  * One usage example for setting the offset parameter is for reading
144  * data from a TAR "archive containing multiple files: TAR files always
145  * add a 512 byte header in front of the actual file, so set the offset
146  * to the next byte after the header (e.g., 513).
147  */
148  int
149  readHeader (const std::string &file_name, pcl::PCLPointCloud2 &cloud,
150  Eigen::Vector4f &origin, Eigen::Quaternionf &orientation,
151  int &ply_version, int &data_type, unsigned int &data_idx, const int offset = 0) override;
152 
153  /** \brief Read a point cloud data from a PLY file and store it into a pcl/PCLPointCloud2.
154  * \param[in] file_name the name of the file containing the actual PointCloud data
155  * \param[out] cloud the resultant PointCloud message read from disk
156  * \param[in] origin the sensor data acquisition origin (translation)
157  * \param[in] orientation the sensor data acquisition origin (rotation)
158  * \param[out] ply_version the PLY version read from the file
159  * \param[in] offset the offset in the file where to expect the true header to begin.
160  * One usage example for setting the offset parameter is for reading
161  * data from a TAR "archive containing multiple files: TAR files always
162  * add a 512 byte header in front of the actual file, so set the offset
163  * to the next byte after the header (e.g., 513).
164  */
165  int
166  read (const std::string &file_name, pcl::PCLPointCloud2 &cloud,
167  Eigen::Vector4f &origin, Eigen::Quaternionf &orientation, int& ply_version, const int offset = 0) override;
168 
169  /** \brief Read a point cloud data from a PLY file and store it into a pcl/PCLPointCloud2.
170  * \note This function is provided for backwards compatibility only
171  * \param[in] file_name the name of the file containing the actual PointCloud data
172  * \param[out] cloud the resultant PointCloud message read from disk
173  * \param[in] offset the offset in the file where to expect the true header to begin.
174  * One usage example for setting the offset parameter is for reading
175  * data from a TAR "archive containing multiple files: TAR files always
176  * add a 512 byte header in front of the actual file, so set the offset
177  * to the next byte after the header (e.g., 513).
178  */
179  inline int
180  read (const std::string &file_name, pcl::PCLPointCloud2 &cloud, const int offset = 0)
181  {
182  Eigen::Vector4f origin;
183  Eigen::Quaternionf orientation;
184  int ply_version;
185  return read (file_name, cloud, origin, orientation, ply_version, offset);
186  }
187 
188  /** \brief Read a point cloud data from any PLY file, and convert it to the given template format.
189  * \param[in] file_name the name of the file containing the actual PointCloud data
190  * \param[out] cloud the resultant PointCloud message read from disk
191  * \param[in] offset the offset in the file where to expect the true header to begin.
192  * One usage example for setting the offset parameter is for reading
193  * data from a TAR "archive containing multiple files: TAR files always
194  * add a 512 byte header in front of the actual file, so set the offset
195  * to the next byte after the header (e.g., 513).
196  */
197  template<typename PointT> inline int
198  read (const std::string &file_name, pcl::PointCloud<PointT> &cloud, const int offset = 0)
199  {
200  pcl::PCLPointCloud2 blob;
201  int ply_version;
202  int res = read (file_name, blob, cloud.sensor_origin_, cloud.sensor_orientation_,
203  ply_version, offset);
204 
205  // Exit in case of error
206  if (res < 0)
207  return (res);
208  pcl::fromPCLPointCloud2 (blob, cloud);
209  return (0);
210  }
211 
212  /** \brief Read a point cloud data from a PLY file and store it into a pcl/PolygonMesh.
213  *
214  * \param[in] file_name the name of the file containing the actual PointCloud data
215  * \param[out] mesh the resultant PolygonMesh message read from disk
216  * \param[in] origin the sensor data acquisition origin (translation)
217  * \param[in] orientation the sensor data acquisition origin (rotation)
218  * \param[out] ply_version the PLY version read from the file
219  * \param[in] offset the offset in the file where to expect the true header to begin.
220  * One usage example for setting the offset parameter is for reading
221  * data from a TAR "archive containing multiple files: TAR files always
222  * add a 512 byte header in front of the actual file, so set the offset
223  * to the next byte after the header (e.g., 513).
224  */
225  int
226  read (const std::string &file_name, pcl::PolygonMesh &mesh,
227  Eigen::Vector4f &origin, Eigen::Quaternionf &orientation,
228  int& ply_version, const int offset = 0);
229 
230  /** \brief Read a point cloud data from a PLY file and store it into a pcl/PolygonMesh.
231  *
232  * \param[in] file_name the name of the file containing the actual PointCloud data
233  * \param[out] mesh the resultant PolygonMesh message read from disk
234  * \param[in] offset the offset in the file where to expect the true header to begin.
235  * One usage example for setting the offset parameter is for reading
236  * data from a TAR "archive containing multiple files: TAR files always
237  * add a 512 byte header in front of the actual file, so set the offset
238  * to the next byte after the header (e.g., 513).
239  */
240  int
241  read (const std::string &file_name, pcl::PolygonMesh &mesh, const int offset = 0);
242 
243  private:
245 
246  bool
247  parse (const std::string& istream_filename);
248 
249  /** \brief Info callback function
250  * \param[in] filename PLY file read
251  * \param[in] line_number line triggering the callback
252  * \param[in] message information message
253  */
254  void
255  infoCallback (const std::string& filename, std::size_t line_number, const std::string& message)
256  {
257  PCL_DEBUG ("[pcl::PLYReader] %s:%lu: %s\n", filename.c_str (), line_number, message.c_str ());
258  }
259 
260  /** \brief Warning callback function
261  * \param[in] filename PLY file read
262  * \param[in] line_number line triggering the callback
263  * \param[in] message warning message
264  */
265  void
266  warningCallback (const std::string& filename, std::size_t line_number, const std::string& message)
267  {
268  PCL_WARN ("[pcl::PLYReader] %s:%lu: %s\n", filename.c_str (), line_number, message.c_str ());
269  }
270 
271  /** \brief Error callback function
272  * \param[in] filename PLY file read
273  * \param[in] line_number line triggering the callback
274  * \param[in] message error message
275  */
276  void
277  errorCallback (const std::string& filename, std::size_t line_number, const std::string& message)
278  {
279  PCL_ERROR ("[pcl::PLYReader] %s:%lu: %s\n", filename.c_str (), line_number, message.c_str ());
280  }
281 
282  /** \brief function called when the keyword element is parsed
283  * \param[in] element_name element name
284  * \param[in] count number of instances
285  */
286  boost::tuple<boost::function<void ()>, boost::function<void ()> >
287  elementDefinitionCallback (const std::string& element_name, std::size_t count);
288 
289  bool
290  endHeaderCallback ();
291 
292  /** \brief function called when a scalar property is parsed
293  * \param[in] element_name element name to which the property belongs
294  * \param[in] property_name property name
295  */
296  template <typename ScalarType> boost::function<void (ScalarType)>
297  scalarPropertyDefinitionCallback (const std::string& element_name, const std::string& property_name);
298 
299  /** \brief function called when a list property is parsed
300  * \param[in] element_name element name to which the property belongs
301  * \param[in] property_name list property name
302  */
303  template <typename SizeType, typename ScalarType>
304  boost::tuple<boost::function<void (SizeType)>, boost::function<void (ScalarType)>, boost::function<void ()> >
305  listPropertyDefinitionCallback (const std::string& element_name, const std::string& property_name);
306 
307  /** \brief function called at the beginning of a list property parsing.
308  * \param[in] size number of elements in the list
309  */
310  template <typename SizeType> void
311  vertexListPropertyBeginCallback (const std::string& property_name, SizeType size);
312 
313  /** \brief function called when a list element is parsed.
314  * \param[in] value the list's element value
315  */
316  template <typename ContentType> void
317  vertexListPropertyContentCallback (ContentType value);
318 
319  /** \brief function called at the end of a list property parsing */
320  inline void
321  vertexListPropertyEndCallback ();
322 
323  /** Callback function for an anonymous vertex scalar property.
324  * Writes down a double value in cloud data.
325  * param[in] value double value parsed
326  */
327  template<typename Scalar> void
328  vertexScalarPropertyCallback (Scalar value);
329 
330  /** Callback function for vertex RGB color.
331  * This callback is in charge of packing red green and blue in a single int
332  * before writing it down in cloud data.
333  * param[in] color_name color name in {red, green, blue}
334  * param[in] color value of {red, green, blue} property
335  */
336  inline void
337  vertexColorCallback (const std::string& color_name, pcl::io::ply::uint8 color);
338 
339  /** Callback function for vertex intensity.
340  * converts intensity from int to float before writing it down in cloud data.
341  * param[in] intensity
342  */
343  inline void
344  vertexIntensityCallback (pcl::io::ply::uint8 intensity);
345 
346  /** Callback function for vertex alpha.
347  * extracts RGB value, append alpha and put it back
348  * param[in] alpha
349  */
350  inline void
351  vertexAlphaCallback (pcl::io::ply::uint8 alpha);
352 
353  /** Callback function for origin x component.
354  * param[in] value origin x value
355  */
356  inline void
357  originXCallback (const float& value) { origin_[0] = value; }
358 
359  /** Callback function for origin y component.
360  * param[in] value origin y value
361  */
362  inline void
363  originYCallback (const float& value) { origin_[1] = value; }
364 
365  /** Callback function for origin z component.
366  * param[in] value origin z value
367  */
368  inline void
369  originZCallback (const float& value) { origin_[2] = value; }
370 
371  /** Callback function for orientation x axis x component.
372  * param[in] value orientation x axis x value
373  */
374  inline void
375  orientationXaxisXCallback (const float& value) { orientation_ (0,0) = value; }
376 
377  /** Callback function for orientation x axis y component.
378  * param[in] value orientation x axis y value
379  */
380  inline void
381  orientationXaxisYCallback (const float& value) { orientation_ (0,1) = value; }
382 
383  /** Callback function for orientation x axis z component.
384  * param[in] value orientation x axis z value
385  */
386  inline void
387  orientationXaxisZCallback (const float& value) { orientation_ (0,2) = value; }
388 
389  /** Callback function for orientation y axis x component.
390  * param[in] value orientation y axis x value
391  */
392  inline void
393  orientationYaxisXCallback (const float& value) { orientation_ (1,0) = value; }
394 
395  /** Callback function for orientation y axis y component.
396  * param[in] value orientation y axis y value
397  */
398  inline void
399  orientationYaxisYCallback (const float& value) { orientation_ (1,1) = value; }
400 
401  /** Callback function for orientation y axis z component.
402  * param[in] value orientation y axis z value
403  */
404  inline void
405  orientationYaxisZCallback (const float& value) { orientation_ (1,2) = value; }
406 
407  /** Callback function for orientation z axis x component.
408  * param[in] value orientation z axis x value
409  */
410  inline void
411  orientationZaxisXCallback (const float& value) { orientation_ (2,0) = value; }
412 
413  /** Callback function for orientation z axis y component.
414  * param[in] value orientation z axis y value
415  */
416  inline void
417  orientationZaxisYCallback (const float& value) { orientation_ (2,1) = value; }
418 
419  /** Callback function for orientation z axis z component.
420  * param[in] value orientation z axis z value
421  */
422  inline void
423  orientationZaxisZCallback (const float& value) { orientation_ (2,2) = value; }
424 
425  /** Callback function to set the cloud height
426  * param[in] height cloud height
427  */
428  inline void
429  cloudHeightCallback (const int &height) { cloud_->height = height; }
430 
431  /** Callback function to set the cloud width
432  * param[in] width cloud width
433  */
434  inline void
435  cloudWidthCallback (const int &width) { cloud_->width = width; }
436 
437  /** Append a scalar property to the cloud fields.
438  * param[in] name property name
439  * param[in] count property count: 1 for scalar properties and higher for a
440  * list property.
441  */
442  template<typename Scalar> void
443  appendScalarProperty (const std::string& name, const size_t& count = 1);
444 
445  /** Amend property from cloud fields identified by \a old_name renaming
446  * it \a new_name.
447  * param[in] old_name property old name
448  * param[in] new_name property new name
449  */
450  void
451  amendProperty (const std::string& old_name, const std::string& new_name, uint8_t datatype = 0);
452 
453  /** Callback function for the begin of vertex line */
454  void
455  vertexBeginCallback ();
456 
457  /** Callback function for the end of vertex line */
458  void
459  vertexEndCallback ();
460 
461  /** Callback function for the begin of range_grid line */
462  void
463  rangeGridBeginCallback ();
464 
465  /** Callback function for the begin of range_grid vertex_indices property
466  * param[in] size vertex_indices list size
467  */
468  void
469  rangeGridVertexIndicesBeginCallback (pcl::io::ply::uint8 size);
470 
471  /** Callback function for each range_grid vertex_indices element
472  * param[in] vertex_index index of the vertex in vertex_indices
473  */
474  void
475  rangeGridVertexIndicesElementCallback (pcl::io::ply::int32 vertex_index);
476 
477  /** Callback function for the end of a range_grid vertex_indices property */
478  void
479  rangeGridVertexIndicesEndCallback ();
480 
481  /** Callback function for the end of a range_grid element end */
482  void
483  rangeGridEndCallback ();
484 
485  /** Callback function for obj_info */
486  void
487  objInfoCallback (const std::string& line);
488 
489  /** Callback function for the begin of face line */
490  void
491  faceBeginCallback ();
492 
493  /** Callback function for the begin of face vertex_indices property
494  * param[in] size vertex_indices list size
495  */
496  void
497  faceVertexIndicesBeginCallback (pcl::io::ply::uint8 size);
498 
499  /** Callback function for each face vertex_indices element
500  * param[in] vertex_index index of the vertex in vertex_indices
501  */
502  void
503  faceVertexIndicesElementCallback (pcl::io::ply::int32 vertex_index);
504 
505  /** Callback function for the end of a face vertex_indices property */
506  void
507  faceVertexIndicesEndCallback ();
508 
509  /** Callback function for the end of a face element end */
510  void
511  faceEndCallback ();
512 
513  /// origin
514  Eigen::Vector4f origin_;
515 
516  /// orientation
517  Eigen::Matrix3f orientation_;
518 
519  //vertex element artifacts
520  pcl::PCLPointCloud2 *cloud_;
521  size_t vertex_count_;
522  int vertex_offset_before_;
523  //range element artifacts
524  std::vector<std::vector <int> > *range_grid_;
525  size_t rgb_offset_before_;
526  bool do_resize_;
527  //face element artifact
528  std::vector<pcl::Vertices> *polygons_;
529  public:
530  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
531 
532  private:
533  // RGB values stored by vertexColorCallback()
534  int32_t r_, g_, b_;
535  // Color values stored by vertexAlphaCallback()
536  uint32_t a_, rgba_;
537  };
538 
539  /** \brief Point Cloud Data (PLY) file format writer.
540  * \author Nizar Sallem
541  * \ingroup io
542  */
543  class PCL_EXPORTS PLYWriter : public FileWriter
544  {
545  public:
546  ///Constructor
547  PLYWriter () {};
548 
549  ///Destructor
550  ~PLYWriter () {};
551 
552  /** \brief Generate the header of a PLY v.7 file format
553  * \param[in] cloud the point cloud data message
554  * \param[in] origin the sensor data acquisition origin (translation)
555  * \param[in] orientation the sensor data acquisition origin (rotation)
556  * \param[in] valid_points number of valid points (finite ones for range_grid and
557  * all of them for camer)
558  * \param[in] use_camera if set to true then PLY file will use element camera else
559  * element range_grid will be used.
560  */
561  inline std::string
563  const Eigen::Vector4f &origin,
564  const Eigen::Quaternionf &orientation,
565  int valid_points,
566  bool use_camera = true)
567  {
568  return (generateHeader (cloud, origin, orientation, true, use_camera, valid_points));
569  }
570 
571  /** \brief Generate the header of a PLY v.7 file format
572  * \param[in] cloud the point cloud data message
573  * \param[in] origin the sensor data acquisition origin (translation)
574  * \param[in] orientation the sensor data acquisition origin (rotation)
575  * \param[in] valid_points number of valid points (finite ones for range_grid and
576  * all of them for camer)
577  * \param[in] use_camera if set to true then PLY file will use element camera else
578  * element range_grid will be used.
579  */
580  inline std::string
582  const Eigen::Vector4f &origin,
583  const Eigen::Quaternionf &orientation,
584  int valid_points,
585  bool use_camera = true)
586  {
587  return (generateHeader (cloud, origin, orientation, false, use_camera, valid_points));
588  }
589 
590  /** \brief Save point cloud data to a PLY file containing n-D points, in ASCII format
591  * \param[in] file_name the output file name
592  * \param[in] cloud the point cloud data message
593  * \param[in] origin the sensor data acquisition origin (translation)
594  * \param[in] orientation the sensor data acquisition origin (rotation)
595  * \param[in] precision the specified output numeric stream precision (default: 8)
596  * \param[in] use_camera if set to true then PLY file will use element camera else
597  * element range_grid will be used.
598  */
599  int
600  writeASCII (const std::string &file_name, const pcl::PCLPointCloud2 &cloud,
601  const Eigen::Vector4f &origin = Eigen::Vector4f::Zero (),
602  const Eigen::Quaternionf &orientation = Eigen::Quaternionf::Identity (),
603  int precision = 8,
604  bool use_camera = true);
605 
606  /** \brief Save point cloud data to a PLY file containing n-D points, in BINARY format
607  * \param[in] file_name the output file name
608  * \param[in] cloud the point cloud data message
609  * \param[in] origin the sensor data acquisition origin (translation)
610  * \param[in] orientation the sensor data acquisition origin (rotation)
611  * \param[in] use_camera if set to true then PLY file will use element camera else
612  * element range_grid will be used
613  */
614  int
615  writeBinary (const std::string &file_name, const pcl::PCLPointCloud2 &cloud,
616  const Eigen::Vector4f &origin = Eigen::Vector4f::Zero (),
617  const Eigen::Quaternionf &orientation = Eigen::Quaternionf::Identity (),
618  bool use_camera = true);
619 
620  /** \brief Save point cloud data to a PLY file containing n-D points
621  * \param[in] file_name the output file name
622  * \param[in] cloud the point cloud data message
623  * \param[in] origin the sensor acquisition origin
624  * \param[in] orientation the sensor acquisition orientation
625  * \param[in] binary set to true if the file is to be written in a binary
626  * PLY format, false (default) for ASCII
627  */
628  inline int
629  write (const std::string &file_name, const pcl::PCLPointCloud2 &cloud,
630  const Eigen::Vector4f &origin = Eigen::Vector4f::Zero (),
631  const Eigen::Quaternionf &orientation = Eigen::Quaternionf::Identity (),
632  const bool binary = false) override
633  {
634  if (binary)
635  return (this->writeBinary (file_name, cloud, origin, orientation, true));
636  else
637  return (this->writeASCII (file_name, cloud, origin, orientation, 8, true));
638  }
639 
640  /** \brief Save point cloud data to a PLY file containing n-D points
641  * \param[in] file_name the output file name
642  * \param[in] cloud the point cloud data message
643  * \param[in] origin the sensor acquisition origin
644  * \param[in] orientation the sensor acquisition orientation
645  * \param[in] binary set to true if the file is to be written in a binary
646  * PLY format, false (default) for ASCII
647  * \param[in] use_camera set to true to use camera element and false to
648  * use range_grid element
649  */
650  inline int
651  write (const std::string &file_name, const pcl::PCLPointCloud2 &cloud,
652  const Eigen::Vector4f &origin = Eigen::Vector4f::Zero (),
653  const Eigen::Quaternionf &orientation = Eigen::Quaternionf::Identity (),
654  bool binary = false,
655  bool use_camera = true)
656  {
657  if (binary)
658  return (this->writeBinary (file_name, cloud, origin, orientation, use_camera));
659  else
660  return (this->writeASCII (file_name, cloud, origin, orientation, 8, use_camera));
661  }
662 
663  /** \brief Save point cloud data to a PLY file containing n-D points
664  * \param[in] file_name the output file name
665  * \param[in] cloud the point cloud data message (boost shared pointer)
666  * \param[in] origin the sensor acquisition origin
667  * \param[in] orientation the sensor acquisition orientation
668  * \param[in] binary set to true if the file is to be written in a binary
669  * PLY format, false (default) for ASCII
670  * \param[in] use_camera set to true to use camera element and false to
671  * use range_grid element
672  */
673  inline int
674  write (const std::string &file_name, const pcl::PCLPointCloud2::ConstPtr &cloud,
675  const Eigen::Vector4f &origin = Eigen::Vector4f::Zero (),
676  const Eigen::Quaternionf &orientation = Eigen::Quaternionf::Identity (),
677  bool binary = false,
678  bool use_camera = true)
679  {
680  return (write (file_name, *cloud, origin, orientation, binary, use_camera));
681  }
682 
683  /** \brief Save point cloud data to a PLY file containing n-D points
684  * \param[in] file_name the output file name
685  * \param[in] cloud the pcl::PointCloud data
686  * \param[in] binary set to true if the file is to be written in a binary
687  * PLY format, false (default) for ASCII
688  * \param[in] use_camera set to true to use camera element and false to
689  * use range_grid element
690  */
691  template<typename PointT> inline int
692  write (const std::string &file_name,
693  const pcl::PointCloud<PointT> &cloud,
694  bool binary = false,
695  bool use_camera = true)
696  {
697  Eigen::Vector4f origin = cloud.sensor_origin_;
698  Eigen::Quaternionf orientation = cloud.sensor_orientation_;
699 
700  pcl::PCLPointCloud2 blob;
701  pcl::toPCLPointCloud2 (cloud, blob);
702 
703  // Save the data
704  return (this->write (file_name, blob, origin, orientation, binary, use_camera));
705  }
706 
707  private:
708  /** \brief Generate a PLY header.
709  * \param[in] cloud the input point cloud
710  * \param[in] binary whether the PLY file should be saved as binary data (true) or ascii (false)
711  */
712  std::string
713  generateHeader (const pcl::PCLPointCloud2 &cloud,
714  const Eigen::Vector4f &origin,
715  const Eigen::Quaternionf &orientation,
716  bool binary,
717  bool use_camera,
718  int valid_points);
719 
720  void
721  writeContentWithCameraASCII (int nr_points,
722  int point_size,
723  const pcl::PCLPointCloud2 &cloud,
724  const Eigen::Vector4f &origin,
725  const Eigen::Quaternionf &orientation,
726  std::ofstream& fs);
727 
728  void
729  writeContentWithRangeGridASCII (int nr_points,
730  int point_size,
731  const pcl::PCLPointCloud2 &cloud,
732  std::ostringstream& fs,
733  int& nb_valid_points);
734  };
735 
736  namespace io
737  {
738  /** \brief Load a PLY v.6 file into a templated PointCloud type.
739  *
740  * Any PLY files containing sensor data will generate a warning as a
741  * pcl/PCLPointCloud2 message cannot hold the sensor origin.
742  *
743  * \param[in] file_name the name of the file to load
744  * \param[in] cloud the resultant templated point cloud
745  * \ingroup io
746  */
747  inline int
748  loadPLYFile (const std::string &file_name, pcl::PCLPointCloud2 &cloud)
749  {
750  pcl::PLYReader p;
751  return (p.read (file_name, cloud));
752  }
753 
754  /** \brief Load any PLY file into a templated PointCloud type.
755  * \param[in] file_name the name of the file to load
756  * \param[in] cloud the resultant templated point cloud
757  * \param[in] origin the sensor acquisition origin (only for > PLY_V7 - null if not present)
758  * \param[in] orientation the sensor acquisition orientation if available,
759  * identity if not present
760  * \ingroup io
761  */
762  inline int
763  loadPLYFile (const std::string &file_name, pcl::PCLPointCloud2 &cloud,
764  Eigen::Vector4f &origin, Eigen::Quaternionf &orientation)
765  {
766  pcl::PLYReader p;
767  int ply_version;
768  return (p.read (file_name, cloud, origin, orientation, ply_version));
769  }
770 
771  /** \brief Load any PLY file into a templated PointCloud type
772  * \param[in] file_name the name of the file to load
773  * \param[in] cloud the resultant templated point cloud
774  * \ingroup io
775  */
776  template<typename PointT> inline int
777  loadPLYFile (const std::string &file_name, pcl::PointCloud<PointT> &cloud)
778  {
779  pcl::PLYReader p;
780  return (p.read (file_name, cloud));
781  }
782 
783  /** \brief Load a PLY file into a PolygonMesh type.
784  *
785  * Any PLY files containing sensor data will generate a warning as a
786  * pcl/PolygonMesh message cannot hold the sensor origin.
787  *
788  * \param[in] file_name the name of the file to load
789  * \param[in] mesh the resultant polygon mesh
790  * \ingroup io
791  */
792  inline int
793  loadPLYFile (const std::string &file_name, pcl::PolygonMesh &mesh)
794  {
795  pcl::PLYReader p;
796  return (p.read (file_name, mesh));
797  }
798 
799  /** \brief Save point cloud data to a PLY file containing n-D points
800  * \param[in] file_name the output file name
801  * \param[in] cloud the point cloud data message
802  * \param[in] origin the sensor data acquisition origin (translation)
803  * \param[in] orientation the sensor data acquisition origin (rotation)
804  * \param[in] binary_mode true for binary mode, false (default) for ASCII
805  * \param[in] use_camera
806  * \ingroup io
807  */
808  inline int
809  savePLYFile (const std::string &file_name, const pcl::PCLPointCloud2 &cloud,
810  const Eigen::Vector4f &origin = Eigen::Vector4f::Zero (),
811  const Eigen::Quaternionf &orientation = Eigen::Quaternionf::Identity (),
812  bool binary_mode = false, bool use_camera = true)
813  {
814  PLYWriter w;
815  return (w.write (file_name, cloud, origin, orientation, binary_mode, use_camera));
816  }
817 
818  /** \brief Templated version for saving point cloud data to a PLY file
819  * containing a specific given cloud format
820  * \param[in] file_name the output file name
821  * \param[in] cloud the point cloud data message
822  * \param[in] binary_mode true for binary mode, false (default) for ASCII
823  * \ingroup io
824  */
825  template<typename PointT> inline int
826  savePLYFile (const std::string &file_name, const pcl::PointCloud<PointT> &cloud, bool binary_mode = false)
827  {
828  PLYWriter w;
829  return (w.write<PointT> (file_name, cloud, binary_mode));
830  }
831 
832  /** \brief Templated version for saving point cloud data to a PLY file
833  * containing a specific given cloud format.
834  * \param[in] file_name the output file name
835  * \param[in] cloud the point cloud data message
836  * \ingroup io
837  */
838  template<typename PointT> inline int
839  savePLYFileASCII (const std::string &file_name, const pcl::PointCloud<PointT> &cloud)
840  {
841  PLYWriter w;
842  return (w.write<PointT> (file_name, cloud, false));
843  }
844 
845  /** \brief Templated version for saving point cloud data to a PLY file containing a specific given cloud format.
846  * \param[in] file_name the output file name
847  * \param[in] cloud the point cloud data message
848  * \ingroup io
849  */
850  template<typename PointT> inline int
851  savePLYFileBinary (const std::string &file_name, const pcl::PointCloud<PointT> &cloud)
852  {
853  PLYWriter w;
854  return (w.write<PointT> (file_name, cloud, true));
855  }
856 
857  /** \brief Templated version for saving point cloud data to a PLY file containing a specific given cloud format
858  * \param[in] file_name the output file name
859  * \param[in] cloud the point cloud data message
860  * \param[in] indices the set of indices to save
861  * \param[in] binary_mode true for binary mode, false (default) for ASCII
862  * \ingroup io
863  */
864  template<typename PointT> int
865  savePLYFile (const std::string &file_name, const pcl::PointCloud<PointT> &cloud,
866  const std::vector<int> &indices, bool binary_mode = false)
867  {
868  // Copy indices to a new point cloud
869  pcl::PointCloud<PointT> cloud_out;
870  copyPointCloud (cloud, indices, cloud_out);
871  // Save the data
872  PLYWriter w;
873  return (w.write<PointT> (file_name, cloud_out, binary_mode));
874  }
875 
876  /** \brief Saves a PolygonMesh in ascii PLY format.
877  * \param[in] file_name the name of the file to write to disk
878  * \param[in] mesh the polygonal mesh to save
879  * \param[in] precision the output ASCII precision default 5
880  * \ingroup io
881  */
882  PCL_EXPORTS int
883  savePLYFile (const std::string &file_name, const pcl::PolygonMesh &mesh, unsigned precision = 5);
884 
885  /** \brief Saves a PolygonMesh in binary PLY format.
886  * \param[in] file_name the name of the file to write to disk
887  * \param[in] mesh the polygonal mesh to save
888  * \ingroup io
889  */
890  PCL_EXPORTS int
891  savePLYFileBinary (const std::string &file_name, const pcl::PolygonMesh &mesh);
892  }
893 }
void fromPCLPointCloud2(const pcl::PCLPointCloud2 &msg, pcl::PointCloud< PointT > &cloud, const MsgFieldMap &field_map)
Convert a PCLPointCloud2 binary data blob into a pcl::PointCloud<T> object using a field_map...
Definition: conversions.h:168
PLYReader(const PLYReader &p)
Definition: ply_io.h:99
std::string generateHeaderASCII(const pcl::PCLPointCloud2 &cloud, const Eigen::Vector4f &origin, const Eigen::Quaternionf &orientation, int valid_points, bool use_camera=true)
Generate the header of a PLY v.7 file format.
Definition: ply_io.h:581
This file defines compatibility wrappers for low level I/O functions.
Definition: convolution.h:44
~PLYWriter()
Destructor.
Definition: ply_io.h:550
void read(std::istream &stream, Type &value)
Function for reading data from a stream.
Definition: region_xy.h:46
Point Cloud Data (FILE) file format writer.
Definition: file_io.h:161
PCL_EXPORTS void copyPointCloud(const pcl::PCLPointCloud2 &cloud_in, const std::vector< int > &indices, pcl::PCLPointCloud2 &cloud_out)
Extract the indices of a given point cloud as a new point cloud.
int write(const std::string &file_name, const pcl::PCLPointCloud2::ConstPtr &cloud, const Eigen::Vector4f &origin=Eigen::Vector4f::Zero(), const Eigen::Quaternionf &orientation=Eigen::Quaternionf::Identity(), bool binary=false, bool use_camera=true)
Save point cloud data to a PLY file containing n-D points.
Definition: ply_io.h:674
Definition: bfgs.h:9
int read(const std::string &file_name, pcl::PointCloud< PointT > &cloud, const int offset=0)
Read a point cloud data from any PLY file, and convert it to the given template format.
Definition: ply_io.h:198
std::string generateHeaderBinary(const pcl::PCLPointCloud2 &cloud, const Eigen::Vector4f &origin, const Eigen::Quaternionf &orientation, int valid_points, bool use_camera=true)
Generate the header of a PLY v.7 file format.
Definition: ply_io.h:562
Eigen::Vector4f sensor_origin_
Sensor acquisition pose (origin/translation).
Definition: point_cloud.h:420
PCL_EXPORTS int savePLYFileBinary(const std::string &file_name, const pcl::PolygonMesh &mesh)
Saves a PolygonMesh in binary PLY format.
Point Cloud Data (PLY) file format writer.
Definition: ply_io.h:543
int savePLYFileASCII(const std::string &file_name, const pcl::PointCloud< PointT > &cloud)
Templated version for saving point cloud data to a PLY file containing a specific given cloud format...
Definition: ply_io.h:839
int loadPLYFile(const std::string &file_name, pcl::PolygonMesh &mesh)
Load a PLY file into a PolygonMesh type.
Definition: ply_io.h:793
Class ply_parser parses a PLY file and generates appropriate atomic parsers for the body...
Definition: ply_parser.h:76
Point Cloud Data (FILE) file format reader interface.
Definition: file_io.h:55
int write(const std::string &file_name, const pcl::PCLPointCloud2 &cloud, const Eigen::Vector4f &origin=Eigen::Vector4f::Zero(), const Eigen::Quaternionf &orientation=Eigen::Quaternionf::Identity(), bool binary=false, bool use_camera=true)
Save point cloud data to a PLY file containing n-D points.
Definition: ply_io.h:651
Eigen::Quaternionf sensor_orientation_
Sensor acquisition pose (rotation).
Definition: point_cloud.h:422
boost::int32_t int32
Definition: ply.h:60
boost::shared_ptr< ::pcl::PCLPointCloud2 const > ConstPtr
PointCloud represents the base class in PCL for storing collections of 3D points. ...
int write(const std::string &file_name, const pcl::PCLPointCloud2 &cloud, const Eigen::Vector4f &origin=Eigen::Vector4f::Zero(), const Eigen::Quaternionf &orientation=Eigen::Quaternionf::Identity(), const bool binary=false) override
Save point cloud data to a PLY file containing n-D points.
Definition: ply_io.h:629
int write(const std::string &file_name, const pcl::PointCloud< PointT > &cloud, bool binary=false, bool use_camera=true)
Save point cloud data to a PLY file containing n-D points.
Definition: ply_io.h:692
void toPCLPointCloud2(const pcl::PointCloud< PointT > &cloud, pcl::PCLPointCloud2 &msg)
Convert a pcl::PointCloud<T> object to a PCLPointCloud2 binary data blob.
Definition: conversions.h:241
int read(const std::string &file_name, pcl::PCLPointCloud2 &cloud, const int offset=0)
Read a point cloud data from a PLY file and store it into a pcl/PCLPointCloud2.
Definition: ply_io.h:180
int read(const std::string &file_name, pcl::PCLPointCloud2 &cloud, Eigen::Vector4f &origin, Eigen::Quaternionf &orientation, int &ply_version, const int offset=0) override
Read a point cloud data from a PLY file and store it into a pcl/PCLPointCloud2.
Point Cloud Data (PLY) file format reader.
Definition: ply_io.h:76
void write(std::ostream &stream, Type value)
Function for writing data to a stream.
Definition: region_xy.h:63
boost::uint8_t uint8
Definition: ply.h:61
A point structure representing Euclidean xyz coordinates, and the RGB color.
PLYWriter()
Constructor.
Definition: ply_io.h:547
PCL_EXPORTS int savePLYFile(const std::string &file_name, const pcl::PolygonMesh &mesh, unsigned precision=5)
Saves a PolygonMesh in ascii PLY format.