diff options
Diffstat (limited to 'src/common/include/gudhi/Off_reader.h')
-rw-r--r-- | src/common/include/gudhi/Off_reader.h | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/src/common/include/gudhi/Off_reader.h b/src/common/include/gudhi/Off_reader.h new file mode 100644 index 00000000..aaff95b8 --- /dev/null +++ b/src/common/include/gudhi/Off_reader.h @@ -0,0 +1,173 @@ +/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. + * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. + * Author(s): David Salinas + * + * Copyright (C) 2014 Inria + * + * Modification(s): + * - YYYY/MM Author: Description of the modification + */ + + +#ifndef OFF_READER_H_ +#define OFF_READER_H_ + + +#include <sstream> +#include <iostream> +#include <iterator> +#include <string> +#include <vector> +#include <fstream> + +namespace Gudhi { + +/** \brief OFF file reader top class visitor. + * + * OFF file must be conform to \ref FileFormatsOFF + */ +class Off_reader { + public: + Off_reader(std::ifstream& stream) : stream_(stream) { } + + ~Off_reader() { + stream_.close(); + } + + /** \brief + * Read an OFF file and calls the following methods : + * + * <CODE>void init(int dim,int num_vertices,int num_faces,int num_edges); // from file header - num_edges may not be set + * + * void point(const std::vector<double>& point); // for each point read + * + * void maximal_face(const std::list<int>& face); // for each face read + * + * void done(); // upon file read is finished</CODE> + * + * of the visitor when reading a point or a maximal face. Edges are not taken into account. + */ + template<typename OffVisitor> + bool read(OffVisitor& off_visitor) { + bool success_read_off_preambule = read_off_preambule(off_visitor); + if (!success_read_off_preambule) { + std::cerr << "could not read off preambule\n"; + return false; + } + + bool success_read_off_points = read_off_points(off_visitor); + if (!success_read_off_points) { + std::cerr << "could not read off points\n"; + return false; + } + + bool success_read_off_faces = read_off_faces(off_visitor); + if (!success_read_off_faces) { + std::cerr << "could not read off faces\n"; + return false; + } + + off_visitor.done(); + return success_read_off_preambule && success_read_off_points && success_read_off_faces; + } + + private: + std::ifstream& stream_; + + struct Off_info { + int dim; + int num_vertices; + int num_edges; + int num_faces; + }; + + Off_info off_info_; + + template<typename OffVisitor> + bool read_off_preambule(OffVisitor& off_visitor) { + std::string line; + if (!goto_next_uncomment_line(line)) return false; + + bool is_off_file = (line.find("OFF") != std::string::npos); + bool is_noff_file = (line.find("nOFF") != std::string::npos); + + + + if (!is_off_file && !is_noff_file) { + std::cerr << line << std::endl; + std::cerr << "missing off header\n"; + return false; + } + + if (is_noff_file) { + // Should be on a separate line, but we accept it on the same line as the number of vertices + stream_ >> off_info_.dim; + } else { + off_info_.dim = 3; + } + + if (!goto_next_uncomment_line(line)) return false; + std::istringstream iss(line); + if (!(iss >> off_info_.num_vertices >> off_info_.num_faces >> off_info_.num_edges)) { + std::cerr << "incorrect number of vertices/faces/edges\n"; + return false; + } + off_visitor.init(off_info_.dim, off_info_.num_vertices, off_info_.num_faces, off_info_.num_edges); + + return true; + } + + bool goto_next_uncomment_line(std::string& uncomment_line) { + do { + // skip whitespace, including empty lines + if (!std::ifstream::sentry(stream_)) return false; + std::getline(stream_, uncomment_line); + } while (uncomment_line[0] == '#'); + return static_cast<bool>(stream_); + } + + template<typename OffVisitor> + bool read_off_points(OffVisitor& visitor) { + int num_vertices_to_read = off_info_.num_vertices; + while (num_vertices_to_read--) { + std::string line; + if (!goto_next_uncomment_line(line)) return false; + std::vector<double> point; + std::istringstream iss(line); + point.assign(std::istream_iterator<double>(iss), std::istream_iterator<double>()); + // if(point.size() != off_info_.dim) return false; + visitor.point(point); + } + return true; + } + + template<typename OffVisitor> + bool read_off_faces(OffVisitor& visitor) { + std::string line; + while (goto_next_uncomment_line(line)) { + std::istringstream iss(line); + int num_face_vertices; + iss >> num_face_vertices; + std::vector<int> face; + face.assign(std::istream_iterator<int>(iss), std::istream_iterator<int>()); + // if (face.size() != (off_info_.dim + 1)) return false; + visitor.maximal_face(face); + } + return true; + } +}; + +template<typename OFFVisitor> +void read_off(const std::string& name_file_off, OFFVisitor& vis) { + std::ifstream stream(name_file_off); + if (!stream.is_open()) { + std::cerr << "could not open file \n"; + } else { + Off_reader off_reader(stream); + off_reader.read(vis); + } +} + +} // namespace Gudhi + +#endif // OFF_READER_H_ |