FileManagerT.cc 19.6 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 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
        header_found = false;
        std::cerr << "The specified file might not be in OpenVolumeMesh format!" << std::endl;
        //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") {
        std::cerr << "Binary files are not supported at the moment!" << std::endl;
        return false;
    }

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

    sstr >> s_tmp;
    std::transform(s_tmp.begin(), s_tmp.end(), s_tmp.begin(), ::toupper);
    if(s_tmp != "VERTICES") {
        std::cerr << "No vertex section defined!" << std::endl;
        return false;
    } else {

        // Read in number of vertices
131
        getCleanLine(_istream, line);
132 133 134 135 136
        sstr.clear();
        sstr.str(line);
        sstr >> c;

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

139
            getCleanLine(_istream, line);
140 141 142 143 144 145 146 147 148 149 150 151
            sstr.clear();
            sstr.str(line);
            sstr >> v[0];
            sstr >> v[1];
            sstr >> v[2];
            _mesh.add_vertex(v);
        }
    }

    /*
     * Edges
     */
152
    getCleanLine(_istream, line);
153 154 155 156 157 158 159 160 161 162
    sstr.clear();
    sstr.str(line);
    sstr >> s_tmp;
    std::transform(s_tmp.begin(), s_tmp.end(), s_tmp.begin(), ::toupper);
    if(s_tmp != "EDGES") {
        std::cerr << "No edge section defined!" << std::endl;
        return false;
    } else {

        // Read in number of edges
163
        getCleanLine(_istream, line);
164 165 166 167 168
        sstr.clear();
        sstr.str(line);
        sstr >> c;

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

Max Lyon's avatar
Max Lyon committed
171 172
            unsigned int v1 = 0;
            unsigned int v2 = 0;
173
            getCleanLine(_istream, line);
174 175 176 177
            sstr.clear();
            sstr.str(line);
            sstr >> v1;
            sstr >> v2;
178
            _mesh.add_edge(VertexHandle(v1), VertexHandle(v2), true);
179 180 181 182 183 184
        }
    }

    /*
     * Faces
     */
185
    getCleanLine(_istream, line);
186 187 188 189 190 191 192 193 194 195
    sstr.clear();
    sstr.str(line);
    sstr >> s_tmp;
    std::transform(s_tmp.begin(), s_tmp.end(), s_tmp.begin(), ::toupper);
    if(s_tmp != "FACES") {
        std::cerr << "No face section defined!" << std::endl;
        return false;
    } else {

        // Read in number of faces
196
        getCleanLine(_istream, line);
197 198 199 200 201
        sstr.clear();
        sstr.str(line);
        sstr >> c;

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

204
            getCleanLine(_istream, line);
205 206 207 208 209 210
            sstr.clear();
            sstr.str(line);

            std::vector<HalfEdgeHandle> hes;

            // Get face valence
Max Lyon's avatar
Max Lyon committed
211
            uint64_t val = 0u;
212 213 214 215
            sstr >> val;

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

217
                unsigned int v1 = 0;
218 219 220 221 222 223 224 225 226 227 228
                sstr >> v1;
                hes.push_back(HalfEdgeHandle(v1));
            }

            _mesh.add_face(hes, _topologyCheck);
        }
    }

    /*
     * Cells
     */
229
    getCleanLine(_istream, line);
230 231 232 233 234 235 236 237 238 239
    sstr.clear();
    sstr.str(line);
    sstr >> s_tmp;
    std::transform(s_tmp.begin(), s_tmp.end(), s_tmp.begin(), ::toupper);
    if(s_tmp != "POLYHEDRA") {
        std::cerr << "No polyhedra section defined!" << std::endl;
        return false;
    } else {

        // Read in number of cells
240
        getCleanLine(_istream, line);
241 242 243 244 245
        sstr.clear();
        sstr.str(line);
        sstr >> c;

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

248
            getCleanLine(_istream, line);
249 250 251 252 253 254
            sstr.clear();
            sstr.str(line);

            std::vector<HalfFaceHandle> hfs;

            // Get cell valence
Max Lyon's avatar
Max Lyon committed
255
            uint64_t val = 0u;
256 257 258 259
            sstr >> val;

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

261
                unsigned int v1 = 0;
262 263 264 265 266 267 268 269
                sstr >> v1;
                hfs.push_back(HalfFaceHandle(v1));
            }

            _mesh.add_cell(hfs, _topologyCheck);
        }
    }

270
    while(!_istream.eof()) {
271 272 273 274
        // "End of file reached while searching for input!"
        // is thrown here. \TODO Fix it!

        // Read property
275
        readProperty(_istream, _mesh);
276 277
    }

278
    if(_computeBottomUpIncidences) {
279
        // Compute bottom-up incidences
280
        _mesh.enable_bottom_up_incidences(true);
281 282
    }

283 284 285 286 287 288 289 290 291 292
    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;

    return true;
}

293 294 295 296 297 298 299 300 301 302 303 304 305 306
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()) {
        std::cerr << "Error: Could not open file " << _filename << " for reading!" << std::endl;
        iff.close();
        return false;
    }
    return readStream(iff, _mesh, _topologyCheck,_computeBottomUpIncidences);
}

307 308
//==================================================

309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
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);

328 329
    std::cerr << "OVM read property " << name << " of type " << prop_t << std::endl;

330 331 332 333 334 335 336 337 338 339 340
    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);
341
    else if(prop_t == typeName<std::map<HalfEdgeHandle, int> >()) generateGenericProperty<std::map<HalfEdgeHandle, int>, MeshT>(entity_t, name, _iff, _mesh);
Heng Liu's avatar
Heng Liu committed
342 343 344 345
    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);
346 347 348 349 350 351 352 353 354 355 356 357

    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
358 359 360
    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);
361 362 363



364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 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
}

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

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);
    }
}

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

405

406 407 408
template<class MeshT>
void FileManager::writeStream(std::ostream &_ostream, const MeshT &_mesh) const
{
409
    // Write header
410
    _ostream << "OVM ASCII" << std::endl;
411

Max Lyon's avatar
Max Lyon committed
412
    uint64_t n_vertices(_mesh.n_vertices());
413 414
    _ostream << "Vertices" << std::endl;
    _ostream << n_vertices << std::endl;
415 416 417 418 419 420 421

    typedef typename MeshT::PointT Point;

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

        Point v = _mesh.vertex(*v_it);
422
        _ostream << v[0] << " " << v[1] << " " << v[2] << std::endl;
423 424
    }

Max Lyon's avatar
Max Lyon committed
425
    uint64_t n_edges(_mesh.n_edges());
426 427
    _ostream << "Edges" << std::endl;
    _ostream << n_edges << std::endl;
428 429 430 431 432 433

    // 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();
434
        _ostream << from_vertex << " " << to_vertex << std::endl;
435 436
    }

Max Lyon's avatar
Max Lyon committed
437
    uint64_t n_faces(_mesh.n_faces());
438 439
    _ostream << "Faces" << std::endl;
    _ostream << n_faces << std::endl;
440 441 442 443

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

444
        _ostream << static_cast<uint64_t>(_mesh.face(*f_it).halfedges().size()) << " ";
445 446 447 448

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

        for(typename std::vector<HalfEdgeHandle>::const_iterator it = halfedges.begin(); it
449
                                                                                         != halfedges.end(); ++it) {
450

451
            _ostream << it->idx();
452 453

            if((it + 1) != halfedges.end())
454
                _ostream << " ";
455 456
        }

457
        _ostream << std::endl;
458 459
    }

Max Lyon's avatar
Max Lyon committed
460
    uint64_t n_cells(_mesh.n_cells());
461 462
    _ostream << "Polyhedra" << std::endl;
    _ostream << n_cells << std::endl;
463 464 465

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

466
        _ostream << static_cast<uint64_t>(_mesh.cell(*c_it).halffaces().size()) << " ";
467 468 469 470

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

        for(typename std::vector<HalfFaceHandle>::const_iterator it = halffaces.begin(); it
471
                                                                                         != halffaces.end(); ++it) {
472

473
            _ostream << it->idx();
474 475

            if((it + 1) != halffaces.end())
476
                _ostream << " ";
477 478
        }

479
        _ostream << std::endl;
480 481
    }

482
    // write vertex props
483
    writeProps(_ostream, _mesh.vertex_props_begin(), _mesh.vertex_props_end());
484
    // write edge props
485
    writeProps(_ostream, _mesh.edge_props_begin(), _mesh.edge_props_end());
486
    // write halfedge props
487
    writeProps(_ostream, _mesh.halfedge_props_begin(), _mesh.halfedge_props_end());
488
    // write face props
489
    writeProps(_ostream, _mesh.face_props_begin(), _mesh.face_props_end());
490
    // write halfface props
491
    writeProps(_ostream, _mesh.halfface_props_begin(), _mesh.halfface_props_end());
492
    // write cell props
493
    writeProps(_ostream, _mesh.cell_props_begin(), _mesh.cell_props_end());
494
    // write mesh props
495 496
    writeProps(_ostream, _mesh.mesh_props_begin(), _mesh.mesh_props_end());
}
497

498 499
template<class MeshT>
bool FileManager::writeFile(const std::string& _filename, const MeshT& _mesh) const {
500

501 502 503 504 505 506 507 508
    std::ofstream off(_filename.c_str(), std::ios::out);

    if(!off.good()) {
        std::cerr << "Error: Could not open file " << _filename << " for writing!" << std::endl;
        return false;
    }
    writeStream(off, _mesh);
    return off.good();
509 510 511 512
}

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

513 514 515 516 517 518 519 520 521 522 523
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()) {
            std::cerr << "Serialization of anonymous properties is not supported!" << std::endl;
            continue;
        }
524

525 526 527 528 529 530 531
        std::string type_name;
        try {
            type_name = (*p_it)->typeNameWrapper();
        } catch (std::runtime_error &e) { // type not serializable
            std::cerr << "Failed to save property, skipping: " << e.what() << std::endl;
            continue;
        }
532
        _ostr << (*p_it)->entityType() << " ";
533
        _ostr << type_name << " ";
534 535
        _ostr << "\"" << (*p_it)->name() << "\"" << std::endl;

536 537 538 539 540 541
        (*p_it)->serialize(_ostr);
    }
}

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

542 543 544
} // Namespace IO

} // Namespace FileManager