Point Cloud Library (PCL)  1.6.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ply_parser.h
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2007-2012, Ares Lagae
6  * Copyright (c) 2010-2011, Willow Garage, Inc.
7  *
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * * Redistributions of source code must retain the above copyright
15  * notice, this list of conditions and the following disclaimer.
16  * * Redistributions in binary form must reproduce the above
17  * copyright notice, this list of conditions and the following
18  * disclaimer in the documentation and/or other materials provided
19  * with the distribution.
20  * * Neither the name of Willow Garage, Inc. nor the names of its
21  * contributors may be used to endorse or promote products derived
22  * from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  *
37  * $Id: ply_parser.h 5323 2012-03-27 12:57:27Z bouffa $
38  *
39  */
40 
41 #ifndef PCL_IO_PLY_PLY_PARSER_H
42 #define PCL_IO_PLY_PLY_PARSER_H
43 
44 #include <fstream>
45 #include <iostream>
46 #include <istream>
47 #include <sstream>
48 #include <string>
49 #include <vector>
50 
51 #include <boost/function.hpp>
52 #include <boost/tuple/tuple.hpp>
53 #include <boost/shared_ptr.hpp>
54 #include <boost/mpl/fold.hpp>
55 #include <boost/mpl/inherit.hpp>
56 #include <boost/mpl/inherit_linearly.hpp>
57 #include <boost/mpl/joint_view.hpp>
58 #include <boost/mpl/transform.hpp>
59 #include <boost/mpl/vector.hpp>
60 
61 #include <pcl/io/ply/ply.h>
63 #include <pcl/pcl_macros.h>
64 
65 #ifdef BUILD_Maintainer
66 # if defined __GNUC__
67 # if __GNUC__ == 4 && __GNUC_MINOR__ > 3
68 # pragma GCC diagnostic ignored "-Weffc++"
69 # pragma GCC diagnostic ignored "-pedantic"
70 # else
71 # pragma GCC system_header
72 # endif
73 # elif defined _MSC_VER
74 # pragma warning(push, 1)
75 # endif
76 #endif
77 
78 namespace pcl
79 {
80  namespace io
81  {
82  namespace ply
83  {
91  {
92  public:
93 
94  typedef boost::function<void (std::size_t, const std::string&)> info_callback_type;
95  typedef boost::function<void (std::size_t, const std::string&)> warning_callback_type;
96  typedef boost::function<void (std::size_t, const std::string&)> error_callback_type;
97 
98  typedef boost::function<void ()> magic_callback_type;
99  typedef boost::function<void (format_type, const std::string&)> format_callback_type;
100  typedef boost::function<void (const std::string&)> comment_callback_type;
101  typedef boost::function<void (const std::string&)> obj_info_callback_type;
102  typedef boost::function<bool ()> end_header_callback_type;
103 
104  typedef boost::function<void ()> begin_element_callback_type;
105  typedef boost::function<void ()> end_element_callback_type;
106  typedef boost::tuple<begin_element_callback_type, end_element_callback_type> element_callbacks_type;
107  typedef boost::function<element_callbacks_type (const std::string&, std::size_t)> element_definition_callback_type;
108 
109  template <typename ScalarType>
111  {
112  typedef boost::function<void (ScalarType)> type;
113  };
114 
115  template <typename ScalarType>
117  {
119  typedef boost::function<scalar_property_callback_type (const std::string&, const std::string&)> type;
120  };
121 
122  typedef boost::mpl::vector<int8, int16, int32, uint8, uint16, uint32, float32, float64> scalar_types;
123 
125  {
126  private:
127  template <typename T>
128  struct callbacks_element
129  {
130 // callbacks_element () : callback ();
131  typedef T scalar_type;
133  };
134 
135  typedef boost::mpl::inherit_linearly<
136  scalar_types,
137  boost::mpl::inherit<
138  boost::mpl::_1,
139  callbacks_element<boost::mpl::_2>
140  >
141  >::type callbacks;
142  callbacks callbacks_;
143 
144  public:
145  template <typename ScalarType>
147  get () const
148  {
149  return (static_cast<const callbacks_element<ScalarType>&> (callbacks_).callback);
150  }
151 
152  template <typename ScalarType>
154  get ()
155  {
156  return (static_cast<callbacks_element<ScalarType>&> (callbacks_).callback);
157  }
158 
159  template <typename ScalarType>
161  at (scalar_property_definition_callbacks_type& scalar_property_definition_callbacks)
162  {
163  return (scalar_property_definition_callbacks.get<ScalarType> ());
164  }
165 
166  template <typename ScalarType>
168  at (const scalar_property_definition_callbacks_type& scalar_property_definition_callbacks)
169  {
170  return (scalar_property_definition_callbacks.get<ScalarType> ());
171  }
172  };
173 
174  template <typename SizeType, typename ScalarType>
176  {
177  typedef boost::function<void (SizeType)> type;
178  };
179 
180  template <typename SizeType, typename ScalarType>
182  {
183  typedef boost::function<void (ScalarType)> type;
184  };
185 
186  template <typename SizeType, typename ScalarType>
188  {
189  typedef boost::function<void ()> type;
190  };
191 
192  template <typename SizeType, typename ScalarType>
194  {
198  typedef boost::function<
199  boost::tuple<
203  > (const std::string&, const std::string&)> type;
204  };
205 
206  typedef boost::mpl::vector<uint8, uint16, uint32> size_types;
207 
209  {
210  private:
211  template <typename T> struct pair_with : boost::mpl::pair<T,boost::mpl::_> {};
212  template<typename Sequence1, typename Sequence2>
213 
214  struct sequence_product :
215  boost::mpl::fold<Sequence1, boost::mpl::vector0<>,
216  boost::mpl::joint_view<
217  boost::mpl::_1,boost::mpl::transform<Sequence2, pair_with<boost::mpl::_2> > > >
218  {};
219 
220  template <typename T>
221  struct callbacks_element
222  {
223  typedef typename T::first size_type;
224  typedef typename T::second scalar_type;
226  };
227 
228  typedef boost::mpl::inherit_linearly<sequence_product<size_types, scalar_types>::type, boost::mpl::inherit<boost::mpl::_1, callbacks_element<boost::mpl::_2> > >::type callbacks;
229  callbacks callbacks_;
230 
231  public:
232  template <typename SizeType, typename ScalarType>
234  get ()
235  {
236  return (static_cast<callbacks_element<boost::mpl::pair<SizeType, ScalarType> >&> (callbacks_).callback);
237  }
238 
239  template <typename SizeType, typename ScalarType>
241  get () const
242  {
243  return (static_cast<const callbacks_element<boost::mpl::pair<SizeType, ScalarType> >&> (callbacks_).callback);
244  }
245 
246  template <typename SizeType, typename ScalarType>
248  at (list_property_definition_callbacks_type& list_property_definition_callbacks)
249  {
250  return (list_property_definition_callbacks.get<SizeType, ScalarType> ());
251  }
252 
253  template <typename SizeType, typename ScalarType>
255  at (const list_property_definition_callbacks_type& list_property_definition_callbacks)
256  {
257  return (list_property_definition_callbacks.get<SizeType, ScalarType> ());
258  }
259  };
260 
261  inline void
262  info_callback (const info_callback_type& info_callback);
263 
264  inline void
265  warning_callback (const warning_callback_type& warning_callback);
266 
267  inline void
268  error_callback (const error_callback_type& error_callback);
269 
270  inline void
271  magic_callback (const magic_callback_type& magic_callback);
272 
273  inline void
274  format_callback (const format_callback_type& format_callback);
275 
276  inline void
277  element_definition_callback (const element_definition_callback_type& element_definition_callback);
278 
279  inline void
280  scalar_property_definition_callbacks (const scalar_property_definition_callbacks_type& scalar_property_definition_callbacks);
281 
282  inline void
283  list_property_definition_callbacks (const list_property_definition_callbacks_type& list_property_definition_callbacks);
284 
285  inline void
286  comment_callback (const comment_callback_type& comment_callback);
287 
288  inline void
289  obj_info_callback (const obj_info_callback_type& obj_info_callback);
290 
291  inline void
292  end_header_callback (const end_header_callback_type& end_header_callback);
293 
294  typedef int flags_type;
295  enum flags { };
296 
298  flags_ (flags),
299  comment_callback_ (), obj_info_callback_ (), end_header_callback_ (),
300  line_number_ (0), current_element_ ()
301  {}
302 
303  bool parse (const std::string& filename);
304  //inline bool parse (const std::string& filename);
305 
306  private:
307 
308  struct property
309  {
310  property (const std::string& name) : name (name) {}
311  virtual ~property () {}
312  virtual bool parse (class ply_parser& ply_parser, format_type format, std::istream& istream) = 0;
313  std::string name;
314  };
315 
316  template <typename ScalarType>
317  struct scalar_property : public property
318  {
319  typedef ScalarType scalar_type;
320  typedef typename scalar_property_callback_type<scalar_type>::type callback_type;
321  scalar_property (const std::string& name, callback_type callback)
322  : property (name)
323  , callback (callback)
324  {}
325  bool parse (class ply_parser& ply_parser,
327  std::istream& istream)
328  {
329  return ply_parser.parse_scalar_property<scalar_type> (format, istream, callback);
330  }
331  callback_type callback;
332  };
333 
334  template <typename SizeType, typename ScalarType>
335  struct list_property : public property
336  {
337  typedef SizeType size_type;
338  typedef ScalarType scalar_type;
339  typedef typename list_property_begin_callback_type<size_type, scalar_type>::type begin_callback_type;
340  typedef typename list_property_element_callback_type<size_type, scalar_type>::type element_callback_type;
341  typedef typename list_property_end_callback_type<size_type, scalar_type>::type end_callback_type;
342  list_property (const std::string& name,
343  begin_callback_type begin_callback,
344  element_callback_type element_callback,
345  end_callback_type end_callback)
346  : property (name)
347  , begin_callback (begin_callback)
348  , element_callback (element_callback)
349  , end_callback (end_callback)
350  {}
351  bool parse (class ply_parser& ply_parser,
353  std::istream& istream)
354  {
355  return ply_parser.parse_list_property<size_type, scalar_type> (format,
356  istream,
357  begin_callback,
358  element_callback,
359  end_callback);
360  }
361  begin_callback_type begin_callback;
362  element_callback_type element_callback;
363  end_callback_type end_callback;
364  };
365 
366  struct element
367  {
368  element (const std::string& name,
369  std::size_t count,
370  const begin_element_callback_type& begin_element_callback,
371  const end_element_callback_type& end_element_callback)
372  : name (name)
373  , count (count)
374  , begin_element_callback (begin_element_callback)
375  , end_element_callback (end_element_callback)
376  , properties ()
377  {}
378  std::string name;
379  std::size_t count;
380  begin_element_callback_type begin_element_callback;
381  end_element_callback_type end_element_callback;
382  std::vector<boost::shared_ptr<property> > properties;
383  };
384 
385  flags_type flags_;
386 
387  info_callback_type info_callback_;
388  warning_callback_type warning_callback_;
389  error_callback_type error_callback_;
390 
391  magic_callback_type magic_callback_;
392  format_callback_type format_callback_;
393  element_definition_callback_type element_definition_callbacks_;
394  scalar_property_definition_callbacks_type scalar_property_definition_callbacks_;
395  list_property_definition_callbacks_type list_property_definition_callbacks_;
396  comment_callback_type comment_callback_;
397  obj_info_callback_type obj_info_callback_;
398  end_header_callback_type end_header_callback_;
399 
400  template <typename ScalarType> inline void
401  parse_scalar_property_definition (const std::string& property_name);
402 
403  template <typename SizeType, typename ScalarType> inline void
404  parse_list_property_definition (const std::string& property_name);
405 
406  template <typename ScalarType> inline bool
407  parse_scalar_property (format_type format,
408  std::istream& istream,
409  const typename scalar_property_callback_type<ScalarType>::type& scalar_property_callback);
410 
411  template <typename SizeType, typename ScalarType> inline bool
412  parse_list_property (format_type format,
413  std::istream& istream,
414  const typename list_property_begin_callback_type<SizeType, ScalarType>::type& list_property_begin_callback,
415  const typename list_property_element_callback_type<SizeType, ScalarType>::type& list_property_element_callback,
416  const typename list_property_end_callback_type<SizeType, ScalarType>::type& list_property_end_callback);
417 
418  std::size_t line_number_;
419  element* current_element_;
420  };
421  } // namespace ply
422  } // namespace io
423 } // namespace pcl
424 
425 /* inline bool pcl::io::ply::ply_parser::parse (const std::string& filename) */
426 /* { */
427 /* std::ifstream ifstream (filename.c_str ()); */
428 /* return (parse (ifstream)); */
429 /* } */
430 
432 {
433  info_callback_ = info_callback;
434 }
435 
437 {
438  warning_callback_ = warning_callback;
439 }
440 
442 {
443  error_callback_ = error_callback;
444 }
445 
447 {
448  magic_callback_ = magic_callback;
449 }
450 
452 {
453  format_callback_ = format_callback;
454 }
455 
457 {
458  element_definition_callbacks_ = element_definition_callback;
459 }
460 
462 {
463  scalar_property_definition_callbacks_ = scalar_property_definition_callbacks;
464 }
465 
467 {
468  list_property_definition_callbacks_ = list_property_definition_callbacks;
469 }
470 
472 {
473  comment_callback_ = comment_callback;
474 }
475 
477 {
478  obj_info_callback_ = obj_info_callback;
479 }
480 
482 {
483  end_header_callback_ = end_header_callback;
484 }
485 
486 template <typename ScalarType>
487 inline void pcl::io::ply::ply_parser::parse_scalar_property_definition (const std::string& property_name)
488 {
489  typedef ScalarType scalar_type;
490  typename scalar_property_definition_callback_type<scalar_type>::type& scalar_property_definition_callback =
491  scalar_property_definition_callbacks_.get<scalar_type> ();
492  typename scalar_property_callback_type<scalar_type>::type scalar_property_callback;
493  if (scalar_property_definition_callback)
494  {
495  scalar_property_callback = scalar_property_definition_callback (current_element_->name, property_name);
496  }
497  if (!scalar_property_callback)
498  {
499  if (warning_callback_)
500  {
501  warning_callback_ (line_number_,
502  "property '" + std::string (type_traits<scalar_type>::name ()) + " " +
503  property_name + "' of element '" + current_element_->name + "' is not handled");
504  }
505  }
506  current_element_->properties.push_back (boost::shared_ptr<property> (new scalar_property<scalar_type> (property_name, scalar_property_callback)));
507 }
508 
509 template <typename SizeType, typename ScalarType>
510 inline void pcl::io::ply::ply_parser::parse_list_property_definition (const std::string& property_name)
511 {
512  typedef SizeType size_type;
513  typedef ScalarType scalar_type;
514  typename list_property_definition_callback_type<size_type, scalar_type>::type& list_property_definition_callback =
515  list_property_definition_callbacks_.get<size_type, scalar_type> ();
516  typedef typename list_property_begin_callback_type<size_type, scalar_type>::type list_property_begin_callback_type;
517  typedef typename list_property_element_callback_type<size_type, scalar_type>::type list_property_element_callback_type;
518  typedef typename list_property_end_callback_type<size_type, scalar_type>::type list_property_end_callback_type;
519  boost::tuple<list_property_begin_callback_type, list_property_element_callback_type, list_property_end_callback_type> list_property_callbacks;
520  if (list_property_definition_callback)
521  {
522  list_property_callbacks = list_property_definition_callback (current_element_->name, property_name);
523  }
524  if (!boost::get<0> (list_property_callbacks) || !boost::get<1> (list_property_callbacks) || !boost::get<2> (list_property_callbacks))
525  {
526  if (warning_callback_)
527  {
528  warning_callback_ (line_number_,
529  "property 'list " + std::string (type_traits<size_type>::name ()) + " " +
530  std::string (type_traits<scalar_type>::name ()) + " " +
531  property_name + "' of element '" +
532  current_element_->name + "' is not handled");
533  }
534  }
535  current_element_->properties.push_back (boost::shared_ptr<property> (
536  new list_property<size_type, scalar_type> (
537  property_name,
538  boost::get<0> (list_property_callbacks),
539  boost::get<1> (list_property_callbacks),
540  boost::get<2> (list_property_callbacks))));
541 }
542 
543 template <typename ScalarType>
544 inline bool pcl::io::ply::ply_parser::parse_scalar_property (format_type format,
545  std::istream& istream,
546  const typename scalar_property_callback_type<ScalarType>::type& scalar_property_callback)
547 {
548  using namespace io_operators;
549  typedef ScalarType scalar_type;
550  if (format == ascii_format)
551  {
552  scalar_type value = std::numeric_limits<scalar_type>::quiet_NaN ();
553  char space = ' ';
554  istream >> value;
555  if (!istream.eof ())
556  istream >> space >> std::ws;
557  if (!istream || !isspace (space))
558  {
559  if (error_callback_)
560  error_callback_ (line_number_, "parse error");
561  return (false);
562  }
563  if (scalar_property_callback)
564  scalar_property_callback (value);
565  return (true);
566  }
567  else
568  {
569  scalar_type value = std::numeric_limits<scalar_type>::quiet_NaN ();
570  istream.read (reinterpret_cast<char*> (&value), sizeof (scalar_type));
571  if (!istream)
572  {
573  if (error_callback_)
574  error_callback_ (line_number_, "parse error");
575  return (false);
576  }
577  if (((format == binary_big_endian_format) && (host_byte_order == little_endian_byte_order)) ||
578  ((format == binary_little_endian_format) && (host_byte_order == big_endian_byte_order)))
579  swap_byte_order (value);
580  if (scalar_property_callback)
581  scalar_property_callback (value);
582  return (true);
583  }
584 }
585 
586 template <typename SizeType, typename ScalarType>
587 inline bool pcl::io::ply::ply_parser::parse_list_property (format_type format, std::istream& istream,
588  const typename list_property_begin_callback_type<SizeType, ScalarType>::type& list_property_begin_callback,
589  const typename list_property_element_callback_type<SizeType, ScalarType>::type& list_property_element_callback,
590  const typename list_property_end_callback_type<SizeType, ScalarType>::type& list_property_end_callback)
591 {
592  using namespace io_operators;
593  typedef SizeType size_type;
594  typedef ScalarType scalar_type;
595  if (format == ascii_format)
596  {
597  size_type size = std::numeric_limits<size_type>::infinity ();
598  char space = ' ';
599  istream >> size;
600  if (!istream.eof ())
601  {
602  istream >> space >> std::ws;
603  }
604  if (!istream || !isspace (space))
605  {
606  if (error_callback_)
607  {
608  error_callback_ (line_number_, "parse error");
609  }
610  return (false);
611  }
612  if (list_property_begin_callback)
613  {
614  list_property_begin_callback (size);
615  }
616  for (std::size_t index = 0; index < size; ++index)
617  {
618  scalar_type value = std::numeric_limits<scalar_type>::quiet_NaN ();
619  char space = ' ';
620  istream >> value;
621  if (!istream.eof ())
622  {
623  istream >> space >> std::ws;
624  }
625  if (!istream || !isspace (space))
626  {
627  if (error_callback_)
628  {
629  error_callback_ (line_number_, "parse error");
630  }
631  return (false);
632  }
633  if (list_property_element_callback)
634  {
635  list_property_element_callback (value);
636  }
637  }
638  if (list_property_end_callback)
639  {
640  list_property_end_callback ();
641  }
642  return (true);
643  }
644  else
645  {
646  size_type size = std::numeric_limits<size_type>::infinity ();
647  istream.read (reinterpret_cast<char*> (&size), sizeof (size_type));
648  if (((format == binary_big_endian_format) && (host_byte_order == little_endian_byte_order)) ||
649  ((format == binary_little_endian_format) && (host_byte_order == big_endian_byte_order)))
650  {
651  swap_byte_order (size);
652  }
653  if (!istream)
654  {
655  if (error_callback_)
656  {
657  error_callback_ (line_number_, "parse error");
658  }
659  return (false);
660  }
661  if (list_property_begin_callback)
662  {
663  list_property_begin_callback (size);
664  }
665  for (std::size_t index = 0; index < size; ++index) {
666  scalar_type value = std::numeric_limits<scalar_type>::quiet_NaN ();
667  istream.read (reinterpret_cast<char*> (&value), sizeof (scalar_type));
668  if (!istream) {
669  if (error_callback_) {
670  error_callback_ (line_number_, "parse error");
671  }
672  return (false);
673  }
674  if (((format == binary_big_endian_format) && (host_byte_order == little_endian_byte_order)) ||
675  ((format == binary_little_endian_format) && (host_byte_order == big_endian_byte_order)))
676  {
677  swap_byte_order (value);
678  }
679  if (list_property_element_callback)
680  {
681  list_property_element_callback (value);
682  }
683  }
684  if (list_property_end_callback)
685  {
686  list_property_end_callback ();
687  }
688  return (true);
689  }
690 }
691 
692 #ifdef BUILD_Maintainer
693 # if defined __GNUC__
694 # if __GNUC__ == 4 && __GNUC_MINOR__ > 3
695 # pragma GCC diagnostic warning "-Weffc++"
696 # pragma GCC diagnostic warning "-pedantic"
697 # endif
698 # elif defined _MSC_VER
699 # pragma warning(pop)
700 # endif
701 #endif
702 
703 #endif // PCL_IO_PLY_PLY_PARSER_H