Code_TYMPAN  4.4.0
Industrial site acoustic simulation
altimetry_file_reader.cpp
Go to the documentation of this file.
1 
9 #include <cassert>
10 
11 #include <boost/foreach.hpp>
12 #include <boost/exception/errinfo_file_name.hpp>
13 #include <boost/exception/errinfo_at_line.hpp>
14 #include <boost/exception/errinfo_errno.hpp>
15 
16 #include "rply.h"
17 
19 
20 // section with C linkage for RPLY callbacks
21 extern "C"
22 {
23  static int vertex_cb(p_ply_argument argument);
24  static int face_cb(p_ply_argument argument);
25  static int material_cb(p_ply_argument argument);
26  static void error_cb(p_ply ply, const char* message);
27 } // extern C
28 
29 static const double NaN = std::numeric_limits<double>::quiet_NaN();
30 
31 namespace tympan
32 {
33 
34 //========== Implementation of free functions ==========
35 
36 std::unique_ptr<IMeshReader> make_altimetry_ply_reader(const std::string filename)
37 {
38  return std::unique_ptr<IMeshReader>(new AltimetryPLYReader(filename));
39 } // make_altimetry_ply_reader
40 
41 //========== Implementation of AltimetryPLYReader methods ==========
42 
43 AltimetryPLYReader::AltimetryPLYReader(const std::string filename)
44  : _filename(filename), _ply(nullptr), _nvertices(-1), _nfaces(-1), _nmaterials(-1)
45 {
46  // Opens the PLY file, no error callback is given
47  _ply = ply_open(_filename.c_str(), ::error_cb, 0 /*unused*/, this);
48  if (_ply == NULL)
49  throw mesh_io_error("Opening PLY file") << tympan_source_loc << boost::errinfo_file_name(filename);
50  // Reads the header
51  if (!ply_read_header(_ply))
52  throw mesh_io_error("Reading the PLY header")
53  << tympan_source_loc << boost::errinfo_file_name(filename);
54 }
55 
57 {
58  ply_close(_ply);
59 }
60 
62 {
64  init_data();
65  read_data();
67 }
68 
70 {
71  long n = 0;
72  assert(_nvertices == -1 && _nfaces == -1);
73  n = ply_set_read_cb(_ply, "vertex", "x", ::vertex_cb, this, X);
74  _nvertices = n;
75  n = ply_set_read_cb(_ply, "vertex", "y", ::vertex_cb, this, Y);
76  assert(n == _nvertices);
77  n = ply_set_read_cb(_ply, "vertex", "z", ::vertex_cb, this, Z);
78  assert(n == _nvertices);
79  n = ply_set_read_cb(_ply, "face", "vertex_indices", ::face_cb, this, VertexIndices);
80  _nfaces = n;
81  n = ply_set_read_cb(_ply, "face", "material_index", ::face_cb, this, MaterialIndex);
82  assert(n == _nfaces);
83  _nmaterials = ply_set_read_cb(_ply, "material", "id", ::material_cb, this, MaterialID);
84 }
85 
87 {
88  _material_indices.resize(_nfaces, -1);
89 }
90 
92 {
93  if (!ply_read(_ply))
94  throw mesh_io_error("Reading the PLY data")
95  << tympan_source_loc << boost::errinfo_file_name(_filename);
96 }
97 
99 {
100  assert(_material_by_face.empty());
101  assert(_material_indices.size() == _nfaces);
102  assert(_faces.size() == _nfaces);
103  BOOST_FOREACH (int material_index, _material_indices)
104  {
105  if (material_index == -1) // No material attributed
106  _material_by_face.push_back("");
107  else if (material_index < _nmaterials)
108  _material_by_face.push_back(_materials[material_index]);
109  else
110  throw mesh_io_error("Invalid material index")
111  << tympan_source_loc << boost::errinfo_file_name(_filename);
112  }
113  assert(_material_by_face.size() == _nfaces);
114 }
115 
116 bool AltimetryPLYReader::vertex_cb(vertex_properties property, unsigned vertex_index, double value)
117 {
118  switch (property)
119  {
120  case X:
121  // Insert a new point
122  _points.push_back(OPoint3D(NaN, NaN, NaN));
123  // Deliberate fall-through
124  case Y:
125  case Z:
126  // Store the coordinate
127  // NB the numerical value of ``property`` is the index of the vertex
128  assert(_points.size() - 1 == vertex_index); // Index consistency
129  _points.back()._value[(unsigned)property] = value;
130  break;
131  default:
132  return false;
133  }
134  return true;
135 }
136 
137 bool AltimetryPLYReader::face_cb(face_properties property, unsigned face_index, unsigned nproperties,
138  int property_index, double value)
139 {
140  switch (property)
141  {
142  case VertexIndices:
143  // Reading vertices index for the face, expected to be a triangle
144  if (nproperties != 3)
145  {
146  // Should probably NOT raise a exception from within a C callback
147  // TODO properly report, e.g. with an error status in the reader
148  return false;
149  }
150  if (property_index == -1)
151  { // RPLY is giving us the length
152  assert(value == 3.0); // Value should be equal to length
153  _faces.push_back(OTriangle(-1, -1, -1));
154  }
155  else
156  {
157  assert(property_index < 3);
158  assert(_faces.size() - 1 == face_index); // Index consistency
159  const unsigned vertex_index = (unsigned)value;
160  OTriangle& triangle = _faces.back();
161  triangle.index(property_index) = vertex_index;
162  // Ensure consistency of the OTriangle redundant representation
163  triangle.vertex(property_index) = _points[vertex_index];
164  }
165  break;
166  case MaterialIndex:
167  assert(_material_indices[face_index] == -1);
168  _material_indices[face_index] = (unsigned)value;
169  break;
170  default:
171  return false;
172  }
173  return true;
174 }
175 
176 bool AltimetryPLYReader::material_cb(material_properties property, unsigned material_index,
177  unsigned nproperties, int property_index, double value)
178 {
179  switch (property)
180  {
181  case MaterialID:
182  if (property_index == -1)
183  { // RPLY is giving us the length of the ID
184  assert(value == nproperties); // Value should be equal to length
185  _materials.push_back(std::string(nproperties, '-'));
186  }
187  else
188  {
189  assert((unsigned)property_index < nproperties);
190  assert(_materials.size() - 1 == material_index); // Index consistency
191  _materials.back()[property_index] = (unsigned char)value;
192  }
193  break;
194  default:
195  return false;
196  }
197  return true;
198 }
199 
200 void AltimetryPLYReader::error_cb(p_ply ply, const char* message)
201 {
202  assert(_ply == NULL || ply == _ply);
203  throw mesh_io_error(message) << tympan_source_loc << boost::errinfo_file_name(_filename);
204 }
205 
206 }; // namespace tympan
207 
208 //========== C callback must be defined outside the namespace tympan ==========
209 
210 using namespace tympan;
211 
215 #define DECLARE_AND_FETCH_PLY_CALLBACK_INFO \
216  long idata; \
217  void* pdata; \
218  tympan::AltimetryPLYReader* p_reader; \
219  long instance_index; \
220  p_ply_element element; \
221  double value; \
222  ply_get_argument_user_data(argument, &pdata, &idata); \
223  p_reader = (tympan::AltimetryPLYReader*)pdata; \
224  ply_get_argument_element(argument, &element, &instance_index); \
225  value = ply_get_argument_value(argument);
226 // END OF DECLARE_AND_FETCH_PLY_CALLBACK_INFO
227 
230 static int vertex_cb(p_ply_argument argument)
231 {
234  assert(0 <= idata && idata < AltimetryPLYReader::NUM_vertex_properties);
235  vertex_property = (AltimetryPLYReader::vertex_properties)idata;
236  return p_reader->vertex_cb(vertex_property, instance_index, value);
237 }
238 
241 static int face_cb(p_ply_argument argument)
242 {
245  assert(0 <= idata && idata < AltimetryPLYReader::NUM_face_properties);
246  face_property = (AltimetryPLYReader::face_properties)idata;
247  // Access to property list
248  long length = 0, value_index = 0;
249  p_ply_property property = nullptr;
250  ply_get_argument_property(argument, &property, &length, &value_index);
251  return p_reader->face_cb(face_property, instance_index, length, value_index, value);
252 }
253 
256 static int material_cb(p_ply_argument argument)
257 {
259  AltimetryPLYReader::material_properties material_property;
260  assert(0 <= idata && idata < AltimetryPLYReader::NUM_material_properties);
261  material_property = (AltimetryPLYReader::material_properties)idata;
262  // Access to property list
263  long length = 0, value_index = 0;
264  p_ply_property property = nullptr;
265  ply_get_argument_property(argument, &property, &length, &value_index);
266  return p_reader->material_cb(material_property, instance_index, length, value_index, value);
267 }
268 
270 static void error_cb(p_ply ply, const char* message)
271 {
272  long idata = 0;
273  void* pdata = nullptr;
274  tympan::AltimetryPLYReader* p_reader = nullptr;
275  if (ply)
276  {
277  ply_get_ply_user_data(ply, &pdata, &idata);
278  p_reader = (tympan::AltimetryPLYReader*)pdata;
279  p_reader->error_cb(ply, message);
280  }
281 }
#define DECLARE_AND_FETCH_PLY_CALLBACK_INFO
macro which extract all relevant callback information form RPLY
Implementation details header for altimetry_reader.cpp.
struct t_ply_ * p_ply
The 3D point class.
Definition: 3d.h:487
Triangle class.
Definition: triangle.h:28
read an Altimetry from a PLY file.
std::vector< unsigned > _material_indices
bool vertex_cb(vertex_properties property, unsigned vertex_index, double value)
virtual void read()
read the file whose name was given at reader's construction time
bool face_cb(face_properties property, unsigned face_index, unsigned nproperties, int property_index, double value)
AltimetryPLYReader(const std::string filename)
void error_cb(p_ply ply, const char *message)
bool material_cb(material_properties property, unsigned material_index, unsigned nproperties, int property_index, double value)
#define tympan_source_loc
This macro build a source_loc object to be attached to a tympan::Exception.
Definition: exceptions.h:76
std::unique_ptr< IMeshReader > make_altimetry_ply_reader(const std::string filename)
@ Makes a reader for the file name given as argument