summaryrefslogtreecommitdiff
path: root/src/common/include
diff options
context:
space:
mode:
authorvrouvrea <vrouvrea@636b058d-ea47-450e-bf9e-a15bfbe3eedb>2014-12-05 13:32:54 +0000
committervrouvrea <vrouvrea@636b058d-ea47-450e-bf9e-a15bfbe3eedb>2014-12-05 13:32:54 +0000
commit425b462d361286822ee0ed7b5fe00881ba312ea3 (patch)
treee8f641a8604418882b916573cf32c87b78d33472 /src/common/include
parent952b77f3b1e2415602d5d9ffc2fb7ff45cc3edc4 (diff)
Moved into trunk
git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/trunk@341 636b058d-ea47-450e-bf9e-a15bfbe3eedb
Diffstat (limited to 'src/common/include')
-rw-r--r--src/common/include/gudhi/Clock.h67
-rw-r--r--src/common/include/gudhi/Off_reader.h177
-rw-r--r--src/common/include/gudhi/Test.h85
-rw-r--r--src/common/include/gudhi/Utils.h34
-rw-r--r--src/common/include/gudhi/distance_functions.h37
-rw-r--r--src/common/include/gudhi/graph_simplicial_complex.h96
-rw-r--r--src/common/include/gudhi/iofile.h236
-rw-r--r--src/common/include/gudhi/reader_utils.h181
8 files changed, 913 insertions, 0 deletions
diff --git a/src/common/include/gudhi/Clock.h b/src/common/include/gudhi/Clock.h
new file mode 100644
index 00000000..ea21659e
--- /dev/null
+++ b/src/common/include/gudhi/Clock.h
@@ -0,0 +1,67 @@
+/*
+ * Clock.h
+ *
+ * Created on: Jun 17, 2014
+ * Author: dsalinas
+ */
+
+#ifndef GUDHI_CLOCK_H_
+#define GUDHI_CLOCK_H_
+
+
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+class Clock{
+
+public:
+ Clock():end_called(false){
+ startTime = boost::posix_time::microsec_clock::local_time( );
+ }
+
+ Clock(const std::string& msg_){
+ end_called = false;
+ begin();
+ msg = msg_;
+ }
+
+
+ void begin() const{
+ end_called = false;
+ startTime = boost::posix_time::microsec_clock::local_time( );
+ }
+
+ void end() const{
+ end_called = true;
+ endTime = boost::posix_time::microsec_clock::local_time( );
+ }
+
+ void print() const{
+ std::cout << *this << std::endl;
+ }
+
+ friend std::ostream& operator<< (std::ostream& stream,const Clock& clock){
+ if(!clock.end_called)
+ clock.end();
+
+ if(!clock.end_called) stream << "end not called";
+ else{
+ stream << clock.msg <<":"<<clock.num_seconds() <<"s";
+ }
+ return stream;
+
+ }
+
+ double num_seconds() const{
+ if(!end_called) return -1;
+ return (endTime-startTime).total_milliseconds()/1000.;
+ }
+
+private:
+ mutable boost::posix_time::ptime startTime, endTime;
+ mutable bool end_called;
+ std::string msg;
+
+};
+
+
+#endif /* GUDHI_CLOCK_H_ */
diff --git a/src/common/include/gudhi/Off_reader.h b/src/common/include/gudhi/Off_reader.h
new file mode 100644
index 00000000..a9c64f97
--- /dev/null
+++ b/src/common/include/gudhi/Off_reader.h
@@ -0,0 +1,177 @@
+/*
+ * Off_reader.h
+ * Created on: Nov 28, 2014
+ * This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): David Salinas
+ *
+ * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#ifndef GUDHI_OFF_READER_H_
+#define GUDHI_OFF_READER_H_
+
+
+#include <sstream>
+#include <iostream>
+#include <iterator>
+
+
+namespace Gudhi {
+
+/**
+ * Read an off file and calls a visitor methods while reading it.
+ * An off file must have its first/snd line in this format :
+ * OFF
+ * num_vert num_faces num_edges
+ *
+ * A noff file must have its first/snd line in this format :
+ * nOFF
+ * dim num_vert num_faces num_edges
+ *
+ * The number of edges num_edges is optional and can be left to zero.
+ */
+class Off_reader{
+public:
+ Off_reader(std::ifstream& stream):stream_(stream){
+ }
+// Off_reader(const std::string& name):stream_(name){
+// if(!stream_.is_open())
+// std::cerr <<"could not open file \n";
+// }
+
+ ~Off_reader(){
+ stream_.close();
+ }
+
+ /**
+ * read an off file and calls the following methods :
+ * void init(int dim,int num_vertices,int num_faces,int num_edges); //num_edges may not be set
+ * void point(const std::vector<double>& point);
+ * void maximal_face(const std::list<int>& face);
+ * void done();
+ * of the visitor when reading a point or a maximal face.
+ */
+ 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) return false;
+
+ if(!goto_next_uncomment_line(line)) return false;
+ std::istringstream iss(line);
+ if(is_off_file){
+ off_info_.dim = 3;
+ if(!(iss >> off_info_.num_vertices >> off_info_.num_faces >> off_info_.num_edges))
+ return false;
+ }
+ else
+ if(!(iss >> off_info_.dim >> off_info_.num_vertices >> off_info_.num_faces >> off_info_.num_edges))
+ 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){
+ uncomment_line.clear();
+ do
+ std::getline(stream_, uncomment_line);
+ while(uncomment_line[0] == '%');
+ return (uncomment_line.size()>0 && uncomment_line[0] != '%');
+ }
+
+
+ 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_.num_vertices) return false;
+ visitor.maximal_face(face);
+ }
+ return true;
+ }
+};
+
+
+} // namespace Gudhi
+
+
+#endif /* GUDHI_OFF_READER_H_ */
diff --git a/src/common/include/gudhi/Test.h b/src/common/include/gudhi/Test.h
new file mode 100644
index 00000000..18b7ca82
--- /dev/null
+++ b/src/common/include/gudhi/Test.h
@@ -0,0 +1,85 @@
+#ifndef __TEST_H
+#define __TEST_H
+
+#include <list>
+#include <string>
+#include <vector>
+#include <sstream>
+#include <iostream>
+
+
+#define TEST(a) std::cout << "TEST: " << (a)<<std::endl
+#define TESTMSG(a,b) std::cout << "TEST: " << a<<b<<std::endl
+#define TESTVALUE(a) std::cout << "TEST: " << #a << ": " << a<<std::endl
+
+
+/**
+ * Class to perform test
+ */
+
+class Test
+{
+private :
+ std::string name;
+ bool (*test)();
+
+ std::string separation() const{
+ return "+++++++++++++++++++++++++++++++++++++++++++++++++\n";
+ }
+
+ std::string print_between_plus(std::string& s) const{
+ std::stringstream res;
+ res << "+++++++++++++++++"<<s<<"+++++++++++++++++\n";
+ return res.str();
+ }
+
+
+public:
+ Test(std::string name_,bool (*test_)()){
+ name=name_;
+ test =test_;
+ }
+
+ bool run(){
+ std::cout << print_between_plus(name);
+ return test();
+ }
+ std::string getName(){
+ return name;
+ }
+};
+
+
+class Tests
+{
+private:
+ std::list<Test> tests;
+
+public:
+ void add(std::string name_,bool (*test_)()){
+ Test test(name_,test_);
+ tests.push_back(test);
+ }
+ bool run(){
+ bool tests_succesful(true);
+ std::vector<bool> res;
+ for (Test test : tests){
+ res.push_back(test.run());
+ }
+ std::cout << "\n\n results of tests : "<<std::endl;
+ int i=0;
+ for (Test t : tests){
+ std::cout << "Test "<<i<< " \""<<t.getName()<<"\" --> ";
+ if (res[i++]) std::cout << "OK"<<std::endl;
+ else {
+ std::cout << "Fail"<<std::endl;
+ tests_succesful = false;
+ break;
+ }
+ }
+ return tests_succesful;
+
+ }
+};
+
+#endif
diff --git a/src/common/include/gudhi/Utils.h b/src/common/include/gudhi/Utils.h
new file mode 100644
index 00000000..cef361dc
--- /dev/null
+++ b/src/common/include/gudhi/Utils.h
@@ -0,0 +1,34 @@
+/*
+ * Utils.h
+ *
+ * Created on: 13 juin 2013
+ * Author: salinasd
+ */
+
+#ifndef GUDHI_UTILS_H_
+#define GUDHI_UTILS_H_
+
+
+#define PRINT(a) std::cerr << #a << ": " << (a) << " (DISP)"<<std::endl
+
+//#define DBG_VERBOSE
+#ifdef DBG_VERBOSE
+#define DBG(a) std::cerr << "DBG: " << (a)<<std::endl
+#define DBGMSG(a,b) std::cerr << "DBG: " << a<<b<<std::endl
+#define DBGVALUE(a) std::cerr << "DBG: " << #a << ": " << a<<std::endl
+#define DBGCONT(a) std::cerr << "DBG: container "<< #a<<" -> "; for(auto x:a) std::cerr<< x << ","; std::cerr<<std::endl
+#else
+//#define DBG(a) a
+//#define DBGMSG(a,b) b
+//#define DBGVALUE(a) a
+//#define DBGCONT(a) a
+#define DBG(a)
+#define DBGMSG(a,b)
+#define DBGVALUE(a)
+#define DBGCONT(a)
+#endif
+
+
+
+
+#endif /* UTILS_H_ */
diff --git a/src/common/include/gudhi/distance_functions.h b/src/common/include/gudhi/distance_functions.h
new file mode 100644
index 00000000..7a2ab035
--- /dev/null
+++ b/src/common/include/gudhi/distance_functions.h
@@ -0,0 +1,37 @@
+ /* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Clément Maria
+ *
+ * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Compute the Euclidean distance between two Points given
+ * by a range of coordinates. The points are assumed to have
+ * the same dimension. */
+template< typename Point >
+double euclidean_distance( Point &p1, Point &p2)
+{
+ double dist = 0.;
+ auto it1 = p1.begin(); auto it2 = p2.begin();
+ for(; it1 != p1.end(); ++it1, ++it2)
+ {
+ double tmp = *it1 - *it2;
+ dist += tmp*tmp;
+ }
+ return sqrt(dist);
+}
diff --git a/src/common/include/gudhi/graph_simplicial_complex.h b/src/common/include/gudhi/graph_simplicial_complex.h
new file mode 100644
index 00000000..e7a8cfe9
--- /dev/null
+++ b/src/common/include/gudhi/graph_simplicial_complex.h
@@ -0,0 +1,96 @@
+ /* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Clément Maria
+ *
+ * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUDHI_GRAPH_SIMPLICIAL_COMPLEX_FILTRATION_TAG_H
+#define GUDHI_GRAPH_SIMPLICIAL_COMPLEX_FILTRATION_TAG_H
+
+#include <boost/graph/adjacency_list.hpp>
+
+/* Edge tag for Boost PropertyGraph. */
+struct edge_filtration_t {
+ typedef boost::edge_property_tag kind;
+};
+/* Vertex tag for Boost PropertyGraph. */
+struct vertex_filtration_t {
+ typedef boost::vertex_property_tag kind;
+};
+
+typedef int Vertex_handle;
+typedef double Filtration_value;
+typedef boost::adjacency_list < boost::vecS, boost::vecS, boost::undirectedS
+ , boost::property < vertex_filtration_t, Filtration_value >
+ , boost::property < edge_filtration_t, Filtration_value >
+ > Graph_t;
+typedef std::pair< Vertex_handle, Vertex_handle > Edge_t;
+
+/** \brief Output the proximity graph of the points.
+ *
+ * If points contains n elements, the proximity graph is the graph
+ * with n vertices, and an edge [u,v] iff the distance function between
+ * points u and v is smaller than threshold.
+ *
+ * The type PointCloud furnishes .begin() and .end() methods, that return
+ * iterators with value_type Point.
+ */
+template< typename PointCloud
+ , typename Point >
+Graph_t compute_proximity_graph( PointCloud &points
+ , Filtration_value threshold
+ , Filtration_value distance(Point p1, Point p2) )
+{
+ std::vector< Edge_t > edges;
+ std::vector< Filtration_value > edges_fil;
+ std::map< Vertex_handle, Filtration_value > vertices;
+
+ Vertex_handle idx_u, idx_v;
+ Filtration_value fil;
+ idx_u = 0;
+ for(auto it_u = points.begin(); it_u != points.end(); ++it_u)
+ {
+ idx_v = idx_u+1;
+ for(auto it_v = it_u+1; it_v != points.end(); ++it_v, ++idx_v)
+ {
+ fil = distance(*it_u,*it_v);
+ if(fil <= threshold) {
+ edges.emplace_back(idx_u,idx_v);
+ edges_fil.push_back(fil);
+ }
+ }
+ ++idx_u;
+ }
+
+ Graph_t skel_graph( edges.begin()
+ , edges.end()
+ , edges_fil.begin()
+ , idx_u); //number of points labeled from 0 to idx_u-1
+
+ auto vertex_prop = boost::get(vertex_filtration_t(),skel_graph);
+
+ boost::graph_traits<Graph_t>::vertex_iterator vi, vi_end;
+ for ( tie(vi, vi_end) = boost::vertices(skel_graph);
+ vi != vi_end; ++vi )
+ { boost::put(vertex_prop, *vi, 0.); }
+
+ return skel_graph;
+}
+
+#endif // GUDHI_GRAPH_SIMPLICIAL_COMPLEX_FILTRATION_TAG_H
diff --git a/src/common/include/gudhi/iofile.h b/src/common/include/gudhi/iofile.h
new file mode 100644
index 00000000..b939d45b
--- /dev/null
+++ b/src/common/include/gudhi/iofile.h
@@ -0,0 +1,236 @@
+//todo remove and use off_reader instead
+
+#ifndef GUDHI_IOFILE_H_
+#define GUDHI_IOFILE_H_
+
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <vector>
+#include <cstdio>
+#include <cstring>
+#include <list>
+#include <cassert>
+
+
+
+//todo use my new visitor based off instead
+/**
+ * @brief OFF reader, save the content of the file (vertices and maximal faces) in 'complex'.
+ * The class Complex has to handle the following operations:
+ * - void add_vertex(double[dim],int dim)
+ * - void add_face(int dimension ,int[dimension] vertices)
+ * Source from : http://www.holmes3d.net/graphics/offfiles/OFFLoading.txt
+ *
+ * @todo todo ignore comments in the file -> # comment
+ */
+template<typename Complex> inline
+bool general_read_off_file(const std::string & file_name, Complex& complex){
+ // Declare temporary variables to read data into.
+ // If the read goes well, we'll copy these into
+ // our class variables, overwriting what used to
+ // be there. If it doesn't, we won't have messed up
+ // our previous data structures.
+ int tempNumPoints = 0; // Number of x,y,z coordinate triples
+ int tempNumFaces = 0; // Number of polygon sets
+ int tempNumEdges = 0; // Unused, except for reading.
+ int tempDimPoints = 0;
+ double** tempPoints = NULL; // An array of x,y,z coordinates.
+ int** tempFaces = NULL; // An array of arrays of point
+ // pointers. Each entry in this
+ // is an array of integers. Each
+ // integer in that array is the
+ // index of the x, y, and z
+ // coordinates in the corresponding
+ // arrays.
+ int* tempFaceSizes = NULL; // An array of polygon point counts.
+ // Each of the arrays in the tempFaces
+ // array may be of different lengths.
+ // This array corresponds to that
+ // array, and gives their lengths.
+ int i; // Generic loop variable.
+ bool goodLoad = true; // Set to false if the file appears
+ // not to be a valid OFF file.
+ char tempBuf[128]; // A buffer for reading strings
+ // from the file.
+
+ // Create an input file stream for the file the CArchive
+ // is connected to. This allows use of the overloaded
+ // extraction operator for conversion from string
+ // data to doubles and ints.
+ std::ifstream ifs (file_name.c_str(), std::ios::in);
+ if(!ifs.is_open()) {
+ std::cerr << "Unable to open file " << file_name << std::endl;
+ return false;
+ }
+
+ // Grab the first string. If it's "OFF", we think this
+ // is an OFF file and continue. Otherwise we give up.
+ ifs >> tempBuf;
+ if (strcmp(tempBuf, "OFF") != 0) {
+ goodLoad = false;
+ std::cerr << "No OFF preambule\n";
+ }
+
+ // Read the sizes for our two arrays, and the third
+ // int on the line. If the important two are zero
+ // sized, this is a messed up OFF file. Otherwise,
+ // we setup our temporary arrays.
+ if (goodLoad) {
+ ifs >> tempNumPoints >> tempNumFaces >> tempNumEdges;
+ if (tempNumPoints < 1 || tempNumFaces < 0) {
+ // If either of these were negative, we make
+ // sure that both are set to zero. This is
+ // important for later deleting our temporary
+ // storage.
+ goodLoad = false;
+ std::cerr << "tempNumPoints < 1 || tempNumFaces < 0\n";
+ tempNumPoints = 0;
+ tempNumFaces = 0;
+ } else {
+ tempPoints = new double*[tempNumPoints];
+ tempFaces = new int*[tempNumFaces];
+ tempFaceSizes = new int[tempNumFaces];
+ }
+ }
+
+ if (goodLoad) {
+ // Load all of the points.
+
+ // we start by loading the first one
+ // the case is difference because then we dont know the dimension by advance
+ // we discover the point dimension by reading the first line
+ std::string lineFirstPoint;
+ std::getline(ifs, lineFirstPoint);
+ while(lineFirstPoint.size()<3){
+ std::getline(ifs, lineFirstPoint);
+ }
+
+ // we store the first point in a temporary list
+ std::istringstream lineFirstPointStream(lineFirstPoint);
+ std::list<double> firstTempPoint;
+ double coord;
+ while(lineFirstPointStream>>coord){
+ firstTempPoint.push_back(coord);
+ ++tempDimPoints;
+ }
+ // we store the point in our points array
+ tempPoints[0]=new double[tempDimPoints];
+ for( int j = 0 ; j<tempDimPoints; ++j){
+ tempPoints[0][j] = firstTempPoint.front();
+ firstTempPoint.pop_front();
+ }
+
+ // now, we know the dimension and can read safely other points
+ for (i = 1; i < tempNumPoints; i++) {
+ tempPoints[i] = new double[tempDimPoints];
+ for (int j = 0 ; j<tempDimPoints ; ++j){
+ ifs>>tempPoints[i][j];
+ }
+ }
+
+ // Load all of the faces.
+ for (i = 0; i < tempNumFaces; i++) {
+ // This tells us how many points make up
+ // this face.
+ ifs >> tempFaceSizes[i];
+ // So we declare a new array of that size
+ tempFaces[i] = new int[tempFaceSizes[i]];
+ // And load its elements with the vertex indices.
+ for (int j = 0; j < tempFaceSizes[i]; j++) {
+ ifs >> tempFaces[i][j];
+ }
+ // Clear out any face color data by reading up to
+ // the newline. 128 is probably considerably more
+ // space than necessary, but better safe than
+ // sorry.
+ ifs.getline(tempBuf, 128);
+ }
+ }
+
+ // Here is where we copy the data from the temp
+ // structures into our permanent structures. We
+ // probably will do some more processing on the
+ // data at the same time. This code you must fill
+ // in on your own.
+ if (goodLoad) {
+ // we save vertices first in the complex
+ for (i = 0; i < tempNumPoints; i++)
+ complex.add_vertex(tempPoints[i],tempDimPoints);
+
+ // we save faces
+ for (i = 0; i < tempNumFaces; i++) {
+ for (int j = 0; j < tempFaceSizes[i]; j++)
+ complex.add_face(tempFaceSizes[i],tempFaces[i]);
+ }
+ }
+
+ // Now that we're done, we have to make sure we
+ // free our dynamic memory.
+ for (i = 0; i < tempNumPoints; i++) {
+ delete []tempPoints[i];
+ }
+ delete []tempPoints;
+
+ for (i = 0; i < tempNumFaces; i++) {
+ delete tempFaces[i];
+ }
+ delete []tempFaces;
+ delete []tempFaceSizes;
+
+ // Clean up our ifstream. The MFC framework will
+ // take care of the CArchive.
+ ifs.close();
+
+ return goodLoad;
+}
+
+
+template<typename Complex>
+class Geometric_flag_complex_wrapper{
+ Complex& complex_;
+ typedef typename Complex::Vertex_handle Vertex_handle;
+ typedef typename Complex::Point Point;
+
+ const bool load_only_points_;
+
+public:
+ Geometric_flag_complex_wrapper(Complex& complex,bool load_only_points = false):
+ complex_(complex),
+ load_only_points_(load_only_points)
+{}
+
+
+ void add_vertex(double* xyz,int dim){
+ Point p(dim);
+ for(int i=0;i<dim;++i)
+ p[i] = xyz[i];
+ complex_.add_vertex(p);
+ }
+
+ void add_face(int dimension ,int* vertices){
+ if (!load_only_points_){
+ for (int i = 0; i<dimension ; ++i)
+ for (int j = i+1; j<dimension ; ++j)
+ complex_.add_edge(Vertex_handle(vertices[i]),Vertex_handle(vertices[j]));
+ }
+ }
+};
+
+
+
+
+/**
+ * @brief Read a mesh into a OFF file
+ * load_only_points should be true if only the points have to be loaded.
+ */
+template<typename Complex>
+bool read_off_file(std::string file_name,Complex &complex,bool load_only_points = false){
+ complex.clear();
+ Geometric_flag_complex_wrapper<Complex> complex_wrapper(complex,load_only_points);
+ return general_read_off_file(file_name,complex_wrapper);
+
+}
+
+
+#endif
diff --git a/src/common/include/gudhi/reader_utils.h b/src/common/include/gudhi/reader_utils.h
new file mode 100644
index 00000000..5c8cbeb7
--- /dev/null
+++ b/src/common/include/gudhi/reader_utils.h
@@ -0,0 +1,181 @@
+ /* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Clément Maria
+ *
+ * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUDHI_READER_UTILS_H
+#define GUDHI_READER_UTILS_H
+
+#include <iostream>
+#include <fstream>
+#include <boost/graph/adjacency_list.hpp>
+#include "gudhi/graph_simplicial_complex.h"
+
+/**
+ * \brief Read a set of points to turn it
+ * into a vector< vector<double> > by filling points
+ *
+ * File format: 1 point per line
+ * X11 X12 ... X1d
+ * X21 X22 ... X2d
+ * etc
+ */
+inline void
+read_points ( std::string file_name
+ , std::vector< std::vector< double > > & points)
+{
+ std::ifstream in_file (file_name.c_str(),std::ios::in);
+ if(!in_file.is_open()) {
+ std::cerr << "Unable to open file " << file_name << std::endl;
+ return;}
+
+ std::string line;
+ double x;
+ while( getline ( in_file , line ) )
+ {
+ std::vector< double > point;
+ std::istringstream iss( line );
+ while(iss >> x) { point.push_back(x); }
+ points.push_back(point);
+ }
+ in_file.close();
+}
+
+/**
+ * \brief Read a graph from a file.
+ *
+ * File format: 1 simplex per line
+ * Dim1 X11 X12 ... X1d Fil1
+ * Dim2 X21 X22 ... X2d Fil2
+ * etc
+ *
+ * The vertices must be labeled from 0 to n-1.
+ * Every simplex must appear exactly once.
+ * Simplices of dimension more than 1 are ignored.
+ */
+inline Graph_t
+read_graph ( std::string file_name )
+{
+ std::ifstream in_ (file_name.c_str(),std::ios::in);
+ if(!in_.is_open()) { std::cerr << "Unable to open file " << file_name << std::endl; }
+
+ std::vector< Edge_t > edges;
+ std::vector< Filtration_value > edges_fil;
+ std::map< Vertex_handle, Filtration_value > vertices;
+
+ std::string line;
+ int dim;
+ Vertex_handle u,v,max_h = -1;
+ Filtration_value fil;
+ while( getline ( in_ , line ) )
+ {
+ std::istringstream iss( line );
+ while(iss >> dim) {
+ switch ( dim ) {
+ case 0 : {
+ iss >> u; iss >> fil;
+ vertices[u] = fil;
+ if(max_h < u) { max_h = u; }
+ break;
+ }
+ case 1 : {
+ iss >> u; iss >> v; iss >> fil;
+ edges.push_back(Edge_t(u,v));
+ edges_fil.push_back(fil);
+ break;
+ }
+ default: {break;}
+ }
+ }
+ }
+ in_.close();
+
+ if((size_t)(max_h+1) != vertices.size())
+ { std::cerr << "Error: vertices must be labeled from 0 to n-1 \n"; }
+
+ Graph_t skel_graph(edges.begin(),edges.end(),edges_fil.begin(),vertices.size());
+ auto vertex_prop = boost::get(vertex_filtration_t(),skel_graph);
+
+ boost::graph_traits<Graph_t>::vertex_iterator vi, vi_end;
+ auto v_it = vertices.begin();
+ for (tie(vi, vi_end) = boost::vertices(skel_graph); vi != vi_end; ++vi,++v_it)
+ { boost::put(vertex_prop, *vi, v_it->second); }
+
+ return skel_graph;
+}
+
+/**
+ * \brief Read a face from a file.
+ *
+ * File format: 1 simplex per line
+ * Dim1 X11 X12 ... X1d Fil1
+ * Dim2 X21 X22 ... X2d Fil2
+ * etc
+ *
+ * The vertices must be labeled from 0 to n-1.
+ * Every simplex must appear exactly once.
+ * Simplices of dimension more than 1 are ignored.
+ */
+template< typename Vertex_handle
+ , typename Filtration_value >
+bool read_simplex ( std::istream & in_
+ , std::vector< Vertex_handle > & simplex
+ , Filtration_value & fil )
+{
+ int dim=0;
+ if(!(in_ >> dim)) return false;
+ Vertex_handle v;
+ for(int i=0; i<dim+1; ++i)
+ { in_ >> v; simplex.push_back(v); }
+ in_ >> fil;
+ in_.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // ignore until the carriage return
+ return true;
+}
+
+/**
+ * \brief Read a hasse simplex from a file.
+ *
+ * File format: 1 simplex per line
+ * Dim1 k11 k12 ... k1Dim1 Fil1
+ * Dim2 k21 k22 ... k2Dim2 Fil2
+ * etc
+ *
+ * The key of a simplex is its position in the filtration order
+ * and also the number of its row in the file.
+ * Dimi ki1 ki2 ... kiDimi Fili means that the ith simplex in the
+ * filtration has dimension Dimi, filtration value fil1 and simplices with
+ * key ki1 ... kiDimi in its boundary.*/
+template< typename Simplex_key
+ , typename Filtration_value >
+bool read_hasse_simplex ( std::istream & in_
+ , std::vector< Simplex_key > & boundary
+ , Filtration_value & fil )
+{
+ int dim;
+ if(!(in_ >> dim)) return false;
+ if(dim == 0) {in_ >> fil; return true;}
+ Simplex_key key;
+ for(int i=0; i<dim+1; ++i)
+ { in_ >> key; boundary.push_back(key); }
+ in_ >> fil;
+ return true;
+}
+
+#endif // GUDHI_READER_UTILS_H