FileManagerT_impl.hh 20.3 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/*===========================================================================*\
 *                                                                           *
 *                            OpenVolumeMesh                                 *
 *        Copyright (C) 2011 by Computer Graphics Group, RWTH Aachen         *
 *                        www.openvolumemesh.org                             *
 *                                                                           *
 *---------------------------------------------------------------------------*
 *  This file is part of OpenVolumeMesh.                                     *
 *                                                                           *
 *  OpenVolumeMesh is free software: you can redistribute it and/or modify   *
 *  it under the terms of the GNU Lesser General Public License as           *
 *  published by the Free Software Foundation, either version 3 of           *
 *  the License, or (at your option) any later version with the              *
 *  following exceptions:                                                    *
 *                                                                           *
 *  If other files instantiate templates or use macros                       *
 *  or inline functions from this file, or you compile this file and         *
 *  link it with other files to produce an executable, this file does        *
 *  not by itself cause the resulting executable to be covered by the        *
 *  GNU Lesser General Public License. This exception does not however       *
 *  invalidate any other reasons why the executable file might be            *
 *  covered by the GNU Lesser General Public License.                        *
 *                                                                           *
 *  OpenVolumeMesh is distributed in the hope that it will be useful,        *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
 *  GNU Lesser General Public License for more details.                      *
 *                                                                           *
 *  You should have received a copy of the GNU LesserGeneral Public          *
 *  License along with OpenVolumeMesh.  If not,                              *
 *  see <http://www.gnu.org/licenses/>.                                      *
 *                                                                           *
\*===========================================================================*/

/*===========================================================================*\
 *                                                                           *
 *   $Revision$                                                         *
 *   $Date$                    *
 *   $LastChangedBy$                                                *
 *                                                                           *
\*===========================================================================*/

#define FILEMANAGERT_CC

#include <vector>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <cctype>
#include <typeinfo>
Max Lyon's avatar
Max Lyon committed
51
#include <stdint.h>
52
53
54
55
56
57
58
59
60
61

#include <OpenVolumeMesh/Geometry/VectorT.hh>
#include <OpenVolumeMesh/Mesh/PolyhedralMesh.hh>

#include "FileManager.hh"

namespace OpenVolumeMesh {

namespace IO {

62
63
using namespace OpenVolumeMesh::Geometry;

64
65
//==================================================

66
67
68
69
template<class MeshT>
bool FileManager::readStream(std::istream &_istream, MeshT &_mesh,
    bool _topologyCheck, bool _computeBottomUpIncidences) const
{
70
71
72
    std::stringstream sstr;
    std::string line;
    std::string s_tmp;
Max Lyon's avatar
Max Lyon committed
73
    uint64_t c = 0u;
74
75
76
    typedef typename MeshT::PointT Point;
    Point v = Point(0.0, 0.0, 0.0);

77
    _mesh.clear(false);
78
79
80
    // Temporarily disable bottom-up incidences
    // since it's way faster to first add all the
    // geometry and compute them in one pass afterwards
81
    _mesh.enable_bottom_up_incidences(false);
82

83
84
85
86
87
88
89
    /*
     * Header
     */

    bool header_found = true;

    // Get first line
90
    getCleanLine(_istream, line);
91
92
93
94
95
96
    sstr.str(line);

    // Check header
    sstr >> s_tmp;
    std::transform(s_tmp.begin(), s_tmp.end(), s_tmp.begin(), ::toupper);
    if(s_tmp != "OVM") {
97
        //_istream.close();
98
        header_found = false;
99
100
101
        if (verbosity_level_ >= 1) {
            std::cerr << "The specified file might not be in OpenVolumeMesh format!" << std::endl;
        }
102
103
104
105
106
107
108
        //return false;
    }

    // Get ASCII/BINARY string
    sstr >> s_tmp;
    std::transform(s_tmp.begin(), s_tmp.end(), s_tmp.begin(), ::toupper);
    if(s_tmp == "BINARY") {
109
110
111
        if (verbosity_level_ >= 1) {
            std::cerr << "Binary files are not supported at the moment!" << std::endl;
        }
112
113
114
115
116
117
118
119
120
121
        return false;
    }

    /*
     * Vertices
     */
    if(!header_found) {
        sstr.clear();
        sstr.str(line);
    } else {
122
        getCleanLine(_istream, line);
123
124
125
126
127
128
129
        sstr.clear();
        sstr.str(line);
    }

    sstr >> s_tmp;
    std::transform(s_tmp.begin(), s_tmp.end(), s_tmp.begin(), ::toupper);
    if(s_tmp != "VERTICES") {
130
131
132
        if (verbosity_level_ >= 1) {
            std::cerr << "No vertex section defined!" << std::endl;
        }
133
134
135
136
        return false;
    } else {

        // Read in number of vertices
137
        getCleanLine(_istream, line);
138
139
140
141
142
        sstr.clear();
        sstr.str(line);
        sstr >> c;

        // Read in vertices
Max Lyon's avatar
Max Lyon committed
143
        for(uint64_t i = 0u; i < c; ++i) {
144

145
            getCleanLine(_istream, line);
146
147
148
149
150
151
152
153
154
155
156
157
            sstr.clear();
            sstr.str(line);
            sstr >> v[0];
            sstr >> v[1];
            sstr >> v[2];
            _mesh.add_vertex(v);
        }
    }

    /*
     * Edges
     */
158
    getCleanLine(_istream, line);
159
160
161
162
163
    sstr.clear();
    sstr.str(line);
    sstr >> s_tmp;
    std::transform(s_tmp.begin(), s_tmp.end(), s_tmp.begin(), ::toupper);
    if(s_tmp != "EDGES") {
164
165
166
        if (verbosity_level_ >= 2) {
            std::cerr << "No edge section defined!" << std::endl;
        }
167
168
169
170
        return false;
    } else {

        // Read in number of edges
171
        getCleanLine(_istream, line);
172
173
174
175
176
        sstr.clear();
        sstr.str(line);
        sstr >> c;

        // Read in edges
Max Lyon's avatar
Max Lyon committed
177
        for(uint64_t i = 0u; i < c; ++i) {
178

Max Lyon's avatar
Max Lyon committed
179
180
            unsigned int v1 = 0;
            unsigned int v2 = 0;
181
            getCleanLine(_istream, line);
182
183
184
185
            sstr.clear();
            sstr.str(line);
            sstr >> v1;
            sstr >> v2;
186
            _mesh.add_edge(VertexHandle(v1), VertexHandle(v2), true);
187
188
189
190
191
192
        }
    }

    /*
     * Faces
     */
193
    getCleanLine(_istream, line);
194
195
196
197
198
    sstr.clear();
    sstr.str(line);
    sstr >> s_tmp;
    std::transform(s_tmp.begin(), s_tmp.end(), s_tmp.begin(), ::toupper);
    if(s_tmp != "FACES") {
199
200
201
        if (verbosity_level_ >= 2) {
            std::cerr << "No face section defined!" << std::endl;
        }
202
203
204
205
        return false;
    } else {

        // Read in number of faces
206
        getCleanLine(_istream, line);
207
208
209
210
211
        sstr.clear();
        sstr.str(line);
        sstr >> c;

        // Read in faces
Max Lyon's avatar
Max Lyon committed
212
        for(uint64_t i = 0u; i < c; ++i) {
213

214
            getCleanLine(_istream, line);
215
216
217
218
219
220
            sstr.clear();
            sstr.str(line);

            std::vector<HalfEdgeHandle> hes;

            // Get face valence
Max Lyon's avatar
Max Lyon committed
221
            uint64_t val = 0u;
222
223
224
225
            sstr >> val;

            // Read half-edge indices
            for(unsigned int e = 0; e < val; ++e) {
226

227
                unsigned int v1 = 0;
228
229
230
231
232
233
234
235
236
237
238
                sstr >> v1;
                hes.push_back(HalfEdgeHandle(v1));
            }

            _mesh.add_face(hes, _topologyCheck);
        }
    }

    /*
     * Cells
     */
239
    getCleanLine(_istream, line);
240
241
242
243
244
    sstr.clear();
    sstr.str(line);
    sstr >> s_tmp;
    std::transform(s_tmp.begin(), s_tmp.end(), s_tmp.begin(), ::toupper);
    if(s_tmp != "POLYHEDRA") {
245
246
247
        if (verbosity_level_ >= 2) {
            std::cerr << "No polyhedra section defined!" << std::endl;
        }
248
249
250
251
        return false;
    } else {

        // Read in number of cells
252
        getCleanLine(_istream, line);
253
254
255
256
257
        sstr.clear();
        sstr.str(line);
        sstr >> c;

        // Read in cells
Max Lyon's avatar
Max Lyon committed
258
        for(uint64_t i = 0u; i < c; ++i) {
259

260
            getCleanLine(_istream, line);
261
262
263
264
265
266
            sstr.clear();
            sstr.str(line);

            std::vector<HalfFaceHandle> hfs;

            // Get cell valence
Max Lyon's avatar
Max Lyon committed
267
            uint64_t val = 0u;
268
269
270
271
            sstr >> val;

            // Read half-face indices
            for(unsigned int f = 0; f < val; ++f) {
272

273
                unsigned int v1 = 0;
274
275
276
277
278
279
280
281
                sstr >> v1;
                hfs.push_back(HalfFaceHandle(v1));
            }

            _mesh.add_cell(hfs, _topologyCheck);
        }
    }

282
    while(!_istream.eof()) {
283
284
285
286
        // "End of file reached while searching for input!"
        // is thrown here. \TODO Fix it!

        // 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
296
297
298
299
300
301
302
    if (verbosity_level_ >= 2) {
        std::cerr << "######## openvolumemesh info #########" << std::endl;
        std::cerr << "#vertices: " << _mesh.n_vertices() << std::endl;
        std::cerr << "#edges:    " << _mesh.n_edges() << std::endl;
        std::cerr << "#faces:    " << _mesh.n_faces() << std::endl;
        std::cerr << "#cells:    " << _mesh.n_cells() << std::endl;
        std::cerr << "######################################" << std::endl;
    }
303
304
305
306

    return true;
}

307
308
309
310
311
312
313
template <class MeshT>
bool FileManager::readFile(const std::string& _filename, MeshT& _mesh,
    bool _topologyCheck, bool _computeBottomUpIncidences) const {

    std::ifstream iff(_filename.c_str(), std::ios::in);

    if(!iff.good()) {
314
315
316
        if (verbosity_level_ >= 1) {
            std::cerr << "Error: Could not open file " << _filename << " for reading!" << std::endl;
        }
317
318
319
320
321
322
        iff.close();
        return false;
    }
    return readStream(iff, _mesh, _topologyCheck,_computeBottomUpIncidences);
}

323
324
//==================================================

325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
template <class MeshT>
void FileManager::readProperty(std::istream& _iff, MeshT& _mesh) const {

    std::string line, entity_t, prop_t, name;
    std::stringstream sstr;

    getCleanLine(_iff, line);

    if(line.empty()) return;

    sstr.clear();
    sstr.str(line);
    sstr >> entity_t;
    std::transform(entity_t.begin(), entity_t.end(), entity_t.begin(), ::tolower);
    sstr >> prop_t;
    std::transform(prop_t.begin(), prop_t.end(), prop_t.begin(), ::tolower);
    name = line;
    extractQuotedText(name);

344
345
346
    if (verbosity_level_ >= 2) {
        std::cerr << "OVM read property " << name << " of type " << prop_t << std::endl;
    }
347

348
349
350
351
352
353
354
355
356
357
358
    if(prop_t == typeName<int>()) generateGenericProperty<int, MeshT>(entity_t, name, _iff, _mesh);
    else if(prop_t == typeName<unsigned int>()) generateGenericProperty<unsigned int, MeshT>(entity_t, name, _iff, _mesh);
    else if(prop_t == typeName<short>()) generateGenericProperty<short, MeshT>(entity_t, name, _iff, _mesh);
    else if(prop_t == typeName<long>()) generateGenericProperty<long, MeshT>(entity_t, name, _iff, _mesh);
    else if(prop_t == typeName<unsigned long>()) generateGenericProperty<unsigned long, MeshT>(entity_t, name, _iff, _mesh);
    else if(prop_t == typeName<char>()) generateGenericProperty<char, MeshT>(entity_t, name, _iff, _mesh);
    else if(prop_t == typeName<unsigned char>()) generateGenericProperty<unsigned char, MeshT>(entity_t, name, _iff, _mesh);
    else if(prop_t == typeName<bool>()) generateGenericProperty<bool, MeshT>(entity_t, name, _iff, _mesh);
    else if(prop_t == typeName<float>()) generateGenericProperty<float, MeshT>(entity_t, name, _iff, _mesh);
    else if(prop_t == typeName<double>()) generateGenericProperty<double, MeshT>(entity_t, name, _iff, _mesh);
    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);
hliu's avatar
hliu committed
360
361
362
363
    else if(prop_t == typeName<std::vector<double> >()) generateGenericProperty<std::vector<double> , MeshT>(entity_t, name, _iff, _mesh);
    else if(prop_t == typeName<std::vector<VertexHandle> >()) generateGenericProperty<std::vector<VertexHandle> , MeshT>(entity_t, name, _iff, _mesh);
    else if(prop_t == typeName<std::vector<HalfFaceHandle> >()) generateGenericProperty<std::vector<HalfFaceHandle> , MeshT>(entity_t, name, _iff, _mesh);
    else if(prop_t == typeName<std::vector<std::vector<HalfFaceHandle> > >()) generateGenericProperty<std::vector<std::vector<HalfFaceHandle> > , MeshT>(entity_t, name, _iff, _mesh);
364
365
366
367
368
369
370
371
372
373
374
375

    else if(prop_t == typeName<Vec2f>()) generateGenericProperty<Vec2f, MeshT>(entity_t, name, _iff, _mesh);
    else if(prop_t == typeName<Vec2d>()) generateGenericProperty<Vec2d, MeshT>(entity_t, name, _iff, _mesh);
    else if(prop_t == typeName<Vec2i>()) generateGenericProperty<Vec2i, MeshT>(entity_t, name, _iff, _mesh);
    else if(prop_t == typeName<Vec2ui>()) generateGenericProperty<Vec2ui, MeshT>(entity_t, name, _iff, _mesh);

    else if(prop_t == typeName<Vec3f>()) generateGenericProperty<Vec3f, MeshT>(entity_t, name, _iff, _mesh);
    else if(prop_t == typeName<Vec3d>()) generateGenericProperty<Vec3d, MeshT>(entity_t, name, _iff, _mesh);
    else if(prop_t == typeName<Vec3i>()) generateGenericProperty<Vec3i, MeshT>(entity_t, name, _iff, _mesh);
    else if(prop_t == typeName<Vec3ui>()) generateGenericProperty<Vec3ui, MeshT>(entity_t, name, _iff, _mesh);

    else if(prop_t == typeName<Vec4f>()) generateGenericProperty<Vec4f, MeshT>(entity_t, name, _iff, _mesh);
Jan Möbius's avatar
Jan Möbius committed
376
377
378
    else if(prop_t == typeName<Vec4d>()) generateGenericProperty<Vec4d, MeshT>(entity_t, name, _iff, _mesh);
    else if(prop_t == typeName<Vec4i>()) generateGenericProperty<Vec4i, MeshT>(entity_t, name, _iff, _mesh);
    else if(prop_t == typeName<Vec4ui>()) generateGenericProperty<Vec4ui, MeshT>(entity_t, name, _iff, _mesh);
379
380
381



382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
}

//==================================================

template <class PropT, class MeshT>
void FileManager::generateGenericProperty(const std::string& _entity_t, const std::string& _name,
                                          std::istream& _iff, MeshT& _mesh) const {

    if(_entity_t == "vprop") {
        VertexPropertyT<PropT> prop = _mesh.template request_vertex_property<PropT>(_name);
        prop.deserialize(_iff);
        _mesh.set_persistent(prop);
    } else if(_entity_t == "eprop") {
        EdgePropertyT<PropT> prop = _mesh.template request_edge_property<PropT>(_name);
        prop.deserialize(_iff);
        _mesh.set_persistent(prop);
    } else if(_entity_t == "heprop") {
        HalfEdgePropertyT<PropT> prop = _mesh.template request_halfedge_property<PropT>(_name);
        prop.deserialize(_iff);
        _mesh.set_persistent(prop);
    } else if(_entity_t == "fprop") {
        FacePropertyT<PropT> prop = _mesh.template request_face_property<PropT>(_name);
        prop.deserialize(_iff);
        _mesh.set_persistent(prop);
    } else if(_entity_t == "hfprop") {
        HalfFacePropertyT<PropT> prop = _mesh.template request_halfface_property<PropT>(_name);
        prop.deserialize(_iff);
        _mesh.set_persistent(prop);
    } else if(_entity_t == "cprop") {
        CellPropertyT<PropT> prop = _mesh.template request_cell_property<PropT>(_name);
        prop.deserialize(_iff);
        _mesh.set_persistent(prop);
    } else if(_entity_t == "mprop") {
        MeshPropertyT<PropT> prop = _mesh.template request_mesh_property<PropT>(_name);
        prop.deserialize(_iff);
        _mesh.set_persistent(prop);
    }
}

//==================================================

423

424
425
426
template<class MeshT>
void FileManager::writeStream(std::ostream &_ostream, const MeshT &_mesh) const
{
427
    // Write header
428
    _ostream << "OVM ASCII" << std::endl;
429

Max Lyon's avatar
Max Lyon committed
430
    uint64_t n_vertices(_mesh.n_vertices());
431
432
    _ostream << "Vertices" << std::endl;
    _ostream << n_vertices << std::endl;
433
434
435
436
437
438
439

    typedef typename MeshT::PointT Point;

    // write vertices
    for(VertexIter v_it = _mesh.v_iter(); v_it; ++v_it) {

        Point v = _mesh.vertex(*v_it);
440
        _ostream << v[0] << " " << v[1] << " " << v[2] << std::endl;
441
442
    }

Max Lyon's avatar
Max Lyon committed
443
    uint64_t n_edges(_mesh.n_edges());
444
445
    _ostream << "Edges" << std::endl;
    _ostream << n_edges << std::endl;
446
447
448
449
450
451

    // write edges
    for(EdgeIter e_it = _mesh.e_iter(); e_it; ++e_it) {

        VertexHandle from_vertex = _mesh.edge(*e_it).from_vertex();
        VertexHandle to_vertex = _mesh.edge(*e_it).to_vertex();
452
        _ostream << from_vertex << " " << to_vertex << std::endl;
453
454
    }

Max Lyon's avatar
Max Lyon committed
455
    uint64_t n_faces(_mesh.n_faces());
456
457
    _ostream << "Faces" << std::endl;
    _ostream << n_faces << std::endl;
458
459
460
461

    // write faces
    for(FaceIter f_it = _mesh.f_iter(); f_it; ++f_it) {

462
        _ostream << static_cast<uint64_t>(_mesh.face(*f_it).halfedges().size()) << " ";
463
464
465
466

        std::vector<HalfEdgeHandle> halfedges = _mesh.face(*f_it).halfedges();

        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
    }

Max Lyon's avatar
Max Lyon committed
478
    uint64_t n_cells(_mesh.n_cells());
479
480
    _ostream << "Polyhedra" << std::endl;
    _ostream << n_cells << std::endl;
481
482
483

    for(CellIter c_it = _mesh.c_iter(); c_it; ++c_it) {

484
        _ostream << static_cast<uint64_t>(_mesh.cell(*c_it).halffaces().size()) << " ";
485
486
487
488

        std::vector<HalfFaceHandle> halffaces = _mesh.cell(*c_it).halffaces();

        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
514
    writeProps(_ostream, _mesh.mesh_props_begin(), _mesh.mesh_props_end());
}
515

516
517
template<class MeshT>
bool FileManager::writeFile(const std::string& _filename, const MeshT& _mesh) const {
518

519
520
521
    std::ofstream off(_filename.c_str(), std::ios::out);

    if(!off.good()) {
522
523
524
        if (verbosity_level_ >= 1) {
            std::cerr << "Error: Could not open file " << _filename << " for writing!" << std::endl;
        }
525
526
527
528
        return false;
    }
    writeStream(off, _mesh);
    return off.good();
529
530
531
532
}

//==================================================

533
534
535
536
537
538
539
540
template<class IteratorT>
void FileManager::writeProps(std::ostream& _ostr, const IteratorT& _begin, const IteratorT& _end) const {

    // write props
    for(IteratorT p_it = _begin;
            p_it != _end; ++p_it) {
        if(!(*p_it)->persistent()) continue;
        if((*p_it)->anonymous()) {
541
542
543
            if (verbosity_level_ >= 2) {
                std::cerr << "Serialization of anonymous properties is not supported!" << std::endl;
            }
544
545
            continue;
        }
546

547
548
549
550
        std::string type_name;
        try {
            type_name = (*p_it)->typeNameWrapper();
        } catch (std::runtime_error &e) { // type not serializable
551
552
553
            if (verbosity_level_ >= 1) {
                std::cerr << "Failed to save property " << (*p_it)->name() << " , skipping: " << e.what() << std::endl;
            }
554
555
            continue;
        }
556
        _ostr << (*p_it)->entityType() << " ";
557
        _ostr << type_name << " ";
558
559
        _ostr << "\"" << (*p_it)->name() << "\"" << std::endl;

560
561
562
563
564
565
        (*p_it)->serialize(_ostr);
    }
}

//==================================================

566
567
568
} // Namespace IO

} // Namespace FileManager