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