summaryrefslogtreecommitdiff
path: root/src/common/include/gudhi/Off_reader.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/include/gudhi/Off_reader.h')
-rw-r--r--src/common/include/gudhi/Off_reader.h173
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_