diff options
Diffstat (limited to 'src/common/include/gudhi')
-rw-r--r-- | src/common/include/gudhi/Clock.h | 48 | ||||
-rw-r--r-- | src/common/include/gudhi/Debug_utils.h (renamed from src/common/include/gudhi/Utils.h) | 43 | ||||
-rw-r--r-- | src/common/include/gudhi/Off_reader.h | 49 | ||||
-rw-r--r-- | src/common/include/gudhi/Points_3D_off_io.h | 202 | ||||
-rw-r--r-- | src/common/include/gudhi/Points_off_io.h | 183 | ||||
-rw-r--r-- | src/common/include/gudhi/Test.h | 105 | ||||
-rw-r--r-- | src/common/include/gudhi/allocator.h | 55 | ||||
-rw-r--r-- | src/common/include/gudhi/console_color.h | 97 | ||||
-rw-r--r-- | src/common/include/gudhi/distance_functions.h | 4 | ||||
-rw-r--r-- | src/common/include/gudhi/random_point_generators.h | 477 | ||||
-rw-r--r-- | src/common/include/gudhi/reader_utils.h | 6 |
11 files changed, 1099 insertions, 170 deletions
diff --git a/src/common/include/gudhi/Clock.h b/src/common/include/gudhi/Clock.h index 04c6ffb9..77f196ca 100644 --- a/src/common/include/gudhi/Clock.h +++ b/src/common/include/gudhi/Clock.h @@ -27,47 +27,55 @@ #include <string> +namespace Gudhi { + 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_; - } + // Construct and start the timer + Clock(const std::string& msg_ = std::string()) + : startTime(boost::posix_time::microsec_clock::local_time()), + end_called(false), + msg(msg_) { } + // Restart the timer void begin() const { end_called = false; startTime = boost::posix_time::microsec_clock::local_time(); } + // Stop the timer void end() const { end_called = true; endTime = boost::posix_time::microsec_clock::local_time(); } + std::string message() const { + return msg; + } + + // Print current value to std::cout 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.msg.empty()) + stream << clock.msg << ": "; - if (!clock.end_called) { - stream << "end not called"; - } else { - stream << clock.msg << ":" << clock.num_seconds() << "s"; - } + stream << clock.num_seconds() << "s"; return stream; } + // Get the number of seconds between the timer start and: + // - the last call of end() if it was called + // - or now otherwise. In this case, the timer is not stopped. double num_seconds() const { - if (!end_called) return -1; - return (endTime - startTime).total_milliseconds() / 1000.; + if (!end_called) { + auto end = boost::posix_time::microsec_clock::local_time(); + return (end - startTime).total_milliseconds() / 1000.; + } else { + return (endTime - startTime).total_milliseconds() / 1000.; + } } private: @@ -76,4 +84,6 @@ class Clock { std::string msg; }; -#endif // CLOCK_H_ +} // namespace Gudhi + +#endif // CLOCK_H_ diff --git a/src/common/include/gudhi/Utils.h b/src/common/include/gudhi/Debug_utils.h index 43916f11..8ed3b7b3 100644 --- a/src/common/include/gudhi/Utils.h +++ b/src/common/include/gudhi/Debug_utils.h @@ -19,28 +19,39 @@ * 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 UTILS_H_ -#define UTILS_H_ +#ifndef DEBUG_UTILS_H_ +#define DEBUG_UTILS_H_ +#include <iostream> + +#ifndef NDEBUG + // GUDHI_DEBUG is the Gudhi official flag for debug mode. + #define GUDHI_DEBUG +#endif + +// GUDHI_CHECK throw an exception if expression is false in debug mode, but does nothing in release mode +// Could assert in release mode, but cmake sets NDEBUG (for "NO DEBUG") in this mode, means assert does nothing. +#ifdef GUDHI_DEBUG + #define GUDHI_CHECK(expression, excpt) if ((expression) == 0) throw excpt + #define GUDHI_CHECK_code(CODE) CODE +#else + #define GUDHI_CHECK(expression, excpt) (void) 0 + #define GUDHI_CHECK_code(CODE) +#endif #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 + #define DBG(a) std::cout << "DBG: " << (a) << std::endl + #define DBGMSG(a, b) std::cout << "DBG: " << a << b << std::endl + #define DBGVALUE(a) std::cout << "DBG: " << #a << ": " << a << std::endl + #define DBGCONT(a) std::cout << "DBG: container " << #a << " -> "; for (auto x : a) std::cout << x << ","; std::cout << 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) + #define DBG(a) (void) 0 + #define DBGMSG(a, b) (void) 0 + #define DBGVALUE(a) (void) 0 + #define DBGCONT(a) (void) 0 #endif -#endif // UTILS_H_ +#endif // DEBUG_UTILS_H_ diff --git a/src/common/include/gudhi/Off_reader.h b/src/common/include/gudhi/Off_reader.h index 81b9e634..4fcd2af2 100644 --- a/src/common/include/gudhi/Off_reader.h +++ b/src/common/include/gudhi/Off_reader.h @@ -31,40 +31,35 @@ #include <iterator> #include <string> #include <vector> +#include <fstream> 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. +/** \brief OFF file reader top class visitor. + * + * OFF file must be conform to format described here : + * http://www.geomview.org/docs/html/OFF.html */ 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. + /** \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) { @@ -118,7 +113,7 @@ class Off_reader { if (!goto_next_uncomment_line(line)) return false; std::istringstream iss(line); - if (is_off_file) { + if ((is_off_file) && (!is_noff_file)) { off_info_.dim = 3; if (!(iss >> off_info_.num_vertices >> off_info_.num_faces >> off_info_.num_edges)) { std::cerr << "incorrect number of vertices/faces/edges\n"; @@ -126,8 +121,8 @@ class Off_reader { } } else { if (!(iss >> off_info_.dim >> off_info_.num_vertices >> off_info_.num_faces >> off_info_.num_edges)) { - std::cerr << "incorrect number of vertices/faces/edges\n"; - return false; + 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); @@ -138,7 +133,7 @@ class Off_reader { bool goto_next_uncomment_line(std::string& uncomment_line) { uncomment_line.clear(); do - std::getline(stream_, uncomment_line); while (uncomment_line[0] == '%'); // || uncomment_line.empty()); + std::getline(stream_, uncomment_line); while (uncomment_line[0] == '%'); return (uncomment_line.size() > 0 && uncomment_line[0] != '%'); } @@ -166,7 +161,7 @@ class Off_reader { 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) return false; + // if (face.size() != (off_info_.dim + 1)) return false; visitor.maximal_face(face); } return true; diff --git a/src/common/include/gudhi/Points_3D_off_io.h b/src/common/include/gudhi/Points_3D_off_io.h new file mode 100644 index 00000000..b0d24998 --- /dev/null +++ b/src/common/include/gudhi/Points_3D_off_io.h @@ -0,0 +1,202 @@ +/* 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): Vincent Rouvreau + * + * Copyright (C) 2015 INRIA Saclay (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 POINTS_3D_OFF_IO_H_ +#define POINTS_3D_OFF_IO_H_ + +#include <gudhi/Off_reader.h> + +#include <string> +#include <vector> +#include <fstream> +#include <map> + +namespace Gudhi { + +/** + * @brief OFF file visitor implementation according to Off_reader in order to read points from an OFF file. + */ +template<typename Point_3> +class Points_3D_off_visitor_reader { + private: + std::vector<Point_3> point_cloud_; + bool valid_; + + public: + /** @brief Off_reader visitor init implementation. + * + * The init parameters are set from OFF file header. + * Dimension value is required and the value must be 3. + * + * @param[in] dim space dimension of vertices. + * @param[in] num_vertices number of vertices in the OFF file (not used). + * @param[in] num_faces number of faces in the OFF file (not used). + * @param[in] num_edges number of edges in the OFF file (not used). + */ + void init(int dim, int num_vertices, int num_faces, int num_edges) { +#ifdef DEBUG_TRACES + std::cout << "Points_3D_off_visitor_reader::init - dim=" << dim << " - num_vertices=" << + num_vertices << " - num_faces=" << num_faces << " - num_edges=" << num_edges << std::endl; +#endif // DEBUG_TRACES + if (dim == 3) { + valid_ = true; + } else { + valid_ = false; + std::cerr << "Points_3D_off_reader::Points_3D_off_reader cannot read OFF files in dimension " << dim << "\n"; + } + + if (num_faces > 0) { + std::cerr << "Points_3D_off_visitor_reader::init faces are not taken into account from OFF file for Points.\n"; + } + if (num_edges > 0) { + std::cerr << "Points_3D_off_visitor_reader::init edges are not taken into account from OFF file for Points.\n"; + } + } + + /** @brief Off_reader visitor point implementation. + * + * The point function is called on each vertex line from OFF file. + * This function inserts the vertex in the vector of points. + * + * @param[in] point vector of vertex coordinates. + * + * @details + * Point_3 must have a constructor with the following form: + * + * @code template<class InputIterator > Point_3::Point_3(double x, double y, double z) @endcode + */ + void point(const std::vector<double>& point) { + if (valid_) { +#ifdef DEBUG_TRACES + std::cout << "Points_3D_off_visitor_reader::point "; + for (auto coordinate : point) { + std::cout << coordinate << " | "; + } + std::cout << std::endl; +#endif // DEBUG_TRACES + // Fill the point cloud + point_cloud_.push_back(Point_3(point[0], point[1], point[2])); + } + } + + // Off_reader visitor maximal_face implementation - Only points are read + + void maximal_face(const std::vector<int>& face) { } + + // Off_reader visitor done implementation - Only points are read + + void done() { } + + /** @brief Point cloud getter. + * + * @return The point cloud. + */ + const std::vector<Point_3>& get_point_cloud() const { + return point_cloud_; + } + + /** @brief Returns if the OFF file read operation was successful or not. + * + * @return OFF file read status. + */ + bool is_valid() const { + return valid_; + } +}; + +/** + * \@brief OFF file reader implementation in order to read dimension 3 points from an OFF file. + * + * @details + * This class is using the Points_3D_off_visitor_reader to visit the OFF file according to Off_reader. + * + * Point_3 must have a constructor with the following form: + * + * @code template<class InputIterator > Point_3::Point_3(double x, double y, double z) @endcode + * + * @section point3doffioexample Example + * + * This example loads points from an OFF file and builds a vector of CGAL points in dimension 3. + * Then, it is asked to display the points. + * + * @include common/example_CGAL_3D_points_off_reader.cpp + * + * When launching: + * + * @code $> ./cgal3Doffreader ../../data/points/tore3D_300.off + * @endcode + * + * the program output is: + * + * @include common/cgal3Doffreader_result.txt + */ +template<typename Point_3> +class Points_3D_off_reader { + public: + /** @brief Reads the OFF file and constructs a vector of points from the points + * that are in the OFF file. + * + * @param[in] name_file OFF file to read. + * + * @post Check with is_valid() function to see if read operation was successful. + */ + Points_3D_off_reader(const std::string& name_file) + : valid_(false) { + std::ifstream stream(name_file); + if (stream.is_open()) { + Off_reader off_reader(stream); + Points_3D_off_visitor_reader<Point_3> off_visitor; + valid_ = off_reader.read(off_visitor); + valid_ = valid_ && off_visitor.is_valid(); + if (valid_) { + point_cloud = off_visitor.get_point_cloud(); + } + } else { + std::cerr << "Points_3D_off_reader::Points_3D_off_reader could not open file " << name_file << "\n"; + } + } + + /** @brief Returns if the OFF file read operation was successful or not. + * + * @return OFF file read status. + */ + bool is_valid() const { + return valid_; + } + + /** @brief Point cloud getter. + * + * @return point_cloud. + */ + const std::vector<Point_3>& get_point_cloud() const { + return point_cloud; + } + + private: + /** @brief point_cloud.*/ + std::vector<Point_3> point_cloud; + /** @brief OFF file read status.*/ + bool valid_; +}; + +} // namespace Gudhi + +#endif // POINTS_3D_OFF_IO_H_ diff --git a/src/common/include/gudhi/Points_off_io.h b/src/common/include/gudhi/Points_off_io.h new file mode 100644 index 00000000..29af8a8a --- /dev/null +++ b/src/common/include/gudhi/Points_off_io.h @@ -0,0 +1,183 @@ +/* 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): Vincent Rouvreau + * + * Copyright (C) 2015 INRIA Saclay (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 POINTS_OFF_IO_H_ +#define POINTS_OFF_IO_H_ + +#include <gudhi/Off_reader.h> + +#include <string> +#include <vector> +#include <fstream> +#include <map> + +namespace Gudhi { + +/** + * \brief OFF file visitor implementation according to Off_reader in order to read points from an OFF file. + */ +template<typename Point_d> +class Points_off_visitor_reader { + private: + std::vector<Point_d> point_cloud; + + public: + /** \brief Off_reader visitor init implementation. + * + * The init parameters are set from OFF file header. + * Dimension value is required in order to construct a vector of points. + * + * @param[in] dim space dimension of vertices. + * @param[in] num_vertices number of vertices in the OFF file (not used). + * @param[in] num_faces number of faces in the OFF file (not used). + * @param[in] num_edges number of edges in the OFF file (not used). + */ + void init(int dim, int num_vertices, int num_faces, int num_edges) { +#ifdef DEBUG_TRACES + std::cout << "Points_off_visitor_reader::init - dim=" << dim << " - num_vertices=" << + num_vertices << " - num_faces=" << num_faces << " - num_edges=" << num_edges << std::endl; +#endif // DEBUG_TRACES + if (num_faces > 0) { + std::cerr << "Points_off_visitor_reader::init faces are not taken into account from OFF file for Points.\n"; + } + if (num_edges > 0) { + std::cerr << "Points_off_visitor_reader::init edges are not taken into account from OFF file for Points.\n"; + } + } + + /** @brief Off_reader visitor point implementation. + * + * The point function is called on each vertex line from OFF file. + * This function inserts the vertex in the vector of points. + * + * @param[in] point vector of vertex coordinates. + * + * @details + * Point_d must have a constructor with the following form: + * + * @code template<class InputIterator > Point_d::Point_d(InputIterator first, InputIterator last) @endcode + * + */ + void point(const std::vector<double>& point) { +#ifdef DEBUG_TRACES + std::cout << "Points_off_visitor_reader::point "; + for (auto coordinate : point) { + std::cout << coordinate << " | "; + } + std::cout << std::endl; +#endif // DEBUG_TRACES + // Fill the point cloud + point_cloud.push_back(Point_d(point.begin(), point.end())); + } + + // Off_reader visitor maximal_face implementation - Only points are read + void maximal_face(const std::vector<int>& face) { } + + // Off_reader visitor done implementation - Only points are read + void done() { } + + /** \brief Point cloud getter. + * + * @return point_cloud. + */ + const std::vector<Point_d>& get_point_cloud() const { + return point_cloud; + } +}; + +/** + * \brief OFF file reader implementation in order to read points from an OFF file. + * + * This class is using the Points_off_visitor_reader to visit the OFF file according to Off_reader. + * + * Point_d must have a constructor with the following form: + * + * \code template<class InputIterator > Point_d::Point_d(int d, InputIterator first, InputIterator last) \endcode + * + * where d is the point dimension. + * + * \section pointoffioexample Example + * + * This example loads points from an OFF file and builds a vector of points (vector of double). + * Then, it is asked to display the points. + * + * \include common/example_vector_double_points_off_reader.cpp + * + * When launching: + * + * \code $> ./vector_double_off_reader ../../data/points/alphacomplexdoc.off + * \endcode + * + * the program output is: + * + * \include common/cgaloffreader_result.txt + */ +template<typename Point_d> +class Points_off_reader { + public: + /** \brief Reads the OFF file and constructs a vector of points from the points + * that are in the OFF file. + * + * @param[in] name_file OFF file to read. + * + * \post Check with is_valid() function to see if read operation was successful. + */ + Points_off_reader(const std::string& name_file) + : valid_(false) { + std::ifstream stream(name_file); + if (stream.is_open()) { + Off_reader off_reader(stream); + Points_off_visitor_reader<Point_d> off_visitor; + valid_ = off_reader.read(off_visitor); + if (valid_) { + point_cloud = off_visitor.get_point_cloud(); + } + } else { + std::cerr << "Points_off_reader::Points_off_reader could not open file " << name_file << "\n"; + } + } + + /** \brief Returns if the OFF file read operation was successful or not. + * + * @return OFF file read status. + */ + bool is_valid() const { + return valid_; + } + + /** \brief Point cloud getter. + * + * @return point_cloud. + */ + const std::vector<Point_d>& get_point_cloud() const { + return point_cloud; + } + + private: + /** \brief point_cloud.*/ + std::vector<Point_d> point_cloud; + /** \brief OFF file read status.*/ + bool valid_; +}; + +} // namespace Gudhi + +#endif // POINTS_OFF_IO_H_ diff --git a/src/common/include/gudhi/Test.h b/src/common/include/gudhi/Test.h deleted file mode 100644 index 6024c822..00000000 --- a/src/common/include/gudhi/Test.h +++ /dev/null @@ -1,105 +0,0 @@ -/* 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-Mediterranee (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 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 // TEST_H_ diff --git a/src/common/include/gudhi/allocator.h b/src/common/include/gudhi/allocator.h new file mode 100644 index 00000000..4ede14e4 --- /dev/null +++ b/src/common/include/gudhi/allocator.h @@ -0,0 +1,55 @@ +/* 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): Marc Glisse + * + * Copyright (C) 2015 INRIA Saclay - Ile de 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 ALLOCATOR_H_ +#define ALLOCATOR_H_ + +#include <memory> +#include <utility> + +namespace Gudhi { + +/** \private + * An allocator that can be used to build an uninitialized vector. + */ +template <class T, class Base = std::allocator<T>> +struct no_init_allocator : Base { + typedef std::allocator_traits<Base> Base_traits; + template <class U> struct rebind { + typedef no_init_allocator<U, typename Base_traits::template rebind_alloc<U>> other; + }; + + // Inherit constructors. + using Base::Base; + + // Do nothing: that's the whole point! + template<class P> + void construct(P*) noexcept {} + + template<class P, class...U> void construct(P*p, U&&...u) { + Base_traits::construct(*(Base*)this, p, std::forward<U>(u)...); + } +}; + +} // namespace Gudhi + +#endif // ALLOCATOR_H_ diff --git a/src/common/include/gudhi/console_color.h b/src/common/include/gudhi/console_color.h new file mode 100644 index 00000000..c4671da3 --- /dev/null +++ b/src/common/include/gudhi/console_color.h @@ -0,0 +1,97 @@ +/* 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): Clement Jamin + * + * Copyright (C) 2016 INRIA Sophia-Antipolis (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 CONSOLE_COLOR_H_ +#define CONSOLE_COLOR_H_ + +#include <iostream> + +#if defined(WIN32) +#include <windows.h> +#endif + +inline std::ostream& blue(std::ostream &s) { +#if defined(WIN32) + HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleTextAttribute(hStdout, + FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY); +#else + s << "\x1b[0;34m"; +#endif + return s; +} + +inline std::ostream& red(std::ostream &s) { +#if defined(WIN32) + HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleTextAttribute(hStdout, FOREGROUND_RED | FOREGROUND_INTENSITY); +#else + s << "\x1b[0;31m"; +#endif + return s; +} + +inline std::ostream& green(std::ostream &s) { +#if defined(WIN32) + HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleTextAttribute(hStdout, FOREGROUND_GREEN | FOREGROUND_INTENSITY); +#else + s << "\x1b[0;32m"; +#endif + return s; +} + +inline std::ostream& yellow(std::ostream &s) { +#if defined(WIN32) + HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleTextAttribute(hStdout, + FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY); +#else + s << "\x1b[0;33m"; +#endif + return s; +} + +inline std::ostream& white(std::ostream &s) { +#if defined(WIN32) + HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleTextAttribute(hStdout, + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); +#else + s << "\x1b[0;37m"; +#endif + return s; +} + +inline std::ostream& black_on_white(std::ostream &s) { +#if defined(WIN32) + HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleTextAttribute(hStdout, + BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); +#else + s << "\x1b[0;33m"; +#endif + return s; +} + + +#endif // CONSOLE_COLOR_H_ diff --git a/src/common/include/gudhi/distance_functions.h b/src/common/include/gudhi/distance_functions.h index e5c79ded..cd518581 100644 --- a/src/common/include/gudhi/distance_functions.h +++ b/src/common/include/gudhi/distance_functions.h @@ -23,6 +23,8 @@ #ifndef DISTANCE_FUNCTIONS_H_ #define DISTANCE_FUNCTIONS_H_ +#include <cmath> // for std::sqrt + /* Compute the Euclidean distance between two Points given * by a range of coordinates. The points are assumed to have * the same dimension. */ @@ -35,7 +37,7 @@ double euclidean_distance(Point &p1, Point &p2) { double tmp = *it1 - *it2; dist += tmp*tmp; } - return sqrt(dist); + return std::sqrt(dist); } #endif // DISTANCE_FUNCTIONS_H_ diff --git a/src/common/include/gudhi/random_point_generators.h b/src/common/include/gudhi/random_point_generators.h new file mode 100644 index 00000000..3050b7ea --- /dev/null +++ b/src/common/include/gudhi/random_point_generators.h @@ -0,0 +1,477 @@ +/* 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): Clement Jamin + * + * Copyright (C) 2016 INRIA + * + * 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 RANDOM_POINT_GENERATORS_H_ +#define RANDOM_POINT_GENERATORS_H_ + +#include <CGAL/number_utils.h> +#include <CGAL/Random.h> +#include <CGAL/point_generators_d.h> + +#include <vector> // for vector<> + +namespace Gudhi { + +/////////////////////////////////////////////////////////////////////////////// +// Note: All these functions have been tested with the CGAL::Epick_d kernel +/////////////////////////////////////////////////////////////////////////////// + +// construct_point: dim 2 + +template <typename Kernel> +typename Kernel::Point_d construct_point(const Kernel &k, + typename Kernel::FT x1, typename Kernel::FT x2) { + typename Kernel::FT tab[2]; + tab[0] = x1; + tab[1] = x2; + return k.construct_point_d_object()(2, &tab[0], &tab[2]); +} + +// construct_point: dim 3 + +template <typename Kernel> +typename Kernel::Point_d construct_point(const Kernel &k, + typename Kernel::FT x1, typename Kernel::FT x2, typename Kernel::FT x3) { + typename Kernel::FT tab[3]; + tab[0] = x1; + tab[1] = x2; + tab[2] = x3; + return k.construct_point_d_object()(3, &tab[0], &tab[3]); +} + +// construct_point: dim 4 + +template <typename Kernel> +typename Kernel::Point_d construct_point(const Kernel &k, + typename Kernel::FT x1, typename Kernel::FT x2, typename Kernel::FT x3, + typename Kernel::FT x4) { + typename Kernel::FT tab[4]; + tab[0] = x1; + tab[1] = x2; + tab[2] = x3; + tab[3] = x4; + return k.construct_point_d_object()(4, &tab[0], &tab[4]); +} + +// construct_point: dim 5 + +template <typename Kernel> +typename Kernel::Point_d construct_point(const Kernel &k, + typename Kernel::FT x1, typename Kernel::FT x2, typename Kernel::FT x3, + typename Kernel::FT x4, typename Kernel::FT x5) { + typename Kernel::FT tab[5]; + tab[0] = x1; + tab[1] = x2; + tab[2] = x3; + tab[3] = x4; + tab[4] = x5; + return k.construct_point_d_object()(5, &tab[0], &tab[5]); +} + +// construct_point: dim 6 + +template <typename Kernel> +typename Kernel::Point_d construct_point(const Kernel &k, + typename Kernel::FT x1, typename Kernel::FT x2, typename Kernel::FT x3, + typename Kernel::FT x4, typename Kernel::FT x5, typename Kernel::FT x6) { + typename Kernel::FT tab[6]; + tab[0] = x1; + tab[1] = x2; + tab[2] = x3; + tab[3] = x4; + tab[4] = x5; + tab[5] = x6; + return k.construct_point_d_object()(6, &tab[0], &tab[6]); +} + +template <typename Kernel> +std::vector<typename Kernel::Point_d> generate_points_on_plane(std::size_t num_points, int intrinsic_dim, + int ambient_dim, + double coord_min = -5., double coord_max = 5.) { + typedef typename Kernel::Point_d Point; + typedef typename Kernel::FT FT; + Kernel k; + CGAL::Random rng; + std::vector<Point> points; + points.reserve(num_points); + for (std::size_t i = 0; i < num_points;) { + std::vector<FT> pt(ambient_dim, FT(0)); + for (int j = 0; j < intrinsic_dim; ++j) + pt[j] = rng.get_double(coord_min, coord_max); + + Point p = k.construct_point_d_object()(ambient_dim, pt.begin(), pt.end()); + points.push_back(p); + ++i; + } + return points; +} + +template <typename Kernel> +std::vector<typename Kernel::Point_d> generate_points_on_moment_curve(std::size_t num_points, int dim, + typename Kernel::FT min_x, + typename Kernel::FT max_x) { + typedef typename Kernel::Point_d Point; + typedef typename Kernel::FT FT; + Kernel k; + CGAL::Random rng; + std::vector<Point> points; + points.reserve(num_points); + for (std::size_t i = 0; i < num_points;) { + FT x = rng.get_double(min_x, max_x); + std::vector<FT> coords; + coords.reserve(dim); + for (int p = 1; p <= dim; ++p) + coords.push_back(std::pow(CGAL::to_double(x), p)); + Point p = k.construct_point_d_object()( + dim, coords.begin(), coords.end()); + points.push_back(p); + ++i; + } + return points; +} + + +// R = big radius, r = small radius +template <typename Kernel/*, typename TC_basis*/> +std::vector<typename Kernel::Point_d> generate_points_on_torus_3D(std::size_t num_points, double R, double r, + bool uniform = false) { + typedef typename Kernel::Point_d Point; + typedef typename Kernel::FT FT; + Kernel k; + CGAL::Random rng; + + // if uniform + std::size_t num_lines = (std::size_t)sqrt(num_points); + + std::vector<Point> points; + points.reserve(num_points); + for (std::size_t i = 0; i < num_points;) { + FT u, v; + if (uniform) { + std::size_t k1 = i / num_lines; + std::size_t k2 = i % num_lines; + u = 6.2832 * k1 / num_lines; + v = 6.2832 * k2 / num_lines; + } else { + u = rng.get_double(0, 6.2832); + v = rng.get_double(0, 6.2832); + } + Point p = construct_point(k, + (R + r * std::cos(u)) * std::cos(v), + (R + r * std::cos(u)) * std::sin(v), + r * std::sin(u)); + points.push_back(p); + ++i; + } + return points; +} + +// "Private" function used by generate_points_on_torus_d +template <typename Kernel, typename OutputIterator> +static void generate_uniform_points_on_torus_d(const Kernel &k, int dim, std::size_t num_slices, + OutputIterator out, + double radius_noise_percentage = 0., + std::vector<typename Kernel::FT> current_point = std::vector<typename Kernel::FT>()) { + CGAL::Random rng; + if (current_point.size() == 2 * dim) { + *out++ = k.construct_point_d_object()( + static_cast<int> (current_point.size()), + current_point.begin(), current_point.end()); + } else { + for (std::size_t slice_idx = 0; slice_idx < num_slices; ++slice_idx) { + double radius_noise_ratio = 1.; + if (radius_noise_percentage > 0.) { + radius_noise_ratio = rng.get_double( + (100. - radius_noise_percentage) / 100., + (100. + radius_noise_percentage) / 100.); + } + std::vector<typename Kernel::FT> cp2 = current_point; + double alpha = 6.2832 * slice_idx / num_slices; + cp2.push_back(radius_noise_ratio * std::cos(alpha)); + cp2.push_back(radius_noise_ratio * std::sin(alpha)); + generate_uniform_points_on_torus_d( + k, dim, num_slices, out, radius_noise_percentage, cp2); + } + } +} + +template <typename Kernel> +std::vector<typename Kernel::Point_d> generate_points_on_torus_d(std::size_t num_points, int dim, bool uniform = false, + double radius_noise_percentage = 0.) { + typedef typename Kernel::Point_d Point; + typedef typename Kernel::FT FT; + Kernel k; + CGAL::Random rng; + + std::vector<Point> points; + points.reserve(num_points); + if (uniform) { + std::size_t num_slices = (std::size_t)std::pow(num_points, 1. / dim); + generate_uniform_points_on_torus_d( + k, dim, num_slices, std::back_inserter(points), radius_noise_percentage); + } else { + for (std::size_t i = 0; i < num_points;) { + double radius_noise_ratio = 1.; + if (radius_noise_percentage > 0.) { + radius_noise_ratio = rng.get_double( + (100. - radius_noise_percentage) / 100., + (100. + radius_noise_percentage) / 100.); + } + std::vector<typename Kernel::FT> pt; + pt.reserve(dim * 2); + for (int curdim = 0; curdim < dim; ++curdim) { + FT alpha = rng.get_double(0, 6.2832); + pt.push_back(radius_noise_ratio * std::cos(alpha)); + pt.push_back(radius_noise_ratio * std::sin(alpha)); + } + + Point p = k.construct_point_d_object()(pt.begin(), pt.end()); + points.push_back(p); + ++i; + } + } + return points; +} + +template <typename Kernel> +std::vector<typename Kernel::Point_d> generate_points_on_sphere_d(std::size_t num_points, int dim, double radius, + double radius_noise_percentage = 0.) { + typedef typename Kernel::Point_d Point; + Kernel k; + CGAL::Random rng; + CGAL::Random_points_on_sphere_d<Point> generator(dim, radius); + std::vector<Point> points; + points.reserve(num_points); + for (std::size_t i = 0; i < num_points;) { + Point p = *generator++; + if (radius_noise_percentage > 0.) { + double radius_noise_ratio = rng.get_double( + (100. - radius_noise_percentage) / 100., + (100. + radius_noise_percentage) / 100.); + + typename Kernel::Point_to_vector_d k_pt_to_vec = + k.point_to_vector_d_object(); + typename Kernel::Vector_to_point_d k_vec_to_pt = + k.vector_to_point_d_object(); + typename Kernel::Scaled_vector_d k_scaled_vec = + k.scaled_vector_d_object(); + p = k_vec_to_pt(k_scaled_vec(k_pt_to_vec(p), radius_noise_ratio)); + } + points.push_back(p); + ++i; + } + return points; +} + +template <typename Kernel> +std::vector<typename Kernel::Point_d> generate_points_on_two_spheres_d(std::size_t num_points, int dim, double radius, + double distance_between_centers, + double radius_noise_percentage = 0.) { + typedef typename Kernel::FT FT; + typedef typename Kernel::Point_d Point; + typedef typename Kernel::Vector_d Vector; + Kernel k; + CGAL::Random rng; + CGAL::Random_points_on_sphere_d<Point> generator(dim, radius); + std::vector<Point> points; + points.reserve(num_points); + + std::vector<FT> t(dim, FT(0)); + t[0] = distance_between_centers; + Vector c1_to_c2(t.begin(), t.end()); + + for (std::size_t i = 0; i < num_points;) { + Point p = *generator++; + if (radius_noise_percentage > 0.) { + double radius_noise_ratio = rng.get_double( + (100. - radius_noise_percentage) / 100., + (100. + radius_noise_percentage) / 100.); + + typename Kernel::Point_to_vector_d k_pt_to_vec = + k.point_to_vector_d_object(); + typename Kernel::Vector_to_point_d k_vec_to_pt = + k.vector_to_point_d_object(); + typename Kernel::Scaled_vector_d k_scaled_vec = + k.scaled_vector_d_object(); + p = k_vec_to_pt(k_scaled_vec(k_pt_to_vec(p), radius_noise_ratio)); + } + + typename Kernel::Translated_point_d k_transl = + k.translated_point_d_object(); + Point p2 = k_transl(p, c1_to_c2); + points.push_back(p); + points.push_back(p2); + i += 2; + } + return points; +} + +// Product of a 3-sphere and a circle => d = 3 / D = 5 + +template <typename Kernel> +std::vector<typename Kernel::Point_d> generate_points_on_3sphere_and_circle(std::size_t num_points, + double sphere_radius) { + typedef typename Kernel::FT FT; + typedef typename Kernel::Point_d Point; + Kernel k; + CGAL::Random rng; + CGAL::Random_points_on_sphere_d<Point> generator(3, sphere_radius); + std::vector<Point> points; + points.reserve(num_points); + + typename Kernel::Translated_point_d k_transl = + k.translated_point_d_object(); + typename Kernel::Compute_coordinate_d k_coord = + k.compute_coordinate_d_object(); + for (std::size_t i = 0; i < num_points;) { + Point p_sphere = *generator++; // First 3 coords + + FT alpha = rng.get_double(0, 6.2832); + std::vector<FT> pt(5); + pt[0] = k_coord(p_sphere, 0); + pt[1] = k_coord(p_sphere, 1); + pt[2] = k_coord(p_sphere, 2); + pt[3] = std::cos(alpha); + pt[4] = std::sin(alpha); + Point p(pt.begin(), pt.end()); + points.push_back(p); + ++i; + } + return points; +} + +// a = big radius, b = small radius +template <typename Kernel> +std::vector<typename Kernel::Point_d> generate_points_on_klein_bottle_3D(std::size_t num_points, double a, double b, + bool uniform = false) { + typedef typename Kernel::Point_d Point; + typedef typename Kernel::FT FT; + Kernel k; + CGAL::Random rng; + + // if uniform + std::size_t num_lines = (std::size_t)sqrt(num_points); + + std::vector<Point> points; + points.reserve(num_points); + for (std::size_t i = 0; i < num_points;) { + FT u, v; + if (uniform) { + std::size_t k1 = i / num_lines; + std::size_t k2 = i % num_lines; + u = 6.2832 * k1 / num_lines; + v = 6.2832 * k2 / num_lines; + } else { + u = rng.get_double(0, 6.2832); + v = rng.get_double(0, 6.2832); + } + double tmp = cos(u / 2) * sin(v) - sin(u / 2) * sin(2. * v); + Point p = construct_point(k, + (a + b * tmp) * cos(u), + (a + b * tmp) * sin(u), + b * (sin(u / 2) * sin(v) + cos(u / 2) * sin(2. * v))); + points.push_back(p); + ++i; + } + return points; +} + +// a = big radius, b = small radius +template <typename Kernel> +std::vector<typename Kernel::Point_d> generate_points_on_klein_bottle_4D(std::size_t num_points, double a, double b, + double noise = 0., bool uniform = false) { + typedef typename Kernel::Point_d Point; + typedef typename Kernel::FT FT; + Kernel k; + CGAL::Random rng; + + // if uniform + std::size_t num_lines = (std::size_t)sqrt(num_points); + + std::vector<Point> points; + points.reserve(num_points); + for (std::size_t i = 0; i < num_points;) { + FT u, v; + if (uniform) { + std::size_t k1 = i / num_lines; + std::size_t k2 = i % num_lines; + u = 6.2832 * k1 / num_lines; + v = 6.2832 * k2 / num_lines; + } else { + u = rng.get_double(0, 6.2832); + v = rng.get_double(0, 6.2832); + } + Point p = construct_point(k, + (a + b * cos(v)) * cos(u) + (noise == 0. ? 0. : rng.get_double(0, noise)), + (a + b * cos(v)) * sin(u) + (noise == 0. ? 0. : rng.get_double(0, noise)), + b * sin(v) * cos(u / 2) + (noise == 0. ? 0. : rng.get_double(0, noise)), + b * sin(v) * sin(u / 2) + (noise == 0. ? 0. : rng.get_double(0, noise))); + points.push_back(p); + ++i; + } + return points; +} + + +// a = big radius, b = small radius + +template <typename Kernel> +std::vector<typename Kernel::Point_d> +generate_points_on_klein_bottle_variant_5D( + std::size_t num_points, double a, double b, bool uniform = false) { + typedef typename Kernel::Point_d Point; + typedef typename Kernel::FT FT; + Kernel k; + CGAL::Random rng; + + // if uniform + std::size_t num_lines = (std::size_t)sqrt(num_points); + + std::vector<Point> points; + points.reserve(num_points); + for (std::size_t i = 0; i < num_points;) { + FT u, v; + if (uniform) { + std::size_t k1 = i / num_lines; + std::size_t k2 = i % num_lines; + u = 6.2832 * k1 / num_lines; + v = 6.2832 * k2 / num_lines; + } else { + u = rng.get_double(0, 6.2832); + v = rng.get_double(0, 6.2832); + } + FT x1 = (a + b * cos(v)) * cos(u); + FT x2 = (a + b * cos(v)) * sin(u); + FT x3 = b * sin(v) * cos(u / 2); + FT x4 = b * sin(v) * sin(u / 2); + FT x5 = x1 + x2 + x3 + x4; + + Point p = construct_point(k, x1, x2, x3, x4, x5); + points.push_back(p); + ++i; + } + return points; +} + +} // namespace Gudhi + +#endif // RANDOM_POINT_GENERATORS_H_ diff --git a/src/common/include/gudhi/reader_utils.h b/src/common/include/gudhi/reader_utils.h index e05714c7..899f9df6 100644 --- a/src/common/include/gudhi/reader_utils.h +++ b/src/common/include/gudhi/reader_utils.h @@ -58,7 +58,9 @@ inline void read_points(std::string file_name, std::vector< std::vector< double while (iss >> x) { point.push_back(x); } - points.push_back(point); + // Check for empty lines + if (!point.empty()) + points.push_back(point); } in_file.close(); } @@ -159,7 +161,7 @@ bool read_simplex(std::istream & in_, std::vector< Vertex_handle > & simplex, Fi simplex.push_back(v); } in_ >> fil; - in_.ignore((std::numeric_limits<std::streamsize>::max)(), '\n'); // ignore until the carriage return + in_.ignore((std::numeric_limits<std::streamsize>::max)(), '\n'); // ignore until the carriage return return true; } |