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