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