Developer Documentation
FileManagerT_impl.hh
1 /*===========================================================================*\
2  * *
3  * OpenVolumeMesh *
4  * Copyright (C) 2011 by Computer Graphics Group, RWTH Aachen *
5  * www.openvolumemesh.org *
6  * *
7  *---------------------------------------------------------------------------*
8  * This file is part of OpenVolumeMesh. *
9  * *
10  * OpenVolumeMesh is free software: you can redistribute it and/or modify *
11  * it under the terms of the GNU Lesser General Public License as *
12  * published by the Free Software Foundation, either version 3 of *
13  * the License, or (at your option) any later version with the *
14  * following exceptions: *
15  * *
16  * If other files instantiate templates or use macros *
17  * or inline functions from this file, or you compile this file and *
18  * link it with other files to produce an executable, this file does *
19  * not by itself cause the resulting executable to be covered by the *
20  * GNU Lesser General Public License. This exception does not however *
21  * invalidate any other reasons why the executable file might be *
22  * covered by the GNU Lesser General Public License. *
23  * *
24  * OpenVolumeMesh is distributed in the hope that it will be useful, *
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
27  * GNU Lesser General Public License for more details. *
28  * *
29  * You should have received a copy of the GNU LesserGeneral Public *
30  * License along with OpenVolumeMesh. If not, *
31  * see <http://www.gnu.org/licenses/>. *
32  * *
33 \*===========================================================================*/
34 
35 /*===========================================================================*\
36  * *
37  * $Revision$ *
38  * $Date$ *
39  * $LastChangedBy$ *
40  * *
41 \*===========================================================================*/
42 
43 #define FILEMANAGERT_CC
44 
45 #include <vector>
46 #include <iostream>
47 #include <sstream>
48 #include <algorithm>
49 #include <cctype>
50 #include <typeinfo>
51 #include <stdint.h>
52 
53 #include <OpenVolumeMesh/Geometry/VectorT.hh>
54 #include <OpenVolumeMesh/Mesh/PolyhedralMesh.hh>
55 
56 #include "FileManager.hh"
57 
58 namespace OpenVolumeMesh {
59 
60 namespace IO {
61 
62 using namespace OpenVolumeMesh::Geometry;
63 
64 //==================================================
65 
66 template<class MeshT>
67 bool FileManager::readStream(std::istream &_istream, MeshT &_mesh,
68  bool _topologyCheck, bool _computeBottomUpIncidences) const
69 {
70  std::stringstream sstr;
71  std::string line;
72  std::string s_tmp;
73  uint64_t c = 0u;
74  typedef typename MeshT::PointT Point;
75  Point v = Point(0.0, 0.0, 0.0);
76 
77  _mesh.clear(false);
78  // Temporarily disable bottom-up incidences
79  // since it's way faster to first add all the
80  // geometry and compute them in one pass afterwards
81  _mesh.enable_bottom_up_incidences(false);
82 
83  /*
84  * Header
85  */
86 
87  bool header_found = true;
88 
89  // Get first line
90  getCleanLine(_istream, line);
91  sstr.str(line);
92 
93  // Check header
94  sstr >> s_tmp;
95  std::transform(s_tmp.begin(), s_tmp.end(), s_tmp.begin(), ::toupper);
96  if(s_tmp != "OVM") {
97  //_istream.close();
98  header_found = false;
99  if (verbosity_level_ >= 1) {
100  std::cerr << "The specified file might not be in OpenVolumeMesh format!" << std::endl;
101  }
102  //return false;
103  }
104 
105  // Get ASCII/BINARY string
106  sstr >> s_tmp;
107  std::transform(s_tmp.begin(), s_tmp.end(), s_tmp.begin(), ::toupper);
108  if(s_tmp == "BINARY") {
109  if (verbosity_level_ >= 1) {
110  std::cerr << "Binary files are not supported at the moment!" << std::endl;
111  }
112  return false;
113  }
114 
115  /*
116  * Vertices
117  */
118  if(!header_found) {
119  sstr.clear();
120  sstr.str(line);
121  } else {
122  getCleanLine(_istream, line);
123  sstr.clear();
124  sstr.str(line);
125  }
126 
127  sstr >> s_tmp;
128  std::transform(s_tmp.begin(), s_tmp.end(), s_tmp.begin(), ::toupper);
129  if(s_tmp != "VERTICES") {
130  if (verbosity_level_ >= 1) {
131  std::cerr << "No vertex section defined!" << std::endl;
132  }
133  return false;
134  } else {
135 
136  // Read in number of vertices
137  getCleanLine(_istream, line);
138  sstr.clear();
139  sstr.str(line);
140  sstr >> c;
141 
142  // Read in vertices
143  for(uint64_t i = 0u; i < c; ++i) {
144 
145  getCleanLine(_istream, line);
146  sstr.clear();
147  sstr.str(line);
148  sstr >> v[0];
149  sstr >> v[1];
150  sstr >> v[2];
151  _mesh.add_vertex(v);
152  }
153  }
154 
155  /*
156  * Edges
157  */
158  getCleanLine(_istream, line);
159  sstr.clear();
160  sstr.str(line);
161  sstr >> s_tmp;
162  std::transform(s_tmp.begin(), s_tmp.end(), s_tmp.begin(), ::toupper);
163  if(s_tmp != "EDGES") {
164  if (verbosity_level_ >= 2) {
165  std::cerr << "No edge section defined!" << std::endl;
166  }
167  return false;
168  } else {
169 
170  // Read in number of edges
171  getCleanLine(_istream, line);
172  sstr.clear();
173  sstr.str(line);
174  sstr >> c;
175 
176  // Read in edges
177  for(uint64_t i = 0u; i < c; ++i) {
178 
179  unsigned int v1 = 0;
180  unsigned int v2 = 0;
181  getCleanLine(_istream, line);
182  sstr.clear();
183  sstr.str(line);
184  sstr >> v1;
185  sstr >> v2;
186  _mesh.add_edge(VertexHandle(v1), VertexHandle(v2), true);
187  }
188  }
189 
190  /*
191  * Faces
192  */
193  getCleanLine(_istream, line);
194  sstr.clear();
195  sstr.str(line);
196  sstr >> s_tmp;
197  std::transform(s_tmp.begin(), s_tmp.end(), s_tmp.begin(), ::toupper);
198  if(s_tmp != "FACES") {
199  if (verbosity_level_ >= 2) {
200  std::cerr << "No face section defined!" << std::endl;
201  }
202  return false;
203  } else {
204 
205  // Read in number of faces
206  getCleanLine(_istream, line);
207  sstr.clear();
208  sstr.str(line);
209  sstr >> c;
210 
211  // Read in faces
212  for(uint64_t i = 0u; i < c; ++i) {
213 
214  getCleanLine(_istream, line);
215  sstr.clear();
216  sstr.str(line);
217 
218  std::vector<HalfEdgeHandle> hes;
219 
220  // Get face valence
221  uint64_t val = 0u;
222  sstr >> val;
223 
224  // Read half-edge indices
225  for(unsigned int e = 0; e < val; ++e) {
226 
227  unsigned int v1 = 0;
228  sstr >> v1;
229  hes.push_back(HalfEdgeHandle(v1));
230  }
231 
232  _mesh.add_face(hes, _topologyCheck);
233  }
234  }
235 
236  /*
237  * Cells
238  */
239  getCleanLine(_istream, line);
240  sstr.clear();
241  sstr.str(line);
242  sstr >> s_tmp;
243  std::transform(s_tmp.begin(), s_tmp.end(), s_tmp.begin(), ::toupper);
244  if(s_tmp != "POLYHEDRA") {
245  if (verbosity_level_ >= 2) {
246  std::cerr << "No polyhedra section defined!" << std::endl;
247  }
248  return false;
249  } else {
250 
251  // Read in number of cells
252  getCleanLine(_istream, line);
253  sstr.clear();
254  sstr.str(line);
255  sstr >> c;
256 
257  // Read in cells
258  for(uint64_t i = 0u; i < c; ++i) {
259 
260  getCleanLine(_istream, line);
261  sstr.clear();
262  sstr.str(line);
263 
264  std::vector<HalfFaceHandle> hfs;
265 
266  // Get cell valence
267  uint64_t val = 0u;
268  sstr >> val;
269 
270  // Read half-face indices
271  for(unsigned int f = 0; f < val; ++f) {
272 
273  unsigned int v1 = 0;
274  sstr >> v1;
275  hfs.push_back(HalfFaceHandle(v1));
276  }
277 
278  _mesh.add_cell(hfs, _topologyCheck);
279  }
280  }
281 
282  while(!_istream.eof()) {
283  // "End of file reached while searching for input!"
284  // is thrown here. \TODO Fix it!
285 
286  // Read property
287  readProperty(_istream, _mesh);
288  }
289 
290  if(_computeBottomUpIncidences) {
291  // Compute bottom-up incidences
292  _mesh.enable_bottom_up_incidences(true);
293  }
294 
295  if (verbosity_level_ >= 2) {
296  std::cerr << "######## openvolumemesh info #########" << std::endl;
297  std::cerr << "#vertices: " << _mesh.n_vertices() << std::endl;
298  std::cerr << "#edges: " << _mesh.n_edges() << std::endl;
299  std::cerr << "#faces: " << _mesh.n_faces() << std::endl;
300  std::cerr << "#cells: " << _mesh.n_cells() << std::endl;
301  std::cerr << "######################################" << std::endl;
302  }
303 
304  return true;
305 }
306 
307 template <class MeshT>
308 bool FileManager::readFile(const std::string& _filename, MeshT& _mesh,
309  bool _topologyCheck, bool _computeBottomUpIncidences) const {
310 
311  std::ifstream iff(_filename.c_str(), std::ios::in);
312 
313  if(!iff.good()) {
314  if (verbosity_level_ >= 1) {
315  std::cerr << "Error: Could not open file " << _filename << " for reading!" << std::endl;
316  }
317  iff.close();
318  return false;
319  }
320  return readStream(iff, _mesh, _topologyCheck,_computeBottomUpIncidences);
321 }
322 
323 //==================================================
324 
325 template <class MeshT>
326 void FileManager::readProperty(std::istream& _iff, MeshT& _mesh) const {
327 
328  std::string line, entity_t, prop_t, name;
329  std::stringstream sstr;
330 
331  getCleanLine(_iff, line);
332 
333  if(line.empty()) return;
334 
335  sstr.clear();
336  sstr.str(line);
337  sstr >> entity_t;
338  std::transform(entity_t.begin(), entity_t.end(), entity_t.begin(), ::tolower);
339  sstr >> prop_t;
340  std::transform(prop_t.begin(), prop_t.end(), prop_t.begin(), ::tolower);
341  name = line;
342  extractQuotedText(name);
343 
344  if (verbosity_level_ >= 2) {
345  std::cerr << "OVM read property " << name << " of type " << prop_t << std::endl;
346  }
347 
348  if(prop_t == typeName<int>()) generateGenericProperty<int, MeshT>(entity_t, name, _iff, _mesh);
349  else if(prop_t == typeName<unsigned int>()) generateGenericProperty<unsigned int, MeshT>(entity_t, name, _iff, _mesh);
350  else if(prop_t == typeName<short>()) generateGenericProperty<short, MeshT>(entity_t, name, _iff, _mesh);
351  else if(prop_t == typeName<long>()) generateGenericProperty<long, MeshT>(entity_t, name, _iff, _mesh);
352  else if(prop_t == typeName<unsigned long>()) generateGenericProperty<unsigned long, MeshT>(entity_t, name, _iff, _mesh);
353  else if(prop_t == typeName<char>()) generateGenericProperty<char, MeshT>(entity_t, name, _iff, _mesh);
354  else if(prop_t == typeName<unsigned char>()) generateGenericProperty<unsigned char, MeshT>(entity_t, name, _iff, _mesh);
355  else if(prop_t == typeName<bool>()) generateGenericProperty<bool, MeshT>(entity_t, name, _iff, _mesh);
356  else if(prop_t == typeName<float>()) generateGenericProperty<float, MeshT>(entity_t, name, _iff, _mesh);
357  else if(prop_t == typeName<double>()) generateGenericProperty<double, MeshT>(entity_t, name, _iff, _mesh);
358  else if(prop_t == typeName<std::string>()) generateGenericProperty<std::string, MeshT>(entity_t, name, _iff, _mesh);
359  else if(prop_t == typeName<std::map<HalfEdgeHandle, int> >()) generateGenericProperty<std::map<HalfEdgeHandle, int>, MeshT>(entity_t, name, _iff, _mesh);
360  else if(prop_t == typeName<std::vector<double> >()) generateGenericProperty<std::vector<double> , MeshT>(entity_t, name, _iff, _mesh);
361  else if(prop_t == typeName<std::vector<VertexHandle> >()) generateGenericProperty<std::vector<VertexHandle> , MeshT>(entity_t, name, _iff, _mesh);
362  else if(prop_t == typeName<std::vector<HalfFaceHandle> >()) generateGenericProperty<std::vector<HalfFaceHandle> , MeshT>(entity_t, name, _iff, _mesh);
363  else if(prop_t == typeName<std::vector<std::vector<HalfFaceHandle> > >()) generateGenericProperty<std::vector<std::vector<HalfFaceHandle> > , MeshT>(entity_t, name, _iff, _mesh);
364 
365  else if(prop_t == typeName<Vec2f>()) generateGenericProperty<Vec2f, MeshT>(entity_t, name, _iff, _mesh);
366  else if(prop_t == typeName<Vec2d>()) generateGenericProperty<Vec2d, MeshT>(entity_t, name, _iff, _mesh);
367  else if(prop_t == typeName<Vec2i>()) generateGenericProperty<Vec2i, MeshT>(entity_t, name, _iff, _mesh);
368  else if(prop_t == typeName<Vec2ui>()) generateGenericProperty<Vec2ui, MeshT>(entity_t, name, _iff, _mesh);
369 
370  else if(prop_t == typeName<Vec3f>()) generateGenericProperty<Vec3f, MeshT>(entity_t, name, _iff, _mesh);
371  else if(prop_t == typeName<Vec3d>()) generateGenericProperty<Vec3d, MeshT>(entity_t, name, _iff, _mesh);
372  else if(prop_t == typeName<Vec3i>()) generateGenericProperty<Vec3i, MeshT>(entity_t, name, _iff, _mesh);
373  else if(prop_t == typeName<Vec3ui>()) generateGenericProperty<Vec3ui, MeshT>(entity_t, name, _iff, _mesh);
374 
375  else if(prop_t == typeName<Vec4f>()) generateGenericProperty<Vec4f, MeshT>(entity_t, name, _iff, _mesh);
376  else if(prop_t == typeName<Vec4d>()) generateGenericProperty<Vec4d, MeshT>(entity_t, name, _iff, _mesh);
377  else if(prop_t == typeName<Vec4i>()) generateGenericProperty<Vec4i, MeshT>(entity_t, name, _iff, _mesh);
378  else if(prop_t == typeName<Vec4ui>()) generateGenericProperty<Vec4ui, MeshT>(entity_t, name, _iff, _mesh);
379 
380 
381 
382 }
383 
384 //==================================================
385 
386 template <class PropT, class MeshT>
387 void FileManager::generateGenericProperty(const std::string& _entity_t, const std::string& _name,
388  std::istream& _iff, MeshT& _mesh) const {
389 
390  if(_entity_t == "vprop") {
391  VertexPropertyT<PropT> prop = _mesh.template request_vertex_property<PropT>(_name);
392  prop.deserialize(_iff);
393  _mesh.set_persistent(prop);
394  } else if(_entity_t == "eprop") {
395  EdgePropertyT<PropT> prop = _mesh.template request_edge_property<PropT>(_name);
396  prop.deserialize(_iff);
397  _mesh.set_persistent(prop);
398  } else if(_entity_t == "heprop") {
399  HalfEdgePropertyT<PropT> prop = _mesh.template request_halfedge_property<PropT>(_name);
400  prop.deserialize(_iff);
401  _mesh.set_persistent(prop);
402  } else if(_entity_t == "fprop") {
403  FacePropertyT<PropT> prop = _mesh.template request_face_property<PropT>(_name);
404  prop.deserialize(_iff);
405  _mesh.set_persistent(prop);
406  } else if(_entity_t == "hfprop") {
407  HalfFacePropertyT<PropT> prop = _mesh.template request_halfface_property<PropT>(_name);
408  prop.deserialize(_iff);
409  _mesh.set_persistent(prop);
410  } else if(_entity_t == "cprop") {
411  CellPropertyT<PropT> prop = _mesh.template request_cell_property<PropT>(_name);
412  prop.deserialize(_iff);
413  _mesh.set_persistent(prop);
414  } else if(_entity_t == "mprop") {
415  MeshPropertyT<PropT> prop = _mesh.template request_mesh_property<PropT>(_name);
416  prop.deserialize(_iff);
417  _mesh.set_persistent(prop);
418  }
419 }
420 
421 //==================================================
422 
423 
424 template<class MeshT>
425 void FileManager::writeStream(std::ostream &_ostream, const MeshT &_mesh) const
426 {
427  // Write header
428  _ostream << "OVM ASCII" << std::endl;
429 
430  uint64_t n_vertices(_mesh.n_vertices());
431  _ostream << "Vertices" << std::endl;
432  _ostream << n_vertices << std::endl;
433 
434  typedef typename MeshT::PointT Point;
435 
436  // write vertices
437  for(VertexIter v_it = _mesh.v_iter(); v_it; ++v_it) {
438 
439  Point v = _mesh.vertex(*v_it);
440  _ostream << v[0] << " " << v[1] << " " << v[2] << std::endl;
441  }
442 
443  uint64_t n_edges(_mesh.n_edges());
444  _ostream << "Edges" << std::endl;
445  _ostream << n_edges << std::endl;
446 
447  // write edges
448  for(EdgeIter e_it = _mesh.e_iter(); e_it; ++e_it) {
449 
450  VertexHandle from_vertex = _mesh.edge(*e_it).from_vertex();
451  VertexHandle to_vertex = _mesh.edge(*e_it).to_vertex();
452  _ostream << from_vertex << " " << to_vertex << std::endl;
453  }
454 
455  uint64_t n_faces(_mesh.n_faces());
456  _ostream << "Faces" << std::endl;
457  _ostream << n_faces << std::endl;
458 
459  // write faces
460  for(FaceIter f_it = _mesh.f_iter(); f_it; ++f_it) {
461 
462  _ostream << static_cast<uint64_t>(_mesh.face(*f_it).halfedges().size()) << " ";
463 
464  std::vector<HalfEdgeHandle> halfedges = _mesh.face(*f_it).halfedges();
465 
466  for(typename std::vector<HalfEdgeHandle>::const_iterator it = halfedges.begin(); it
467  != halfedges.end(); ++it) {
468 
469  _ostream << it->idx();
470 
471  if((it + 1) != halfedges.end())
472  _ostream << " ";
473  }
474 
475  _ostream << std::endl;
476  }
477 
478  uint64_t n_cells(_mesh.n_cells());
479  _ostream << "Polyhedra" << std::endl;
480  _ostream << n_cells << std::endl;
481 
482  for(CellIter c_it = _mesh.c_iter(); c_it; ++c_it) {
483 
484  _ostream << static_cast<uint64_t>(_mesh.cell(*c_it).halffaces().size()) << " ";
485 
486  std::vector<HalfFaceHandle> halffaces = _mesh.cell(*c_it).halffaces();
487 
488  for(typename std::vector<HalfFaceHandle>::const_iterator it = halffaces.begin(); it
489  != halffaces.end(); ++it) {
490 
491  _ostream << it->idx();
492 
493  if((it + 1) != halffaces.end())
494  _ostream << " ";
495  }
496 
497  _ostream << std::endl;
498  }
499 
500  // write vertex props
501  writeProps(_ostream, _mesh.vertex_props_begin(), _mesh.vertex_props_end());
502  // write edge props
503  writeProps(_ostream, _mesh.edge_props_begin(), _mesh.edge_props_end());
504  // write halfedge props
505  writeProps(_ostream, _mesh.halfedge_props_begin(), _mesh.halfedge_props_end());
506  // write face props
507  writeProps(_ostream, _mesh.face_props_begin(), _mesh.face_props_end());
508  // write halfface props
509  writeProps(_ostream, _mesh.halfface_props_begin(), _mesh.halfface_props_end());
510  // write cell props
511  writeProps(_ostream, _mesh.cell_props_begin(), _mesh.cell_props_end());
512  // write mesh props
513  writeProps(_ostream, _mesh.mesh_props_begin(), _mesh.mesh_props_end());
514 }
515 
516 template<class MeshT>
517 bool FileManager::writeFile(const std::string& _filename, const MeshT& _mesh) const {
518 
519  std::ofstream off(_filename.c_str(), std::ios::out);
520 
521  if(!off.good()) {
522  if (verbosity_level_ >= 1) {
523  std::cerr << "Error: Could not open file " << _filename << " for writing!" << std::endl;
524  }
525  return false;
526  }
527  writeStream(off, _mesh);
528  return off.good();
529 }
530 
531 //==================================================
532 
533 template<class IteratorT>
534 void FileManager::writeProps(std::ostream& _ostr, const IteratorT& _begin, const IteratorT& _end) const {
535 
536  // write props
537  for(IteratorT p_it = _begin;
538  p_it != _end; ++p_it) {
539  if(!(*p_it)->persistent()) continue;
540  if((*p_it)->anonymous()) {
541  if (verbosity_level_ >= 2) {
542  std::cerr << "Serialization of anonymous properties is not supported!" << std::endl;
543  }
544  continue;
545  }
546 
547  std::string type_name;
548  try {
549  type_name = (*p_it)->typeNameWrapper();
550  } catch (std::runtime_error &e) { // type not serializable
551  if (verbosity_level_ >= 1) {
552  std::cerr << "Failed to save property " << (*p_it)->name() << " , skipping: " << e.what() << std::endl;
553  }
554  continue;
555  }
556  _ostr << (*p_it)->entityType() << " ";
557  _ostr << type_name << " ";
558  _ostr << "\"" << (*p_it)->name() << "\"" << std::endl;
559 
560  (*p_it)->serialize(_ostr);
561  }
562 }
563 
564 //==================================================
565 
566 } // Namespace IO
567 
568 } // Namespace FileManager
bool writeFile(const std::string &_filename, const MeshT &_mesh) const
Write a mesh to a file.
DLLEXPORT QString typeName(DataType _id)
Get the name of a type with given id.
Definition: Types.cc:154
void writeStream(std::ostream &_ostream, const MeshT &_mesh) const
Write a mesh to an std::ostream.
bool readFile(const std::string &_filename, MeshT &_mesh, bool _topologyCheck=true, bool _computeBottomUpIncidences=true) const
Read a mesh from a file.
bool readStream(std::istream &_istream, MeshT &_mesh, bool _topologyCheck=true, bool _computeBottomUpIncidences=true) const
Read a mesh from an std::istream.