Developer Documentation
FileManagerT.cc
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 
52 #include <OpenVolumeMesh/Geometry/VectorT.hh>
53 #include <OpenVolumeMesh/Mesh/PolyhedralMesh.hh>
54 
55 #include "FileManager.hh"
56 
57 namespace OpenVolumeMesh {
58 
59 namespace IO {
60 
61 using namespace OpenVolumeMesh::Geometry;
62 
63 //==================================================
64 
65 template <class MeshT>
66 bool FileManager::readFile(const std::string& _filename, MeshT& _mesh,
67  bool _topologyCheck, bool _computeBottomUpIncidences) const {
68 
69  std::ifstream iff(_filename.c_str(), std::ios::in);
70 
71  if(!iff.good()) {
72  std::cerr << "Error: Could not open file " << _filename << " for reading!" << std::endl;
73  iff.close();
74  return false;
75  }
76 
77  std::stringstream sstr;
78  std::string line;
79  std::string s_tmp;
80  unsigned int c = 0u;
81  typedef typename MeshT::PointT Point;
82  Point v = Point(0.0, 0.0, 0.0);
83 
84  _mesh.clear(false);
85  // Temporarily disable bottom-up incidences
86  // since it's way faster to first add all the
87  // geometry and compute them in one pass afterwards
88  _mesh.enable_bottom_up_incidences(false);
89 
90  /*
91  * Header
92  */
93 
94  bool header_found = true;
95 
96  // Get first line
97  getCleanLine(iff, line);
98  sstr.str(line);
99 
100  // Check header
101  sstr >> s_tmp;
102  std::transform(s_tmp.begin(), s_tmp.end(), s_tmp.begin(), ::toupper);
103  if(s_tmp != "OVM") {
104  //iff.close();
105  header_found = false;
106  std::cerr << "The specified file might not be in OpenVolumeMesh format!" << std::endl;
107  //return false;
108  }
109 
110  // Get ASCII/BINARY string
111  sstr >> s_tmp;
112  std::transform(s_tmp.begin(), s_tmp.end(), s_tmp.begin(), ::toupper);
113  if(s_tmp == "BINARY") {
114  iff.close();
115  std::cerr << "Binary files are not supported at the moment!" << std::endl;
116  return false;
117  }
118 
119  /*
120  * Vertices
121  */
122  if(!header_found) {
123  sstr.clear();
124  sstr.str(line);
125  } else {
126  getCleanLine(iff, line);
127  sstr.clear();
128  sstr.str(line);
129  }
130 
131  sstr >> s_tmp;
132  std::transform(s_tmp.begin(), s_tmp.end(), s_tmp.begin(), ::toupper);
133  if(s_tmp != "VERTICES") {
134  iff.close();
135  std::cerr << "No vertex section defined!" << std::endl;
136  return false;
137  } else {
138 
139  // Read in number of vertices
140  getCleanLine(iff, line);
141  sstr.clear();
142  sstr.str(line);
143  sstr >> c;
144 
145  // Read in vertices
146  for(unsigned int i = 0u; i < c; ++i) {
147 
148  getCleanLine(iff, line);
149  sstr.clear();
150  sstr.str(line);
151  sstr >> v[0];
152  sstr >> v[1];
153  sstr >> v[2];
154  _mesh.add_vertex(v);
155  }
156  }
157 
158  /*
159  * Edges
160  */
161  getCleanLine(iff, line);
162  sstr.clear();
163  sstr.str(line);
164  sstr >> s_tmp;
165  std::transform(s_tmp.begin(), s_tmp.end(), s_tmp.begin(), ::toupper);
166  if(s_tmp != "EDGES") {
167  iff.close();
168  std::cerr << "No edge section defined!" << std::endl;
169  return false;
170  } else {
171 
172  // Read in number of edges
173  getCleanLine(iff, line);
174  sstr.clear();
175  sstr.str(line);
176  sstr >> c;
177 
178  // Read in edges
179  for(unsigned int i = 0u; i < c; ++i) {
180 
181  unsigned int v1 = 0;
182  unsigned int v2 = 0;
183  getCleanLine(iff, line);
184  sstr.clear();
185  sstr.str(line);
186  sstr >> v1;
187  sstr >> v2;
188  _mesh.add_edge(VertexHandle(v1), VertexHandle(v2), true);
189  }
190  }
191 
192  /*
193  * Faces
194  */
195  getCleanLine(iff, line);
196  sstr.clear();
197  sstr.str(line);
198  sstr >> s_tmp;
199  std::transform(s_tmp.begin(), s_tmp.end(), s_tmp.begin(), ::toupper);
200  if(s_tmp != "FACES") {
201  iff.close();
202  std::cerr << "No face section defined!" << std::endl;
203  return false;
204  } else {
205 
206  // Read in number of faces
207  getCleanLine(iff, line);
208  sstr.clear();
209  sstr.str(line);
210  sstr >> c;
211 
212  // Read in faces
213  for(unsigned int i = 0u; i < c; ++i) {
214 
215  getCleanLine(iff, line);
216  sstr.clear();
217  sstr.str(line);
218 
219  std::vector<HalfEdgeHandle> hes;
220 
221  // Get face valence
222  unsigned int val = 0u;
223  sstr >> val;
224 
225  // Read half-edge indices
226  for(unsigned int e = 0; e < val; ++e) {
227 
228  unsigned int v1 = 0;
229  sstr >> v1;
230  hes.push_back(HalfEdgeHandle(v1));
231  }
232 
233  _mesh.add_face(hes, _topologyCheck);
234  }
235  }
236 
237  /*
238  * Cells
239  */
240  getCleanLine(iff, line);
241  sstr.clear();
242  sstr.str(line);
243  sstr >> s_tmp;
244  std::transform(s_tmp.begin(), s_tmp.end(), s_tmp.begin(), ::toupper);
245  if(s_tmp != "POLYHEDRA") {
246  iff.close();
247  std::cerr << "No polyhedra section defined!" << std::endl;
248  return false;
249  } else {
250 
251  // Read in number of cells
252  getCleanLine(iff, line);
253  sstr.clear();
254  sstr.str(line);
255  sstr >> c;
256 
257  // Read in cells
258  for(unsigned int i = 0u; i < c; ++i) {
259 
260  getCleanLine(iff, line);
261  sstr.clear();
262  sstr.str(line);
263 
264  std::vector<HalfFaceHandle> hfs;
265 
266  // Get cell valence
267  unsigned int 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(!iff.eof()) {
283  // "End of file reached while searching for input!"
284  // is thrown here. \TODO Fix it!
285 
286  // Read property
287  readProperty(iff, _mesh);
288  }
289 
290  iff.close();
291 
292  if(_computeBottomUpIncidences) {
293  // Compute bottom-up incidences
294  _mesh.enable_bottom_up_incidences(true);
295  }
296 
297  std::cerr << "######## openvolumemesh info #########" << std::endl;
298  std::cerr << "#vertices: " << _mesh.n_vertices() << std::endl;
299  std::cerr << "#edges: " << _mesh.n_edges() << std::endl;
300  std::cerr << "#faces: " << _mesh.n_faces() << std::endl;
301  std::cerr << "#cells: " << _mesh.n_cells() << std::endl;
302  std::cerr << "######################################" << std::endl;
303 
304  return true;
305 }
306 
307 //==================================================
308 
309 template <class MeshT>
310 void FileManager::readProperty(std::istream& _iff, MeshT& _mesh) const {
311 
312  std::string line, entity_t, prop_t, name;
313  std::stringstream sstr;
314 
315  getCleanLine(_iff, line);
316 
317  if(line.empty()) return;
318 
319  sstr.clear();
320  sstr.str(line);
321  sstr >> entity_t;
322  std::transform(entity_t.begin(), entity_t.end(), entity_t.begin(), ::tolower);
323  sstr >> prop_t;
324  std::transform(prop_t.begin(), prop_t.end(), prop_t.begin(), ::tolower);
325  name = line;
326  extractQuotedText(name);
327 
328  if(prop_t == typeName<int>()) generateGenericProperty<int, MeshT>(entity_t, name, _iff, _mesh);
329  else if(prop_t == typeName<unsigned int>()) generateGenericProperty<unsigned int, MeshT>(entity_t, name, _iff, _mesh);
330  else if(prop_t == typeName<short>()) generateGenericProperty<short, MeshT>(entity_t, name, _iff, _mesh);
331  else if(prop_t == typeName<long>()) generateGenericProperty<long, MeshT>(entity_t, name, _iff, _mesh);
332  else if(prop_t == typeName<unsigned long>()) generateGenericProperty<unsigned long, MeshT>(entity_t, name, _iff, _mesh);
333  else if(prop_t == typeName<char>()) generateGenericProperty<char, MeshT>(entity_t, name, _iff, _mesh);
334  else if(prop_t == typeName<unsigned char>()) generateGenericProperty<unsigned char, MeshT>(entity_t, name, _iff, _mesh);
335  else if(prop_t == typeName<bool>()) generateGenericProperty<bool, MeshT>(entity_t, name, _iff, _mesh);
336  else if(prop_t == typeName<float>()) generateGenericProperty<float, MeshT>(entity_t, name, _iff, _mesh);
337  else if(prop_t == typeName<double>()) generateGenericProperty<double, MeshT>(entity_t, name, _iff, _mesh);
338  else if(prop_t == typeName<std::string>()) generateGenericProperty<std::string, MeshT>(entity_t, name, _iff, _mesh);
339 
340  else if(prop_t == typeName<Vec2f>()) generateGenericProperty<Vec2f, MeshT>(entity_t, name, _iff, _mesh);
341  else if(prop_t == typeName<Vec2d>()) generateGenericProperty<Vec2d, MeshT>(entity_t, name, _iff, _mesh);
342  else if(prop_t == typeName<Vec2i>()) generateGenericProperty<Vec2i, MeshT>(entity_t, name, _iff, _mesh);
343  else if(prop_t == typeName<Vec2ui>()) generateGenericProperty<Vec2ui, MeshT>(entity_t, name, _iff, _mesh);
344 
345  else if(prop_t == typeName<Vec3f>()) generateGenericProperty<Vec3f, MeshT>(entity_t, name, _iff, _mesh);
346  else if(prop_t == typeName<Vec3d>()) generateGenericProperty<Vec3d, MeshT>(entity_t, name, _iff, _mesh);
347  else if(prop_t == typeName<Vec3i>()) generateGenericProperty<Vec3i, MeshT>(entity_t, name, _iff, _mesh);
348  else if(prop_t == typeName<Vec3ui>()) generateGenericProperty<Vec3ui, MeshT>(entity_t, name, _iff, _mesh);
349 
350  else if(prop_t == typeName<Vec4f>()) generateGenericProperty<Vec4f, MeshT>(entity_t, name, _iff, _mesh);
351  else if(prop_t == typeName<Vec4d>()) generateGenericProperty<Vec4d, MeshT>(entity_t, name, _iff, _mesh);
352  else if(prop_t == typeName<Vec4i>()) generateGenericProperty<Vec4i, MeshT>(entity_t, name, _iff, _mesh);
353  else if(prop_t == typeName<Vec4ui>()) generateGenericProperty<Vec4ui, MeshT>(entity_t, name, _iff, _mesh);
354 
355 
356 
357 }
358 
359 //==================================================
360 
361 template <class PropT, class MeshT>
362 void FileManager::generateGenericProperty(const std::string& _entity_t, const std::string& _name,
363  std::istream& _iff, MeshT& _mesh) const {
364 
365  if(_entity_t == "vprop") {
366  VertexPropertyT<PropT> prop = _mesh.template request_vertex_property<PropT>(_name);
367  prop.deserialize(_iff);
368  _mesh.set_persistent(prop);
369  } else if(_entity_t == "eprop") {
370  EdgePropertyT<PropT> prop = _mesh.template request_edge_property<PropT>(_name);
371  prop.deserialize(_iff);
372  _mesh.set_persistent(prop);
373  } else if(_entity_t == "heprop") {
374  HalfEdgePropertyT<PropT> prop = _mesh.template request_halfedge_property<PropT>(_name);
375  prop.deserialize(_iff);
376  _mesh.set_persistent(prop);
377  } else if(_entity_t == "fprop") {
378  FacePropertyT<PropT> prop = _mesh.template request_face_property<PropT>(_name);
379  prop.deserialize(_iff);
380  _mesh.set_persistent(prop);
381  } else if(_entity_t == "hfprop") {
382  HalfFacePropertyT<PropT> prop = _mesh.template request_halfface_property<PropT>(_name);
383  prop.deserialize(_iff);
384  _mesh.set_persistent(prop);
385  } else if(_entity_t == "cprop") {
386  CellPropertyT<PropT> prop = _mesh.template request_cell_property<PropT>(_name);
387  prop.deserialize(_iff);
388  _mesh.set_persistent(prop);
389  } else if(_entity_t == "mprop") {
390  MeshPropertyT<PropT> prop = _mesh.template request_mesh_property<PropT>(_name);
391  prop.deserialize(_iff);
392  _mesh.set_persistent(prop);
393  }
394 }
395 
396 //==================================================
397 
398 template<class MeshT>
399 bool FileManager::writeFile(const std::string& _filename, const MeshT& _mesh) const {
400 
401  std::ofstream off(_filename.c_str(), std::ios::out);
402 
403  if(!off.good()) {
404  std::cerr << "Error: Could not open file " << _filename << " for writing!" << std::endl;
405  off.close();
406  return false;
407  }
408 
409  // Write header
410  off << "OVM ASCII" << std::endl;
411 
412  unsigned int n_vertices(_mesh.n_vertices());
413  off << "Vertices" << std::endl;
414  off << n_vertices << std::endl;
415 
416  typedef typename MeshT::PointT Point;
417 
418  // write vertices
419  for(VertexIter v_it = _mesh.v_iter(); v_it; ++v_it) {
420 
421  Point v = _mesh.vertex(*v_it);
422  off << v[0] << " " << v[1] << " " << v[2] << std::endl;
423  }
424 
425  unsigned int n_edges(_mesh.n_edges());
426  off << "Edges" << std::endl;
427  off << n_edges << std::endl;
428 
429  // write edges
430  for(EdgeIter e_it = _mesh.e_iter(); e_it; ++e_it) {
431 
432  VertexHandle from_vertex = _mesh.edge(*e_it).from_vertex();
433  VertexHandle to_vertex = _mesh.edge(*e_it).to_vertex();
434  off << from_vertex << " " << to_vertex << std::endl;
435  }
436 
437  unsigned int n_faces(_mesh.n_faces());
438  off << "Faces" << std::endl;
439  off << n_faces << std::endl;
440 
441  // write faces
442  for(FaceIter f_it = _mesh.f_iter(); f_it; ++f_it) {
443 
444  off << _mesh.face(*f_it).halfedges().size() << " ";
445 
446  std::vector<HalfEdgeHandle> halfedges = _mesh.face(*f_it).halfedges();
447 
448  for(typename std::vector<HalfEdgeHandle>::const_iterator it = halfedges.begin(); it
449  != halfedges.end(); ++it) {
450 
451  off << it->idx();
452 
453  if((it + 1) != halfedges.end())
454  off << " ";
455  }
456 
457  off << std::endl;
458  }
459 
460  unsigned int n_cells(_mesh.n_cells());
461  off << "Polyhedra" << std::endl;
462  off << n_cells << std::endl;
463 
464  for(CellIter c_it = _mesh.c_iter(); c_it; ++c_it) {
465 
466  off << _mesh.cell(*c_it).halffaces().size() << " ";
467 
468  std::vector<HalfFaceHandle> halffaces = _mesh.cell(*c_it).halffaces();
469 
470  for(typename std::vector<HalfFaceHandle>::const_iterator it = halffaces.begin(); it
471  != halffaces.end(); ++it) {
472 
473  off << it->idx();
474 
475  if((it + 1) != halffaces.end())
476  off << " ";
477  }
478 
479  off << std::endl;
480  }
481 
482  // write vertex props
483  writeProps(off, _mesh.vertex_props_begin(), _mesh.vertex_props_end());
484  // write edge props
485  writeProps(off, _mesh.edge_props_begin(), _mesh.edge_props_end());
486  // write halfedge props
487  writeProps(off, _mesh.halfedge_props_begin(), _mesh.halfedge_props_end());
488  // write face props
489  writeProps(off, _mesh.face_props_begin(), _mesh.face_props_end());
490  // write halfface props
491  writeProps(off, _mesh.halfface_props_begin(), _mesh.halfface_props_end());
492  // write cell props
493  writeProps(off, _mesh.cell_props_begin(), _mesh.cell_props_end());
494  // write mesh props
495  writeProps(off, _mesh.mesh_props_begin(), _mesh.mesh_props_end());
496 
497  off.close();
498 
499  return true;
500 }
501 
502 //==================================================
503 
504 template<class IteratorT>
505 void FileManager::writeProps(std::ostream& _ostr, const IteratorT& _begin, const IteratorT& _end) const {
506 
507  // write props
508  for(IteratorT p_it = _begin;
509  p_it != _end; ++p_it) {
510  if(!(*p_it)->persistent()) continue;
511  if((*p_it)->anonymous()) {
512  std::cerr << "Serialization of anonymous properties is not supported!" << std::endl;
513  continue;
514  }
515 
516  std::string type_name;
517  try {
518  type_name = (*p_it)->typeNameWrapper();
519  } catch (std::runtime_error &e) { // type not serializable
520  std::cerr << "Failed to save property, skipping: " << e.what() << std::endl;
521  continue;
522  }
523  _ostr << (*p_it)->entityType() << " ";
524  _ostr << type_name << " ";
525  _ostr << "\"" << (*p_it)->name() << "\"" << std::endl;
526 
527  (*p_it)->serialize(_ostr);
528  }
529 }
530 
531 //==================================================
532 
533 } // Namespace IO
534 
535 } // Namespace FileManager
bool readFile(const std::string &_filename, MeshT &_mesh, bool _topologyCheck=true, bool _computeBottomUpIncidences=true) const
Read a mesh from a file.
Definition: FileManagerT.cc:66
Property classes for the different entity types.
bool writeFile(const std::string &_filename, const MeshT &_mesh) const
Write a mesh to a file.