MEPP2 Project
pcl_point_cloud_reader.hpp
Go to the documentation of this file.
1 // Copyright (c) 2012-2019 University of Lyon and CNRS (France).
2 // All rights reserved.
3 //
4 // This file is part of MEPP2; you can redistribute it and/or modify
5 // it under the terms of the GNU Lesser General Public License as
6 // published by the Free Software Foundation; either version 3 of
7 // the License, or (at your option) any later version.
8 //
9 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
10 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11 #pragma once
12 
15 
17 
18 #include "FEVV/Tools/IO/FileUtilities.hpp" // for FileUtils::has_extension()
19 
20 
21 #if defined _MSC_VER
22 #pragma warning(push)
23 #pragma warning(disable : 4267) // for VS-2015
24 #endif
25 
26 #include <pcl/io/ascii_io.h>
27 #include <pcl/io/pcd_io.h>
28 #include <pcl/io/ply_io.h>
29 
30 #include <pcl/pcl_config.h>
31 
32 #if defined _MSC_VER
33 #pragma warning(pop)
34 #endif
35 
36 
37 #include <string>
38 #include <stdexcept> // for std::invalid_argument
39 
40 
41 namespace FEVV {
42 
43 // parse PLY header to detect normals and colors
44 inline
45 void
46 parse_ply_header(const std::string &filename,
47  bool &has_normal,
48  bool &has_color)
49 {
50  // open input file
51  std::ifstream in(filename);
52  if(! in)
53  {
54  throw std::invalid_argument("read_mesh() error: can not open file " +
55  filename);
56  }
57 
58  // parse file
59  std::string line, word;
60  has_normal = false;
61  has_color = false;
62 
63  do
64  {
65  std::getline(in, line);
66  std::istringstream line_ss(line);
67 
68  // look for "property ... nx" and "property ... r"
69  line_ss >> word;
70  if(word == "property")
71  {
72  line_ss >> word;
73  line_ss >> word;
74 
75  if(word == "nx")
76  {
77  has_normal = true;
78  }
79  else if(word == "red")
80  {
81  has_color = true;
82  }
83  }
84  }
85  while(word != "end_header");
86 }
87 
88 // parse PCD header to detect normals and colors
89 inline
90 void
91 parse_pcd_header(const std::string &filename,
92  bool &has_normal,
93  bool &has_color)
94 {
95  // open input file
96  std::ifstream in(filename);
97  if(! in)
98  {
99  throw std::invalid_argument("read_mesh() error: can not open file " +
100  filename);
101  }
102 
103  // parse file
104  std::string line, word;
105  has_normal = false;
106  has_color = false;
107 
108  do
109  {
110  std::getline(in, line);
111  std::istringstream line_ss(line);
112 
113  // look for "FIELDS x y z normal_x normal_y normal_z r g b"
114  line_ss >> word;
115  if(word == "FIELDS")
116  {
117  while(line_ss >> word)
118  {
119  if(word == "normal_x")
120  {
121  has_normal = true;
122  }
123 
124  if(word == "rgb")
125  {
126  has_color = true;
127  }
128  }
129  break;
130  }
131  }
132  while(in);
133 }
134 
135 // parse XYZ 1st line to detect normals
136 inline
137 void
138 parse_xyz_1stline(const std::string &filename,
139  bool &has_normal)
140 {
141  // open input file
142  std::ifstream in(filename);
143  if(! in)
144  {
145  throw std::invalid_argument("read_mesh() error: can not open file " +
146  filename);
147  }
148 
149  std::string line, word;
150  has_normal = false;
151 
152  // load 1st line
153  std::getline(in, line);
154  std::istringstream line_ss(line);
155 
156  // count number of values on line
157  unsigned int val_nbr = 0;
158  while(line_ss >> word)
159  {
160  val_nbr++;
161  }
162 
163  // 3 values -> geometry only
164  // 6 values -> geometry + normals
165  // other -> unsupported
166  if(val_nbr == 3)
167  has_normal = false;
168  else if(val_nbr == 6)
169  has_normal = true;
170  else
171  {
172  throw std::invalid_argument("read_mesh() error: unsupported XYZ format in file " +
173  filename);
174  }
175 }
176 
177 } // namespace FEVV
178 
179 
180 namespace FEVV {
181 namespace Filters {
182 
183 
194 inline
195 void
197  const std::string &filename,
199  PMapsContainer &pmaps,
200  bool /*only_pts*/ = false)
201 {
202 #if 1
203  bool success = false;
204  bool has_normal = false;
205  bool has_color = false;
206 
207  if(FEVV::FileUtils::has_extension(filename, ".xyz"))
208  {
209  // parse header to detect normals
210  parse_xyz_1stline(filename, has_normal);
211 
212  // configure PCL reader
213  pcl::ASCIIReader reader;
214  reader.setExtension(".xyz");
215  if(has_normal)
216  {
217  // note:
218  // - 'reader.setInputFields< pcl::PointNormal >()' doesn't
219  // work because pcl::PointNormal type has a 'curvature' field,
220  // and all field must be present in the file else the reading
221  // fails ; no other predefined PCL Point type matches our needs
222  // - the solution seems to use the function
223  // 'setInputFields(const std::vector<pcl::PCLPointField>& fields)',
224  // but how to build the fields vector with the right values ?
225  // - answer: call 'pcl::getFields< pcl::PointNormal >(fields)'
226  // to get the fields vector for pcl::PointNormal, then remove
227  // the last unwanted field (curvature)
228  // - pcl::getFields< pcl::PointNormal >(fields);
229  // -> fields = std::vector of length 7, capacity 8 =
230  // {
231  // {name = "x", offset = 0, datatype = 7 '\a', count = 1},
232  // {name = "y", offse t = 4, datatype = 7 '\a', count = 1},
233  // {name = "z", offset = 8, datatype = 7 '\a', count = 1},
234  // {name = "normal_x", offs et = 16, datatype = 7 '\a', count = 1},
235  // {name = "normal_y", offset = 20, datatype = 7 '\a', count = 1},
236  // {name = "normal_z", offset = 24, datatype = 7 '\a', count = 1},
237  // {name = "curvature", offset = 32, datatype = 7 '\a', count = 1}
238  // }
239  //
240 
241  // retrieve all pcl::PointNormal fields
242  std::vector<pcl::PCLPointField> fields;
243 #if PCL_VERSION_COMPARE(<, 1, 10, 0)
244  pcl::getFields< pcl::PointNormal >(fields);
245 #else
246  fields = pcl::getFields< pcl::PointNormal >();
247 #endif
248  // remove the last unwanted field (curvature)
249  fields.pop_back();
250  reader.setInputFields(fields);
251  }
252  else
253  reader.setInputFields< pcl::PointXYZ >();
254 
255  // read XYZ file
256  success = (reader.read(filename, g) >= 0);
257  }
258  else if(FEVV::FileUtils::has_extension(filename, ".pcd"))
259  {
260  // parse header to detect normals and colors
261  parse_pcd_header(filename, has_normal, has_color);
262 
263  // load point cloud
264  success = (pcl::io::loadPCDFile(filename, g) >= 0);
265  }
266  else if(FEVV::FileUtils::has_extension(filename, ".ply"))
267  {
268  // parse header to detect normals and colors
269  parse_ply_header(filename, has_normal, has_color);
270 
271  // load point cloud
272  success = (pcl::io::loadPLYFile(filename, g) >= 0);
273  }
274 
275  if(success)
276  {
277  // store Normal and Color property maps into bag
278  if(has_normal)
279  {
280  auto v_nm = make_property_map(FEVV::vertex_normal, g);
281  put_property_map(FEVV::vertex_normal, g, pmaps, v_nm);
282  }
283 
284  if(has_color)
285  {
286  auto v_cm = make_property_map(FEVV::vertex_color, g);
287  put_property_map(FEVV::vertex_color, g, pmaps, v_cm);
288  }
289  }
290  else
291  {
292  throw std::invalid_argument("read_mesh() error: can not read file " +
293  filename);
294  }
295 #else
296  // DBG
297  g.points.push_back(FEVV::PCLPoint(-1, -1, 2));
298  g.points.push_back(FEVV::PCLPoint(-1, 1, 2));
299  g.points.push_back(FEVV::PCLPoint( 1, 1, 2));
300  g.points.push_back(FEVV::PCLPoint( 1, -1, 2));
301 #endif
302 }
303 
304 
305 } // namespace Filters
306 } // namespace FEVV
FEVV::parse_xyz_1stline
void parse_xyz_1stline(const std::string &filename, bool &has_normal)
Definition: pcl_point_cloud_reader.hpp:138
FEVV::put_property_map
void put_property_map(PropertyT p, const MeshT &, PMapsContainer &pmaps, const typename PMap_traits< PropertyT, MeshT >::pmap_type &pmap)
Definition: properties.h:664
FEVV::PCLPointCloud
pcl::PointCloud< PCLEnrichedPoint > PCLPointCloud
Definition: DataStructures_pcl_point_cloud.h:28
FEVV::PMapsContainer
std::map< std::string, boost::any > PMapsContainer
Definition: properties.h:99
FEVV
Interfaces for plugins These interfaces will be used for different plugins.
Definition: Assert.h:16
FEVV::PCLPoint
Eigen::Vector3f PCLPoint
Definition: DataStructures_pcl_point_cloud.h:32
FEVV::parse_ply_header
void parse_ply_header(std::ifstream &in, bool &has_normal, bool &has_color, bool &is_binary)
Definition: cgal_point_set_reader.hpp:31
DataStructures_pcl_point_cloud.h
FEVV::Filters::read_mesh
void read_mesh(const std::string &filename, FEVV::CGALPointSet &g, PMapsContainer &pmaps, bool=false)
Load mesh from file.
Definition: cgal_point_set_reader.hpp:110
FEVV::vertex_color
@ vertex_color
Definition: properties.h:47
Wrappings_pcl_point_cloud.h
FEVV::parse_pcd_header
void parse_pcd_header(const std::string &filename, bool &has_normal, bool &has_color)
Definition: pcl_point_cloud_reader.hpp:91
FEVV::FileUtils::has_extension
bool has_extension(const std::string &file_name)
Definition: FileUtilities.hpp:58
properties.h
FileUtilities.hpp
FEVV::vertex_normal
@ vertex_normal
Definition: properties.h:35
FEVV::make_property_map
PMap_traits< PropertyT, MeshT >::pmap_type make_property_map(PropertyT, const MeshT &m)
Definition: properties.h:630