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
OpenVolumeMesh::FaceIter
Definition: Iterators.hh:995
typeName
DLLEXPORT QString typeName(DataType _id)
Get the name of a type with given id.
Definition: Types.cc:154
OpenVolumeMesh::IO::FileManager::readStream
bool readStream(std::istream &_istream, MeshT &_mesh, bool _topologyCheck=true, bool _computeBottomUpIncidences=true) const
Read a mesh from an std::istream.
Definition: FileManagerT_impl.hh:67
OpenVolumeMesh::IO::FileManager::readFile
bool readFile(const std::string &_filename, MeshT &_mesh, bool _topologyCheck=true, bool _computeBottomUpIncidences=true) const
Read a mesh from a file.
Definition: FileManagerT_impl.hh:308
OpenVolumeMesh::Geometry
Definition: Vector11T.hh:59
OpenVolumeMesh::VertexIter
Definition: Iterators.hh:833
OpenVolumeMesh::HandleT< Entity::Vertex >
OpenVolumeMesh
Definition: ColorAttrib.hh:53
OpenVolumeMesh::CellIter
Definition: Iterators.hh:1103
OpenVolumeMesh::PropertyTT
Definition: ForwardDeclarations.hh:18
OpenVolumeMesh::IO::FileManager::writeStream
void writeStream(std::ostream &_ostream, const MeshT &_mesh) const
Write a mesh to an std::ostream.
Definition: FileManagerT_impl.hh:425
OpenVolumeMesh::EdgeIter
Definition: Iterators.hh:887
OpenVolumeMesh::IO::FileManager::writeFile
bool writeFile(const std::string &_filename, const MeshT &_mesh) const
Write a mesh to a file.
Definition: FileManagerT_impl.hh:517