diff options
Diffstat (limited to 'src/common')
87 files changed, 18186 insertions, 19 deletions
diff --git a/src/common/doc/main_page.h b/src/common/doc/main_page.h index 21cf6925..fe23c4e7 100644 --- a/src/common/doc/main_page.h +++ b/src/common/doc/main_page.h @@ -93,6 +93,25 @@ </td> </tr> </table> + \subsection TangentialComplexDataStructure Tangential complex + \image html "tc_examples.png" "Tangential complex representation" +<table border="0"> + <tr> + <td width="25%"> + <b>Author:</b> Clément Jamin<br> + <b>Introduced in:</b> GUDHI 1.4.0<br> + <b>Copyright:</b> GPL v3<br> + </td> + <td width="75%"> + A Tangential Delaunay complex is a <a target="_blank" href="https://en.wikipedia.org/wiki/Simplicial_complex">simplicial complex</a> + designed to reconstruct a \f$ k \f$-dimensional manifold embedded in \f$ d \f$-dimensional Euclidean space. + The input is a point sample coming from an unknown manifold. + The running time depends only linearly on the extrinsic dimension \f$ d \f$ + and exponentially on the intrinsic dimension \f$ k \f$.<br> + <b>User manual:</b> \ref tangential_complex - <b>Reference manual:</b> Gudhi::tangential_complex::Tangential_complex + </td> + </tr> +</table> \subsection WitnessComplexDataStructure Witness complex \image html "Witness_complex_representation.png" "Witness complex representation" <table border="0"> @@ -337,6 +356,8 @@ make \endverbatim * @example Skeleton_blocker/Skeleton_blocker_from_simplices.cpp * @example Skeleton_blocker/Skeleton_blocker_iteration.cpp * @example Skeleton_blocker/Skeleton_blocker_link.cpp + * @example Tangential_complex/example_basic.cpp + * @example Tangential_complex/example_with_perturb.cpp * @example Witness_complex/witness_complex_from_file.cpp * @example Witness_complex/witness_complex_sphere.cpp */ 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/Debug_utils.h b/src/common/include/gudhi/Debug_utils.h index 7573a9db..8ed3b7b3 100644 --- a/src/common/include/gudhi/Debug_utils.h +++ b/src/common/include/gudhi/Debug_utils.h @@ -33,8 +33,10 @@ // 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 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/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_patches/CGAL/Convex_hull.h b/src/common/include/gudhi_patches/CGAL/Convex_hull.h new file mode 100644 index 00000000..a8f91bf8 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/Convex_hull.h @@ -0,0 +1,56 @@ +// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Samuel Hornus + +/* RANDOM DESIGN IDEAS: +- Use a policy tag to choose for incremental with inserts only or + incremental with removals and inserts. + In the first case: use Triangulation for storage. + In the second case: use Delaunay ! + In this second case, we must keeps the points that are inserted in the hull, + as they may become part of the boundary later on, when some points are removed. +- Constructor with range argument uses quickhull. +*/ + +#ifndef CGAL_CONVEX_HULL_H +#define CGAL_CONVEX_HULL_H + +namespace CGAL { + +template < class CHTraits, class TDS_ = Default > +class Convex_hull +{ + typedef typename Maximal_dimension<typename CHTraits::Point_d>::type + Maximal_dimension_; + typedef typename Default::Get<TDS_, Triangulation_data_structure + < Maximal_dimension_, + Triangulation_vertex<CHTraits>, + Triangulation_full_cell<CHTraits> > + >::type TDS; + typedef Convex_hull<CHTraits, TDS_> Self; + + typedef typename CHTraits::Coaffine_orientation_d + Coaffine_orientation_d; + typedef typename CHTraits::Orientation_d Orientation_d; + +public: +}; + +} //namespace CGAL + +#endif // CGAL_CONVEX_HULL_H diff --git a/src/common/include/gudhi_patches/CGAL/Delaunay_triangulation.h b/src/common/include/gudhi_patches/CGAL/Delaunay_triangulation.h new file mode 100644 index 00000000..071cd184 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/Delaunay_triangulation.h @@ -0,0 +1,933 @@ +// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Samuel Hornus + +#ifndef CGAL_DELAUNAY_COMPLEX_H +#define CGAL_DELAUNAY_COMPLEX_H + +#include <CGAL/tss.h> +#include <CGAL/Triangulation.h> +#include <CGAL/Dimension.h> +#include <CGAL/Default.h> + +#include <boost/iterator/transform_iterator.hpp> + +#include <algorithm> + +namespace CGAL { + +template< typename DCTraits, typename _TDS = Default > +class Delaunay_triangulation +: public Triangulation<DCTraits, + typename Default::Get<_TDS, Triangulation_data_structure< + typename DCTraits::Dimension, + Triangulation_vertex<DCTraits>, + Triangulation_full_cell<DCTraits> > + >::type > +{ + typedef typename DCTraits::Dimension Maximal_dimension_; + typedef typename Default::Get<_TDS, Triangulation_data_structure< + Maximal_dimension_, + Triangulation_vertex<DCTraits>, + Triangulation_full_cell<DCTraits> > + >::type TDS; + typedef Triangulation<DCTraits, TDS> Base; + typedef Delaunay_triangulation<DCTraits, _TDS> Self; + + typedef typename DCTraits::Side_of_oriented_sphere_d + Side_of_oriented_sphere_d; + typedef typename DCTraits::Orientation_d Orientation_d; + +public: // PUBLIC NESTED TYPES + + typedef DCTraits Geom_traits; + typedef typename Base::Triangulation_ds Triangulation_ds; + + typedef typename Base::Vertex Vertex; + typedef typename Base::Full_cell Full_cell; + typedef typename Base::Facet Facet; + typedef typename Base::Face Face; + + typedef typename Base::Maximal_dimension Maximal_dimension; + typedef typename DCTraits::Point_d Point; + typedef typename DCTraits::Point_d Point_d; + + typedef typename Base::Vertex_handle Vertex_handle; + typedef typename Base::Vertex_iterator Vertex_iterator; + typedef typename Base::Vertex_const_handle Vertex_const_handle; + typedef typename Base::Vertex_const_iterator Vertex_const_iterator; + + typedef typename Base::Full_cell_handle Full_cell_handle; + typedef typename Base::Full_cell_iterator Full_cell_iterator; + typedef typename Base::Full_cell_const_handle Full_cell_const_handle; + typedef typename Base::Full_cell_const_iterator Full_cell_const_iterator; + typedef typename Base::Finite_full_cell_const_iterator + Finite_full_cell_const_iterator; + + typedef typename Base::size_type size_type; + typedef typename Base::difference_type difference_type; + + typedef typename Base::Locate_type Locate_type; + + //Tag to distinguish triangulations with weighted_points + typedef Tag_false Weighted_tag; + +protected: // DATA MEMBERS + + +public: + + using typename Base::Rotor; + using Base::maximal_dimension; + using Base::are_incident_full_cells_valid; + using Base::coaffine_orientation_predicate; + using Base::reset_flat_orientation; + using Base::current_dimension; + //using Base::star; + //using Base::incident_full_cells; + using Base::geom_traits; + using Base::index_of_covertex; + //using Base::index_of_second_covertex; + using Base::infinite_vertex; + using Base::rotate_rotor; + using Base::insert_in_hole; + using Base::insert_outside_convex_hull_1; + using Base::is_infinite; + using Base::locate; + using Base::points_begin; + using Base::set_neighbors; + using Base::new_full_cell; + using Base::number_of_vertices; + using Base::orientation; + using Base::tds; + using Base::reorient_full_cells; + using Base::full_cell; + using Base::full_cells_begin; + using Base::full_cells_end; + using Base::finite_full_cells_begin; + using Base::finite_full_cells_end; + using Base::vertices_begin; + using Base::vertices_end; + // using Base:: + +private: + //*** Side_of_oriented_subsphere_d *** + typedef typename Base::Flat_orientation_d Flat_orientation_d; + typedef typename Base::Construct_flat_orientation_d Construct_flat_orientation_d; + typedef typename DCTraits::In_flat_side_of_oriented_sphere_d In_flat_side_of_oriented_sphere_d; + // Wrapper + struct Side_of_oriented_subsphere_d + { + boost::optional<Flat_orientation_d>* fop; + Construct_flat_orientation_d cfo; + In_flat_side_of_oriented_sphere_d ifsoos; + + Side_of_oriented_subsphere_d( + boost::optional<Flat_orientation_d>& x, + Construct_flat_orientation_d const&y, + In_flat_side_of_oriented_sphere_d const&z) + : fop(&x), cfo(y), ifsoos(z) {} + + template<class Iter> + CGAL::Orientation operator()(Iter a, Iter b, const Point & p)const + { + if(!*fop) + *fop=cfo(a,b); + return ifsoos(fop->get(),a,b,p); + } + }; +public: + +// - - - - - - - - - - - - - - - - - - - - - - - - - - CREATION / CONSTRUCTORS + + Delaunay_triangulation(int dim, const Geom_traits &k = Geom_traits()) + : Base(dim, k) + { + } + + // With this constructor, + // the user can specify a Flat_orientation_d object to be used for + // orienting simplices of a specific dimension + // (= preset_flat_orientation_.first) + // It it used by the dark triangulations created by DT::remove + Delaunay_triangulation( + int dim, + const std::pair<int, const Flat_orientation_d *> &preset_flat_orientation, + const Geom_traits &k = Geom_traits()) + : Base(dim, preset_flat_orientation, k) + { + } + + ~Delaunay_triangulation() {} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ACCESS + + // Not Documented + Side_of_oriented_subsphere_d side_of_oriented_subsphere_predicate() const + { + return Side_of_oriented_subsphere_d ( + flat_orientation_, + geom_traits().construct_flat_orientation_d_object(), + geom_traits().in_flat_side_of_oriented_sphere_d_object() + ); + } + + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS + + Full_cell_handle remove(Vertex_handle); + Full_cell_handle remove(const Point & p, Full_cell_handle hint = Full_cell_handle()) + { + Locate_type lt; + Face f(maximal_dimension()); + Facet ft; + Full_cell_handle s = locate(p, lt, f, ft, hint); + if( Base::ON_VERTEX == lt ) + { + return remove(s->vertex(f.index(0))); + } + return Full_cell_handle(); + } + + template< typename ForwardIterator > + void remove(ForwardIterator start, ForwardIterator end) + { + while( start != end ) + remove(*start++); + } + + // Not documented + void remove_decrease_dimension(Vertex_handle); + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INSERTIONS + + template< typename ForwardIterator > + size_type insert(ForwardIterator start, ForwardIterator end) + { + size_type n = number_of_vertices(); + std::vector<Point> points(start, end); + spatial_sort(points.begin(), points.end(), geom_traits()); + Full_cell_handle hint; + for( typename std::vector<Point>::const_iterator p = points.begin(); p != points.end(); ++p ) + { + hint = insert(*p, hint)->full_cell(); + } + return number_of_vertices() - n; + } + Vertex_handle insert(const Point &, Locate_type, const Face &, const Facet &, Full_cell_handle); + Vertex_handle insert(const Point & p, Full_cell_handle start = Full_cell_handle()) + { + Locate_type lt; + Face f(maximal_dimension()); + Facet ft; + Full_cell_handle s = locate(p, lt, f, ft, start); + return insert(p, lt, f, ft, s); + } + Vertex_handle insert(const Point & p, Vertex_handle hint) + { + CGAL_assertion( Vertex_handle() != hint ); + return insert(p, hint->full_cell()); + } + Vertex_handle insert_outside_affine_hull(const Point &); + Vertex_handle insert_in_conflicting_cell(const Point &, Full_cell_handle); + +// - - - - - - - - - - - - - - - - - - - - - - - - - GATHERING CONFLICTING SIMPLICES + + bool is_in_conflict(const Point &, Full_cell_const_handle) const; + template< class OrientationPredicate > + Oriented_side perturbed_side_of_positive_sphere(const Point &, + Full_cell_const_handle, const OrientationPredicate &) const; + + template< typename OutputIterator > + Facet compute_conflict_zone(const Point &, Full_cell_handle, OutputIterator) const; + + template < typename OrientationPredicate, typename SideOfOrientedSpherePredicate > + class Conflict_predicate + { + const Self & dc_; + const Point & p_; + OrientationPredicate ori_; + SideOfOrientedSpherePredicate side_of_s_; + int cur_dim_; + public: + Conflict_predicate( + const Self & dc, + const Point & p, + const OrientationPredicate & ori, + const SideOfOrientedSpherePredicate & side) + : dc_(dc), p_(p), ori_(ori), side_of_s_(side), cur_dim_(dc.current_dimension()) {} + + inline + bool operator()(Full_cell_const_handle s) const + { + bool ok; + if( ! dc_.is_infinite(s) ) + { + Oriented_side side = side_of_s_(dc_.points_begin(s), dc_.points_begin(s) + cur_dim_ + 1, p_); + if( ON_POSITIVE_SIDE == side ) + ok = true; + else if( ON_NEGATIVE_SIDE == side ) + ok = false; + else + ok = ON_POSITIVE_SIDE == dc_.perturbed_side_of_positive_sphere<OrientationPredicate>(p_, s, ori_); + } + else + { + typedef typename Full_cell::Vertex_handle_const_iterator VHCI; + typedef Substitute_point_in_vertex_iterator<VHCI> F; + F spivi(dc_.infinite_vertex(), &p_); + + Orientation o = ori_( + boost::make_transform_iterator(s->vertices_begin(), spivi), + boost::make_transform_iterator(s->vertices_begin() + cur_dim_ + 1, + spivi)); + + if( POSITIVE == o ) + ok = true; + else if( o == NEGATIVE ) + ok = false; + else + ok = (*this)(s->neighbor( s->index( dc_.infinite_vertex() ) )); + } + return ok; + } + }; + + template < typename ConflictPredicate > + class Conflict_traversal_predicate + { + const Self & dc_; + const ConflictPredicate & pred_; + public: + Conflict_traversal_predicate(const Self & dc, const ConflictPredicate & pred) + : dc_(dc), pred_(pred) + {} + inline + bool operator()(const Facet & f) const + { + return pred_(dc_.full_cell(f)->neighbor(dc_.index_of_covertex(f))); + } + }; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY + + bool is_valid(bool verbose = false, int level = 0) const; + +private: + // Some internal types to shorten notation + typedef typename Base::Coaffine_orientation_d Coaffine_orientation_d; + using Base::flat_orientation_; + typedef Conflict_predicate<Coaffine_orientation_d, Side_of_oriented_subsphere_d> + Conflict_pred_in_subspace; + typedef Conflict_predicate<Orientation_d, Side_of_oriented_sphere_d> + Conflict_pred_in_fullspace; + typedef Conflict_traversal_predicate<Conflict_pred_in_subspace> + Conflict_traversal_pred_in_subspace; + typedef Conflict_traversal_predicate<Conflict_pred_in_fullspace> + Conflict_traversal_pred_in_fullspace; +}; + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +// FUNCTIONS THAT ARE MEMBER METHODS: + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS + +template< typename DCTraits, typename TDS > +typename Delaunay_triangulation<DCTraits, TDS>::Full_cell_handle +Delaunay_triangulation<DCTraits, TDS> +::remove( Vertex_handle v ) +{ + CGAL_precondition( ! is_infinite(v) ); + CGAL_expensive_precondition( is_vertex(v) ); + + // THE CASE cur_dim == 0 + if( 0 == current_dimension() ) + { + remove_decrease_dimension(v); + return Full_cell_handle(); + } + else if( 1 == current_dimension() ) + { // THE CASE cur_dim == 1 + if( 2 == number_of_vertices() ) + { + remove_decrease_dimension(v); + return Full_cell_handle(); + } + Full_cell_handle left = v->full_cell(); + if( 0 == left->index(v) ) + left = left->neighbor(1); + CGAL_assertion( 1 == left->index(v) ); + Full_cell_handle right = left->neighbor(0); + + tds().associate_vertex_with_full_cell(left, 1, right->vertex(1)); + set_neighbors(left, 0, right->neighbor(0), right->mirror_index(0)); + + tds().delete_vertex(v); + tds().delete_full_cell(right); + return left; + } + + // THE CASE cur_dim >= 2 + // Gather the finite vertices sharing an edge with |v| + typedef typename Base::template Full_cell_set<Full_cell_handle> Simplices; + Simplices simps; + std::back_insert_iterator<Simplices> out(simps); + tds().incident_full_cells(v, out); + typedef std::set<Vertex_handle> Vertex_set; + Vertex_set verts; + Vertex_handle vh; + for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it ) + for( int i = 0; i <= current_dimension(); ++i ) + { + vh = (*it)->vertex(i); + if( is_infinite(vh) ) + continue; + if( vh == v ) + continue; + verts.insert(vh); + } + + // After gathering finite neighboring vertices, create their Dark Delaunay triangulation + typedef Triangulation_vertex<Geom_traits, Vertex_handle> Dark_vertex_base; + typedef Triangulation_full_cell<Geom_traits, + internal::Triangulation::Dark_full_cell_data<Self> > Dark_full_cell_base; + typedef Triangulation_data_structure<Maximal_dimension, Dark_vertex_base, Dark_full_cell_base> Dark_tds; + typedef Delaunay_triangulation<DCTraits, Dark_tds> Dark_triangulation; + typedef typename Dark_triangulation::Face Dark_face; + typedef typename Dark_triangulation::Facet Dark_facet; + typedef typename Dark_triangulation::Vertex_handle Dark_v_handle; + typedef typename Dark_triangulation::Full_cell_handle Dark_s_handle; + + // If flat_orientation_ is defined, we give it the Dark triangulation + // so that the orientation it uses for "current_dimension()"-simplices is + // coherent with the global triangulation + Dark_triangulation dark_side( + maximal_dimension(), + flat_orientation_ ? + std::pair<int, const Flat_orientation_d *>(current_dimension(), flat_orientation_.get_ptr()) + : std::pair<int, const Flat_orientation_d *>((std::numeric_limits<int>::max)(), (Flat_orientation_d*) NULL) ); + + Dark_s_handle dark_s; + Dark_v_handle dark_v; + typedef std::map<Vertex_handle, Dark_v_handle> Vertex_map; + Vertex_map light_to_dark; + typename Vertex_set::iterator vit = verts.begin(); + while( vit != verts.end() ) + { + dark_v = dark_side.insert((*vit)->point(), dark_s); + dark_s = dark_v->full_cell(); + dark_v->data() = *vit; + light_to_dark[*vit] = dark_v; + ++vit; + } + + if( dark_side.current_dimension() != current_dimension() ) + { + CGAL_assertion( dark_side.current_dimension() + 1 == current_dimension() ); + // Here, the finite neighbors of |v| span a affine subspace of + // dimension one less than the current dimension. Two cases are possible: + if( (size_type)(verts.size() + 1) == number_of_vertices() ) + { + remove_decrease_dimension(v); + return Full_cell_handle(); + } + else + { // |v| is strictly outside the convex hull of the rest of the points. This is an + // easy case: first, modify the finite full_cells, then, delete the infinite ones. + // We don't even need the Dark triangulation. + Simplices infinite_simps; + { + Simplices finite_simps; + for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it ) + if( is_infinite(*it) ) + infinite_simps.push_back(*it); + else + finite_simps.push_back(*it); + simps.swap(finite_simps); + } // now, simps only contains finite simplices + // First, modify the finite full_cells: + for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it ) + { + int v_idx = (*it)->index(v); + tds().associate_vertex_with_full_cell(*it, v_idx, infinite_vertex()); + } + // Make the handles to infinite full cells searchable + infinite_simps.make_searchable(); + // Then, modify the neighboring relation + for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it ) + { + for( int i = 0; i <= current_dimension(); ++i ) + { + if (is_infinite((*it)->vertex(i))) + continue; + (*it)->vertex(i)->set_full_cell(*it); + Full_cell_handle n = (*it)->neighbor(i); + // Was |n| a finite full cell prior to removing |v| ? + if( ! infinite_simps.contains(n) ) + continue; + int n_idx = n->index(v); + set_neighbors(*it, i, n->neighbor(n_idx), n->neighbor(n_idx)->index(n)); + } + } + Full_cell_handle ret_s; + // Then, we delete the infinite full_cells + for( typename Simplices::iterator it = infinite_simps.begin(); it != infinite_simps.end(); ++it ) + tds().delete_full_cell(*it); + tds().delete_vertex(v); + return simps.front(); + } + } + else // From here on, dark_side.current_dimension() == current_dimension() + { + dark_side.infinite_vertex()->data() = infinite_vertex(); + light_to_dark[infinite_vertex()] = dark_side.infinite_vertex(); + } + + // Now, compute the conflict zone of v->point() in + // the dark side. This is precisely the set of full_cells + // that we have to glue back into the light side. + Dark_face dark_f(dark_side.maximal_dimension()); + Dark_facet dark_ft; + typename Dark_triangulation::Locate_type lt; + dark_s = dark_side.locate(v->point(), lt, dark_f, dark_ft); + CGAL_assertion( lt != Dark_triangulation::ON_VERTEX + && lt != Dark_triangulation::OUTSIDE_AFFINE_HULL ); + + // |ret_s| is the full_cell that we return + Dark_s_handle dark_ret_s = dark_s; + Full_cell_handle ret_s; + + typedef typename Base::template Full_cell_set<Dark_s_handle> Dark_full_cells; + Dark_full_cells conflict_zone; + std::back_insert_iterator<Dark_full_cells> dark_out(conflict_zone); + + dark_ft = dark_side.compute_conflict_zone(v->point(), dark_s, dark_out); + // Make the dark simplices in the conflict zone searchable + conflict_zone.make_searchable(); + + // THE FOLLOWING SHOULD MAYBE GO IN TDS. + // Here is the plan: + // 1. Pick any Facet from boundary of the light zone + // 2. Find corresponding Facet on boundary of dark zone + // 3. stitch. + + // 1. Build a facet on the boudary of the light zone: + Full_cell_handle light_s = *simps.begin(); + Facet light_ft(light_s, light_s->index(v)); + + // 2. Find corresponding Dark_facet on boundary of the dark zone + Dark_full_cells dark_incident_s; + for( int i = 0; i <= current_dimension(); ++i ) + { + if( index_of_covertex(light_ft) == i ) + continue; + Dark_v_handle dark_v = light_to_dark[full_cell(light_ft)->vertex(i)]; + dark_incident_s.clear(); + dark_out = std::back_inserter(dark_incident_s); + dark_side.tds().incident_full_cells(dark_v, dark_out); + for( typename Dark_full_cells::iterator it = dark_incident_s.begin(); it != dark_incident_s.end(); ++it ) + { + (*it)->data().count_ += 1; + } + } + + for( typename Dark_full_cells::iterator it = dark_incident_s.begin(); it != dark_incident_s.end(); ++it ) + { + if( current_dimension() != (*it)->data().count_ ) + continue; + if( ! conflict_zone.contains(*it) ) + continue; + // We found a full_cell incident to the dark facet corresponding to the light facet |light_ft| + int ft_idx = 0; + while( light_s->has_vertex( (*it)->vertex(ft_idx)->data() ) ) + ++ft_idx; + dark_ft = Dark_facet(*it, ft_idx); + break; + } + // Pre-3. Now, we are ready to traverse both boundary and do the stiching. + + // But first, we create the new full_cells in the light triangulation, + // with as much adjacency information as possible. + + // Create new full_cells with vertices + for( typename Dark_full_cells::iterator it = conflict_zone.begin(); it != conflict_zone.end(); ++it ) + { + Full_cell_handle new_s = new_full_cell(); + (*it)->data().light_copy_ = new_s; + for( int i = 0; i <= current_dimension(); ++i ) + tds().associate_vertex_with_full_cell(new_s, i, (*it)->vertex(i)->data()); + if( dark_ret_s == *it ) + ret_s = new_s; + } + + // Setup adjacencies inside the hole + for( typename Dark_full_cells::iterator it = conflict_zone.begin(); it != conflict_zone.end(); ++it ) + { + Full_cell_handle new_s = (*it)->data().light_copy_; + for( int i = 0; i <= current_dimension(); ++i ) + if( conflict_zone.contains((*it)->neighbor(i)) ) + tds().set_neighbors(new_s, i, (*it)->neighbor(i)->data().light_copy_, (*it)->mirror_index(i)); + } + + // 3. Stitch + simps.make_searchable(); + typedef std::queue<std::pair<Facet, Dark_facet> > Queue; + Queue q; + q.push(std::make_pair(light_ft, dark_ft)); + dark_s = dark_side.full_cell(dark_ft); + int dark_i = dark_side.index_of_covertex(dark_ft); + // mark dark_ft as visited: + // TODO try by marking with Dark_v_handle (vertex) + dark_s->neighbor(dark_i)->set_neighbor(dark_s->mirror_index(dark_i), Dark_s_handle()); + while( ! q.empty() ) + { + std::pair<Facet, Dark_facet> p = q.front(); + q.pop(); + light_ft = p.first; + dark_ft = p.second; + light_s = full_cell(light_ft); + int light_i = index_of_covertex(light_ft); + dark_s = dark_side.full_cell(dark_ft); + int dark_i = dark_side.index_of_covertex(dark_ft); + Full_cell_handle light_n = light_s->neighbor(light_i); + set_neighbors(dark_s->data().light_copy_, dark_i, light_n, light_s->mirror_index(light_i)); + for( int di = 0; di <= current_dimension(); ++di ) + { + if( di == dark_i ) + continue; + int li = light_s->index(dark_s->vertex(di)->data()); + Rotor light_r(light_s, li, light_i); + typename Dark_triangulation::Rotor dark_r(dark_s, di, dark_i); + + while (simps.contains(cpp11::get<0>(light_r)->neighbor(cpp11::get<1>(light_r)))) + light_r = rotate_rotor(light_r); + + while (conflict_zone.contains(cpp11::get<0>(dark_r)->neighbor(cpp11::get<1>(dark_r)))) + dark_r = dark_side.rotate_rotor(dark_r); + + Dark_s_handle dark_ns = cpp11::get<0>(dark_r); + int dark_ni = cpp11::get<1>(dark_r); + Full_cell_handle light_ns = cpp11::get<0>(light_r); + int light_ni = cpp11::get<1>(light_r); + // mark dark_r as visited: + // TODO try by marking with Dark_v_handle (vertex) + Dark_s_handle outside = dark_ns->neighbor(dark_ni); + Dark_v_handle mirror = dark_ns->mirror_vertex(dark_ni, current_dimension()); + int dn = outside->index(mirror); + if( Dark_s_handle() == outside->neighbor(dn) ) + continue; + outside->set_neighbor(dn, Dark_s_handle()); + q.push(std::make_pair(Facet(light_ns, light_ni), Dark_facet(dark_ns, dark_ni))); + } + } + tds().delete_full_cells(simps.begin(), simps.end()); + tds().delete_vertex(v); + return ret_s; +} + +template< typename DCTraits, typename TDS > +void +Delaunay_triangulation<DCTraits, TDS> +::remove_decrease_dimension(Vertex_handle v) +{ + CGAL_precondition( current_dimension() >= 0 ); + tds().remove_decrease_dimension(v, infinite_vertex()); + // reset the predicates: + reset_flat_orientation(); + if( 1 <= current_dimension() ) + { + Full_cell_handle inf_v_cell = infinite_vertex()->full_cell(); + int inf_v_index = inf_v_cell->index(infinite_vertex()); + Full_cell_handle s = inf_v_cell->neighbor(inf_v_index); + Orientation o = orientation(s); + CGAL_assertion( ZERO != o ); + if( NEGATIVE == o ) + reorient_full_cells(); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INSERTIONS + +template< typename DCTraits, typename TDS > +typename Delaunay_triangulation<DCTraits, TDS>::Vertex_handle +Delaunay_triangulation<DCTraits, TDS> +::insert(const Point & p, Locate_type lt, const Face & f, const Facet &, Full_cell_handle s) +{ + switch( lt ) + { + case Base::OUTSIDE_AFFINE_HULL: + return insert_outside_affine_hull(p); + break; + case Base::ON_VERTEX: + { + Vertex_handle v = s->vertex(f.index(0)); + v->set_point(p); + return v; + break; + } + default: + if( 1 == current_dimension() ) + { + if( Base::OUTSIDE_CONVEX_HULL == lt ) + { + return insert_outside_convex_hull_1(p, s); + } + Vertex_handle v = tds().insert_in_full_cell(s); + v->set_point(p); + return v; + } + else + return insert_in_conflicting_cell(p, s); + break; + } +} + +/* +[Undocumented function] + +Inserts the point `p` in the Delaunay triangulation. Returns a handle to the +(possibly newly created) vertex at that position. +\pre The point `p` +must lie outside the affine hull of the Delaunay triangulation. This implies that +`dt`.`current_dimension()` must be less than `dt`.`maximal_dimension()`. +*/ +template< typename DCTraits, typename TDS > +typename Delaunay_triangulation<DCTraits, TDS>::Vertex_handle +Delaunay_triangulation<DCTraits, TDS> +::insert_outside_affine_hull(const Point & p) +{ + // we don't use Base::insert_outside_affine_hull(...) because here, we + // also need to reset the side_of_oriented_subsphere functor. + CGAL_precondition( current_dimension() < maximal_dimension() ); + Vertex_handle v = tds().insert_increase_dimension(infinite_vertex()); + // reset the predicates: + reset_flat_orientation(); + v->set_point(p); + if( current_dimension() >= 1 ) + { + Full_cell_handle inf_v_cell = infinite_vertex()->full_cell(); + int inf_v_index = inf_v_cell->index(infinite_vertex()); + Full_cell_handle s = inf_v_cell->neighbor(inf_v_index); + Orientation o = orientation(s); + CGAL_assertion( ZERO != o ); + if( NEGATIVE == o ) + reorient_full_cells(); + + // We just inserted the second finite point and the right infinite + // cell is like : (inf_v, v), but we want it to be (v, inf_v) to be + // consistent with the rest of the cells + if (current_dimension() == 1) + { + // Is "inf_v_cell" the right infinite cell? + // Then inf_v_index should be 1 + if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0 + && inf_v_index == 0) + { + inf_v_cell->swap_vertices( + current_dimension() - 1, current_dimension()); + } + // Otherwise, let's find the right infinite cell + else + { + inf_v_cell = inf_v_cell->neighbor((inf_v_index + 1) % 2); + inf_v_index = inf_v_cell->index(infinite_vertex()); + // Is "inf_v_cell" the right infinite cell? + // Then inf_v_index should be 1 + if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0 + && inf_v_index == 0) + { + inf_v_cell->swap_vertices( + current_dimension() - 1, current_dimension()); + } + } + } + } + return v; +} + +/*! +[Undocumented function] + +Inserts the point `p` in the Delaunay triangulation. Returns a handle to the +(possibly newly created) vertex at that position. +\pre The point `p` must be in conflict with the full cell `c`. +*/ +template< typename DCTraits, typename TDS > +typename Delaunay_triangulation<DCTraits, TDS>::Vertex_handle +Delaunay_triangulation<DCTraits, TDS> +::insert_in_conflicting_cell(const Point & p, Full_cell_handle s) +{ + CGAL_precondition(is_in_conflict(p, s)); + + // for storing conflicting full_cells. + typedef std::vector<Full_cell_handle> Full_cell_h_vector; + CGAL_STATIC_THREAD_LOCAL_VARIABLE(Full_cell_h_vector,cs,0); + cs.clear(); + + std::back_insert_iterator<Full_cell_h_vector> out(cs); + Facet ft = compute_conflict_zone(p, s, out); + return insert_in_hole(p, cs.begin(), cs.end(), ft); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - GATHERING CONFLICTING SIMPLICES + +// NOT DOCUMENTED +template< typename DCTraits, typename TDS > +template< typename OrientationPred > +Oriented_side +Delaunay_triangulation<DCTraits, TDS> +::perturbed_side_of_positive_sphere(const Point & p, Full_cell_const_handle s, + const OrientationPred & ori) const +{ + CGAL_precondition_msg( ! is_infinite(s), "full cell must be finite"); + CGAL_expensive_precondition( POSITIVE == orientation(s) ); + typedef std::vector<const Point *> Points; + Points points(current_dimension() + 2); + int i(0); + for( ; i <= current_dimension(); ++i ) + points[i] = &(s->vertex(i)->point()); + points[i] = &p; + std::sort(points.begin(), points.end(), + internal::Triangulation::Compare_points_for_perturbation<Self>(*this)); + typename Points::const_reverse_iterator cut_pt = points.rbegin(); + Points test_points; + while( cut_pt != points.rend() ) + { + if( &p == *cut_pt ) + // because the full_cell "s" is assumed to be positively oriented + return ON_NEGATIVE_SIDE; // we consider |p| to lie outside the sphere + test_points.clear(); + typename Base::Point_const_iterator spit = points_begin(s); + int adjust_sign = -1; + for( i = 0; i < current_dimension(); ++i ) + { + if( &(*spit) == *cut_pt ) + { + ++spit; + adjust_sign = (((current_dimension() + i) % 2) == 0) ? -1 : +1; + } + test_points.push_back(&(*spit)); + ++spit; + } + test_points.push_back(&p); + + typedef typename CGAL::Iterator_project<typename Points::iterator, + internal::Triangulation::Point_from_pointer<Self>, + const Point &, const Point *> Point_pointer_iterator; + + Orientation ori_value = ori( + Point_pointer_iterator(test_points.begin()), + Point_pointer_iterator(test_points.end())); + + if( ZERO != ori_value ) + return Oriented_side( - adjust_sign * ori_value ); + + ++cut_pt; + } + CGAL_assertion(false); // we should never reach here + return ON_NEGATIVE_SIDE; +} + +template< typename DCTraits, typename TDS > +bool +Delaunay_triangulation<DCTraits, TDS> +::is_in_conflict(const Point & p, Full_cell_const_handle s) const +{ + CGAL_precondition( 2 <= current_dimension() ); + if( current_dimension() < maximal_dimension() ) + { + Conflict_pred_in_subspace c(*this, p, coaffine_orientation_predicate(), side_of_oriented_subsphere_predicate()); + return c(s); + } + else + { + Orientation_d ori = geom_traits().orientation_d_object(); + Side_of_oriented_sphere_d side = geom_traits().side_of_oriented_sphere_d_object(); + Conflict_pred_in_fullspace c(*this, p, ori, side); + return c(s); + } +} + +template< typename DCTraits, typename TDS > +template< typename OutputIterator > +typename Delaunay_triangulation<DCTraits, TDS>::Facet +Delaunay_triangulation<DCTraits, TDS> +::compute_conflict_zone(const Point & p, Full_cell_handle s, OutputIterator out) const +{ + CGAL_precondition( 2 <= current_dimension() ); + if( current_dimension() < maximal_dimension() ) + { + Conflict_pred_in_subspace c(*this, p, coaffine_orientation_predicate(), side_of_oriented_subsphere_predicate()); + Conflict_traversal_pred_in_subspace tp(*this, c); + return tds().gather_full_cells(s, tp, out); + } + else + { + Orientation_d ori = geom_traits().orientation_d_object(); + Side_of_oriented_sphere_d side = geom_traits().side_of_oriented_sphere_d_object(); + Conflict_pred_in_fullspace c(*this, p, ori, side); + Conflict_traversal_pred_in_fullspace tp(*this, c); + return tds().gather_full_cells(s, tp, out); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY + +template< typename DCTraits, typename TDS > +bool +Delaunay_triangulation<DCTraits, TDS> +::is_valid(bool verbose, int level) const +{ + if (!Base::is_valid(verbose, level)) + return false; + + int dim = current_dimension(); + if (dim == maximal_dimension()) + { + for (Finite_full_cell_const_iterator cit = this->finite_full_cells_begin() ; + cit != this->finite_full_cells_end() ; ++cit ) + { + Full_cell_const_handle ch = cit.base(); + for(int i = 0; i < dim+1 ; ++i ) + { + // If the i-th neighbor is not an infinite cell + Vertex_handle opposite_vh = + ch->neighbor(i)->vertex(ch->neighbor(i)->index(ch)); + if (!is_infinite(opposite_vh)) + { + Side_of_oriented_sphere_d side = + geom_traits().side_of_oriented_sphere_d_object(); + if (side(Point_const_iterator(ch->vertices_begin()), + Point_const_iterator(ch->vertices_end()), + opposite_vh->point()) == ON_BOUNDED_SIDE) + { + if (verbose) + CGAL_warning_msg(false, "Non-empty sphere"); + return false; + } + } + } + } + } + return true; +} + + +} //namespace CGAL + +#endif // CGAL_DELAUNAY_COMPLEX_H diff --git a/src/common/include/gudhi_patches/CGAL/Epeck_d.h b/src/common/include/gudhi_patches/CGAL/Epeck_d.h new file mode 100644 index 00000000..52bce84c --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/Epeck_d.h @@ -0,0 +1,53 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_EPECK_D_H +#define CGAL_EPECK_D_H +#include <CGAL/NewKernel_d/Cartesian_base.h> +#include <CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h> +#include <CGAL/NewKernel_d/Kernel_d_interface.h> +#include <CGAL/internal/Exact_type_selector.h> + + +namespace CGAL { +#define CGAL_BASE \ + Cartesian_base_d<internal::Exact_field_selector<double>::Type, Dim> +template<class Dim> +struct Epeck_d_help1 +: CGAL_BASE +{ + CGAL_CONSTEXPR Epeck_d_help1(){} + CGAL_CONSTEXPR Epeck_d_help1(int d):CGAL_BASE(d){} +}; +#undef CGAL_BASE +#define CGAL_BASE \ + Kernel_d_interface< \ + Cartesian_wrap< \ + Epeck_d_help1<Dim>, \ + Epeck_d<Dim> > > +template<class Dim> +struct Epeck_d +: CGAL_BASE +{ + CGAL_CONSTEXPR Epeck_d(){} + CGAL_CONSTEXPR Epeck_d(int d):CGAL_BASE(d){} +}; +#undef CGAL_BASE +} +#endif diff --git a/src/common/include/gudhi_patches/CGAL/Epick_d.h b/src/common/include/gudhi_patches/CGAL/Epick_d.h new file mode 100644 index 00000000..64438539 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/Epick_d.h @@ -0,0 +1,71 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_EPICK_D_H +#define CGAL_EPICK_D_H +#include <CGAL/NewKernel_d/Cartesian_base.h> +#include <CGAL/NewKernel_d/Cartesian_static_filters.h> +#include <CGAL/NewKernel_d/Cartesian_filter_K.h> +#include <CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h> +#include <CGAL/NewKernel_d/Kernel_d_interface.h> +#include <CGAL/internal/Exact_type_selector.h> +#include <CGAL/Interval_nt.h> +#include <CGAL/NewKernel_d/Types/Weighted_point.h> + + +namespace CGAL { +#define CGAL_BASE \ + Cartesian_filter_K< \ + Cartesian_base_d<double, Dim>, \ + Cartesian_base_d<Interval_nt_advanced, Dim>, \ + Cartesian_base_d<internal::Exact_field_selector<double>::Type, Dim> \ + > +template<class Dim> +struct Epick_d_help1 +: CGAL_BASE +{ + CGAL_CONSTEXPR Epick_d_help1(){} + CGAL_CONSTEXPR Epick_d_help1(int d):CGAL_BASE(d){} +}; +#undef CGAL_BASE +#define CGAL_BASE \ + Cartesian_static_filters<Dim,Epick_d_help1<Dim>,Epick_d_help2<Dim> > +template<class Dim> +struct Epick_d_help2 +: CGAL_BASE +{ + CGAL_CONSTEXPR Epick_d_help2(){} + CGAL_CONSTEXPR Epick_d_help2(int d):CGAL_BASE(d){} +}; +#undef CGAL_BASE +#define CGAL_BASE \ + Kernel_d_interface< \ + Cartesian_wrap< \ + Epick_d_help2<Dim>, \ + Epick_d<Dim> > > +template<class Dim> +struct Epick_d +: CGAL_BASE +{ + CGAL_CONSTEXPR Epick_d(){} + CGAL_CONSTEXPR Epick_d(int d):CGAL_BASE(d){} +}; +#undef CGAL_BASE +} +#endif diff --git a/src/common/include/gudhi_patches/CGAL/IO/Triangulation_off_ostream.h b/src/common/include/gudhi_patches/CGAL/IO/Triangulation_off_ostream.h new file mode 100644 index 00000000..701f0820 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/IO/Triangulation_off_ostream.h @@ -0,0 +1,320 @@ +// Copyright (c) 2014 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: $ +// $Id: $ +// +// Author(s) : Clement Jamin + + +#ifndef CGAL_TRIANGULATION_IO_H +#define CGAL_TRIANGULATION_IO_H + +#include <CGAL/Epick_d.h> +#include <CGAL/Triangulation.h> +#include <sstream> +#include <iostream> + +namespace CGAL { + +namespace Triangulation_IO +{ +// TODO: test if the stream is binary or text? +template<typename Traits, typename P> +int +output_point(std::ostream & os, const Traits &traits, const P & p) +{ + typedef typename Traits::Compute_coordinate_d Ccd; + const Ccd ccd = traits.compute_coordinate_d_object(); + const int dim = traits.point_dimension_d_object()(p); + if (dim > 0) + { + os << ccd(p, 0); + for (int i = 1 ; i < dim ; ++i) + os << " " << CGAL::to_double(ccd(p, i)); + } + return dim; +} + +// TODO: test if the stream is binary or text? +template<typename Traits, typename P> +int +output_weighted_point(std::ostream & os, const Traits &traits, const P & p, + bool output_weight = true) +{ + typedef typename Traits::Compute_coordinate_d Ccd; + typename Traits::Construct_point_d cp = + traits.construct_point_d_object(); + typename Traits::Compute_weight_d pt_weight = traits.compute_weight_d_object(); + const Ccd ccd = traits.compute_coordinate_d_object(); + const int dim = traits.point_dimension_d_object()(p); + if (dim > 0) + { + output_point(os, traits, p); + if (output_weight) + os << " " << pt_weight(p); + } + return dim; +} + +// TODO: test if the stream is binary or text? +template<typename Traits, typename FCH> +void +output_full_cell(std::ostream & os, const Traits &traits, const FCH & fch, + bool output_weights = false) +{ + typename FCH::value_type::Vertex_handle_iterator vit = fch->vertices_begin(); + for( ; vit != fch->vertices_end(); ++vit ) + { + int dim; + if (output_weights) + dim = output_weighted_point(os, traits, (*vit)->point()); + else + dim = output_point(os, traits, (*vit)->point()); + if (dim > 0) + os << std::endl; + } +} + +// TODO: test if the stream is binary or text? +/*template<typename Traits, typename P> +void +input_point(std::istream & is, const Traits &traits, P & p) +{ + typedef typename Traits::FT FT; + std::vector<FT> coords; + + std::string line; + for(;;) + { + if (!std::getline(is, line)) + return is; + if (line != "") + break; + } + std::stringstream line_sstr(line); + FT temp; + while (line_sstr >> temp) + coords.push_back(temp); + + p = traits.construct_point_d_object()(coords.begin(), coords.end()); +}*/ + +} // namespace Triangulation_IO + +/////////////////////////////////////////////////////////////// +// TODO: replace these operator>> by an "input_point" function +/////////////////////////////////////////////////////////////// + +// TODO: test if the stream is binary or text? +template<typename K> +std::istream & +operator>>(std::istream &is, typename Wrap::Point_d<K> & p) +{ + typedef typename Wrap::Point_d<K> P; + typedef typename K::FT FT; + std::vector<FT> coords; + + std::string line; + for(;;) + { + if (!std::getline(is, line)) + return is; + if (line != "") + break; + } + std::stringstream line_sstr(line); + FT temp; + while (line_sstr >> temp) + coords.push_back(temp); + + p = P(coords.begin(), coords.end()); + return is; +} + +// TODO: test if the stream is binary or text? +template<typename K> +std::istream & +operator>>(std::istream &is, typename Wrap::Weighted_point_d<K> & wp) +{ + typedef typename Wrap::Point_d<K> P; + typedef typename Wrap::Weighted_point_d<K> WP; + typedef typename K::FT FT; + + std::string line; + for(;;) + { + if (!std::getline(is, line)) + return is; + if (line != "") + break; + } + std::stringstream line_sstr(line); + FT temp; + std::vector<FT> coords; + while (line_sstr >> temp) + coords.push_back(temp); + + typename std::vector<FT>::iterator last = coords.end() - 1; + P p = P(coords.begin(), last); + wp = WP(p, *last); + + return is; +} + +// TODO: test if the stream is binary or text? +template<typename K> +std::istream & +operator>>(std::istream &is, typename Wrap::Vector_d<K> & v) +{ + typedef typename Wrap::Vector_d<K> V; + typedef typename K::FT FT; + std::vector<FT> coords; + + std::string line; + for (;;) + { + if (!std::getline(is, line)) + return is; + if (line != "") + break; + } + std::stringstream line_sstr(line); + FT temp; + while (line_sstr >> temp) + coords.push_back(temp); + + v = V(coords.begin(), coords.end()); + return is; +} + +template < class GT, class TDS > +std::ostream & +export_triangulation_to_off(std::ostream & os, + const Triangulation<GT,TDS> & tr, + bool in_3D_export_surface_only = false) +{ + typedef Triangulation<GT,TDS> Tr; + typedef typename Tr::Vertex_const_handle Vertex_handle; + typedef typename Tr::Finite_vertex_const_iterator Finite_vertex_iterator; + typedef typename Tr::Finite_full_cell_const_iterator Finite_full_cell_iterator; + typedef typename Tr::Full_cell_const_iterator Full_cell_iterator; + typedef typename Tr::Full_cell Full_cell; + typedef typename Full_cell::Vertex_handle_const_iterator Full_cell_vertex_iterator; + + if (tr.maximal_dimension() < 2 || tr.maximal_dimension() > 3) + { + std::cerr << "Warning: export_tds_to_off => dimension should be 2 or 3."; + os << "Warning: export_tds_to_off => dimension should be 2 or 3."; + return os; + } + + size_t n = tr.number_of_vertices(); + + std::stringstream output; + + // write the vertices + std::map<Vertex_handle, int> index_of_vertex; + int i = 0; + for(Finite_vertex_iterator it = tr.finite_vertices_begin(); + it != tr.finite_vertices_end(); ++it, ++i) + { + Triangulation_IO::output_point(output, tr.geom_traits(), it->point()); + if (tr.maximal_dimension() == 2) + output << " 0"; + output << std::endl; + index_of_vertex[it.base()] = i; + } + CGAL_assertion( i == n ); + + size_t number_of_triangles = 0; + if (tr.maximal_dimension() == 2) + { + for (Finite_full_cell_iterator fch = tr.finite_full_cells_begin() ; + fch != tr.finite_full_cells_end() ; ++fch) + { + output << "3 "; + for (Full_cell_vertex_iterator vit = fch->vertices_begin() ; + vit != fch->vertices_end() ; ++vit) + { + output << index_of_vertex[*vit] << " "; + } + output << std::endl; + ++number_of_triangles; + } + } + else if (tr.maximal_dimension() == 3) + { + if (in_3D_export_surface_only) + { + // Parse boundary facets + for (Full_cell_iterator fch = tr.full_cells_begin() ; + fch != tr.full_cells_end() ; ++fch) + { + if (tr.is_infinite(fch)) + { + output << "3 "; + for (Full_cell_vertex_iterator vit = fch->vertices_begin() ; + vit != fch->vertices_end() ; ++vit) + { + if (!tr.is_infinite(*vit)) + output << index_of_vertex[*vit] << " "; + } + output << std::endl; + ++number_of_triangles; + } + } + } + else + { + // Parse finite cells + for (Finite_full_cell_iterator fch = tr.finite_full_cells_begin() ; + fch != tr.finite_full_cells_end() ; ++fch) + { + output << "3 " + << index_of_vertex[fch->vertex(0)] << " " + << index_of_vertex[fch->vertex(1)] << " " + << index_of_vertex[fch->vertex(2)] + << std::endl; + output << "3 " + << index_of_vertex[fch->vertex(0)] << " " + << index_of_vertex[fch->vertex(2)] << " " + << index_of_vertex[fch->vertex(3)] + << std::endl; + output << "3 " + << index_of_vertex[fch->vertex(1)] << " " + << index_of_vertex[fch->vertex(2)] << " " + << index_of_vertex[fch->vertex(3)] + << std::endl; + output << "3 " + << index_of_vertex[fch->vertex(0)] << " " + << index_of_vertex[fch->vertex(1)] << " " + << index_of_vertex[fch->vertex(3)] + << std::endl; + number_of_triangles += 4; + } + } + } + + os << "OFF \n" + << n << " " + << number_of_triangles << " 0\n" + << output.str(); + + return os; +} + +} //namespace CGAL + +#endif // CGAL_TRIANGULATION_IO_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_LA_base.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_LA_base.h new file mode 100644 index 00000000..c13a9801 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_LA_base.h @@ -0,0 +1,177 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KERNEL_D_CARTESIAN_LA_BASE_H +#define CGAL_KERNEL_D_CARTESIAN_LA_BASE_H + +#include <CGAL/basic.h> +#include <CGAL/Origin.h> +#include <boost/type_traits/integral_constant.hpp> +#include <CGAL/representation_tags.h> +#include <CGAL/NewKernel_d/functor_tags.h> +#include <CGAL/Uncertain.h> +#include <CGAL/typeset.h> +#include <CGAL/NewKernel_d/Dimension_base.h> +#include <CGAL/NewKernel_d/Cartesian_LA_functors.h> +#include <CGAL/NewKernel_d/Vector/array.h> +#include <CGAL/NewKernel_d/Vector/vector.h> +#include <CGAL/NewKernel_d/Vector/mix.h> +#ifdef CGAL_EIGEN3_ENABLED +#include <CGAL/NewKernel_d/LA_eigen/LA.h> +#else +#error Eigen3 is required +#endif + +namespace CGAL { + +template < typename FT_, typename Dim_, +#if 1 + typename Vec_=Mix_vector<Array_vector<FT_, Dim_>, + Vector_vector<FT_, Dim_>, + FT_, Dim_>, +#elif 0 + typename Vec_=Array_vector<FT_, Dim_>, +#elif 0 + typename Vec_=Vector_vector<FT_, Dim_>, +#else + // Dangerous because of alignment. Ok on x86_64 without AVX. + typename Vec_=LA_eigen<FT_, Dim_>, +#endif + typename LA_=LA_eigen<FT_,Dim_> > + /* Default LA to Vec or to LA_eigen? */ +struct Cartesian_LA_base_d : public Dimension_base<Dim_> +{ + typedef Cartesian_LA_base_d<FT_,Dim_> Self; + typedef Cartesian_tag Rep_tag; + typedef Cartesian_tag Kernel_tag; + typedef Dim_ Default_ambient_dimension; + typedef Dim_ Max_ambient_dimension; + typedef Dim_ Dimension; + typedef LA_ LA; + template <class> struct Ambient_dimension { typedef Dim_ type; }; + + typedef Vec_ LA_vector; + typedef typename LA_vector::Vector Point; + typedef typename LA_vector::Vector Vector; + typedef typename LA_vector::Vector Vector_; + typedef typename LA_vector::Construct_vector Constructor; + typedef typename LA_vector::Vector_const_iterator Point_cartesian_const_iterator; + typedef typename LA_vector::Vector_const_iterator Vector_cartesian_const_iterator; + + template<class, class=void> struct Type {}; + template<class D> struct Type< Point_tag, D> { typedef Vector_ type; }; + template<class D> struct Type<Vector_tag, D> { typedef Vector_ type; }; + template<class D> struct Type< FT_tag, D> { typedef FT_ type; }; + template<class D> struct Type< RT_tag, D> { typedef FT_ type; }; + + typedef typeset<Point_tag> + ::add<Vector_tag>::type + // FIXME: These have nothing to do here. + ::add<Segment_tag>::type + ::add<Hyperplane_tag>::type + ::add<Sphere_tag>::type + ::add<Weighted_point_tag>::type + Object_list; + + typedef typeset< Point_cartesian_const_iterator_tag>::type + ::add<Vector_cartesian_const_iterator_tag>::type + Iterator_list; + + template<class, class=void, class=boost::integral_constant<int,0> > struct Functor { + typedef Null_functor type; + }; + template<class D> struct Functor<Construct_ttag<Vector_tag>,D> { + typedef CartesianDVectorBase::Construct_LA_vector<Self,Null_vector> type; + }; + template<class D> struct Functor<Construct_ttag<Point_tag>,D> { + typedef CartesianDVectorBase::Construct_LA_vector<Self,Origin> type; + }; + template<class D> struct Functor<Construct_ttag<Point_cartesian_const_iterator_tag>,D> { + typedef CartesianDVectorBase::Construct_cartesian_const_iterator<Self> type; + }; + template<class D> struct Functor<Construct_ttag<Vector_cartesian_const_iterator_tag>,D> { + typedef CartesianDVectorBase::Construct_cartesian_const_iterator<Self> type; + }; + template<class D> struct Functor<Sum_of_vectors_tag,D, + boost::integral_constant<int,!LA_vector::template Property<Has_vector_plus_minus_tag>::value> > { + typedef CartesianDVectorBase::Sum_of_vectors<Self> type; + }; + template<class D> struct Functor<Difference_of_vectors_tag,D, + boost::integral_constant<int,!LA_vector::template Property<Has_vector_plus_minus_tag>::value> > { + typedef CartesianDVectorBase::Difference_of_vectors<Self> type; + }; + template<class D> struct Functor<Opposite_vector_tag,D, + boost::integral_constant<int,!LA_vector::template Property<Has_vector_plus_minus_tag>::value> > { + typedef CartesianDVectorBase::Opposite_vector<Self> type; + }; + template<class D> struct Functor<Midpoint_tag,D, + boost::integral_constant<int, + !LA_vector::template Property<Has_vector_plus_minus_tag>::value + || !LA_vector::template Property<Has_vector_scalar_ops_tag>::value> > { + typedef CartesianDVectorBase::Midpoint<Self> type; + }; + template<class D> struct Functor<Compute_point_cartesian_coordinate_tag,D> { + typedef CartesianDVectorBase::Compute_cartesian_coordinate<Self> type; + }; + template<class D> struct Functor<Compute_vector_cartesian_coordinate_tag,D> { + typedef CartesianDVectorBase::Compute_cartesian_coordinate<Self> type; + }; + template<class D> struct Functor<Point_dimension_tag,D> { + typedef CartesianDVectorBase::PV_dimension<Self> type; + }; + template<class D> struct Functor<Vector_dimension_tag,D> { + typedef CartesianDVectorBase::PV_dimension<Self> type; + }; + template<class D> struct Functor<Orientation_of_vectors_tag,D, + boost::integral_constant<int,!LA_vector::template Property<Has_determinant_of_iterator_to_vectors_tag>::value> > { + typedef CartesianDVectorBase::Orientation_of_vectors<Self> type; + }; + template<class D> struct Functor<Orientation_of_points_tag,D, + boost::integral_constant<int,!LA_vector::template Property<Has_determinant_of_iterator_to_points_tag>::value> > { + typedef CartesianDVectorBase::Orientation_of_points<Self> type; + }; + template<class D> struct Functor<Scalar_product_tag,D, + boost::integral_constant<int,!LA_vector::template Property<Has_dot_product_tag>::value> > { + typedef CartesianDVectorBase::Scalar_product<Self> type; + }; + template<class D> struct Functor<Squared_distance_to_origin_tag,D, + boost::integral_constant<int,!LA_vector::template Property<Stores_squared_norm_tag>::value> > { + typedef CartesianDVectorBase::Squared_distance_to_origin_stored<Self> type; + }; + // Use integral_constant<int,2> in case of failure, to distinguish from the previous one. + template<class D> struct Functor<Squared_distance_to_origin_tag,D, + boost::integral_constant<int, + (LA_vector::template Property<Stores_squared_norm_tag>::value + || !LA_vector::template Property<Has_dot_product_tag>::value)*2> > { + typedef CartesianDVectorBase::Squared_distance_to_origin_via_dotprod<Self> type; + }; + template<class D> struct Functor<Point_to_vector_tag,D> { + typedef CartesianDVectorBase::Identity_functor<Self> type; + }; + template<class D> struct Functor<Vector_to_point_tag,D> { + typedef CartesianDVectorBase::Identity_functor<Self> type; + }; + + CGAL_CONSTEXPR Cartesian_LA_base_d(){} + CGAL_CONSTEXPR Cartesian_LA_base_d(int d):Dimension_base<Dim_>(d){} +}; + +} //namespace CGAL + +#endif // CGAL_KERNEL_D_CARTESIAN_LA_BASE_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_LA_functors.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_LA_functors.h new file mode 100644 index 00000000..871c463a --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_LA_functors.h @@ -0,0 +1,344 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_CARTESIAN_LA_FUNCTORS_H +#define CGAL_CARTESIAN_LA_FUNCTORS_H + +#include <CGAL/NewKernel_d/utils.h> +#include <CGAL/is_iterator.h> +#include <CGAL/argument_swaps.h> +#include <CGAL/Kernel/Return_base_tag.h> +#include <CGAL/transforming_iterator.h> +#include <CGAL/NewKernel_d/store_kernel.h> +#include <CGAL/Dimension.h> + +namespace CGAL { +namespace CartesianDVectorBase { +#ifndef CGAL_CXX11 +namespace internal { +template<class R_,class Dim_> struct Construct_LA_vector_ { + struct Never_use {}; + void operator()(Never_use)const; +}; +#define CGAL_CODE(Z,N,_) template<class R> struct Construct_LA_vector_<R,Dimension_tag<N> > { \ + typedef typename R::Constructor Constructor; \ + typedef typename Get_type<R, RT_tag>::type RT; \ + typedef typename R::Vector_ result_type; \ + result_type operator() \ + (BOOST_PP_ENUM_PARAMS(N,RT const& t)) const { \ + return typename Constructor::Values()(BOOST_PP_ENUM_PARAMS(N,t)); \ + } \ + result_type operator() \ + (BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(N),RT const& t)) const { \ + return typename Constructor::Values_divide()(t##N,BOOST_PP_ENUM_PARAMS(N,t)); \ + } \ + }; +BOOST_PP_REPEAT_FROM_TO(2, 11, CGAL_CODE, _ ) +#undef CGAL_CODE +} +#endif + +template<class R_,class Zero_> struct Construct_LA_vector +: private Store_kernel<R_> +#ifndef CGAL_CXX11 +, public internal::Construct_LA_vector_<R_,typename R_::Default_ambient_dimension> +#endif +{ + //CGAL_FUNCTOR_INIT_IGNORE(Construct_LA_vector) + CGAL_FUNCTOR_INIT_STORE(Construct_LA_vector) + typedef R_ R; + typedef typename R::Constructor Constructor; + typedef typename Get_type<R, RT_tag>::type RT; + typedef typename Get_type<R, FT_tag>::type FT; + typedef typename R::Vector_ result_type; + typedef typename R_::Default_ambient_dimension Dimension; + result_type operator()(int d)const{ + CGAL_assertion(check_dimension_eq(d,this->kernel().dimension())); + return typename Constructor::Dimension()(d); + } + result_type operator()()const{ + return typename Constructor::Dimension()((std::max)(0,this->kernel().dimension())); + } + result_type operator()(int d, Zero_ const&)const{ + CGAL_assertion(check_dimension_eq(d,this->kernel().dimension())); + return typename Constructor::Dimension()(d); + } + result_type operator()(Zero_ const&)const{ + // Makes no sense for an unknown dimension. + return typename Constructor::Dimension()(this->kernel().dimension()); + } + result_type operator()(result_type const& v)const{ + return v; + } +#ifdef CGAL_CXX11 + result_type operator()(result_type&& v)const{ + return std::move(v); + } +#endif +#ifdef CGAL_CXX11 + template<class...U> + typename std::enable_if<Constructible_from_each<RT,U...>::value && + boost::is_same<Dimension_tag<sizeof...(U)>, Dimension>::value, + result_type>::type + operator()(U&&...u)const{ + return typename Constructor::Values()(std::forward<U>(u)...); + } + //template<class...U,class=typename std::enable_if<Constructible_from_each<RT,U...>::value>::type,class=typename std::enable_if<(sizeof...(U)==static_dim+1)>::type,class=void> + template<class...U> + typename std::enable_if<Constructible_from_each<RT,U...>::value && + boost::is_same<Dimension_tag<sizeof...(U)-1>, Dimension>::value, + result_type>::type + operator()(U&&...u)const{ + return Apply_to_last_then_rest()(typename Constructor::Values_divide(),std::forward<U>(u)...); + } +#else + using internal::Construct_LA_vector_<R_,typename R::Default_ambient_dimension>::operator(); +#endif + template<class Iter> inline + typename boost::enable_if<is_iterator_type<Iter,std::forward_iterator_tag>,result_type>::type operator() + (Iter f,Iter g,Cartesian_tag t)const + { + return this->operator()((int)std::distance(f,g),f,g,t); + } + template<class Iter> inline + typename boost::enable_if<is_iterator_type<Iter,std::forward_iterator_tag>,result_type>::type operator() + (int d,Iter f,Iter g,Cartesian_tag)const + { + CGAL_assertion(d==std::distance(f,g)); + CGAL_assertion(check_dimension_eq(d,this->kernel().dimension())); + return typename Constructor::Iterator()(d,f,g); + } + template<class Iter> inline + typename boost::enable_if<is_iterator_type<Iter,std::bidirectional_iterator_tag>,result_type>::type operator() + (Iter f,Iter g,Homogeneous_tag)const + { + --g; + return this->operator()((int)std::distance(f,g),f,g,*g); + } + template<class Iter> inline + typename boost::enable_if<is_iterator_type<Iter,std::bidirectional_iterator_tag>,result_type>::type operator() + (int d,Iter f,Iter g,Homogeneous_tag)const + { + --g; + return this->operator()(d,f,g,*g); + } + template<class Iter> inline + typename boost::enable_if<is_iterator_type<Iter,std::forward_iterator_tag>,result_type>::type operator() + (Iter f,Iter g)const + { + // Shouldn't it try comparing dist(f,g) to the dimension if it is known? + return this->operator()(f,g,typename R::Rep_tag()); + } + template<class Iter> inline + typename boost::enable_if<is_iterator_type<Iter,std::forward_iterator_tag>,result_type>::type operator() + (int d,Iter f,Iter g)const + { + return this->operator()(d,f,g,typename R::Rep_tag()); + } + + // Last homogeneous coordinate given separately + template<class Iter,class NT> inline + typename boost::enable_if<is_iterator_type<Iter,std::forward_iterator_tag>,result_type>::type operator() + (int d,Iter f,Iter g,NT const&l)const + { + CGAL_assertion(d==std::distance(f,g)); + CGAL_assertion(check_dimension_eq(d,this->kernel().dimension())); + // RT? better be safe for now + return typename Constructor::Iterator()(d,CGAL::make_transforming_iterator(f,Divide<FT,NT>(l)),CGAL::make_transforming_iterator(g,Divide<FT,NT>(l))); + } + template<class Iter,class NT> inline + typename boost::enable_if<is_iterator_type<Iter,std::forward_iterator_tag>,result_type>::type operator() + (Iter f,Iter g,NT const&l)const + { + return this->operator()((int)std::distance(f,g),f,g,l); + } +}; + +template<class R_> struct Compute_cartesian_coordinate { + CGAL_FUNCTOR_INIT_IGNORE(Compute_cartesian_coordinate) + typedef R_ R; + typedef typename Get_type<R, RT_tag>::type RT; + typedef typename R::Vector_ first_argument_type; + typedef int second_argument_type; + typedef Tag_true Is_exact; +#ifdef CGAL_CXX11 + typedef decltype(std::declval<const first_argument_type>()[0]) result_type; +#else + typedef RT const& result_type; + // RT const& doesn't work with some LA (Eigen2 for instance) so we + // should use plain RT or find a way to detect this. +#endif + + result_type operator()(first_argument_type const& v,int i)const{ + return v[i]; + } +}; + +template<class R_> struct Construct_cartesian_const_iterator { + CGAL_FUNCTOR_INIT_IGNORE(Construct_cartesian_const_iterator) + typedef R_ R; + typedef typename R::Vector_ argument_type; + typedef typename R::LA_vector S_; + typedef typename R::Point_cartesian_const_iterator result_type; + // same as Vector + typedef Tag_true Is_exact; + + result_type operator()(argument_type const& v,Begin_tag)const{ + return S_::vector_begin(v); + } + result_type operator()(argument_type const& v,End_tag)const{ + return S_::vector_end(v); + } +}; + +template<class R_> struct Midpoint { + CGAL_FUNCTOR_INIT_IGNORE(Midpoint) + typedef R_ R; + typedef typename Get_type<R, Point_tag>::type first_argument_type; + typedef typename Get_type<R, Point_tag>::type second_argument_type; + typedef typename Get_type<R, Point_tag>::type result_type; + + result_type operator()(result_type const& a, result_type const& b)const{ + return (a+b)/2; + } +}; + +template<class R_> struct Sum_of_vectors { + CGAL_FUNCTOR_INIT_IGNORE(Sum_of_vectors) + typedef R_ R; + typedef typename Get_type<R, Vector_tag>::type first_argument_type; + typedef typename Get_type<R, Vector_tag>::type second_argument_type; + typedef typename Get_type<R, Vector_tag>::type result_type; + + result_type operator()(result_type const& a, result_type const& b)const{ + return a+b; + } +}; + +template<class R_> struct Difference_of_vectors { + CGAL_FUNCTOR_INIT_IGNORE(Difference_of_vectors) + typedef R_ R; + typedef typename Get_type<R, Vector_tag>::type first_argument_type; + typedef typename Get_type<R, Vector_tag>::type second_argument_type; + typedef typename Get_type<R, Vector_tag>::type result_type; + + result_type operator()(result_type const& a, result_type const& b)const{ + return a-b; + } +}; + +template<class R_> struct Opposite_vector { + CGAL_FUNCTOR_INIT_IGNORE(Opposite_vector) + typedef R_ R; + typedef typename Get_type<R, Vector_tag>::type result_type; + typedef typename Get_type<R, Vector_tag>::type argument_type; + + result_type operator()(result_type const& v)const{ + return -v; + } +}; + +template<class R_> struct Scalar_product { + CGAL_FUNCTOR_INIT_IGNORE(Scalar_product) + typedef R_ R; + typedef typename R::LA_vector LA; + typedef typename Get_type<R, RT_tag>::type result_type; + typedef typename Get_type<R, Vector_tag>::type first_argument_type; + typedef typename Get_type<R, Vector_tag>::type second_argument_type; + + result_type operator()(first_argument_type const& a, second_argument_type const& b)const{ + return LA::dot_product(a,b); + } +}; + +template<class R_> struct Squared_distance_to_origin_stored { + CGAL_FUNCTOR_INIT_IGNORE(Squared_distance_to_origin_stored) + typedef R_ R; + typedef typename R::LA_vector LA; + typedef typename Get_type<R, RT_tag>::type result_type; + typedef typename Get_type<R, Point_tag>::type argument_type; + + result_type operator()(argument_type const& a)const{ + return LA::squared_norm(a); + } +}; + +template<class R_> struct Squared_distance_to_origin_via_dotprod { + CGAL_FUNCTOR_INIT_IGNORE(Squared_distance_to_origin_via_dotprod) + typedef R_ R; + typedef typename R::LA_vector LA; + typedef typename Get_type<R, RT_tag>::type result_type; + typedef typename Get_type<R, Point_tag>::type argument_type; + + result_type operator()(argument_type const& a)const{ + return LA::dot_product(a,a); + } +}; + +template<class R_> struct Orientation_of_vectors { + CGAL_FUNCTOR_INIT_IGNORE(Orientation_of_vectors) + typedef R_ R; + typedef typename R::Vector_cartesian_const_iterator first_argument_type; + typedef typename R::Vector_cartesian_const_iterator second_argument_type; + typedef typename Get_type<R, Orientation_tag>::type result_type; + typedef typename R::LA_vector LA; + + template<class Iter> + result_type operator()(Iter const& f, Iter const& e) const { + return LA::determinant_of_iterators_to_vectors(f,e); + } +}; + +template<class R_> struct Orientation_of_points { + CGAL_FUNCTOR_INIT_IGNORE(Orientation_of_points) + typedef R_ R; + typedef typename R::Point_cartesian_const_iterator first_argument_type; + typedef typename R::Point_cartesian_const_iterator second_argument_type; + typedef typename Get_type<R, Orientation_tag>::type result_type; + typedef typename R::LA_vector LA; + + template<class Iter> + result_type operator()(Iter const& f, Iter const& e) const { + return LA::determinant_of_iterators_to_points(f,e); + } +}; + +template<class R_> struct PV_dimension { + CGAL_FUNCTOR_INIT_IGNORE(PV_dimension) + typedef R_ R; + typedef typename R::Vector_ argument_type; + typedef int result_type; + typedef typename R::LA_vector LA; + typedef Tag_true Is_exact; + + template<class T> + result_type operator()(T const& v) const { + return LA::size_of_vector(v); + } +}; + +template<class R_> struct Identity_functor { + CGAL_FUNCTOR_INIT_IGNORE(Identity_functor) + template<class T> + T const& operator()(T const&t) const { return t; } +}; + +} +} // namespace CGAL +#endif // CGAL_CARTESIAN_LA_FUNCTORS_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_base.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_base.h new file mode 100644 index 00000000..641bf8ae --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_base.h @@ -0,0 +1,40 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KERNEL_D_CARTESIAN_BASE_H +#define CGAL_KERNEL_D_CARTESIAN_BASE_H + +#include <CGAL/basic.h> +#include <CGAL/NewKernel_d/Cartesian_complete.h> +#include <CGAL/NewKernel_d/Cartesian_LA_base.h> + +namespace CGAL { +#define CGAL_BASE \ + Cartesian_LA_base_d< FT_, Dim_ > +template < typename FT_, typename Dim_, typename Derived_=Default> +struct Cartesian_base_d : public CGAL_BASE +{ + CGAL_CONSTEXPR Cartesian_base_d(){} + CGAL_CONSTEXPR Cartesian_base_d(int d):CGAL_BASE(d){} +}; +#undef CGAL_BASE + +} //namespace CGAL + +#endif // CGAL_KERNEL_D_CARTESIAN_BASE_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_change_FT.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_change_FT.h new file mode 100644 index 00000000..e09c72d0 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_change_FT.h @@ -0,0 +1,117 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KERNEL_D_CARTESIAN_CHANGE_FT_H +#define CGAL_KERNEL_D_CARTESIAN_CHANGE_FT_H + +#include <CGAL/basic.h> +#include <CGAL/NT_converter.h> +#include <CGAL/transforming_iterator.h> +#include <CGAL/NewKernel_d/Cartesian_complete.h> + +namespace CGAL { + +template < typename Base_, typename FT_, typename LA_=CGAL::LA_eigen<FT_,typename Base_::Default_ambient_dimension> > +struct Cartesian_change_FT_base : public + Base_ +{ + CGAL_CONSTEXPR Cartesian_change_FT_base(){} + CGAL_CONSTEXPR Cartesian_change_FT_base(int d):Base_(d){} + + typedef Cartesian_change_FT_base Self; + typedef Base_ Kernel_base; + typedef LA_ LA; + + template <class T, class D=void> struct Type : Inherit_type<Base_, T> {}; + template <class D> struct Type <FT_tag, D> { typedef FT_ type; }; + template <class D> struct Type <RT_tag, D> { typedef FT_ type; }; + + typedef NT_converter<typename Get_type<Kernel_base, FT_tag>::type,FT_> FT_converter; + typedef transforming_iterator<FT_converter,typename Kernel_base::Point_cartesian_const_iterator> Point_cartesian_const_iterator; + typedef transforming_iterator<FT_converter,typename Kernel_base::Vector_cartesian_const_iterator> Vector_cartesian_const_iterator; + //FIXME: use Iterator_list! + /* + template<class T,bool=CGAL_BOOSTD is_same<typename iterator_tag_traits<T>::value_tag,FT_tag>::value> + struct Iterator : Get_type<Kernel_base,T> {}; + template<class T> struct Iterator<T,true> { + typedef transforming_iterator<FT_converter,typename Get_type<Kernel_base,T>::type> type; + }; + */ + + template<class Tag_,class Type_> + struct Construct_cartesian_const_iterator_ { + typedef typename Get_functor<Kernel_base, Tag_>::type Functor_base; + Construct_cartesian_const_iterator_(){} + Construct_cartesian_const_iterator_(Self const&r):f(r){} + Functor_base f; + typedef Type_ result_type; + template<class T> + result_type operator()(T const& v, Begin_tag)const{ + return make_transforming_iterator(f(v,Begin_tag()),FT_converter()); + } + template<class T> + result_type operator()(T const& v, End_tag)const{ + return make_transforming_iterator(f(v,End_tag()),FT_converter()); + } + }; + typedef Construct_cartesian_const_iterator_<Construct_ttag<Point_cartesian_const_iterator_tag>,Point_cartesian_const_iterator> Construct_point_cartesian_const_iterator; + typedef Construct_cartesian_const_iterator_<Construct_ttag<Vector_cartesian_const_iterator_tag>,Vector_cartesian_const_iterator> Construct_vector_cartesian_const_iterator; + + template<class Tag_> + struct Compute_cartesian_coordinate { + typedef typename Get_functor<Kernel_base, Tag_>::type Functor_base; + Compute_cartesian_coordinate(){} + Compute_cartesian_coordinate(Self const&r):f(r){} + Functor_base f; + typedef FT_ result_type; + template<class Obj_> + result_type operator()(Obj_ const& v,int i)const{ + return FT_converter()(f(v,i)); + } + }; + + template<class T,class U=void,class=typename Get_functor_category<Cartesian_change_FT_base,T>::type> struct Functor : + Inherit_functor<Kernel_base,T,U> { }; + template<class T,class U> struct Functor<T,U,Compute_tag> { }; + template<class T,class U> struct Functor<T,U,Predicate_tag> { }; + template<class D> struct Functor<Compute_point_cartesian_coordinate_tag,D,Compute_tag> { + typedef Compute_cartesian_coordinate<Compute_point_cartesian_coordinate_tag> type; + }; + template<class D> struct Functor<Compute_vector_cartesian_coordinate_tag,D,Compute_tag> { + typedef Compute_cartesian_coordinate<Compute_vector_cartesian_coordinate_tag> type; + }; + template<class D> struct Functor<Construct_ttag<Point_cartesian_const_iterator_tag>,D,Construct_iterator_tag> { + typedef Construct_point_cartesian_const_iterator type; + }; + template<class D> struct Functor<Construct_ttag<Vector_cartesian_const_iterator_tag>,D,Construct_iterator_tag> { + typedef Construct_vector_cartesian_const_iterator type; + }; +}; + +template < typename Base_, typename FT_> +struct Cartesian_change_FT : public + Cartesian_change_FT_base<Base_,FT_> +{ + CGAL_CONSTEXPR Cartesian_change_FT(){} + CGAL_CONSTEXPR Cartesian_change_FT(int d):Cartesian_change_FT_base<Base_,FT_>(d){} +}; + +} //namespace CGAL + +#endif // CGAL_KERNEL_D_CARTESIAN_CHANGE_FT_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_complete.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_complete.h new file mode 100644 index 00000000..ef8921db --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_complete.h @@ -0,0 +1,33 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KERNEL_D_CARTESIAN_COMPLETE_H +#define CGAL_KERNEL_D_CARTESIAN_COMPLETE_H + +#include <CGAL/NewKernel_d/function_objects_cartesian.h> +#include <CGAL/NewKernel_d/Cartesian_per_dimension.h> +#include <CGAL/NewKernel_d/Types/Segment.h> +#include <CGAL/NewKernel_d/Types/Sphere.h> +#include <CGAL/NewKernel_d/Types/Hyperplane.h> +#include <CGAL/NewKernel_d/Types/Aff_transformation.h> +#include <CGAL/NewKernel_d/Types/Line.h> +#include <CGAL/NewKernel_d/Types/Ray.h> +#include <CGAL/NewKernel_d/Types/Iso_box.h> + +#endif // CGAL_KERNEL_D_CARTESIAN_COMPLETE_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_filter_K.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_filter_K.h new file mode 100644 index 00000000..179e97bf --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_filter_K.h @@ -0,0 +1,79 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KERNEL_D_CARTESIAN_FILTER_K_H +#define CGAL_KERNEL_D_CARTESIAN_FILTER_K_H + +#include <CGAL/basic.h> +#include <CGAL/NewKernel_d/KernelD_converter.h> +#include <CGAL/NewKernel_d/Filtered_predicate2.h> +#include <boost/mpl/if.hpp> +#include <boost/mpl/and.hpp> + +namespace CGAL { + +template < typename Base_, typename AK_, typename EK_ > +struct Cartesian_filter_K : public Base_, + private Store_kernel<AK_>, private Store_kernel2<EK_> +{ + CGAL_CONSTEXPR Cartesian_filter_K(){} + CGAL_CONSTEXPR Cartesian_filter_K(int d):Base_(d){} + //FIXME: or do we want an instance of AK and EK belonging to this kernel, + //instead of a reference to external ones? + CGAL_CONSTEXPR Cartesian_filter_K(AK_ const&a,EK_ const&b):Base_(),Store_kernel<AK_>(a),Store_kernel2<EK_>(b){} + CGAL_CONSTEXPR Cartesian_filter_K(int d,AK_ const&a,EK_ const&b):Base_(d),Store_kernel<AK_>(a),Store_kernel2<EK_>(b){} + typedef Base_ Kernel_base; + typedef AK_ AK; + typedef EK_ EK; + typedef typename Store_kernel<AK_>::reference_type AK_rt; + AK_rt approximate_kernel()const{return this->kernel();} + typedef typename Store_kernel2<EK_>::reference2_type EK_rt; + EK_rt exact_kernel()const{return this->kernel2();} + + // MSVC is too dumb to perform the empty base optimization. + typedef boost::mpl::and_< + internal::Do_not_store_kernel<Kernel_base>, + internal::Do_not_store_kernel<AK>, + internal::Do_not_store_kernel<EK> > Do_not_store_kernel; + + //TODO: C2A/C2E could be able to convert *this into this->kernel() or this->kernel2(). + typedef KernelD_converter<Kernel_base,AK> C2A; + typedef KernelD_converter<Kernel_base,EK> C2E; + + // fix the types + // TODO: only fix some types, based on some criterion? + template<class T> struct Type : Get_type<Kernel_base,T> {}; + + template<class T,class D=void,class=typename Get_functor_category<Cartesian_filter_K,T>::type> struct Functor : + Inherit_functor<Kernel_base,T,D> {}; + template<class T,class D> struct Functor<T,D,Predicate_tag> { + typedef typename Get_functor<AK, T>::type AP; + typedef typename Get_functor<EK, T>::type EP; + typedef Filtered_predicate2<EP,AP,C2E,C2A> type; + }; +// TODO: +// template<class T> struct Functor<T,No_filter_tag,Predicate_tag> : +// Kernel_base::template Functor<T,No_filter_tag> {}; +// TODO: +// detect when Less_cartesian_coordinate doesn't need filtering +}; + +} //namespace CGAL + +#endif // CGAL_KERNEL_D_CARTESIAN_FILTER_K_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_filter_NT.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_filter_NT.h new file mode 100644 index 00000000..c390a55c --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_filter_NT.h @@ -0,0 +1,93 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KERNEL_D_CARTESIAN_FILTER_NT_H +#define CGAL_KERNEL_D_CARTESIAN_FILTER_NT_H + +#include <CGAL/basic.h> +#include <CGAL/NewKernel_d/Cartesian_change_FT.h> +#include <CGAL/internal/Exact_type_selector.h> + +namespace CGAL { + +template < typename Base_ > +struct Cartesian_filter_NT : public Base_ +{ + CGAL_CONSTEXPR Cartesian_filter_NT(){} + CGAL_CONSTEXPR Cartesian_filter_NT(int d):Base_(d){} + typedef Base_ Kernel_base; + typedef Cartesian_change_FT<Kernel_base,Interval_nt_advanced> K1; + typedef typename internal::Exact_field_selector<typename Get_type<Kernel_base, FT_tag>::type>::Type Exact_nt; + typedef Cartesian_change_FT<Kernel_base,Exact_nt> K2; + + template<class T,class D=void,class=typename Get_functor_category<Cartesian_filter_NT,T>::type> struct Functor : + Inherit_functor<Kernel_base,T,D> {}; + template<class T,class D> struct Functor<T,D,Predicate_tag> { + struct type { + //TODO: use compression (derive from a compressed_pair?) + typedef typename Get_functor<K1, T>::type P1; P1 p1; + typedef typename Get_functor<K2, T>::type P2; P2 p2; + typedef typename P2::result_type result_type; + type(){} + type(Cartesian_filter_NT const&k):p1(reinterpret_cast<K1 const&>(k)),p2(reinterpret_cast<K2 const&>(k)){} + //FIXME: if predicate's constructor takes a kernel as argument, how do we translate that? reinterpret_cast is really ugly and possibly unsafe. + +#ifdef CGAL_CXX11 + template<class...U> result_type operator()(U&&...u)const{ + { + Protect_FPU_rounding<true> p; + try { + typename P1::result_type res=p1(u...); // don't forward as u may be reused + if(is_certain(res)) return get_certain(res); + } catch (Uncertain_conversion_exception) {} + } + return p2(std::forward<U>(u)...); + } +#else + result_type operator()()const{ // does it make sense to have 0 argument? + { + Protect_FPU_rounding<true> p; + try { + typename P1::result_type res=p1(); + if(is_certain(res)) return get_certain(res); + } catch (Uncertain_conversion_exception) {} + } + return p2(); + } +#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class T)> result_type operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t))const{ \ + { \ + Protect_FPU_rounding<true> p; \ + try { \ + typename P1::result_type res=p1(BOOST_PP_ENUM_PARAMS(N,t)); \ + if(is_certain(res)) return get_certain(res); \ + } catch (Uncertain_conversion_exception) {} \ + } \ + return p2(BOOST_PP_ENUM_PARAMS(N,t)); \ + } + BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_) +#undef CGAL_CODE + +#endif + }; + }; +}; + +} //namespace CGAL + +#endif // CGAL_KERNEL_D_CARTESIAN_FILTER_NT_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_per_dimension.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_per_dimension.h new file mode 100644 index 00000000..179f7319 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_per_dimension.h @@ -0,0 +1,33 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KD_CARTESIAN_PER_DIM_H +#define CGAL_KD_CARTESIAN_PER_DIM_H +#include <CGAL/NewKernel_d/functor_tags.h> +#include <CGAL/Dimension.h> +#include <CGAL/predicates/sign_of_determinant.h> + +// Should probably disappear. + +namespace CGAL { +template <class Dim_, class R_, class Derived_> +struct Cartesian_per_dimension : public R_ {}; +} + +#endif diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_static_filters.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_static_filters.h new file mode 100644 index 00000000..693e962a --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Cartesian_static_filters.h @@ -0,0 +1,95 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KD_CARTESIAN_STATIC_FILTERS_H +#define CGAL_KD_CARTESIAN_STATIC_FILTERS_H +#include <CGAL/NewKernel_d/functor_tags.h> +#include <CGAL/Dimension.h> +#include <CGAL/internal/Static_filters/tools.h> // bug, should be included by the next one +#include <CGAL/internal/Static_filters/Orientation_2.h> +#include <boost/mpl/if.hpp> + +namespace CGAL { +namespace SFA { // static filter adapter +// Note that this would be quite a bit simpler without stateful kernels +template <class Base_,class R_> struct Orientation_of_points_2 : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Orientation_of_points_2) + typedef typename Get_type<R_, Point_tag>::type Point; + typedef typename Get_type<R_, Orientation_tag>::type result_type; + typedef typename Get_type<R_, FT_tag>::type FT; + typedef typename Get_functor<R_, Compute_point_cartesian_coordinate_tag>::type CC; + typedef typename Get_functor<Base_, Orientation_of_points_tag>::type Orientation_base; + // TODO: Move this out for easy reuse + struct Adapter { + struct Point_2 { + R_ const&r; CC const&c; Point const& p; + Point_2(R_ const&r_, CC const&c_, Point const&p_):r(r_),c(c_),p(p_){} + // use result_of instead? + typename CC::result_type x()const{return c(p,0);} + typename CC::result_type y()const{return c(p,1);} + }; + struct Vector_2 {}; + struct Circle_2 {}; + struct Orientation_2 { + typedef typename Orientation_of_points_2::result_type result_type; + result_type operator()(Point_2 const&A, Point_2 const&B, Point_2 const&C)const{ + Point const* t[3]={&A.p,&B.p,&C.p}; + return Orientation_base(A.r)(make_transforming_iterator<Dereference_functor>(t+0),make_transforming_iterator<Dereference_functor>(t+3)); + } + }; + }; + template<class Iter> result_type operator()(Iter f, Iter CGAL_assertion_code(e))const{ + CC c(this->kernel()); + Point const& A=*f; + Point const& B=*++f; + Point const& C=*++f; + CGAL_assertion(++f==e); + typedef typename Adapter::Point_2 P; + return typename internal::Static_filters_predicates::Orientation_2<Adapter>()(P(this->kernel(),c,A),P(this->kernel(),c,B),P(this->kernel(),c,C)); + } +}; +} + +template <class Dim_ /* should be implicit */, class R_, class Derived_=Default> +struct Cartesian_static_filters : public R_ { + CGAL_CONSTEXPR Cartesian_static_filters(){} + CGAL_CONSTEXPR Cartesian_static_filters(int d):R_(d){} +}; + +template <class R_, class Derived_> +struct Cartesian_static_filters<Dimension_tag<2>, R_, Derived_> : public R_ { + CGAL_CONSTEXPR Cartesian_static_filters(){} + CGAL_CONSTEXPR Cartesian_static_filters(int d):R_(d){} + typedef Cartesian_static_filters<Dimension_tag<2>, R_, Derived_> Self; + typedef typename Default::Get<Derived_,Self>::type Derived; + template <class T, class=void> struct Functor : Inherit_functor<R_, T> {}; + template <class D> struct Functor <Orientation_of_points_tag,D> { + typedef + //typename boost::mpl::if_ < + //boost::is_same<D,No_filter_tag>, + //typename Get_functor<R_, Orientation_of_points_tag>::type, + SFA::Orientation_of_points_2<R_,Derived> + // >::type + type; + }; +}; + +} + +#endif diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Coaffine.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Coaffine.h new file mode 100644 index 00000000..43015d24 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Coaffine.h @@ -0,0 +1,330 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KD_COAFFINE_H +#define CGAL_KD_COAFFINE_H +#include <vector> +#include <algorithm> +#include <iterator> +#include <CGAL/Dimension.h> +#include <CGAL/NewKernel_d/functor_tags.h> + +namespace CGAL { +namespace CartesianDKernelFunctors { +struct Flat_orientation { + std::vector<int> proj; + std::vector<int> rest; + bool reverse; +}; + +// For debugging purposes +inline std::ostream& operator<< (std::ostream& o, Flat_orientation const& f) { + o << "Proj: "; + for(std::vector<int>::const_iterator i=f.proj.begin(); + i!=f.proj.end(); ++i) + o << *i << ' '; + o << "\nRest: "; + for(std::vector<int>::const_iterator i=f.rest.begin(); + i!=f.rest.end(); ++i) + o << *i << ' '; + o << "\nInv: " << f.reverse; + return o << '\n'; +} + +namespace internal { +namespace coaffine { +template<class Mat> +inline void debug_matrix(std::ostream& o, Mat const&mat) { + for(int i=0;i<mat.rows();++i){ + for(int j=0;j<mat.cols();++j){ + o<<mat(i,j)<<' '; + } + o<<'\n'; + } +} +} +} + +template<class R_> struct Construct_flat_orientation : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Construct_flat_orientation) + typedef R_ R; + typedef typename Get_type<R, FT_tag>::type FT; + typedef typename Get_type<R, Point_tag>::type Point; + typedef typename Increment_dimension<typename R::Max_ambient_dimension>::type Dplusone; + typedef typename R::LA::template Rebind_dimension<Dynamic_dimension_tag,Dplusone>::Other LA; + typedef typename LA::Square_matrix Matrix; + typedef typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type CCC; + typedef typename Get_functor<R, Point_dimension_tag>::type PD; + typedef Flat_orientation result_type; + + // This implementation is going to suck. Maybe we should push the + // functionality into LA. And we should check (in debug mode) that + // the points are affinely independent. + template<class Iter> + result_type operator()(Iter f, Iter e)const{ + Iter f_save = f; + PD pd (this->kernel()); + CCC ccc (this->kernel()); + int dim = pd(*f); + Matrix coord (dim+1, dim+1); // use distance(f,e)? This matrix doesn't need to be square. + int col = 0; + Flat_orientation o; + std::vector<int>& proj=o.proj; + std::vector<int>& rest=o.rest; rest.reserve(dim+1); + for(int i=0; i<dim+1; ++i) rest.push_back(i); + for( ; f != e ; ++col, ++f ) { + //std::cerr << "(*f)[0]=" << (*f)[0] << std::endl; + Point const&p=*f; + // use a coordinate iterator instead? + for(int i=0; i<dim; ++i) coord(col, i) = ccc(p, i); + coord(col,dim)=1; + int d = (int)proj.size()+1; + Matrix m (d, d); + // Fill the matrix with what we already have + for(int i=0; i<d; ++i) + for(int j=0; j<d-1; ++j) + m(i,j) = coord(i, proj[j]); + // Try to complete with any other coordinate + // TODO: iterate on rest by the end, or use a (forward_)list. + for(std::vector<int>::iterator it=rest.begin();;++it) { + CGAL_assertion(it!=rest.end()); + for(int i=0; i<d; ++i) m(i,d-1) = coord(i, *it); + if(LA::sign_of_determinant(m)!=0) { + proj.push_back(*it); + rest.erase(it); + break; + } + } + } + std::sort(proj.begin(),proj.end()); + typename Get_functor<R, In_flat_orientation_tag>::type ifo(this->kernel()); + o.reverse = false; + o.reverse = ifo(o, f_save, e) != CGAL::POSITIVE; + return o; + } +}; + +template<class R_> struct Contained_in_affine_hull : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Contained_in_affine_hull) + typedef R_ R; + typedef typename Get_type<R, FT_tag>::type FT; + typedef typename Get_type<R, Point_tag>::type Point; + typedef typename Get_type<R, Bool_tag>::type result_type; + typedef typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type CCC; + typedef typename Get_functor<R, Point_dimension_tag>::type PD; + //typedef typename Increment_dimension<typename R::Default_ambient_dimension>::type D1; + //typedef typename Increment_dimension<typename R::Max_ambient_dimension>::type D2; + //typedef typename R::LA::template Rebind_dimension<D1,D2>::Other LA; + typedef typename Increment_dimension<typename R::Max_ambient_dimension>::type Dplusone; + typedef typename R::LA::template Rebind_dimension<Dynamic_dimension_tag,Dplusone>::Other LA; + typedef typename LA::Square_matrix Matrix; + + // mostly copied from Construct_flat_orientation. TODO: dedup this code or use LA. + template<class Iter> + result_type operator()(Iter f, Iter e, Point const&x) const { + // FIXME: are the points in (f,e) required to be affinely independent? + PD pd (this->kernel()); + CCC ccc (this->kernel()); + int dim=pd(*f); + Matrix coord (dim+1, dim+1); // use distance + int col = 0; + std::vector<int> proj; + std::vector<int> rest; rest.reserve(dim+1); + for(int i=0; i<dim+1; ++i) rest.push_back(i); + for( ; f != e ; ++col, ++f ) { + Point const&p=*f; + for(int i=0; i<dim; ++i) coord(col, i) = ccc(p, i); + coord(col,dim)=1; + int d = (int)proj.size()+1; + Matrix m (d, d); + for(int i=0; i<d; ++i) + for(int j=0; j<d-1; ++j) + m(i,j) = coord(i, proj[j]); + for(std::vector<int>::iterator it=rest.begin();it!=rest.end();++it) { + for(int i=0; i<d; ++i) m(i,d-1) = coord(i, *it); + if(LA::sign_of_determinant(m)!=0) { + proj.push_back(*it); + rest.erase(it); + break; + } + } + } + for(int i=0; i<dim; ++i) coord(col, i) = ccc(x, i); + coord(col,dim)=1; + int d = (int)proj.size()+1; + Matrix m (d, d); + for(int i=0; i<d; ++i) + for(int j=0; j<d-1; ++j) + m(i,j) = coord(i, proj[j]); + for(std::vector<int>::iterator it=rest.begin();it!=rest.end();++it) { + for(int i=0; i<d; ++i) m(i,d-1) = coord(i, *it); + if(LA::sign_of_determinant(m)!=0) return false; + } + return true; + } +}; + +template<class R_> struct In_flat_orientation : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(In_flat_orientation) + typedef R_ R; + typedef typename Get_type<R, FT_tag>::type FT; + typedef typename Get_type<R, Point_tag>::type Point; + typedef typename Get_type<R, Orientation_tag>::type result_type; + typedef typename Increment_dimension<typename R::Default_ambient_dimension>::type D1; + typedef typename Increment_dimension<typename R::Max_ambient_dimension>::type D2; + typedef typename R::LA::template Rebind_dimension<D1,D2>::Other LA; + typedef typename LA::Square_matrix Matrix; + + template<class Iter> + result_type operator()(Flat_orientation const&o, Iter f, Iter e) const { + // TODO: work in the projection instead of the ambient space. + typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type c(this->kernel()); + typename Get_functor<R, Point_dimension_tag>::type pd(this->kernel()); + int d=pd(*f); + Matrix m(d+1,d+1); + int i=0; + for(;f!=e;++f,++i) { + Point const& p=*f; + m(i,0)=1; + for(int j=0;j<d;++j){ + m(i,j+1)=c(p,j); + } + } + for(std::vector<int>::const_iterator it = o.rest.begin(); it != o.rest.end() /* i<d+1 */; ++i, ++it) { + m(i,0)=1; + for(int j=0;j<d;++j){ + m(i,j+1)=0; // unneeded if the matrix is initialized to 0 + } + if(*it != d) m(i,1+*it)=1; + } + + result_type ret = LA::sign_of_determinant(CGAL_MOVE(m)); + if(o.reverse) ret=-ret; + return ret; + } +}; + +template<class R_> struct In_flat_side_of_oriented_sphere : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(In_flat_side_of_oriented_sphere) + typedef R_ R; + typedef typename Get_type<R, FT_tag>::type FT; + typedef typename Get_type<R, Point_tag>::type Point; + typedef typename Get_type<R, Orientation_tag>::type result_type; + typedef typename Increment_dimension<typename R::Default_ambient_dimension,2>::type D1; + typedef typename Increment_dimension<typename R::Max_ambient_dimension,2>::type D2; + typedef typename R::LA::template Rebind_dimension<D1,D2>::Other LA; + typedef typename LA::Square_matrix Matrix; + + template<class Iter> + result_type operator()(Flat_orientation const&o, Iter f, Iter e, Point const&x) const { + // TODO: can't work in the projection, but we should at least remove the row of 1s. + typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type c(this->kernel()); + typename Get_functor<R, Point_dimension_tag>::type pd(this->kernel()); + int d=pd(*f); + Matrix m(d+2,d+2); + int i=0; + for(;f!=e;++f,++i) { + Point const& p=*f; + m(i,0)=1; + m(i,d+1)=0; + for(int j=0;j<d;++j){ + m(i,j+1)=c(p,j); + m(i,d+1)+=CGAL_NTS square(m(i,j+1)); + } + } + for(std::vector<int>::const_iterator it = o.rest.begin(); it != o.rest.end() /* i<d+1 */; ++i, ++it) { + m(i,0)=1; + for(int j=0;j<d;++j){ + m(i,j+1)=0; // unneeded if the matrix is initialized to 0 + } + if(*it != d) m(i,d+1)=m(i,1+*it)=1; + else m(i,d+1)=0; + } + m(d+1,0)=1; + m(d+1,d+1)=0; + for(int j=0;j<d;++j){ + m(d+1,j+1)=c(x,j); + m(d+1,d+1)+=CGAL_NTS square(m(d+1,j+1)); + } + + result_type ret = -LA::sign_of_determinant(CGAL_MOVE(m)); + if(o.reverse) ret=-ret; + return ret; + } +}; + +template<class R_> struct In_flat_power_side_of_power_sphere_raw : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(In_flat_power_side_of_power_sphere_raw) + typedef R_ R; + typedef typename Get_type<R, FT_tag>::type FT; + typedef typename Get_type<R, Point_tag>::type Point; + typedef typename Get_type<R, Orientation_tag>::type result_type; + typedef typename Increment_dimension<typename R::Default_ambient_dimension,2>::type D1; + typedef typename Increment_dimension<typename R::Max_ambient_dimension,2>::type D2; + typedef typename R::LA::template Rebind_dimension<D1,D2>::Other LA; + typedef typename LA::Square_matrix Matrix; + + template<class Iter, class IterW, class Wt> + result_type operator()(Flat_orientation const&o, Iter f, Iter e, IterW fw, Point const&x, Wt const&w) const { + // TODO: can't work in the projection, but we should at least remove the row of 1s. + typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type c(this->kernel()); + typename Get_functor<R, Point_dimension_tag>::type pd(this->kernel()); + int d=pd(*f); + Matrix m(d+2,d+2); + int i=0; + for(;f!=e;++f,++fw,++i) { + Point const& p=*f; + m(i,0)=1; + m(i,d+1)=-*fw; + for(int j=0;j<d;++j){ + m(i,j+1)=c(p,j); + m(i,d+1)+=CGAL_NTS square(m(i,j+1)); + } + } + for(std::vector<int>::const_iterator it = o.rest.begin(); it != o.rest.end() /* i<d+1 */; ++i, ++it) { + m(i,0)=1; + for(int j=0;j<d;++j){ + m(i,j+1)=0; // unneeded if the matrix is initialized to 0 + } + if(*it != d) m(i,d+1)=m(i,1+*it)=1; + else m(i,d+1)=0; + } + m(d+1,0)=1; + m(d+1,d+1)=-w; + for(int j=0;j<d;++j){ + m(d+1,j+1)=c(x,j); + m(d+1,d+1)+=CGAL_NTS square(m(d+1,j+1)); + } + + result_type ret = -LA::sign_of_determinant(CGAL_MOVE(m)); + if(o.reverse) ret=-ret; + return ret; + } +}; + + +} +CGAL_KD_DEFAULT_TYPE(Flat_orientation_tag,(CGAL::CartesianDKernelFunctors::Flat_orientation),(),()); +CGAL_KD_DEFAULT_FUNCTOR(In_flat_orientation_tag,(CartesianDKernelFunctors::In_flat_orientation<K>),(Point_tag),(Compute_point_cartesian_coordinate_tag,Point_dimension_tag)); +CGAL_KD_DEFAULT_FUNCTOR(In_flat_side_of_oriented_sphere_tag,(CartesianDKernelFunctors::In_flat_side_of_oriented_sphere<K>),(Point_tag),(Compute_point_cartesian_coordinate_tag,Point_dimension_tag)); +CGAL_KD_DEFAULT_FUNCTOR(In_flat_power_side_of_power_sphere_raw_tag,(CartesianDKernelFunctors::In_flat_power_side_of_power_sphere_raw<K>),(Point_tag),(Compute_point_cartesian_coordinate_tag,Point_dimension_tag)); +CGAL_KD_DEFAULT_FUNCTOR(Construct_flat_orientation_tag,(CartesianDKernelFunctors::Construct_flat_orientation<K>),(Point_tag),(Compute_point_cartesian_coordinate_tag,Point_dimension_tag,In_flat_orientation_tag)); +CGAL_KD_DEFAULT_FUNCTOR(Contained_in_affine_hull_tag,(CartesianDKernelFunctors::Contained_in_affine_hull<K>),(Point_tag),(Compute_point_cartesian_coordinate_tag,Point_dimension_tag)); +} +#endif diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Define_kernel_types.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Define_kernel_types.h new file mode 100644 index 00000000..6a40515b --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Define_kernel_types.h @@ -0,0 +1,50 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_DEFINE_KERNEL_TYPES_H +#define CGAL_DEFINE_KERNEL_TYPES_H +#include <CGAL/config.h> +#include <CGAL/NewKernel_d/functor_tags.h> +#include <CGAL/typeset.h> +#ifdef CGAL_CXX11 +#include <type_traits> +#else +#include <boost/type_traits.hpp> +#endif + +namespace CGAL { + namespace internal { + template<class K,class Tag_,bool=iterator_tag_traits<Tag_>::is_iterator> + struct Type_or_iter : K::template Type<Tag_> {}; + template<class K,class Tag_> + struct Type_or_iter<K, Tag_, true> : K::template Iterator<Tag_> {}; + } + template<class K, class Base=K, class List=typename typeset_union<typename K::Object_list,typename K::Iterator_list>::type> struct Define_kernel_types; + template<class K, class Base> + struct Define_kernel_types <K, Base, typeset<> > : Base {}; + template<class K> + struct Define_kernel_types <K, void, typeset<> > {}; + template<class K, class Base, class List> + struct Define_kernel_types : + Typedef_tag_type<typename List::head, + typename internal::Type_or_iter<K,typename List::head>::type, + Define_kernel_types<K, Base, typename List::tail> + > {}; +} +#endif diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Dimension_base.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Dimension_base.h new file mode 100644 index 00000000..be875e63 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Dimension_base.h @@ -0,0 +1,49 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KD_DIMENSION_BASE_h +#define CGAL_KD_DIMENSION_BASE_h +#include <CGAL/Dimension.h> +#include <CGAL/assertions.h> +#include <CGAL/NewKernel_d/utils.h> +namespace CGAL { +struct Store_dimension_base { + //TODO: add some assertions + Store_dimension_base(int dim=UNKNOWN_DIMENSION):dim_(dim){} + int dimension()const{return dim_;} + void set_dimension(int dim){dim_=dim;} + private: + int dim_; +}; +template<class=Dynamic_dimension_tag> +struct Dimension_base { + Dimension_base(int = UNKNOWN_DIMENSION){} + int dimension() const { return UNKNOWN_DIMENSION; } + void set_dimension(int) {} +}; +template<int dim_> +struct Dimension_base<Dimension_tag<dim_> > { + Dimension_base(){} + Dimension_base(int CGAL_assertion_code(dim)){CGAL_assertion(dim_==dim);} + int dimension()const{return dim_;} + void set_dimension(int dim){CGAL_assertion(dim_==dim);} +}; +} +#endif + diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Filtered_predicate2.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Filtered_predicate2.h new file mode 100644 index 00000000..1a6a67bc --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Filtered_predicate2.h @@ -0,0 +1,137 @@ +// Copyright (c) 2001-2005 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Sylvain Pion + +#ifndef CGAL_FILTERED_PREDICATE2_H +#define CGAL_FILTERED_PREDICATE2_H + +#include <string> +#include <CGAL/config.h> +#include <CGAL/Interval_nt.h> +#include <CGAL/Uncertain.h> +#include <CGAL/Profile_counter.h> +#include <CGAL/NewKernel_d/store_kernel.h> +#include <boost/preprocessor.hpp> + +namespace CGAL { + +// This template class is a wrapper that implements the filtering for any +// predicate (dynamic filters with IA). + +// TODO : +// - each predicate in the default kernel should define a tag that says if it +// wants to be filtered or not (=> all homogeneous predicate define this +// tag). We could even test-suite that automatically. It makes a strong +// new requirement on the kernel though... +// Could be done with a traits mechanism ? +// A default template could use the current IA, but other tags or whatever +// could specify no filtering at all, or static filtering... +// - same thing for constructions => virtual operator() ? +// - similarly, constructions should have a tag saying if they can throw or +// not, or we let all this up to the compiler optimizer to figure out ? +// - Some caching could be done at the Point_2 level. + + +template <class EP, class AP, class C2E, class C2A, bool Protection = true> +class Filtered_predicate2 +{ +//TODO: pack (at least use a tuple) +//FIXME: is it better to store those, or just store enough to recreate them +//(i.e. possibly references to the kernels)? + EP ep; + AP ap; + C2E c2e; + C2A c2a; + + typedef typename AP::result_type Ares; + +public: + + typedef AP Approximate_predicate; + typedef EP Exact_predicate; + typedef C2E To_exact_converter; + typedef C2A To_approximate_converter; + + // FIXME: should use result_of, see emails by Nico + typedef typename EP::result_type result_type; + // AP::result_type must be convertible to EP::result_type. + + Filtered_predicate2() + {} + + template <class K> + Filtered_predicate2(const K& k) + : ep(k.exact_kernel()), ap(k.approximate_kernel()), c2e(k,k.exact_kernel()), c2a(k,k.approximate_kernel()) + {} + +#ifdef CGAL_CXX11 + template <typename... Args> + result_type + operator()(Args&&... args) const + { + CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); + // Protection is outside the try block as VC8 has the CGAL_CFG_FPU_ROUNDING_MODE_UNWINDING_VC_BUG + { + Protect_FPU_rounding<Protection> p; + try + { + // No forward here, the arguments may still be needed + Ares res = ap(c2a(args)...); + if (is_certain(res)) + return get_certain(res); + } + catch (Uncertain_conversion_exception) {} + } + CGAL_BRANCH_PROFILER_BRANCH(tmp); + Protect_FPU_rounding<!Protection> p(CGAL_FE_TONEAREST); + return ep(c2e(std::forward<Args>(args))...); + } +#else + +#define CGAL_VAR(Z,N,C) C(a##N) +#define CGAL_CODE(Z,N,_) \ + template <BOOST_PP_ENUM_PARAMS(N,class A)> \ + result_type \ + operator()(BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& a)) const \ + { \ + CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); \ + { \ + Protect_FPU_rounding<Protection> p; \ + try \ + { \ + Ares res = ap(BOOST_PP_ENUM(N,CGAL_VAR,c2a)); \ + if (is_certain(res)) \ + return get_certain(res); \ + } \ + catch (Uncertain_conversion_exception) {} \ + } \ + CGAL_BRANCH_PROFILER_BRANCH(tmp); \ + Protect_FPU_rounding<!Protection> p(CGAL_FE_TONEAREST); \ + return ep(BOOST_PP_ENUM(N,CGAL_VAR,c2e)); \ + } + BOOST_PP_REPEAT_FROM_TO(1, 10, CGAL_CODE, _ ) +#undef CGAL_CODE +#undef CGAL_VAR + +#endif +}; + +} //namespace CGAL + +#endif // CGAL_FILTERED_PREDICATE2_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/KernelD_converter.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/KernelD_converter.h new file mode 100644 index 00000000..a8896976 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/KernelD_converter.h @@ -0,0 +1,199 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KERNEL_D_CARTESIAN_CONVERTER_H +#define CGAL_KERNEL_D_CARTESIAN_CONVERTER_H + +#include <CGAL/basic.h> +#include <CGAL/tuple.h> +#include <CGAL/typeset.h> +#include <CGAL/Object.h> +#include <CGAL/Origin.h> +#include <CGAL/NT_converter.h> +#include <CGAL/NewKernel_d/functor_tags.h> +#include <CGAL/Kernel/mpl.h> +#include <CGAL/is_iterator.h> +#include <CGAL/transforming_iterator.h> +#include <boost/utility/enable_if.hpp> +#include <boost/mpl/if.hpp> +#include <CGAL/NewKernel_d/store_kernel.h> +#include <CGAL/NewKernel_d/Kernel_object_converter.h> + +namespace CGAL { +namespace internal { +// Reverses order, but that shouldn't matter. +template<class K,class T> struct Map_taglist_to_typelist : + Map_taglist_to_typelist<K,typename T::tail>::type + ::template add<typename Get_type<K, typename T::head>::type> +{}; +template<class K> struct Map_taglist_to_typelist<K,typeset<> > : typeset<> {}; +} + +template<class List = typeset<> > +struct Object_converter { + typedef Object result_type; + template<class F> + result_type operator()(Object const& o, F const& f) const { + typedef typename List::head H; + if (H const* ptr = object_cast<H>(&o)) + return make_object(f(*ptr)); + else + return Object_converter<typename List::tail>()(o,f); + } +}; +template<> +struct Object_converter <typeset<> > { + typedef Object result_type; + template<class F> + result_type operator()(Object const&,F const&)const { + CGAL_error_msg("Cartesiand_converter is unable to determine what is wrapped in the Object"); + return Object(); + } +}; + + + //TODO: special case when K1==K2 (or they are very close?) +template<class Final_, class K1, class K2, class List> +class KernelD_converter_ +: public KernelD_converter_<Final_,K1,K2,typename List::tail> +{ + typedef typename List::head Tag_; + typedef typename List::tail Rest; + typedef KernelD_converter_<Final_,K1,K2,Rest> Base; + typedef typename Get_type<K1,Tag_>::type K1_Obj; + typedef typename Get_type<K2,Tag_>::type K2_Obj; + typedef typename Get_functor<K1, Convert_ttag<Tag_> >::type K1_Conv; + typedef KO_converter<Tag_,K1,K2> KOC; + typedef CGAL_BOOSTD is_same<K1_Conv, Null_functor> no_converter; + typedef typename internal::Map_taglist_to_typelist<K1,Rest>::type::template contains<K1_Obj> duplicate; + + // Disable the conversion in some cases: + struct Do_not_use{}; + + // Explicit calls to boost::mpl functions to avoid parenthesis + // warning on some versions of GCC + typedef typename boost::mpl::if_ < + // If Point==Vector, keep only one conversion + boost::mpl::or_<boost::mpl::bool_<duplicate::value>, + // For iterator objects, the default is make_transforming_iterator + boost::mpl::bool_<(iterator_tag_traits<Tag_>::is_iterator && no_converter::value)> >, + Do_not_use,K1_Obj>::type argument_type; + //typedef typename KOC::argument_type K1_Obj; + //typedef typename KOC::result_type K2_Obj; + public: + using Base::operator(); // don't use directly, just make it accessible to the next level + K2_Obj helper(K1_Obj const& o,CGAL_BOOSTD true_type)const{ + return KOC()(this->myself().kernel(),this->myself().kernel2(),this->myself(),o); + } + K2_Obj helper(K1_Obj const& o,CGAL_BOOSTD false_type)const{ + return K1_Conv(this->myself().kernel())(this->myself().kernel2(),this->myself(),o); + } + K2_Obj operator()(argument_type const& o)const{ + return helper(o,no_converter()); + } + template<class X,int=0> struct result:Base::template result<X>{}; + template<int i> struct result<Final_(argument_type),i> {typedef K2_Obj type;}; +}; + +template<class Final_, class K1, class K2> +class KernelD_converter_<Final_,K1,K2,typeset<> > { + public: + struct Do_not_use2{}; + void operator()(Do_not_use2)const{} + template<class T> struct result; + Final_& myself(){return *static_cast<Final_*>(this);} + Final_ const& myself()const{return *static_cast<Final_ const*>(this);} +}; + + +// TODO: use the intersection of Kn::Object_list. +template<class K1, class K2, class List_= +typename typeset_intersection<typename K1::Object_list, typename K2::Object_list>::type +//typeset<Point_tag>::add<Vector_tag>::type/*::add<Segment_tag>::type*/ +> class KernelD_converter + : public Store_kernel<K1>, public Store_kernel2<K2>, + public KernelD_converter_<KernelD_converter<K1,K2,List_>,K1,K2,List_> +{ + typedef KernelD_converter Self; + typedef Self Final_; + typedef KernelD_converter_<Self,K1,K2,List_> Base; + typedef typename Get_type<K1, FT_tag>::type FT1; + typedef typename Get_type<K2, FT_tag>::type FT2; + typedef NT_converter<FT1, FT2> NTc; + NTc c; // TODO: compressed storage as this is likely empty and the converter gets passed around (and stored in iterators) + + public: + KernelD_converter(){} + KernelD_converter(K1 const&a,K2 const&b):Store_kernel<K1>(a),Store_kernel2<K2>(b){} + + // For boost::result_of, used in transforming_iterator + template<class T,int i=is_iterator<T>::value?42:0> struct result:Base::template result<T>{}; + template<class T> struct result<Final_(T),42> { + typedef transforming_iterator<Final_,T> type; + }; + template<int i> struct result<Final_(K1),i>{typedef K2 type;}; + template<int i> struct result<Final_(int),i>{typedef int type;}; + // Ideally the next 2 would come with Point_tag and Vector_tag, but that's hard... + template<int i> struct result<Final_(Origin),i>{typedef Origin type;}; + template<int i> struct result<Final_(Null_vector),i>{typedef Null_vector type;}; + template<int i> struct result<Final_(Object),i>{typedef Object type;}; + template<int i> struct result<Final_(FT1),i>{typedef FT2 type;}; + + using Base::operator(); + typename Store_kernel2<K2>::reference2_type operator()(K1 const&)const{return this->kernel2();} + int operator()(int i)const{return i;} + Origin operator()(Origin const&o)const{return o;} + Null_vector operator()(Null_vector const&v)const{return v;} + FT2 operator()(FT1 const&x)const{return c(x);} + //RT2 operator()(typename First_if_different<RT1,FT1>::Type const&x)const{return cr(x);} + + typename Get_type<K2, Flat_orientation_tag>::type const& + operator()(typename Get_type<K1, Flat_orientation_tag>::type const&o)const + { return o; } // Both kernels should have the same, returning a reference should warn if not. + + template<class It> + transforming_iterator<Final_,typename boost::enable_if<is_iterator<It>,It>::type> + operator()(It const& it) const { + return make_transforming_iterator(it,*this); + } + + template<class T> + //TODO: use decltype in C++11 instead of result + std::vector<typename result<Final_(T)>::type> + operator()(const std::vector<T>& v) const { + return std::vector<typename result<Final_(T)>::type>(operator()(v.begin()),operator()(v.begin())); + } + + //TODO: convert std::list and other containers? + + Object + operator()(const Object &obj) const + { + typedef typename internal::Map_taglist_to_typelist<K1,List_>::type Possibilities; + //TODO: add Empty, vector<Point>, etc to the list. + return Object_converter<Possibilities>()(obj,*this); + } + + //TODO: convert boost::variant + +}; + +} //namespace CGAL + +#endif // CGAL_KERNEL_D_CARTESIAN_CONVERTER_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Kernel_2_interface.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Kernel_2_interface.h new file mode 100644 index 00000000..fa30dff0 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Kernel_2_interface.h @@ -0,0 +1,104 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KD_KERNEL_2_INTERFACE_H +#define CGAL_KD_KERNEL_2_INTERFACE_H + +#include <CGAL/NewKernel_d/functor_tags.h> +#include <CGAL/transforming_iterator.h> +#include <CGAL/NewKernel_d/utils.h> +#include <CGAL/tuple.h> + + +namespace CGAL { +template <class Base_> struct Kernel_2_interface : public Base_ { + typedef Base_ Base; + typedef Kernel_2_interface<Base> Kernel; + typedef typename Get_type<Base, RT_tag>::type RT; + typedef typename Get_type<Base, FT_tag>::type FT; + typedef typename Get_type<Base, Bool_tag>::type Boolean; + typedef typename Get_type<Base, Sign_tag>::type Sign; + typedef typename Get_type<Base, Comparison_result_tag>::type Comparison_result; + typedef typename Get_type<Base, Orientation_tag>::type Orientation; + typedef typename Get_type<Base, Oriented_side_tag>::type Oriented_side; + typedef typename Get_type<Base, Bounded_side_tag>::type Bounded_side; + typedef typename Get_type<Base, Angle_tag>::type Angle; + typedef typename Get_type<Base, Point_tag>::type Point_2; + typedef typename Get_type<Base, Vector_tag>::type Vector_2; + typedef typename Get_type<Base, Segment_tag>::type Segment_2; + typedef cpp0x::tuple<Point_2,Point_2,Point_2> Triangle_2; // triangulation insists... + template <class T,int i> struct Help_2p_i { + typedef typename Get_functor<Base, T>::type LT; + typedef typename LT::result_type result_type; + LT lt; + Help_2p_i(Kernel const&k):lt(k){} + result_type operator()(Point_2 const&a, Point_2 const&b) { + return lt(a,b,i); + } + }; + typedef Help_2p_i<Less_point_cartesian_coordinate_tag,0> Less_x_2; + typedef Help_2p_i<Less_point_cartesian_coordinate_tag,1> Less_y_2; + typedef Help_2p_i<Compare_point_cartesian_coordinate_tag,0> Compare_x_2; + typedef Help_2p_i<Compare_point_cartesian_coordinate_tag,1> Compare_y_2; + struct Compare_distance_2 { + typedef typename Get_functor<Base, Compare_distance_tag>::type CD; + typedef typename CD::result_type result_type; + CD cd; + Compare_distance_2(Kernel const&k):cd(k){} + result_type operator()(Point_2 const&a, Point_2 const&b, Point_2 const&c) { + return cd(a,b,c); + } + result_type operator()(Point_2 const&a, Point_2 const&b, Point_2 const&c, Point_2 const&d) { + return cd(a,b,c,d); + } + }; + struct Orientation_2 { + typedef typename Get_functor<Base, Orientation_of_points_tag>::type O; + typedef typename O::result_type result_type; + O o; + Orientation_2(Kernel const&k):o(k){} + result_type operator()(Point_2 const&a, Point_2 const&b, Point_2 const&c) { + //return o(a,b,c); + Point_2 const* t[3]={&a,&b,&c}; + return o(make_transforming_iterator<Dereference_functor>(t+0),make_transforming_iterator<Dereference_functor>(t+3)); + + } + }; + struct Side_of_oriented_circle_2 { + typedef typename Get_functor<Base, Side_of_oriented_sphere_tag>::type SOS; + typedef typename SOS::result_type result_type; + SOS sos; + Side_of_oriented_circle_2(Kernel const&k):sos(k){} + result_type operator()(Point_2 const&a, Point_2 const&b, Point_2 const&c, Point_2 const&d) { + //return sos(a,b,c,d); + Point_2 const* t[4]={&a,&b,&c,&d}; + return sos(make_transforming_iterator<Dereference_functor>(t+0),make_transforming_iterator<Dereference_functor>(t+4)); + } + }; + Less_x_2 less_x_2_object()const{ return Less_x_2(*this); } + Less_y_2 less_y_2_object()const{ return Less_y_2(*this); } + Compare_x_2 compare_x_2_object()const{ return Compare_x_2(*this); } + Compare_y_2 compare_y_2_object()const{ return Compare_y_2(*this); } + Compare_distance_2 compare_distance_2_object()const{ return Compare_distance_2(*this); } + Orientation_2 orientation_2_object()const{ return Orientation_2(*this); } + Side_of_oriented_circle_2 side_of_oriented_circle_2_object()const{ return Side_of_oriented_circle_2(*this); } +}; +} + +#endif diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Kernel_3_interface.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Kernel_3_interface.h new file mode 100644 index 00000000..96076aa8 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Kernel_3_interface.h @@ -0,0 +1,102 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KD_KERNEL_3_INTERFACE_H +#define CGAL_KD_KERNEL_3_INTERFACE_H + +#include <CGAL/NewKernel_d/functor_tags.h> +#include <CGAL/transforming_iterator.h> +#include <CGAL/NewKernel_d/utils.h> +#include <CGAL/tuple.h> + + +namespace CGAL { +template <class Base_> struct Kernel_3_interface : public Base_ { + typedef Base_ Base; + typedef Kernel_3_interface<Base> Kernel; + typedef typename Get_type<Base, RT_tag>::type RT; + typedef typename Get_type<Base, FT_tag>::type FT; + typedef typename Get_type<Base, Bool_tag>::type Boolean; + typedef typename Get_type<Base, Sign_tag>::type Sign; + typedef typename Get_type<Base, Comparison_result_tag>::type Comparison_result; + typedef typename Get_type<Base, Orientation_tag>::type Orientation; + typedef typename Get_type<Base, Oriented_side_tag>::type Oriented_side; + typedef typename Get_type<Base, Bounded_side_tag>::type Bounded_side; + typedef typename Get_type<Base, Angle_tag>::type Angle; + typedef typename Get_type<Base, Point_tag>::type Point_3; + typedef typename Get_type<Base, Vector_tag>::type Vector_3; + typedef typename Get_type<Base, Segment_tag>::type Segment_3; + typedef cpp0x::tuple<Point_3,Point_3,Point_3> Triangle_3; // placeholder + typedef cpp0x::tuple<Point_3,Point_3,Point_3,Point_3> Tetrahedron_3; // placeholder + struct Compare_xyz_3 { + typedef typename Get_functor<Base, Compare_lexicographically_tag>::type CL; + typedef typename CL::result_type result_type; + CL cl; + Compare_xyz_3(Kernel const&k):cl(k){} + result_type operator()(Point_3 const&a, Point_3 const&b) { + return cl(a,b); + } + }; + struct Compare_distance_3 { + typedef typename Get_functor<Base, Compare_distance_tag>::type CD; + typedef typename CD::result_type result_type; + CD cd; + Compare_distance_3(Kernel const&k):cd(k){} + result_type operator()(Point_3 const&a, Point_3 const&b, Point_3 const&c) { + return cd(a,b,c); + } + result_type operator()(Point_3 const&a, Point_3 const&b, Point_3 const&c, Point_3 const&d) { + return cd(a,b,c,d); + } + }; + struct Orientation_3 { + typedef typename Get_functor<Base, Orientation_of_points_tag>::type O; + typedef typename O::result_type result_type; + O o; + Orientation_3(Kernel const&k):o(k){} + result_type operator()(Point_3 const&a, Point_3 const&b, Point_3 const&c, Point_3 const&d) { + //return o(a,b,c,d); + Point_3 const* t[4]={&a,&b,&c,&d}; + return o(make_transforming_iterator<Dereference_functor>(t+0),make_transforming_iterator<Dereference_functor>(t+4)); + + } + }; + struct Side_of_oriented_sphere_3 { + typedef typename Get_functor<Base, Side_of_oriented_sphere_tag>::type SOS; + typedef typename SOS::result_type result_type; + SOS sos; + Side_of_oriented_sphere_3(Kernel const&k):sos(k){} + result_type operator()(Point_3 const&a, Point_3 const&b, Point_3 const&c, Point_3 const&d, Point_3 const&e) { + //return sos(a,b,c,d); + Point_3 const* t[5]={&a,&b,&c,&d,&e}; + return sos(make_transforming_iterator<Dereference_functor>(t+0),make_transforming_iterator<Dereference_functor>(t+5)); + } + }; + + // I don't have the Coplanar predicates (yet) + + + Compare_xyz_3 compare_xyz_3_object()const{ return Compare_xyz_3(*this); } + Compare_distance_3 compare_distance_3_object()const{ return Compare_distance_3(*this); } + Orientation_3 orientation_3_object()const{ return Orientation_3(*this); } + Side_of_oriented_sphere_3 side_of_oriented_sphere_3_object()const{ return Side_of_oriented_sphere_3(*this); } +}; +} + +#endif diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Kernel_d_interface.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Kernel_d_interface.h new file mode 100644 index 00000000..dd888005 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Kernel_d_interface.h @@ -0,0 +1,298 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KD_KERNEL_D_INTERFACE_H +#define CGAL_KD_KERNEL_D_INTERFACE_H + +#include <CGAL/NewKernel_d/functor_tags.h> +#include <CGAL/transforming_iterator.h> +#include <CGAL/NewKernel_d/utils.h> +#include <CGAL/tuple.h> + + +namespace CGAL { +template <class Base_> struct Kernel_d_interface : public Base_ { + CGAL_CONSTEXPR Kernel_d_interface(){} + CGAL_CONSTEXPR Kernel_d_interface(int d):Base_(d){} + + typedef Base_ Base; + typedef Kernel_d_interface<Base> Kernel; + typedef Base_ R_; // for the macros + typedef typename Get_type<Base, RT_tag>::type RT; + typedef typename Get_type<Base, FT_tag>::type FT; + typedef typename Get_type<Base, Bool_tag>::type Boolean; + typedef typename Get_type<Base, Sign_tag>::type Sign; + typedef typename Get_type<Base, Comparison_result_tag>::type Comparison_result; + typedef typename Get_type<Base, Orientation_tag>::type Orientation; + typedef typename Get_type<Base, Oriented_side_tag>::type Oriented_side; + typedef typename Get_type<Base, Bounded_side_tag>::type Bounded_side; + typedef typename Get_type<Base, Angle_tag>::type Angle; + typedef typename Get_type<Base, Flat_orientation_tag>::type Flat_orientation_d; + typedef typename Get_type<Base, Point_tag>::type Point_d; + typedef typename Get_type<Base, Vector_tag>::type Vector_d; + typedef typename Get_type<Base, Segment_tag>::type Segment_d; + typedef typename Get_type<Base, Sphere_tag>::type Sphere_d; + typedef typename Get_type<Base, Hyperplane_tag>::type Hyperplane_d; + typedef Vector_d Direction_d; + typedef typename Get_type<Base, Line_tag>::type Line_d; + typedef typename Get_type<Base, Ray_tag>::type Ray_d; + typedef typename Get_type<Base, Iso_box_tag>::type Iso_box_d; + typedef typename Get_type<Base, Aff_transformation_tag>::type Aff_transformation_d; + typedef typename Get_type<Base, Weighted_point_tag>::type Weighted_point_d; + typedef typename Get_functor<Base, Compute_point_cartesian_coordinate_tag>::type Compute_coordinate_d; + typedef typename Get_functor<Base, Compare_lexicographically_tag>::type Compare_lexicographically_d; + typedef typename Get_functor<Base, Equal_points_tag>::type Equal_d; + typedef typename Get_functor<Base, Less_lexicographically_tag>::type Less_lexicographically_d; + typedef typename Get_functor<Base, Less_or_equal_lexicographically_tag>::type Less_or_equal_lexicographically_d; + // FIXME: and vectors? + typedef typename Get_functor<Base, Orientation_of_points_tag>::type Orientation_d; + typedef typename Get_functor<Base, Less_point_cartesian_coordinate_tag>::type Less_coordinate_d; + typedef typename Get_functor<Base, Point_dimension_tag>::type Point_dimension_d; + typedef typename Get_functor<Base, Side_of_oriented_sphere_tag>::type Side_of_oriented_sphere_d; + typedef typename Get_functor<Base, Power_side_of_power_sphere_tag>::type Power_side_of_power_sphere_d; + typedef typename Get_functor<Base, Power_center_tag>::type Power_center_d; + typedef typename Get_functor<Base, Power_distance_tag>::type Power_distance_d; + typedef typename Get_functor<Base, Contained_in_affine_hull_tag>::type Contained_in_affine_hull_d; + typedef typename Get_functor<Base, Construct_flat_orientation_tag>::type Construct_flat_orientation_d; + typedef typename Get_functor<Base, In_flat_orientation_tag>::type In_flat_orientation_d; + typedef typename Get_functor<Base, In_flat_side_of_oriented_sphere_tag>::type In_flat_side_of_oriented_sphere_d; + typedef typename Get_functor<Base, In_flat_power_side_of_power_sphere_tag>::type In_flat_power_side_of_power_sphere_d; + typedef typename Get_functor<Base, Point_to_vector_tag>::type Point_to_vector_d; + typedef typename Get_functor<Base, Vector_to_point_tag>::type Vector_to_point_d; + typedef typename Get_functor<Base, Translated_point_tag>::type Translated_point_d; + typedef typename Get_functor<Base, Scaled_vector_tag>::type Scaled_vector_d; + typedef typename Get_functor<Base, Difference_of_vectors_tag>::type Difference_of_vectors_d; + typedef typename Get_functor<Base, Difference_of_points_tag>::type Difference_of_points_d; + //typedef typename Get_functor<Base, Construct_ttag<Point_tag> >::type Construct_point_d; + struct Construct_point_d : private Store_kernel<Kernel> { + typedef Kernel R_; // for the macro + CGAL_FUNCTOR_INIT_STORE(Construct_point_d) + typedef typename Get_functor<Base, Construct_ttag<Point_tag> >::type CP; + typedef Point_d result_type; + Point_d operator()(Weighted_point_d const&wp)const{ + return typename Get_functor<Base, Point_drop_weight_tag>::type(this->kernel())(wp); + } +#ifdef CGAL_CXX11 + Point_d operator()(Weighted_point_d &wp)const{ + return typename Get_functor<Base, Point_drop_weight_tag>::type(this->kernel())(wp); + } + Point_d operator()(Weighted_point_d &&wp)const{ + return typename Get_functor<Base, Point_drop_weight_tag>::type(this->kernel())(std::move(wp)); + } + Point_d operator()(Weighted_point_d const&&wp)const{ + return typename Get_functor<Base, Point_drop_weight_tag>::type(this->kernel())(std::move(wp)); + } + template<class...T> +# if __cplusplus >= 201402L + decltype(auto) +# else + Point_d +# endif + operator()(T&&...t)const{ + return CP(this->kernel())(std::forward<T>(t)...); + //return CP(this->kernel())(t...); + } +#else +# define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class T)> \ + Point_d operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t))const{ \ + return CP(this->kernel())(BOOST_PP_ENUM_PARAMS(N,t)); \ + } + BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_) +# undef CGAL_CODE + Point_d operator()()const{ \ + return CP(this->kernel())(); \ + } +#endif + }; + typedef typename Get_functor<Base, Construct_ttag<Vector_tag> >::type Construct_vector_d; + typedef typename Get_functor<Base, Construct_ttag<Segment_tag> >::type Construct_segment_d; + typedef typename Get_functor<Base, Construct_ttag<Sphere_tag> >::type Construct_sphere_d; + typedef typename Get_functor<Base, Construct_ttag<Hyperplane_tag> >::type Construct_hyperplane_d; + typedef Construct_vector_d Construct_direction_d; + typedef typename Get_functor<Base, Construct_ttag<Line_tag> >::type Construct_line_d; + typedef typename Get_functor<Base, Construct_ttag<Ray_tag> >::type Construct_ray_d; + typedef typename Get_functor<Base, Construct_ttag<Iso_box_tag> >::type Construct_iso_box_d; + typedef typename Get_functor<Base, Construct_ttag<Aff_transformation_tag> >::type Construct_aff_transformation_d; + typedef typename Get_functor<Base, Construct_ttag<Weighted_point_tag> >::type Construct_weighted_point_d; + typedef typename Get_functor<Base, Midpoint_tag>::type Midpoint_d; + struct Component_accessor_d : private Store_kernel<Kernel> { + typedef Kernel R_; // for the macro + CGAL_FUNCTOR_INIT_STORE(Component_accessor_d) + int dimension(Point_d const&p){ + return this->kernel().point_dimension_d_object()(p); + } + FT cartesian(Point_d const&p, int i){ + return this->kernel().compute_coordinate_d_object()(p,i); + } + RT homogeneous(Point_d const&p, int i){ + if (i == dimension(p)) + return 1; + return cartesian(p, i); + } + }; + struct Construct_cartesian_const_iterator_d : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Construct_cartesian_const_iterator_d) + typedef typename Get_functor<Base, Construct_ttag<Point_cartesian_const_iterator_tag> >::type CPI; + typedef typename Get_functor<Base, Construct_ttag<Vector_cartesian_const_iterator_tag> >::type CVI; + // FIXME: The following sometimes breaks compilation. The typedef below forces instantiation of this, which forces Point_d, which itself (in the wrapper) needs the derived kernel to tell it what the base kernel is, and that's a cycle. The exact circumstances are not clear, g++ and clang++ are ok in both C++03 and C++11, it is only clang in C++11 without CGAL_CXX11 that breaks. For now, rely on result_type. + //typedef typename CGAL::decay<typename boost::result_of<CPI(Point_d,CGAL::Begin_tag)>::type>::type result_type; + typedef typename CGAL::decay<typename CPI::result_type>::type result_type; + // Kernel_d requires a common iterator type for points and vectors + // TODO: provide this mixed functor in preKernel? + //CGAL_static_assertion((boost::is_same<typename CGAL::decay<typename boost::result_of<CVI(Vector_d,CGAL::Begin_tag)>::type>::type, result_type>::value)); + CGAL_static_assertion((boost::is_same<typename CGAL::decay<typename CVI::result_type>::type, result_type>::value)); + template <class Tag_> + result_type operator()(Point_d const&p, Tag_ t)const{ + return CPI(this->kernel())(p,t); + } + template <class Tag_> + result_type operator()(typename First_if_different<Vector_d,Point_d>::Type const&v, Tag_ t)const{ + return CVI(this->kernel())(v,t); + } + + template <class Obj> + result_type operator()(Obj const&o)const{ + return operator()(o, Begin_tag()); + } + result_type operator()(Point_d const&p, int)const{ + return operator()(p, End_tag()); + } + result_type operator()(typename First_if_different<Vector_d,Point_d>::Type const&v, int)const{ + return operator()(v, End_tag()); + } + }; + struct Compute_squared_radius_d : private Store_kernel<Kernel> { + typedef Kernel R_; // for the macro + CGAL_FUNCTOR_INIT_STORE(Compute_squared_radius_d) + typedef FT result_type; + template<class S> FT operator()(CGAL_FORWARDABLE(S) s)const{ + return typename Get_functor<Base, Squared_radius_tag>::type(this->kernel())(CGAL_FORWARD(S,s)); + } + template<class I> FT operator()(I b, I e)const{ + return typename Get_functor<Base, Squared_circumradius_tag>::type(this->kernel())(b,e); + } + }; + typedef typename Construct_cartesian_const_iterator_d::result_type Cartesian_const_iterator_d; + typedef typename Get_functor<Base, Squared_distance_tag>::type Squared_distance_d; + typedef typename Get_functor<Base, Squared_length_tag>::type Squared_length_d; + typedef typename Get_functor<Base, Scalar_product_tag>::type Scalar_product_d; + typedef typename Get_functor<Base, Affine_rank_tag>::type Affine_rank_d; + typedef typename Get_functor<Base, Affinely_independent_tag>::type Affinely_independent_d; + typedef typename Get_functor<Base, Contained_in_linear_hull_tag>::type Contained_in_linear_hull_d; + typedef typename Get_functor<Base, Contained_in_simplex_tag>::type Contained_in_simplex_d; + typedef typename Get_functor<Base, Has_on_positive_side_tag>::type Has_on_positive_side_d; + typedef typename Get_functor<Base, Linear_rank_tag>::type Linear_rank_d; + typedef typename Get_functor<Base, Linearly_independent_tag>::type Linearly_independent_d; + typedef typename Get_functor<Base, Oriented_side_tag>::type Oriented_side_d; + typedef typename Get_functor<Base, Side_of_bounded_circumsphere_tag>::type Side_of_bounded_sphere_d; + + typedef typename Get_functor<Base, Center_of_sphere_tag>::type Center_of_sphere_d; + typedef Center_of_sphere_d Construct_center_d; // RangeSearchTraits + typedef typename Get_functor<Base, Construct_circumcenter_tag>::type Construct_circumcenter_d; + typedef typename Get_functor<Base, Value_at_tag>::type Value_at_d; + typedef typename Get_functor<Base, Point_of_sphere_tag>::type Point_of_sphere_d; + typedef typename Get_functor<Base, Orthogonal_vector_tag>::type Orthogonal_vector_d; + typedef typename Get_functor<Base, Linear_base_tag>::type Linear_base_d; + typedef typename Get_functor<Base, Construct_min_vertex_tag>::type Construct_min_vertex_d; + typedef typename Get_functor<Base, Construct_max_vertex_tag>::type Construct_max_vertex_d; + + typedef typename Get_functor<Base, Point_weight_tag>::type Compute_weight_d; + typedef typename Get_functor<Base, Point_drop_weight_tag>::type Point_drop_weight_d; + + //TODO: + //typedef ??? Intersect_d; + + + Compute_coordinate_d compute_coordinate_d_object()const{ return Compute_coordinate_d(*this); } + Has_on_positive_side_d has_on_positive_side_d_object()const{ return Has_on_positive_side_d(*this); } + Compare_lexicographically_d compare_lexicographically_d_object()const{ return Compare_lexicographically_d(*this); } + Equal_d equal_d_object()const{ return Equal_d(*this); } + Less_lexicographically_d less_lexicographically_d_object()const{ return Less_lexicographically_d(*this); } + Less_or_equal_lexicographically_d less_or_equal_lexicographically_d_object()const{ return Less_or_equal_lexicographically_d(*this); } + Less_coordinate_d less_coordinate_d_object()const{ return Less_coordinate_d(*this); } + Orientation_d orientation_d_object()const{ return Orientation_d(*this); } + Oriented_side_d oriented_side_d_object()const{ return Oriented_side_d(*this); } + Point_dimension_d point_dimension_d_object()const{ return Point_dimension_d(*this); } + Point_of_sphere_d point_of_sphere_d_object()const{ return Point_of_sphere_d(*this); } + Side_of_oriented_sphere_d side_of_oriented_sphere_d_object()const{ return Side_of_oriented_sphere_d(*this); } + Power_side_of_power_sphere_d power_side_of_power_sphere_d_object()const{ return Power_side_of_power_sphere_d(*this); } + Power_center_d power_center_d_object()const{ return Power_center_d(*this); } + Power_distance_d power_distance_d_object()const{ return Power_distance_d(*this); } + Side_of_bounded_sphere_d side_of_bounded_sphere_d_object()const{ return Side_of_bounded_sphere_d(*this); } + Contained_in_affine_hull_d contained_in_affine_hull_d_object()const{ return Contained_in_affine_hull_d(*this); } + Contained_in_linear_hull_d contained_in_linear_hull_d_object()const{ return Contained_in_linear_hull_d(*this); } + Contained_in_simplex_d contained_in_simplex_d_object()const{ return Contained_in_simplex_d(*this); } + Construct_flat_orientation_d construct_flat_orientation_d_object()const{ return Construct_flat_orientation_d(*this); } + In_flat_orientation_d in_flat_orientation_d_object()const{ return In_flat_orientation_d(*this); } + In_flat_side_of_oriented_sphere_d in_flat_side_of_oriented_sphere_d_object()const{ return In_flat_side_of_oriented_sphere_d(*this); } + In_flat_power_side_of_power_sphere_d in_flat_power_side_of_power_sphere_d_object()const{ return In_flat_power_side_of_power_sphere_d(*this); } + Point_to_vector_d point_to_vector_d_object()const{ return Point_to_vector_d(*this); } + Vector_to_point_d vector_to_point_d_object()const{ return Vector_to_point_d(*this); } + Translated_point_d translated_point_d_object()const{ return Translated_point_d(*this); } + Scaled_vector_d scaled_vector_d_object()const{ return Scaled_vector_d(*this); } + Difference_of_vectors_d difference_of_vectors_d_object()const{ return Difference_of_vectors_d(*this); } + Difference_of_points_d difference_of_points_d_object()const{ return Difference_of_points_d(*this); } + Affine_rank_d affine_rank_d_object()const{ return Affine_rank_d(*this); } + Affinely_independent_d affinely_independent_d_object()const{ return Affinely_independent_d(*this); } + Linear_base_d linear_base_d_object()const{ return Linear_base_d(*this); } + Linear_rank_d linear_rank_d_object()const{ return Linear_rank_d(*this); } + Linearly_independent_d linearly_independent_d_object()const{ return Linearly_independent_d(*this); } + Midpoint_d midpoint_d_object()const{ return Midpoint_d(*this); } + Value_at_d value_at_d_object()const{ return Value_at_d(*this); } + /// Intersect_d intersect_d_object()const{ return Intersect_d(*this); } + Component_accessor_d component_accessor_d_object()const{ return Component_accessor_d(*this); } + Orthogonal_vector_d orthogonal_vector_d_object()const{ return Orthogonal_vector_d(*this); } + Construct_cartesian_const_iterator_d construct_cartesian_const_iterator_d_object()const{ return Construct_cartesian_const_iterator_d(*this); } + Construct_point_d construct_point_d_object()const{ return Construct_point_d(*this); } + Construct_vector_d construct_vector_d_object()const{ return Construct_vector_d(*this); } + Construct_segment_d construct_segment_d_object()const{ return Construct_segment_d(*this); } + Construct_sphere_d construct_sphere_d_object()const{ return Construct_sphere_d(*this); } + Construct_hyperplane_d construct_hyperplane_d_object()const{ return Construct_hyperplane_d(*this); } + Compute_squared_radius_d compute_squared_radius_d_object()const{ return Compute_squared_radius_d(*this); } + Squared_distance_d squared_distance_d_object()const{ return Squared_distance_d(*this); } + Squared_length_d squared_length_d_object()const{ return Squared_length_d(*this); } + Scalar_product_d scalar_product_d_object()const{ return Scalar_product_d(*this); } + Center_of_sphere_d center_of_sphere_d_object()const{ return Center_of_sphere_d(*this); } + Construct_circumcenter_d construct_circumcenter_d_object()const{ return Construct_circumcenter_d(*this); } + Construct_direction_d construct_direction_d_object()const{ return Construct_direction_d(*this); } + Construct_line_d construct_line_d_object()const{ return Construct_line_d(*this); } + Construct_ray_d construct_ray_d_object()const{ return Construct_ray_d(*this); } + Construct_iso_box_d construct_iso_box_d_object()const{ return Construct_iso_box_d(*this); } + Construct_aff_transformation_d construct_aff_transformation_d_object()const{ return Construct_aff_transformation_d(*this); } + Construct_min_vertex_d construct_min_vertex_d_object()const{ return Construct_min_vertex_d(*this); } + Construct_max_vertex_d construct_max_vertex_d_object()const{ return Construct_max_vertex_d(*this); } + Construct_weighted_point_d construct_weighted_point_d_object()const{ return Construct_weighted_point_d(*this); } + + Compute_weight_d compute_weight_d_object()const{ return Compute_weight_d(*this); } + Point_drop_weight_d point_drop_weight_d_object()const{ return Point_drop_weight_d(*this); } + + // Dummies for those required functors missing a concept. + typedef Null_functor Position_on_line_d; + Position_on_line_d position_on_line_d_object()const{return Null_functor();} + typedef Null_functor Barycentric_coordinates_d; + Barycentric_coordinates_d barycentric_coordinates_d_object()const{return Null_functor();} + + /* Not provided because they don't make sense here: + Lift_to_paraboloid_d + Project_along_d_axis_d + */ +}; +} + +#endif // CGAL_KD_KERNEL_D_INTERFACE_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Kernel_object_converter.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Kernel_object_converter.h new file mode 100644 index 00000000..99918ed2 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Kernel_object_converter.h @@ -0,0 +1,134 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KD_KO_CONVERTER_H +#define CGAL_KD_KO_CONVERTER_H +#include <CGAL/NewKernel_d/utils.h> +#include <CGAL/NewKernel_d/functor_tags.h> +#include <CGAL/Kernel/mpl.h> // First_if_different +#include <CGAL/Dimension.h> +namespace CGAL { +template <class Tag_, class K1, class K2> struct KO_converter; +//TODO: It would probably be better if this was a Misc Functor in K1. +// This way K1 could chose how it wants to present its points (sparse +// iterator?) and derived classes would inherit it. + +namespace internal { +template <class D /*=Dynamic_dimension_tag*/, class K1, class K2> +struct Point_converter_help { + typedef typename Get_type<K1, Point_tag>::type argument_type; + typedef typename Get_type<K2, Point_tag>::type result_type; + template <class C> + result_type operator()(K1 const& k1, K2 const& k2, C const& conv, argument_type const& p) const { + typename Get_functor<K1, Construct_ttag<Point_cartesian_const_iterator_tag> >::type i(k1); + typename Get_functor<K2, Construct_ttag<Point_tag> >::type cp(k2); + return cp(conv(i(p,Begin_tag())),conv(i(p,End_tag()))); + } +}; +#ifdef CGAL_CXX11 +// This doesn't seem so useful, the compiler should be able to handle +// the iterators just as efficiently. +template <int d, class K1, class K2> +struct Point_converter_help<Dimension_tag<d>,K1,K2> { + typedef typename Get_type<K1, Point_tag>::type argument_type; + typedef typename Get_type<K2, Point_tag>::type result_type; + template <class C,int...I> + result_type help(Indices<I...>, K1 const& k1, K2 const& k2, C const& conv, argument_type const& p) const { + typename Get_functor<K1, Compute_point_cartesian_coordinate_tag>::type cc(k1); + typename Get_functor<K2, Construct_ttag<Point_tag> >::type cp(k2); + return cp(conv(cc(p,I))...); + } + template <class C> + result_type operator()(K1 const& k1, K2 const& k2, C const& conv, argument_type const& p) const { + return help(typename N_increasing_indices<d>::type(),k1,k2,conv,p); + } +}; +#endif +} +template <class K1, class K2> struct KO_converter<Point_tag,K1,K2> +: internal::Point_converter_help<typename K1::Default_ambient_dimension,K1,K2> +{}; + +template <class K1, class K2> struct KO_converter<Vector_tag,K1,K2>{ + typedef typename Get_type<K1, Vector_tag>::type K1_Vector; + + // Disabling is now done in KernelD_converter + // // can't use vector without at least a placeholder point because of this + // typedef typename K1:: Point K1_Point; + // typedef typename First_if_different<K1_Vector,K1_Point>::Type argument_type; + + typedef K1_Vector argument_type; + typedef typename Get_type<K2, Vector_tag>::type result_type; + template <class C> + result_type operator()(K1 const& k1, K2 const& k2, C const& conv, argument_type const& v) const { + typename Get_functor<K1, Construct_ttag<Vector_cartesian_const_iterator_tag> >::type i(k1); + typename Get_functor<K2, Construct_ttag<Vector_tag> >::type cp(k2); + return cp(conv(i(v,Begin_tag())),conv(i(v,End_tag()))); + } +}; + +template <class K1, class K2> struct KO_converter<Segment_tag,K1,K2>{ + typedef typename Get_type<K1, Segment_tag>::type argument_type; + typedef typename Get_type<K2, Segment_tag>::type result_type; + template <class C> + result_type operator()(K1 const& k1, K2 const& k2, C const& conv, argument_type const& s) const { + typename Get_functor<K1, Segment_extremity_tag>::type f(k1); + typename Get_functor<K2, Construct_ttag<Segment_tag> >::type cs(k2); + return cs(conv(f(s,0)),conv(f(s,1))); + } +}; + +template <class K1, class K2> struct KO_converter<Hyperplane_tag,K1,K2>{ + typedef typename Get_type<K1, Hyperplane_tag>::type argument_type; + typedef typename Get_type<K2, Hyperplane_tag>::type result_type; + template <class C> + result_type operator()(K1 const& k1, K2 const& k2, C const& conv, argument_type const& h) const { + typename Get_functor<K1, Orthogonal_vector_tag>::type ov(k1); + typename Get_functor<K1, Hyperplane_translation_tag>::type ht(k1); + typename Get_functor<K2, Construct_ttag<Hyperplane_tag> >::type ch(k2); + return ch(conv(ov(h)),conv(ht(h))); + } +}; + +template <class K1, class K2> struct KO_converter<Sphere_tag,K1,K2>{ + typedef typename Get_type<K1, Sphere_tag>::type argument_type; + typedef typename Get_type<K2, Sphere_tag>::type result_type; + template <class C> + result_type operator()(K1 const& k1, K2 const& k2, C const& conv, argument_type const& s) const { + typename Get_functor<K1, Center_of_sphere_tag>::type cos(k1); + typename Get_functor<K1, Squared_radius_tag>::type sr(k1); + typename Get_functor<K2, Construct_ttag<Sphere_tag> >::type cs(k2); + return cs(conv(cos(s)),conv(sr(s))); + } +}; + +template <class K1, class K2> struct KO_converter<Weighted_point_tag,K1,K2>{ + typedef typename Get_type<K1, Weighted_point_tag>::type argument_type; + typedef typename Get_type<K2, Weighted_point_tag>::type result_type; + template <class C> + result_type operator()(K1 const& k1, K2 const& k2, C const& conv, argument_type const& s) const { + typename Get_functor<K1, Point_drop_weight_tag>::type pdw(k1); + typename Get_functor<K1, Point_weight_tag>::type pw(k1); + typename Get_functor<K2, Construct_ttag<Weighted_point_tag> >::type cwp(k2); + return cwp(conv(pdw(s)),conv(pw(s))); + } +}; + +} +#endif diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/LA_eigen/LA.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/LA_eigen/LA.h new file mode 100644 index 00000000..ddbdc37b --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/LA_eigen/LA.h @@ -0,0 +1,175 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_LA_EIGEN_H +#define CGAL_LA_EIGEN_H +#include <CGAL/config.h> +#ifndef CGAL_EIGEN3_ENABLED +#error Requires Eigen +#endif +#include <boost/type_traits/is_arithmetic.hpp> +#include <boost/utility/enable_if.hpp> +#include <CGAL/Dimension.h> +#include <Eigen/Dense> +#include <CGAL/NewKernel_d/LA_eigen/constructors.h> +#include <CGAL/iterator_from_indices.h> + +namespace CGAL { + +//FIXME: where could we use Matrix_base instead of Matrix? +// Dim_ real dimension +// Max_dim_ upper bound on the dimension +template<class NT_,class Dim_,class Max_dim_=Dim_> struct LA_eigen { + typedef NT_ NT; + typedef Dim_ Dimension; + typedef Max_dim_ Max_dimension; + enum { dimension = Eigen_dimension<Dimension>::value }; + enum { max_dimension = Eigen_dimension<Max_dimension>::value }; + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef LA_eigen< NT, D2, D3 > Other; + }; + template<class,class=void> struct Property : boost::false_type {}; + template<class D> struct Property<Has_vector_plus_minus_tag,D> : boost::true_type {}; + template<class D> struct Property<Has_vector_scalar_ops_tag,D> : boost::true_type {}; + template<class D> struct Property<Has_dot_product_tag,D> : boost::true_type {}; + + typedef Eigen::Matrix<NT,Eigen_dimension<Dim_>::value,1,Eigen::ColMajor|Eigen::AutoAlign,Eigen_dimension<Max_dim_>::value,1> Vector; + typedef Eigen::Matrix<NT,Eigen::Dynamic,1> Dynamic_vector; + typedef Construct_eigen<Vector> Construct_vector; + +#if (EIGEN_WORLD_VERSION>=3) + typedef NT const* Vector_const_iterator; +#else + typedef Iterator_from_indices<const type,const NT +#ifndef CGAL_CXX11 + ,NT +#endif + > Vector_const_iterator; +#endif + + template<class Vec_>static Vector_const_iterator vector_begin(Vec_ const&a){ +#if (EIGEN_WORLD_VERSION>=3) + return &a[0]; +#else + return Vector_const_iterator(a,0); +#endif + } + + template<class Vec_>static Vector_const_iterator vector_end(Vec_ const&a){ +#if (EIGEN_WORLD_VERSION>=3) + // FIXME: Isn't that dangerous if a is an expression and not a concrete vector? + return &a[0]+a.size(); +#else + return Vector_const_iterator(a,a.size()); +#endif + } + + typedef Eigen::Matrix<NT,dimension,dimension,Eigen::ColMajor|Eigen::AutoAlign,max_dimension,max_dimension> Square_matrix; + typedef Eigen::Matrix<NT,dimension,Eigen::Dynamic,Eigen::ColMajor|Eigen::AutoAlign,max_dimension,Eigen::Dynamic> Dynamic_matrix; + //TODO: don't pass on the values of Max_* for an expensive NT + // typedef ... Constructor + // typedef ... Accessor +#if 0 + private: + template <class T> class Canonicalize_vector { + typedef typename Dimension_eigen<T::SizeAtCompileTime>::type S1; + typedef typename Dimension_eigen<T::MaxSizeAtCompileTime>::type S2; + public: + typedef typename Vector<S1,S2>::type type; + }; + public: +#endif + + template<class Vec_>static int size_of_vector(Vec_ const&v){ + return (int)v.size(); + } + + template<class Vec_>static NT dot_product(Vec_ const&a,Vec_ const&b){ + return a.dot(b); + } + + template<class Vec_> static int rows(Vec_ const&v) { + return (int)v.rows(); + } + template<class Vec_> static int columns(Vec_ const&v) { + return (int)v.cols(); + } + + template<class Mat_> static NT determinant(Mat_ const&m,bool=false){ + return m.determinant(); + } + + template<class Mat_> static typename + Same_uncertainty_nt<CGAL::Sign, NT>::type + sign_of_determinant(Mat_ const&m,bool=false) + { + return CGAL::sign(m.determinant()); + } + + template<class Mat_> static int rank(Mat_ const&m){ + // return m.rank(); + // This one uses sqrt so cannot be used with Gmpq + // TODO: use different algo for different NT? + // Eigen::ColPivHouseholderQR<Mat_> decomp(m); + Eigen::FullPivLU<Mat_> decomp(m); + // decomp.setThreshold(0); + return static_cast<int>(decomp.rank()); + } + + // m*a==b + template<class DV, class DM, class V> + static void solve(DV&a, DM const&m, V const& b){ + //a = m.colPivHouseholderQr().solve(b); + a = m.fullPivLu().solve(b); + } + template<class DV, class DM, class V> + static bool solve_and_check(DV&a, DM const&m, V const& b){ + //a = m.colPivHouseholderQr().solve(b); + a = m.fullPivLu().solve(b); + return b.isApprox(m*a); + } + + static Dynamic_matrix basis(Dynamic_matrix const&m){ + return m.fullPivLu().image(m); + } + + template<class Vec1,class Vec2> static Vector homogeneous_add(Vec1 const&a,Vec2 const&b){ + //TODO: use compile-time size when available + int d=a.size(); + Vector v(d); + v << b[d-1]*a.topRows(d-1)+a[d-1]*b.topRows(d-1), a[d-1]*b[d-1]; + return v; + } + + template<class Vec1,class Vec2> static Vector homogeneous_sub(Vec1 const&a,Vec2 const&b){ + int d=a.size(); + Vector v(d); + v << b[d-1]*a.topRows(d-1)-a[d-1]*b.topRows(d-1), a[d-1]*b[d-1]; + return v; + } + + template<class Vec1,class Vec2> static std::pair<NT,NT> homogeneous_dot_product(Vec1 const&a,Vec2 const&b){ + int d=a.size(); + return make_pair(a.topRows(d-1).dot(b.topRows(d-1)), a[d-1]*b[d-1]); + } + +}; +} +#endif diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/LA_eigen/constructors.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/LA_eigen/constructors.h new file mode 100644 index 00000000..3636996f --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/LA_eigen/constructors.h @@ -0,0 +1,162 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_LA_EIGEN_CONSTRUCTORS_H +#define CGAL_LA_EIGEN_CONSTRUCTORS_H +#include <CGAL/config.h> + +#if defined(BOOST_MSVC) +# pragma warning(push) +# pragma warning(disable:4003) // not enough actual parameters for macro 'BOOST_PP_EXPAND_I' + // http://lists.boost.org/boost-users/2014/11/83291.php +#endif + +#ifndef CGAL_EIGEN3_ENABLED +#error Requires Eigen +#endif +#include <boost/type_traits/is_arithmetic.hpp> +#include <boost/utility/enable_if.hpp> +#include <CGAL/Dimension.h> +#include <Eigen/Dense> +#include <CGAL/iterator_from_indices.h> +#include <CGAL/NewKernel_d/utils.h> +#include <boost/preprocessor/repetition.hpp> +#include <boost/preprocessor/repetition/enum.hpp> +#include <boost/preprocessor/repetition/enum_params.hpp> + +namespace CGAL { + template <class Vector_> struct Construct_eigen { + typedef Vector_ result_type; + typedef typename Vector_::Scalar NT; + + private: + static void check_dim(int CGAL_assertion_code(d)){ + CGAL_assertion_code(int m = result_type::MaxSizeAtCompileTime;) + CGAL_assertion((m == Eigen::Dynamic) || (d <= m)); + } + public: + + struct Dimension { + // Initialize with NaN if possible? + result_type operator()(int d) const { + check_dim(d); + return result_type(d); + } + }; + + struct Iterator { + template<typename Iter> + result_type operator()(int d,Iter const& f,Iter const& e) const { + check_dim(d); + CGAL_assertion(d==std::distance(f,e)); + result_type a(d); + // TODO: check the right way to do this + std::copy(f,e,&a[0]); + return a; + } + }; + +#if 0 + struct Iterator_add_one { + template<typename Iter> + result_type operator()(int d,Iter const& f,Iter const& e) const { + check_dim(d); + CGAL_assertion(d==std::distance(f,e)+1); + result_type a(d); + std::copy(f,e,&a[0]); + a[d-1]=1; + return a; + } + }; +#endif + + struct Iterator_and_last { + template<typename Iter,typename T> + result_type operator()(int d,Iter const& f,Iter const& e,CGAL_FORWARDABLE(T) t) const { + check_dim(d); + CGAL_assertion(d==std::distance(f,e)+1); + result_type a(d); + std::copy(f,e,&a[0]); + a[d-1]=CGAL_FORWARD(T,t); + return a; + } + }; + +#ifdef CGAL_CXX11 + struct Initializer_list { + // Fix T==NT? + template<class T> + result_type operator()(std::initializer_list<T> l) const { + return Iterator()(l.size(),l.begin(),l.end()); + } + }; +#endif + + struct Values { +#ifdef CGAL_CXX11 + // TODO avoid going through Initializer_list which may cause extra copies. Possibly use forward_as_tuple. + template<class...U> + result_type operator()(U&&...u) const { + check_dim(sizeof...(U)); // TODO: use static_assert + return Initializer_list()({forward_safe<NT,U>(u)...}); + } +#else + +#define CGAL_CODE(Z,N,_) result_type operator()(BOOST_PP_ENUM_PARAMS(N,NT const& t)) const { \ + check_dim(N); \ + result_type a(N); \ + a << BOOST_PP_ENUM_PARAMS(N,t); \ + return a; \ +} +BOOST_PP_REPEAT_FROM_TO(1, 11, CGAL_CODE, _ ) +#undef CGAL_CODE + +#endif + }; + + struct Values_divide { +#ifdef CGAL_CXX11 + template<class H,class...U> + result_type operator()(H const&h,U&&...u) const { + check_dim(sizeof...(U)); // TODO: use static_assert + return Initializer_list()({Rational_traits<NT>().make_rational(std::forward<U>(u),h)...}); + } +#else + +#define CGAL_VAR(Z,N,_) ( Rational_traits<NT>().make_rational( t##N ,h) ) +#define CGAL_CODE(Z,N,_) template <class H> result_type \ + operator()(H const&h, BOOST_PP_ENUM_PARAMS(N,NT const& t)) const { \ + check_dim(N); \ + result_type a(N); \ + a << BOOST_PP_ENUM(N,CGAL_VAR,); \ + return a; \ + } + BOOST_PP_REPEAT_FROM_TO(1, 11, CGAL_CODE, _ ) +#undef CGAL_CODE +#undef CGAL_VAR + +#endif + }; + }; +} +#if defined(BOOST_MSVC) +# pragma warning(pop) +#endif + +#endif diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Lazy_cartesian.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Lazy_cartesian.h new file mode 100644 index 00000000..9ecc2b63 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Lazy_cartesian.h @@ -0,0 +1,188 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KERNEL_D_LAZY_CARTESIAN_H +#define CGAL_KERNEL_D_LAZY_CARTESIAN_H + +#include <CGAL/basic.h> +#include <CGAL/algorithm.h> +#include <CGAL/Lazy.h> +#include <CGAL/Default.h> +#include <CGAL/NewKernel_d/Filtered_predicate2.h> +#include <CGAL/iterator_from_indices.h> +#include <CGAL/NewKernel_d/Define_kernel_types.h> + +namespace CGAL { + +template<class K,class T> +struct Nth_iterator_element : private Store_kernel<K> { + Nth_iterator_element(){} + Nth_iterator_element(K const&k):Store_kernel<K>(k){} + typedef typename Get_type<K, typename iterator_tag_traits<T>::value_tag>::type result_type; + template<class U> result_type operator()(CGAL_FORWARDABLE(U) u, int i) const { + typename Get_functor<K, Construct_ttag<T> >::type ci(this->kernel()); + return *cpp0x::next(ci(CGAL_FORWARD(U,u),Begin_tag()),i); + } +}; + //typedef typename Functor<typename iterator_tag_traits<T>::nth_element>::type nth_elem; +template<class K, class T, bool = iterator_tag_traits<T>::has_nth_element> +struct Select_nth_element_functor { + typedef Nth_iterator_element<K, T> type; +}; +template<class K, class T> +struct Select_nth_element_functor <K, T, true> : + Get_functor<K, typename iterator_tag_traits<T>::nth_element> {}; + +namespace internal { + template<class A,class B,class C,bool/*is_NT=false*/> + struct Lazy_construction_maybe_nt { + typedef Lazy_construction<A,B,C> type; + }; + template<class A,class B,class C> + struct Lazy_construction_maybe_nt<A,B,C,true> { + typedef Lazy_construction_nt<A,B,C> type; + }; +} + +template <class EK_, class AK_, class E2A_, class Kernel_> +struct Lazy_cartesian_types +{ + typedef typename typeset_intersection< + typename AK_::Object_list, + typename EK_::Object_list + >::type Object_list; + + typedef typename typeset_intersection< + typename AK_::Iterator_list, + typename EK_::Iterator_list + >::type Iterator_list; + + template <class T,class=typename Get_type_category<Kernel_,T>::type> struct Type {}; + template <class T> struct Type<T,Object_tag> { + typedef Lazy< + typename Get_type<AK_,T>::type, + typename Get_type<EK_,T>::type, + typename Get_type<EK_, FT_tag>::type, + E2A_> type; + }; + template <class T> struct Type<T,Number_tag> { + typedef CGAL::Lazy_exact_nt<typename Get_type<EK_,T>::type> type; + }; + + template <class T> struct Iterator { + typedef typename iterator_tag_traits<T>::value_tag Vt; + typedef typename Type<Vt>::type V; + typedef typename Select_nth_element_functor<AK_,T>::type AF; + typedef typename Select_nth_element_functor<EK_,T>::type EF; + + typedef typename internal::Lazy_construction_maybe_nt< + Kernel_, AF, EF, is_NT_tag<Vt>::value + >::type nth_elem; + + typedef Iterator_from_indices< + const typename Type<typename iterator_tag_traits<T>::container>::type, + const V, V, nth_elem + > type; + }; +}; + +template <class EK_, class AK_, class E2A_/*, class Kernel_=Default*/> +struct Lazy_cartesian : Dimension_base<typename EK_::Default_ambient_dimension>, + Lazy_cartesian_types<EK_,AK_,E2A_,Lazy_cartesian<EK_,AK_,E2A_> > +{ + //CGAL_CONSTEXPR Lazy_cartesian(){} + //CGAL_CONSTEXPR Lazy_cartesian(int d):Base_(d){} + + //TODO: Do we want to store an AK and an EK? Or just references? + //FIXME: references would be better I guess. + //TODO: In any case, make sure that we don't end up storing this kernel for + //nothing (it is not empty but references empty kernels or something) + AK_ ak; EK_ ek; + AK_ const& approximate_kernel()const{return ak;} + EK_ const& exact_kernel()const{return ek;} + + typedef Lazy_cartesian Self; + typedef Lazy_cartesian_types<EK_,AK_,E2A_,Self> Base; + //typedef typename Default::Get<Kernel_,Self>::type Kernel; + typedef Self Kernel; + typedef AK_ Approximate_kernel; + typedef EK_ Exact_kernel; + typedef E2A_ E2A; + typedef Approx_converter<Kernel, Approximate_kernel> C2A; + typedef Exact_converter<Kernel, Exact_kernel> C2E; + + typedef typename Exact_kernel::Rep_tag Rep_tag; + typedef typename Exact_kernel::Kernel_tag Kernel_tag; + typedef typename Exact_kernel::Default_ambient_dimension Default_ambient_dimension; + typedef typename Exact_kernel::Max_ambient_dimension Max_ambient_dimension; + //typedef typename Exact_kernel::Flat_orientation Flat_orientation; + // Check that Approximate_kernel agrees with all that... + + template<class T,class D=void,class=typename Get_functor_category<Lazy_cartesian,T,D>::type> struct Functor { + typedef Null_functor type; + }; + //FIXME: what do we do with D here? + template<class T,class D> struct Functor<T,D,Predicate_tag> { + typedef typename Get_functor<Approximate_kernel, T>::type FA; + typedef typename Get_functor<Exact_kernel, T>::type FE; + typedef Filtered_predicate2<FE,FA,C2E,C2A> type; + }; + template<class T,class D> struct Functor<T,D,Compute_tag> { + typedef typename Get_functor<Approximate_kernel, T>::type FA; + typedef typename Get_functor<Exact_kernel, T>::type FE; + typedef Lazy_construction_nt<Kernel,FA,FE> type; + }; + template<class T,class D> struct Functor<T,D,Construct_tag> { + typedef typename Get_functor<Approximate_kernel, T>::type FA; + typedef typename Get_functor<Exact_kernel, T>::type FE; + typedef Lazy_construction<Kernel,FA,FE> type; + }; + + //typedef typename Iterator<Point_cartesian_const_iterator_tag>::type Point_cartesian_const_iterator; + //typedef typename Iterator<Vector_cartesian_const_iterator_tag>::type Vector_cartesian_const_iterator; + + template<class U> + struct Construct_iter : private Store_kernel<Kernel> { + Construct_iter(){} + Construct_iter(Kernel const&k):Store_kernel<Kernel>(k){} + //FIXME: pass the kernel to the functor in the iterator + typedef U result_type; + template<class T> + result_type operator()(T const& t,Begin_tag)const{ + return result_type(t,0,this->kernel()); + } + template<class T> + result_type operator()(T const& t,End_tag)const{ + return result_type(t,Self().dimension(),this->kernel()); + } + }; + template<class T,class D> struct Functor<T,D,Construct_iterator_tag> { + typedef Construct_iter<typename Base::template Iterator<typename map_result_tag<T>::type>::type> type; + }; + + + //TODO: what about other functors of the Misc category? + // for Point_dimension, we should apply it to the approximate point + // for printing, we should??? just not do printing this way? +}; + + +} //namespace CGAL + +#endif // CGAL_KERNEL_D_LAZY_CARTESIAN_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Aff_transformation.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Aff_transformation.h new file mode 100644 index 00000000..6d9f070f --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Aff_transformation.h @@ -0,0 +1,59 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KD_TYPE_AFF_TRANSFORMATION_H +#define CGAL_KD_TYPE_AFF_TRANSFORMATION_H +#include <CGAL/config.h> +#include <CGAL/NewKernel_d/store_kernel.h> +#include <boost/preprocessor/repetition.hpp> + +// Dummy, that's all the Kernel_d concept requires, so a useful class will wait. + +namespace CGAL { +template<class R_> +struct Aff_transformation { + typedef R_ R; +}; +namespace CartesianDKernelFunctors { +template<class R_> struct Construct_aff_transformation { + CGAL_FUNCTOR_INIT_IGNORE(Construct_aff_transformation) + typedef R_ R; + typedef typename Get_type<R, Aff_transformation_tag>::type result_type; +#ifdef CGAL_CXX11 + template<class...T> + result_type operator()(T&&...)const{return result_type();} +#else + result_type operator()()const{ + return result_type(); + } +#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class U)> \ + result_type operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,U,const& BOOST_PP_INTERCEPT))const{ \ + return result_type(); \ + } + BOOST_PP_REPEAT_FROM_TO(1, 9, CGAL_CODE, _ ) +#undef CGAL_CODE + +#endif +}; +} +CGAL_KD_DEFAULT_TYPE(Aff_transformation_tag,(CGAL::Aff_transformation<K>),(),()); +CGAL_KD_DEFAULT_FUNCTOR(Construct_ttag<Aff_transformation_tag>,(CartesianDKernelFunctors::Construct_aff_transformation<K>),(Aff_transformation_tag),()); + +} +#endif diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Hyperplane.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Hyperplane.h new file mode 100644 index 00000000..14e35b01 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Hyperplane.h @@ -0,0 +1,159 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KD_TYPE_HYPERPLANE_H +#define CGAL_KD_TYPE_HYPERPLANE_H +#include <CGAL/enum.h> +#include <CGAL/number_utils.h> +#include <CGAL/NewKernel_d/store_kernel.h> +#include <boost/iterator/transform_iterator.hpp> +#include <boost/iterator/counting_iterator.hpp> +namespace CGAL { +template <class R_> class Hyperplane { + typedef typename Get_type<R_, FT_tag>::type FT_; + typedef typename Get_type<R_, Vector_tag>::type Vector_; + Vector_ v_; + FT_ s_; + + public: + Hyperplane(Vector_ const&v, FT_ const&s): v_(v), s_(s) {} + // TODO: Add a piecewise constructor? + + Vector_ const& orthogonal_vector()const{return v_;} + FT_ translation()const{return s_;} +}; +namespace CartesianDKernelFunctors { +template <class R_> struct Construct_hyperplane : Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Construct_hyperplane) + typedef typename Get_type<R_, Hyperplane_tag>::type result_type; + typedef typename Get_type<R_, Point_tag>::type Point; + typedef typename Get_type<R_, Vector_tag>::type Vector; + typedef typename Get_type<R_, FT_tag>::type FT; + private: + struct One { + typedef int result_type; + template<class T>int const& operator()(T const&)const{ + static const int one = 1; + return one; + } + }; + public: + + result_type operator()(Vector const&a, FT const&b)const{ + return result_type(a,b); + } + // Not really needed + result_type operator()()const{ + typename Get_functor<R_, Construct_ttag<Vector_tag> >::type cv(this->kernel()); + return result_type(cv(),0); + } + + template <class Iter> + result_type through(Iter f, Iter e)const{ + typedef typename R_::LA LA; + typedef typename R_::Default_ambient_dimension D1; + typedef typename R_::Max_ambient_dimension D2; + typedef typename Increment_dimension<D1>::type D1i; + typedef typename Increment_dimension<D2>::type D2i; + + typedef Eigen::Matrix<FT, Eigen_dimension<D1>::value, Eigen_dimension<D1i>::value, + Eigen::ColMajor|Eigen::AutoAlign, Eigen_dimension<D2>::value, Eigen_dimension<D2i>::value> Matrix; + typedef Eigen::Matrix<FT, Eigen_dimension<D1i>::value, 1, + Eigen::ColMajor|Eigen::AutoAlign, Eigen_dimension<D2i>::value, 1> Vec; + typename Get_functor<R_, Compute_point_cartesian_coordinate_tag>::type c(this->kernel()); + typename Get_functor<R_, Construct_ttag<Vector_tag> >::type cv(this->kernel()); + typename Get_functor<R_, Point_dimension_tag>::type pd(this->kernel()); + + Point const& p0=*f; + int d = pd(p0); + Matrix m(d,d+1); + for(int j=0;j<d;++j) + m(0,j)=c(p0,j); + // Write the point coordinates in lines. + int i; + for (i=1; ++f!=e; ++i) { + Point const& p=*f; + for(int j=0;j<d;++j) + m(i,j)=c(p,j); + } + CGAL_assertion (i == d); + for(i=0;i<d;++i) + m(i,d)=-1; + Eigen::FullPivLU<Matrix> lu(m); + Vec res = lu.kernel().col(0); + return this->operator()(cv(d,LA::vector_begin(res),LA::vector_end(res)-1),res(d)); + } + template <class Iter> + result_type operator()(Iter f, Iter e, Point const&p, CGAL::Oriented_side s=ON_ORIENTED_BOUNDARY)const{ + result_type ret = through(f, e); + // I don't really like using ON_ORIENTED_BOUNDARY to mean that we don't care, we might as well not pass 'p' at all. + if (s == ON_ORIENTED_BOUNDARY) + return ret; + typename Get_functor<R_, Oriented_side_tag>::type os(this->kernel()); + CGAL::Oriented_side o = os(ret, p); + if (o == ON_ORIENTED_BOUNDARY || o == s) + return ret; + typename Get_functor<R_, Opposite_vector_tag>::type ov(this->kernel()); + typename Get_functor<R_, Construct_ttag<Vector_tag> >::type cv(this->kernel()); + return this->operator()(ov(ret.orthogonal_vector()), -ret.translation()); + } +}; +template <class R_> struct Orthogonal_vector { + CGAL_FUNCTOR_INIT_IGNORE(Orthogonal_vector) + typedef typename Get_type<R_, Hyperplane_tag>::type Hyperplane; + typedef typename Get_type<R_, Vector_tag>::type const& result_type; + result_type operator()(Hyperplane const&s)const{ + return s.orthogonal_vector(); + } +}; +template <class R_> struct Hyperplane_translation { + CGAL_FUNCTOR_INIT_IGNORE(Hyperplane_translation) + typedef typename Get_type<R_, Hyperplane_tag>::type Hyperplane; + typedef typename Get_type<R_, FT_tag>::type result_type; + // TODO: Is_exact? + result_type operator()(Hyperplane const&s)const{ + return s.translation(); + } +}; +template <class R_> struct Value_at : Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Value_at) + typedef typename Get_type<R_, Hyperplane_tag>::type Hyperplane; + typedef typename Get_type<R_, Vector_tag>::type Vector; + typedef typename Get_type<R_, Point_tag>::type Point; + typedef typename Get_type<R_, FT_tag>::type FT; + typedef FT result_type; + typedef typename Get_functor<R_, Scalar_product_tag>::type Dot; + typedef typename Get_functor<R_, Point_to_vector_tag>::type P2V; + result_type operator()(Hyperplane const&h, Point const&p)const{ + Dot dot(this->kernel()); + P2V p2v(this->kernel()); + return dot(h.orthogonal_vector(),p2v(p)); + // Use Orthogonal_vector to make it generic? + // Copy the code from Scalar_product to avoid p2v? + } +}; +} +//TODO: Add a condition that the hyperplane type is the one from this file. +CGAL_KD_DEFAULT_TYPE(Hyperplane_tag,(CGAL::Hyperplane<K>),(Vector_tag),()); +CGAL_KD_DEFAULT_FUNCTOR(Construct_ttag<Hyperplane_tag>,(CartesianDKernelFunctors::Construct_hyperplane<K>),(Vector_tag,Hyperplane_tag),(Opposite_vector_tag,Oriented_side_tag)); +CGAL_KD_DEFAULT_FUNCTOR(Orthogonal_vector_tag,(CartesianDKernelFunctors::Orthogonal_vector<K>),(Vector_tag,Hyperplane_tag),()); +CGAL_KD_DEFAULT_FUNCTOR(Hyperplane_translation_tag,(CartesianDKernelFunctors::Hyperplane_translation<K>),(Hyperplane_tag),()); +CGAL_KD_DEFAULT_FUNCTOR(Value_at_tag,(CartesianDKernelFunctors::Value_at<K>),(Point_tag,Vector_tag,Hyperplane_tag),(Scalar_product_tag,Point_to_vector_tag)); +} // namespace CGAL +#endif diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Iso_box.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Iso_box.h new file mode 100644 index 00000000..d053f351 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Iso_box.h @@ -0,0 +1,88 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KERNELD_TYPES_ISO_BOX_H +#define CGAL_KERNELD_TYPES_ISO_BOX_H +#include <utility> +#include <CGAL/basic.h> +#include <CGAL/NewKernel_d/functor_tags.h> +#include <CGAL/Kernel/mpl.h> +#include <CGAL/transforming_pair_iterator.h> +namespace CGAL { +template <class R_> class Iso_box { + typedef typename Get_type<R_, FT_tag>::type FT_; + typedef typename Get_type<R_, Point_tag>::type Point_; + typedef std::pair<Point_,Point_> Data_; + Data_ data; + public: + Iso_box(){} + Iso_box(Point_ const&a, Point_ const&b): data(a,b) {} + Point_ min BOOST_PREVENT_MACRO_SUBSTITUTION ()const{ + return data.first; + } + Point_ max BOOST_PREVENT_MACRO_SUBSTITUTION ()const{ + return data.second; + } +}; +namespace CartesianDKernelFunctors { + template <class R_> struct Construct_iso_box : Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Construct_iso_box) + typedef typename Get_type<R_, Iso_box_tag>::type result_type; + typedef typename Get_type<R_, RT_tag>::type RT; + typedef typename Get_type<R_, Point_tag>::type Point; + typedef typename Get_functor<R_, Construct_ttag<Point_tag> >::type Cp_; + typedef typename Get_functor<R_, Construct_ttag<Point_cartesian_const_iterator_tag> >::type Ci_; + result_type operator()(Point const&a, Point const&b)const{ + Cp_ cp(this->kernel()); + Ci_ ci(this->kernel()); + return result_type(cp( + make_transforming_pair_iterator(ci(a,Begin_tag()), ci(b,Begin_tag()), Min<RT>()), + make_transforming_pair_iterator(ci(a,End_tag()), ci(b,End_tag()), Min<RT>())), + cp( + make_transforming_pair_iterator(ci(a,Begin_tag()), ci(b,Begin_tag()), Max<RT>()), + make_transforming_pair_iterator(ci(a,End_tag()), ci(b,End_tag()), Max<RT>()))); + } + }; + + template <class R_> struct Construct_min_vertex { + CGAL_FUNCTOR_INIT_IGNORE(Construct_min_vertex) + typedef typename Get_type<R_, Iso_box_tag>::type argument_type; + //TODO: make result_type a reference + typedef typename Get_type<R_, Point_tag>::type result_type; + result_type operator()(argument_type const&b)const{ + return b.min BOOST_PREVENT_MACRO_SUBSTITUTION (); + } + }; + template <class R_> struct Construct_max_vertex { + CGAL_FUNCTOR_INIT_IGNORE(Construct_max_vertex) + typedef typename Get_type<R_, Iso_box_tag>::type argument_type; + typedef typename Get_type<R_, Point_tag>::type result_type; + result_type operator()(argument_type const&b)const{ + return b.max BOOST_PREVENT_MACRO_SUBSTITUTION (); + } + }; +} +//TODO (other types as well) only enable these functors if the Iso_box type is the one defined in this file... +CGAL_KD_DEFAULT_TYPE(Iso_box_tag,(CGAL::Iso_box<K>),(Point_tag),()); +CGAL_KD_DEFAULT_FUNCTOR(Construct_ttag<Iso_box_tag>,(CartesianDKernelFunctors::Construct_iso_box<K>),(Iso_box_tag,Point_tag),(Construct_ttag<Point_cartesian_const_iterator_tag>,Construct_ttag<Point_tag>)); +CGAL_KD_DEFAULT_FUNCTOR(Construct_min_vertex_tag,(CartesianDKernelFunctors::Construct_min_vertex<K>),(Iso_box_tag),()); +CGAL_KD_DEFAULT_FUNCTOR(Construct_max_vertex_tag,(CartesianDKernelFunctors::Construct_max_vertex<K>),(Iso_box_tag),()); +} // namespace CGAL + +#endif // CGAL_KERNELD_TYPES_ISO_BOX_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Line.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Line.h new file mode 100644 index 00000000..6a09571c --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Line.h @@ -0,0 +1,66 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KERNELD_TYPES_LINE_H +#define CGAL_KERNELD_TYPES_LINE_H +#include <utility> +#include <CGAL/NewKernel_d/functor_tags.h> +#include <CGAL/Kernel/mpl.h> +namespace CGAL { +template <class R_> class Line { + typedef typename Get_type<R_, FT_tag>::type FT_; + typedef typename Get_type<R_, Point_tag>::type Point_; + typedef std::pair<Point_,Point_> Data_; + Data_ data; + public: + Line(){} + Line(Point_ const&a, Point_ const&b): data(a,b) {} + Point_ point(int i)const{ + if(i==0) return data.first; + if(i==1) return data.second; + throw "not implemented"; + } + Line opposite()const{ + return Line(data.second,data.first); + } +}; +namespace CartesianDKernelFunctors { + template <class R_> struct Construct_line : Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Construct_line) + typedef typename Get_type<R_, Line_tag>::type result_type; + typedef typename Get_type<R_, Point_tag>::type Point; + typedef typename Get_type<R_, Vector_tag>::type Vector; + typedef typename Get_functor<R_, Translated_point_tag>::type Tp_; + //typedef typename Get_functor<R_, Difference_of_points_tag>::type Dp_; + //typedef typename Get_functor<R_, Scaled_vector_tag>::type Sv_; + result_type operator()(Point const&a, Point const&b)const{ + return result_type(a,b); + } + result_type operator()(Point const&a, typename First_if_different<Vector,Point>::Type const&b)const{ + Tp_ tp(this->kernel()); + return result_type(a,tp(a,b)); + } + }; +} +CGAL_KD_DEFAULT_TYPE(Line_tag,(CGAL::Line<K>),(Point_tag),()); +CGAL_KD_DEFAULT_FUNCTOR(Construct_ttag<Line_tag>,(CartesianDKernelFunctors::Construct_line<K>),(Line_tag,Point_tag,Vector_tag),(Translated_point_tag)); + +} // namespace CGAL + +#endif // CGAL_KERNELD_TYPES_LINE_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Ray.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Ray.h new file mode 100644 index 00000000..be845e76 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Ray.h @@ -0,0 +1,66 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KERNELD_TYPES_RAY_H +#define CGAL_KERNELD_TYPES_RAY_H +#include <utility> +#include <CGAL/NewKernel_d/functor_tags.h> +#include <CGAL/Kernel/mpl.h> +namespace CGAL { +template <class R_> class Ray { + typedef typename Get_type<R_, FT_tag>::type FT_; + typedef typename Get_type<R_, Point_tag>::type Point_; + typedef typename Get_type<R_, Vector_tag>::type Vector_; + typedef std::pair<Point_,Vector_> Data_; + Data_ data; + public: + Ray(){} + Ray(Point_ const&a, Vector_ const&b): data(a,b) {} + Point_ source()const{ + return data.first; + } + // FIXME: return a R_::Direction? + Vector_ direction()const{ + return data.second; + } +}; +namespace CartesianDKernelFunctors { + template <class R_> struct Construct_ray : Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Construct_ray) + typedef typename Get_type<R_, Ray_tag>::type result_type; + typedef typename Get_type<R_, Point_tag>::type Point; + typedef typename Get_type<R_, Vector_tag>::type Vector; + typedef typename Get_functor<R_, Difference_of_points_tag>::type Dp_; + //typedef typename Get_functor<R_, Translated_point_tag>::type Tp_; + //typedef typename Get_functor<R_, Scaled_vector_tag>::type Sv_; + result_type operator()(Point const&a, Vector const&b)const{ + return result_type(a,b); + } + result_type operator()(Point const&a, typename First_if_different<Point,Vector>::Type const&b)const{ + Dp_ dp(this->kernel()); + return result_type(a,dp(b,a)); + } + }; +} +CGAL_KD_DEFAULT_TYPE(Ray_tag,(CGAL::Ray<K>),(Point_tag,Vector_tag),()); +CGAL_KD_DEFAULT_FUNCTOR(Construct_ttag<Ray_tag>,(CartesianDKernelFunctors::Construct_ray<K>),(Point_tag,Ray_tag,Vector_tag),(Difference_of_points_tag)); + +} // namespace CGAL + +#endif // CGAL_KERNELD_TYPES_RAY_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Segment.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Segment.h new file mode 100644 index 00000000..38361c2b --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Segment.h @@ -0,0 +1,121 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KERNELD_SEGMENTD_H +#define CGAL_KERNELD_SEGMENTD_H +#include <CGAL/config.h> +#include <utility> +#include <CGAL/NewKernel_d/functor_tags.h> +namespace CGAL { +template <class R_> class Segment { + typedef typename Get_type<R_, FT_tag>::type FT_; + typedef typename Get_type<R_, Point_tag>::type Point_; + //typedef typename R_::Vector Vector_; + //typedef typename Get_functor<R_, Construct_ttag<Vector_tag> >::type Cv_; +// typedef typename R_::Squared_distance Csd_; + typedef std::pair<Point_,Point_> Data_; + Data_ data; + public: + //typedef Segmentd<R_> Segment; +#ifdef CGAL_CXX11 + //FIXME: don't forward directly, piecewise_constuct should call the point construction functor (I guess? or is it unnecessary?) + template<class...U,class=typename std::enable_if<!std::is_same<std::tuple<typename std::decay<U>::type...>,std::tuple<Segment>>::value>::type> + Segment(U&&...u):data(std::forward<U>(u)...){} +#else + Segment(){} + Segment(Point_ const&a, Point_ const&b): data(a,b) {} + //template<class A,class T1,class T2> + //Segment(A const&,T1 const&t1,T2 const&t2) +#endif + Point_ source()const{return data.first;} + Point_ target()const{return data.second;} + Point_ operator[](int i)const{ + if((i%2)==0) + return source(); + else + return target(); + } + Segment opposite()const{ + return Segment(target(),source()); + } + //Vector_ vector()const{ + // return Cv_()(data.first,data.second); + //} +// FT_ squared_length()const{ +// return Csd_()(data.first,data.second); +// } +}; + +namespace CartesianDKernelFunctors { + +template<class R_> struct Construct_segment : Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Construct_segment) + typedef R_ R; + typedef typename Get_type<R_, Point_tag>::type Point; + typedef typename Get_type<R_, Segment_tag>::type Segment; + typedef typename Get_functor<R_, Construct_ttag<Point_tag> >::type CP; + typedef Segment result_type; + result_type operator()(Point const&a, Point const&b)const{ + return result_type(a,b); + } + // Not really needed, especially since it forces us to store the kernel + result_type operator()()const{ + Point p = typename Get_functor<R_, Construct_ttag<Point_tag> >::type (this->kernel()) (); + return result_type (p, p); + } + // T should only be std::piecewise_construct_t, but we shouldn't fail if it doesn't exist. + template<class T,class U,class V> + result_type operator()(CGAL_FORWARDABLE(T),CGAL_FORWARDABLE(U) u,CGAL_FORWARDABLE(V) v)const{ + CP cp(this->kernel()); + result_type r = {{ + call_on_tuple_elements<Point>(cp, CGAL_FORWARD(U,u)), + call_on_tuple_elements<Point>(cp, CGAL_FORWARD(V,v)) }}; + return r; + } +}; + +// This should be part of Construct_point, according to Kernel_23 conventions +template<class R_> struct Segment_extremity { + CGAL_FUNCTOR_INIT_IGNORE(Segment_extremity) + typedef R_ R; + typedef typename Get_type<R_, Point_tag>::type Point; + typedef typename Get_type<R_, Segment_tag>::type Segment; + typedef Point result_type; + result_type operator()(Segment const&s, int i)const{ + if(i==0) return s.source(); + CGAL_assertion(i==1); + return s.target(); + } +#ifdef CGAL_CXX11 + result_type operator()(Segment &&s, int i)const{ + if(i==0) return std::move(s.source()); + CGAL_assertion(i==1); + return std::move(s.target()); + } +#endif +}; +} // CartesianDKernelFunctors + +CGAL_KD_DEFAULT_TYPE(Segment_tag,(CGAL::Segment<K>),(Point_tag),()); +CGAL_KD_DEFAULT_FUNCTOR(Construct_ttag<Segment_tag>,(CartesianDKernelFunctors::Construct_segment<K>),(Segment_tag,Point_tag),(Construct_ttag<Point_tag>)); +CGAL_KD_DEFAULT_FUNCTOR(Segment_extremity_tag,(CartesianDKernelFunctors::Segment_extremity<K>),(Segment_tag,Point_tag),()); + +} // namespace CGAL + +#endif // CGAL_KERNELD_SEGMENTD_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Sphere.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Sphere.h new file mode 100644 index 00000000..114410b4 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Sphere.h @@ -0,0 +1,132 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KD_TYPE_SPHERE_H +#define CGAL_KD_TYPE_SPHERE_H +#include <CGAL/NewKernel_d/store_kernel.h> +#include <boost/iterator/counting_iterator.hpp> +namespace CGAL { +template <class R_> class Sphere { + typedef typename Get_type<R_, FT_tag>::type FT_; + typedef typename Get_type<R_, Point_tag>::type Point_; + Point_ c_; + FT_ r2_; + + public: + Sphere(Point_ const&p, FT_ const&r2): c_(p), r2_(r2) {} + // TODO: Add a piecewise constructor? + + Point_ const& center()const{return c_;} + FT_ const& squared_radius()const{return r2_;} +}; + +namespace CartesianDKernelFunctors { +template <class R_> struct Construct_sphere : Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Construct_sphere) + typedef typename Get_type<R_, Sphere_tag>::type result_type; + typedef typename Get_type<R_, Point_tag>::type Point; + typedef typename Get_type<R_, FT_tag>::type FT; + result_type operator()(Point const&a, FT const&b)const{ + return result_type(a,b); + } + // Not really needed + result_type operator()()const{ + typename Get_functor<R_, Construct_ttag<Point_tag> >::type cp(this->kernel()); + return result_type(cp(),0); + } + template <class Iter> + result_type operator()(Iter f, Iter e)const{ + typename Get_functor<R_, Construct_circumcenter_tag>::type cc(this->kernel()); + typename Get_functor<R_, Squared_distance_tag>::type sd(this->kernel()); + + // It should be possible to avoid copying the center by moving this code to a constructor. + Point center = cc(f, e); + FT const& r2 = sd(center, *f); + return this->operator()(CGAL_MOVE(center), r2); + } +}; + +template <class R_> struct Center_of_sphere : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Center_of_sphere) + typedef typename Get_type<R_, Sphere_tag>::type Sphere; + // No reference because of the second overload + typedef typename Get_type<R_, Point_tag>::type result_type; + + result_type const& operator()(Sphere const&s)const{ + return s.center(); + } + + template<class Iter> + result_type operator()(Iter b, Iter e)const{ + typename Get_functor<R_, Construct_ttag<Sphere_tag> >::type cs(this->kernel()); + return operator()(cs(b,e)); // computes the radius needlessly + } +}; + +template <class R_> struct Squared_radius { + CGAL_FUNCTOR_INIT_IGNORE(Squared_radius) + typedef typename Get_type<R_, Sphere_tag>::type Sphere; + typedef typename Get_type<R_, FT_tag>::type const& result_type; + // TODO: Is_exact? + result_type operator()(Sphere const&s)const{ + return s.squared_radius(); + } +}; + +// FIXME: Move it to the generic functors, using the two above and conditional to the existence of sqrt(FT) +template<class R_> struct Point_of_sphere : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Point_of_sphere) + typedef R_ R; + typedef typename Get_type<R, FT_tag>::type FT; + typedef typename Get_type<R, RT_tag>::type RT; + typedef typename Get_type<R, Point_tag>::type Point; + typedef typename Get_type<R, Sphere_tag>::type Sphere; + typedef typename Get_functor<R, Construct_ttag<Point_tag> >::type CP; + typedef typename Get_functor<R, Construct_ttag<Point_cartesian_const_iterator_tag> >::type CI; + typedef typename Get_functor<R, Point_dimension_tag>::type PD; + typedef Point result_type; + typedef Sphere first_argument_type; + typedef int second_argument_type; + struct Trans : std::binary_function<FT,int,FT> { + FT const& r_; int idx; bool sgn; + Trans (int n, FT const& r, bool b) : r_(r), idx(n), sgn(b) {} + FT operator()(FT const&x, int i)const{ + return (i == idx) ? sgn ? x + r_ : x - r_ : x; + } + }; + result_type operator()(Sphere const&s, int i)const{ + CI ci(this->kernel()); + PD pd(this->kernel()); + typedef boost::counting_iterator<int,std::random_access_iterator_tag> Count; + Point const&c = s.center(); + int d=pd(c); + bool last = (i == d); + FT r = sqrt(s.squared_radius()); + Trans t(last ? 0 : i, r, !last); + return CP(this->kernel())(make_transforming_pair_iterator(ci(c,Begin_tag()),Count(0),t),make_transforming_pair_iterator(ci(c,End_tag()),Count(d),t)); + } +}; +} +CGAL_KD_DEFAULT_TYPE(Sphere_tag,(CGAL::Sphere<K>),(Point_tag),()); +CGAL_KD_DEFAULT_FUNCTOR(Construct_ttag<Sphere_tag>,(CartesianDKernelFunctors::Construct_sphere<K>),(Sphere_tag,Point_tag),(Construct_ttag<Point_tag>,Compute_point_cartesian_coordinate_tag,Squared_distance_tag,Squared_distance_to_origin_tag,Point_dimension_tag)); +CGAL_KD_DEFAULT_FUNCTOR(Center_of_sphere_tag,(CartesianDKernelFunctors::Center_of_sphere<K>),(Sphere_tag,Point_tag),(Construct_ttag<Sphere_tag>)); +CGAL_KD_DEFAULT_FUNCTOR(Squared_radius_tag,(CartesianDKernelFunctors::Squared_radius<K>),(Sphere_tag),()); +CGAL_KD_DEFAULT_FUNCTOR(Point_of_sphere_tag,(CartesianDKernelFunctors::Point_of_sphere<K>),(Sphere_tag,Point_tag),(Construct_ttag<Point_tag>, Construct_ttag<Point_cartesian_const_iterator_tag>)); +} // namespace CGAL +#endif diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Weighted_point.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Weighted_point.h new file mode 100644 index 00000000..1caf8701 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Types/Weighted_point.h @@ -0,0 +1,205 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KD_TYPE_WP_H +#define CGAL_KD_TYPE_WP_H +#include <CGAL/NewKernel_d/store_kernel.h> +#include <boost/iterator/counting_iterator.hpp> +namespace CGAL { +namespace KerD { +template <class R_> class Weighted_point { + typedef typename Get_type<R_, FT_tag>::type FT_; + typedef typename Get_type<R_, Point_tag>::type Point_; + Point_ c_; + FT_ w_; + + public: + Weighted_point(Point_ const&p, FT_ const&w): c_(p), w_(w) {} + // TODO: Add a piecewise constructor? + + Point_ const& point()const{return c_;} + FT_ const& weight()const{return w_;} +}; +} + +namespace CartesianDKernelFunctors { +template <class R_> struct Construct_weighted_point : Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Construct_weighted_point) + typedef typename Get_type<R_, Weighted_point_tag>::type result_type; + typedef typename Get_type<R_, Point_tag>::type Point; + typedef typename Get_type<R_, FT_tag>::type FT; + result_type operator()(Point const&a, FT const&b)const{ + return result_type(a,b); + } + // Not really needed + result_type operator()()const{ + typename Get_functor<R_, Construct_ttag<Point_tag> >::type cp(this->kernel()); + return result_type(cp(),0); + } +}; + +template <class R_> struct Point_drop_weight { + CGAL_FUNCTOR_INIT_IGNORE(Point_drop_weight) + typedef typename Get_type<R_, Weighted_point_tag>::type argument_type; + typedef typename Get_type<R_, Point_tag>::type const& result_type; + // Returning a reference is fragile + + result_type operator()(argument_type const&s)const{ + return s.point(); + } +}; + +template <class R_> struct Point_weight { + CGAL_FUNCTOR_INIT_IGNORE(Point_weight) + typedef typename Get_type<R_, Weighted_point_tag>::type argument_type; + typedef typename Get_type<R_, FT_tag>::type result_type; + + result_type operator()(argument_type const&s)const{ + return s.weight(); + } +}; + +template <class R_> struct Power_distance : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Power_distance) + typedef typename Get_type<R_, Weighted_point_tag>::type first_argument_type; + typedef first_argument_type second_argument_type; + typedef typename Get_type<R_, FT_tag>::type result_type; + + result_type operator()(first_argument_type const&a, second_argument_type const&b)const{ + typename Get_functor<R_, Point_drop_weight_tag>::type pdw(this->kernel()); + typename Get_functor<R_, Point_weight_tag>::type pw(this->kernel()); + typename Get_functor<R_, Squared_distance_tag>::type sd(this->kernel()); + return sd(pdw(a),pdw(b))-pw(a)-pw(b); + } +}; +template <class R_> struct Power_distance_to_point : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Power_distance_to_point) + typedef typename Get_type<R_, Weighted_point_tag>::type first_argument_type; + typedef typename Get_type<R_, Point_tag>::type second_argument_type; + typedef typename Get_type<R_, FT_tag>::type result_type; + + result_type operator()(first_argument_type const&a, second_argument_type const&b)const{ + typename Get_functor<R_, Point_drop_weight_tag>::type pdw(this->kernel()); + typename Get_functor<R_, Point_weight_tag>::type pw(this->kernel()); + typename Get_functor<R_, Squared_distance_tag>::type sd(this->kernel()); + return sd(pdw(a),b)-pw(a); + } +}; + +template<class R_> struct Power_side_of_power_sphere : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Power_side_of_power_sphere) + typedef R_ R; + typedef typename Get_type<R, Oriented_side_tag>::type result_type; + + template<class Iter, class Pt> + result_type operator()(Iter const& f, Iter const& e, Pt const& p0) const { + typename Get_functor<R, Power_side_of_power_sphere_raw_tag>::type ptr(this->kernel()); + typename Get_functor<R, Point_drop_weight_tag>::type pdw(this->kernel()); + typename Get_functor<R, Point_weight_tag>::type pw(this->kernel()); + return ptr ( + make_transforming_iterator (f, pdw), + make_transforming_iterator (e, pdw), + make_transforming_iterator (f, pw), + pdw (p0), + pw (p0)); + } +}; + +template<class R_> struct In_flat_power_side_of_power_sphere : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(In_flat_power_side_of_power_sphere) + typedef R_ R; + typedef typename Get_type<R, Oriented_side_tag>::type result_type; + + template<class Fo, class Iter, class Pt> + result_type operator()(Fo const& fo, Iter const& f, Iter const& e, Pt const& p0) const { + typename Get_functor<R, In_flat_power_side_of_power_sphere_raw_tag>::type ptr(this->kernel()); + typename Get_functor<R, Point_drop_weight_tag>::type pdw(this->kernel()); + typename Get_functor<R, Point_weight_tag>::type pw(this->kernel()); + return ptr ( + fo, + make_transforming_iterator (f, pdw), + make_transforming_iterator (e, pdw), + make_transforming_iterator (f, pw), + pdw (p0), + pw (p0)); + } +}; + +// Construct a point at (weighted) distance 0 from all the input +template <class R_> struct Power_center : Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Power_center) + typedef typename Get_type<R_, Weighted_point_tag>::type WPoint; + typedef WPoint result_type; + typedef typename Get_type<R_, Point_tag>::type Point; + typedef typename Get_type<R_, FT_tag>::type FT; + template <class Iter> + result_type operator()(Iter f, Iter e)const{ + // 2*(x-y).c == (x^2-wx^2)-(y^2-wy^2) + typedef typename R_::LA LA; + typedef typename LA::Square_matrix Matrix; + typedef typename LA::Vector Vec; + typedef typename LA::Construct_vector CVec; + typename Get_functor<R_, Compute_point_cartesian_coordinate_tag>::type c(this->kernel()); + typename Get_functor<R_, Construct_ttag<Point_tag> >::type cp(this->kernel()); + typename Get_functor<R_, Point_dimension_tag>::type pd(this->kernel()); + typename Get_functor<R_, Squared_distance_to_origin_tag>::type sdo(this->kernel()); + typename Get_functor<R_, Power_distance_to_point_tag>::type pdp(this->kernel()); + typename Get_functor<R_, Point_drop_weight_tag>::type pdw(this->kernel()); + typename Get_functor<R_, Point_weight_tag>::type pw(this->kernel()); + typename Get_functor<R_, Construct_ttag<Weighted_point_tag> >::type cwp(this->kernel()); + + WPoint const& wp0 = *f; + Point const& p0 = pdw(wp0); + int d = pd(p0); + FT const& n0 = sdo(p0) - pw(wp0); + Matrix m(d,d); + Vec b = typename CVec::Dimension()(d); + // Write the point coordinates in lines. + int i; + for(i=0; ++f!=e; ++i) { + WPoint const& wp=*f; + Point const& p=pdw(wp); + FT const& np = sdo(p) - pw(wp); + for(int j=0;j<d;++j) { + m(i,j)=2*(c(p,j)-c(p0,j)); + b[i] = np - n0; + } + } + CGAL_assertion (i == d); + Vec res = typename CVec::Dimension()(d);; + //std::cout << "Mat: " << m << "\n Vec: " << one << std::endl; + LA::solve(res, CGAL_MOVE(m), CGAL_MOVE(b)); + //std::cout << "Sol: " << res << std::endl; + Point center = cp(d,LA::vector_begin(res),LA::vector_end(res)); + FT const& r2 = pdp (wp0, center); + return cwp(CGAL_MOVE(center), r2); + } +}; +} +CGAL_KD_DEFAULT_TYPE(Weighted_point_tag,(CGAL::KerD::Weighted_point<K>),(Point_tag),()); +CGAL_KD_DEFAULT_FUNCTOR(Construct_ttag<Weighted_point_tag>,(CartesianDKernelFunctors::Construct_weighted_point<K>),(Weighted_point_tag,Point_tag),()); +CGAL_KD_DEFAULT_FUNCTOR(Point_drop_weight_tag,(CartesianDKernelFunctors::Point_drop_weight<K>),(Weighted_point_tag,Point_tag),()); +CGAL_KD_DEFAULT_FUNCTOR(Point_weight_tag,(CartesianDKernelFunctors::Point_weight<K>),(Weighted_point_tag,Point_tag),()); +CGAL_KD_DEFAULT_FUNCTOR(Power_side_of_power_sphere_tag,(CartesianDKernelFunctors::Power_side_of_power_sphere<K>),(Weighted_point_tag),(Power_side_of_power_sphere_raw_tag,Point_drop_weight_tag,Point_weight_tag)); +CGAL_KD_DEFAULT_FUNCTOR(In_flat_power_side_of_power_sphere_tag,(CartesianDKernelFunctors::In_flat_power_side_of_power_sphere<K>),(Weighted_point_tag),(In_flat_power_side_of_power_sphere_raw_tag,Point_drop_weight_tag,Point_weight_tag)); +CGAL_KD_DEFAULT_FUNCTOR(Power_distance_tag,(CartesianDKernelFunctors::Power_distance<K>),(Weighted_point_tag,Point_tag),(Squared_distance_tag,Point_drop_weight_tag,Point_weight_tag)); +CGAL_KD_DEFAULT_FUNCTOR(Power_distance_to_point_tag,(CartesianDKernelFunctors::Power_distance_to_point<K>),(Weighted_point_tag,Point_tag),(Squared_distance_tag,Point_drop_weight_tag,Point_weight_tag)); +CGAL_KD_DEFAULT_FUNCTOR(Power_center_tag,(CartesianDKernelFunctors::Power_center<K>),(Weighted_point_tag,Point_tag),(Compute_point_cartesian_coordinate_tag,Construct_ttag<Point_tag>,Construct_ttag<Weighted_point_tag>,Point_dimension_tag,Squared_distance_to_origin_tag,Point_drop_weight_tag,Point_weight_tag,Power_distance_to_point_tag)); +} // namespace CGAL +#endif diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/array.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/array.h new file mode 100644 index 00000000..0ad9bb36 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/array.h @@ -0,0 +1,165 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_VECTOR_ARRAY_H +#define CGAL_VECTOR_ARRAY_H +#include <boost/type_traits/is_arithmetic.hpp> +#include <boost/utility/enable_if.hpp> +#include <CGAL/Dimension.h> +#include <CGAL/NewKernel_d/utils.h> +#include <CGAL/array.h> +#include <boost/preprocessor/repetition.hpp> +#include <boost/preprocessor/repetition/enum.hpp> + +#include <CGAL/NewKernel_d/Vector/determinant_of_points_from_vectors.h> +#include <CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim.h> +#include <CGAL/NewKernel_d/Vector/determinant_of_iterator_to_points_from_iterator_to_vectors.h> +#include <CGAL/NewKernel_d/Vector/determinant_of_iterator_to_points_from_points.h> +#include <CGAL/NewKernel_d/Vector/determinant_of_iterator_to_vectors_from_vectors.h> + + + +namespace CGAL { + +// May not be safe to use with dim!=max_dim. +// In that case, we should store the real dim next to the array. +template<class NT_,class Dim_,class Max_dim_=Dim_> struct Array_vector { + typedef NT_ NT; + typedef Dim_ Dimension; + typedef Max_dim_ Max_dimension; + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef Array_vector< NT, D2, D3 > Other; + }; + template<class> struct Property : boost::false_type {}; + + static const unsigned d_=Max_dim_::value; + CGAL_static_assertion(d_ != (unsigned)UNKNOWN_DIMENSION); + + typedef cpp0x::array<NT,d_> Vector; + struct Construct_vector { + struct Dimension { + // Initialize with NaN if possible? + Vector operator()(unsigned CGAL_assertion_code(d)) const { + CGAL_assertion(d<=d_); + return Vector(); + } + }; + + struct Iterator { + template<typename Iter> + Vector operator()(unsigned CGAL_assertion_code(d),Iter const& f,Iter const& e) const { + CGAL_assertion(d==(unsigned) std::distance(f,e)); + CGAL_assertion(d<=d_); + //TODO: optimize for forward iterators + Vector a; + std::copy(f,e,a.begin()); + return a; + } + }; + +#if 0 + struct Iterator_add_one { + template<typename Iter> + Vector operator()(unsigned d,Iter const& f,Iter const& e) const { + CGAL_assertion(d==std::distance(f,e)+1); + CGAL_assertion(d<=d_); + //TODO: optimize + Vector a; + std::copy(f,e,a.begin()); + a.back()=1; + return a; + } + }; +#endif + + struct Iterator_and_last { + template<typename Iter,typename T> + Vector operator()(unsigned CGAL_assertion_code(d),Iter const& f,Iter const& e,CGAL_FORWARDABLE(T) t) const { + CGAL_assertion(d==std::distance(f,e)+1); + CGAL_assertion(d<=d_); + //TODO: optimize for forward iterators + Vector a; + std::copy(f,e,a.begin()); + a.back()=CGAL_FORWARD(T,t); + return a; + } + }; + + struct Values { +#ifdef CGAL_CXX11 + template<class...U> + Vector operator()(U&&...u) const { + static_assert(sizeof...(U)<=d_,"too many arguments"); + Vector a={{forward_safe<NT,U>(u)...}}; + return a; + } +#else + +#define CGAL_CODE(Z,N,_) Vector operator()(BOOST_PP_ENUM_PARAMS(N,NT const& t)) const { \ + CGAL_assertion(N<=d_); \ + Vector a={{BOOST_PP_ENUM_PARAMS(N,t)}}; \ + return a; \ +} +BOOST_PP_REPEAT_FROM_TO(1, 11, CGAL_CODE, _ ) +#undef CGAL_CODE + +#endif + }; + + struct Values_divide { +#ifdef CGAL_CXX11 + template<class H,class...U> + Vector operator()(H const& h,U&&...u) const { + static_assert(sizeof...(U)<=d_,"too many arguments"); + Vector a={{Rational_traits<NT>().make_rational(std::forward<U>(u),h)...}}; + return a; + } +#else + +#define CGAL_VAR(Z,N,_) Rational_traits<NT>().make_rational( t##N , h) +#define CGAL_CODE(Z,N,_) template <class H> Vector \ + operator()(H const&h, BOOST_PP_ENUM_PARAMS(N,NT const& t)) const { \ + CGAL_assertion(N<=d_); \ + Vector a={{BOOST_PP_ENUM(N,CGAL_VAR,_)}}; \ + return a; \ + } + BOOST_PP_REPEAT_FROM_TO(1, 11, CGAL_CODE, _ ) +#undef CGAL_CODE +#undef CGAL_VAR + +#endif + }; + }; + + typedef NT const* Vector_const_iterator; + static Vector_const_iterator vector_begin(Vector const&a){ + return &a[0]; + } + static Vector_const_iterator vector_end(Vector const&a){ + return &a[0]+d_; // Don't know the real size + } + static unsigned size_of_vector(Vector const&){ + return d_; // Don't know the real size + } + +}; + +} +#endif diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/avx4.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/avx4.h new file mode 100644 index 00000000..954a3c1b --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/avx4.h @@ -0,0 +1,213 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_VECTOR_AVX4_H +#define CGAL_VECTOR_AVX4_H + +#if !defined __AVX__ || (__GNUC__ * 100 + __GNUC_MINOR__ < 408) +#error Requires AVX and gcc 4.8+ +#endif +#include <x86intrin.h> + +#include <CGAL/NewKernel_d/functor_tags.h> +#include <CGAL/Dimension.h> +#include <CGAL/enum.h> // CGAL::Sign +#include <CGAL/number_utils.h> // CGAL::sign + + + +namespace CGAL { + + struct Avx_vector_4 { + typedef double NT; + typedef Dimension_tag<4> Dimension; + typedef Dimension_tag<4> Max_dimension; + // No Rebind_dimension, this is a building block + template<class,bool=true> struct Property : boost::false_type {}; + template<bool b> struct Property<Has_vector_plus_minus_tag,b> + : boost::true_type {}; + /* MAYBE? + template<bool b> struct Property<Has_vector_scalar_ops_tag,b> + : boost::true_type {}; + */ + template<bool b> struct Property<Has_determinant_of_vectors_tag,b> + : boost::true_type {}; + template<bool b> struct Property<Has_dot_product_tag,b> + : boost::true_type {}; + template<bool b> struct Property<Has_determinant_of_vectors_omit_last_tag,b> + : boost::true_type {}; + + typedef __m256d Vector; + struct Construct_vector { + struct Dimension { + // Initialize with NaN? + Vector operator()(unsigned d) const { + CGAL_assertion(d==4); + return Vector(); + } + }; + + struct Iterator { + template<typename Iter> + Vector operator()(unsigned d,Iter const& f,Iter const& e) const { + CGAL_assertion(d==4); + double x0 = *f; + double x1 = *++f; + double x2 = *++f; + double x3 = *++f; + CGAL_assertion(++f==e); + Vector a = { x0, x1, x2, x3 }; + return a; + } + }; + + struct Iterator_and_last { + template<typename Iter,typename T> + Vector operator()(unsigned d,Iter const& f,Iter const& e,double t) const { + CGAL_assertion(d==4); + double x0 = *f; + double x1 = *++f; + double x2 = *++f; + CGAL_assertion(++f==e); + Vector a = { x0, x1, x2, t }; + return a; + } + }; + + struct Values { + Vector operator()(double a,double b,double c,double d) const { + Vector r = { a, b, c, d }; + return r; + } + }; + + struct Values_divide { + Vector operator()(double h,double a,double b,double c,double d) const { + // {a,b,c,d}/{h,h,h,h} should be roughly the same + Vector r = { a/h, b/h, c/h, d/h }; + return r; + } + }; + }; + + public: + typedef double const* Vector_const_iterator; + static inline Vector_const_iterator vector_begin(Vector const&a){ + return (Vector_const_iterator)(&a); + } + static inline Vector_const_iterator vector_end(Vector const&a){ + return (Vector_const_iterator)(&a)+4; + } + static inline unsigned size_of_vector(Vector){ + return 4; + } + static inline double dot_product(__m256d x, __m256d y){ + __m256d p=x*y; + __m256d z=_mm256_hadd_pd(p,p); + return z[0]+z[2]; + } + private: + static inline __m256d avx_sym(__m256d x){ +#if 0 + return __builtin_shuffle(x,(__m256i){2,3,0,1}); +#else + return _mm256_permute2f128_pd(x,x,1); +#endif + } + static inline __m256d avx_left(__m256d x){ +#if 0 + return __builtin_shuffle(x,(__m256i){1,2,3,0}); +#else +#ifdef __AVX2__ + return _mm256_permute4x64_pd(x,1+2*4+3*16+0*64); +#else + __m256d s = _mm256_permute2f128_pd(x,x,1); + return _mm256_shuffle_pd(x,s,5); +#endif +#endif + } + static inline __m256d avx_right(__m256d x){ +#if 0 + return __builtin_shuffle(x,(__m256i){3,0,1,2}); +#else +#ifdef __AVX2__ + return _mm256_permute4x64_pd(x,3+0*4+1*16+2*64); +#else + __m256d s = _mm256_permute2f128_pd(x,x,1); + return _mm256_shuffle_pd(s,x,5); +#endif +#endif + } + static inline double avx_altprod(__m256d x, __m256d y){ + __m256d p=x*y; + __m256d z=_mm256_hsub_pd(p,p); + return z[0]+z[2]; + } + public: + static double + determinant_of_vectors(Vector a, Vector b, Vector c, Vector d) { + __m256d x=a*avx_left(b)-avx_left(a)*b; + __m256d yy=a*avx_sym(b); + __m256d y=yy-avx_sym(yy); + __m256d z0=x*avx_sym(c); + __m256d z1=avx_left(x)*c; + __m256d z2=y*avx_left(c); + __m256d z=z0+z1-z2; + return avx_altprod(z,avx_right(d)); + } + static CGAL::Sign + sign_of_determinant_of_vectors(Vector a, Vector b, Vector c, Vector d) { + return CGAL::sign(determinant_of_vectors(a,b,c,d)); + } + + private: + static inline __m256d avx3_right(__m256d x){ +#if 0 + return __builtin_shuffle(x,(__m256i){2,0,1,3}); // can replace 3 with anything +#else +#ifdef __AVX2__ + return _mm256_permute4x64_pd(x,2+0*4+1*16+3*64); +#else + __m256d s = _mm256_permute2f128_pd(x,x,1); + return _mm256_shuffle_pd(s,x,12); +#endif +#endif + } + public: + static inline double dot_product_omit_last(__m256d x, __m256d y){ + __m256d p=x*y; + __m128d q=_mm256_extractf128_pd(p,0); + double z=_mm_hadd_pd(q,q)[0]; + return z+p[2]; + } + // Note: without AVX2, is it faster than the scalar computation? + static double + determinant_of_vectors_omit_last(Vector a, Vector b, Vector c) { + __m256d x=a*avx3_right(b)-avx3_right(a)*b; + return dot_product_omit_last(c,avx3_right(x)); + } + static CGAL::Sign + sign_of_determinant_of_vectors_omit_last(Vector a, Vector b, Vector c) { + return CGAL::sign(determinant_of_vectors_omit_last(a,b,c)); + } + + }; + +} +#endif diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_iterator_to_points_from_iterator_to_vectors.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_iterator_to_points_from_iterator_to_vectors.h new file mode 100644 index 00000000..b8efbe28 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_iterator_to_points_from_iterator_to_vectors.h @@ -0,0 +1,76 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_VECTOR_DET_ITER_PTS_ITER_VEC_H +#define CGAL_VECTOR_DET_ITER_PTS_ITER_VEC_H +#include <functional> +#include <CGAL/transforming_iterator.h> +#include <CGAL/NewKernel_d/functor_tags.h> +#include <CGAL/Dimension.h> + +namespace CGAL { + +template <class LA, class Dim_=typename LA::Dimension, + class Max_dim_=typename LA::Max_dimension, + bool = LA::template Property<Has_determinant_of_iterator_to_points_tag>::value, + bool = LA::template Property<Has_determinant_of_iterator_to_vectors_tag>::value> +struct Add_determinant_of_iterator_to_points_from_iterator_to_vectors : LA { + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef typename LA::template Rebind_dimension<D2,D3> LA2; + typedef Add_determinant_of_iterator_to_points_from_iterator_to_vectors<LA2> Other; + }; +}; + +template <class LA, class Dim_,class Max_dim_> +struct Add_determinant_of_iterator_to_points_from_iterator_to_vectors +<LA, Dim_, Max_dim_, false, true> : LA { + typedef typename LA::NT NT; + typedef typename LA::Vector Vector; + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef typename LA::template Rebind_dimension<D2,D3> LA2; + typedef Add_determinant_of_iterator_to_points_from_iterator_to_vectors<LA2> Other; + }; + template<class P,class=void> struct Property : LA::template Property<P> {}; + template<class D> struct Property<Has_determinant_of_iterator_to_points_tag, D> : + boost::true_type {}; + + // TODO: use std::minus, boost::bind, etc + template<class T> struct Minus_fixed { + T const& a; + Minus_fixed(T const&a_):a(a_){} + T operator()(T const&b)const{return b-a;} + }; + template<class Iter> + static NT determinant_of_iterator_to_points(Iter const&first, Iter const&end){ + Vector const&a=*first; ++first; + Minus_fixed<Vector> f(a); + return LA::determinant_of_iterator_to_vectors(make_transforming_iterator(first,f),make_transforming_iterator(end,f)); + } + template<class Iter> + static Sign sign_of_determinant_of_iterator_to_points(Iter const&first, Iter const&end){ + Vector const&a=*first; ++first; + Minus_fixed<Vector> f(a); + return LA::sign_of_determinant_of_iterator_to_vectors(make_transforming_iterator(first,f),make_transforming_iterator(end,f)); + } +}; + +} +#endif diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_iterator_to_points_from_points.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_iterator_to_points_from_points.h new file mode 100644 index 00000000..71a31d81 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_iterator_to_points_from_points.h @@ -0,0 +1,211 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_VECTOR_DET_ITER_PTS_PTS_H +#define CGAL_VECTOR_DET_ITER_PTS_PTS_H +#include <CGAL/NewKernel_d/functor_tags.h> +#include <CGAL/Dimension.h> + +namespace CGAL { + +template <class LA, class Dim_=typename LA::Dimension, + class Max_dim_=typename LA::Max_dimension, + bool = LA::template Property<Has_determinant_of_iterator_to_points_tag>::value, + bool = LA::template Property<Has_determinant_of_points_tag>::value> +struct Add_determinant_of_iterator_to_points_from_points : LA { + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef typename LA::template Rebind_dimension<D2,D3> LA2; + typedef Add_determinant_of_iterator_to_points_from_points<LA2> Other; + }; +}; + +//FIXME: Use variadics and boost so it works in any dimension. +template <class LA, class Max_dim_> +struct Add_determinant_of_iterator_to_points_from_points +<LA, Dimension_tag<2>, Max_dim_, false, true> : LA { + typedef typename LA::NT NT; + typedef typename LA::Vector Vector; + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef typename LA::template Rebind_dimension<D2,D3> LA2; + typedef Add_determinant_of_iterator_to_points_from_points<LA2> Other; + }; + template<class P,class=void> struct Property : LA::template Property<P> {}; + template<class D> struct Property<Has_determinant_of_iterator_to_points_tag, D> : + boost::true_type {}; + + template<class Iter> + static NT determinant_of_iterator_to_points(Iter const&first, Iter const&end){ + Vector const&a=*first; ++first; + Vector const&b=*first; ++first; + Vector const&c=*first; CGAL_assertion(++first==end); + return LA::determinant_of_points(a,b,c); + } + template<class Iter> + static Sign sign_of_determinant_of_iterator_to_points(Iter const&first, Iter const&end){ + Vector const&a=*first; ++first; + Vector const&b=*first; ++first; + Vector const&c=*first; CGAL_assertion(++first==end); + return LA::sign_of_determinant_of_points(a,b,c); + } +}; + +template <class LA, class Max_dim_> +struct Add_determinant_of_iterator_to_points_from_points +<LA, Dimension_tag<3>, Max_dim_, false, true> : LA { + typedef typename LA::NT NT; + typedef typename LA::Vector Vector; + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef typename LA::template Rebind_dimension<D2,D3> LA2; + typedef Add_determinant_of_iterator_to_points_from_points<LA2> Other; + }; + template<class P,class=void> struct Property : LA::template Property<P> {}; + template<class D> struct Property<Has_determinant_of_iterator_to_points_tag, D> : + boost::true_type {}; + + template<class Iter> + static NT determinant_of_iterator_to_points(Iter const&first, Iter const&end){ + Vector const&a=*first; ++first; + Vector const&b=*first; ++first; + Vector const&c=*first; ++first; + Vector const&d=*first; CGAL_assertion(++first==end); + return LA::determinant_of_points(a,b,c,d); + } + template<class Iter> + static Sign sign_of_determinant_of_iterator_to_points(Iter const&first, Iter const&end){ + Vector const&a=*first; ++first; + Vector const&b=*first; ++first; + Vector const&c=*first; ++first; + Vector const&d=*first; CGAL_assertion(++first==end); + return LA::sign_of_determinant_of_points(a,b,c,d); + } +}; + +template <class LA, class Max_dim_> +struct Add_determinant_of_iterator_to_points_from_points +<LA, Dimension_tag<4>, Max_dim_, false, true> : LA { + typedef typename LA::NT NT; + typedef typename LA::Vector Vector; + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef typename LA::template Rebind_dimension<D2,D3> LA2; + typedef Add_determinant_of_iterator_to_points_from_points<LA2> Other; + }; + template<class P,class=void> struct Property : LA::template Property<P> {}; + template<class D> struct Property<Has_determinant_of_iterator_to_points_tag, D> : + boost::true_type {}; + + template<class Iter> + static NT determinant_of_iterator_to_points(Iter const&first, Iter const&end){ + Vector const&a=*first; ++first; + Vector const&b=*first; ++first; + Vector const&c=*first; ++first; + Vector const&d=*first; ++first; + Vector const&e=*first; CGAL_assertion(++first==end); + return LA::determinant_of_points(a,b,c,d,e); + } + template<class Iter> + static Sign sign_of_determinant_of_iterator_to_points(Iter const&first, Iter const&end){ + Vector const&a=*first; ++first; + Vector const&b=*first; ++first; + Vector const&c=*first; ++first; + Vector const&d=*first; ++first; + Vector const&e=*first; CGAL_assertion(++first==end); + return LA::sign_of_determinant_of_points(a,b,c,d,e); + } +}; + +template <class LA, class Max_dim_> +struct Add_determinant_of_iterator_to_points_from_points +<LA, Dimension_tag<5>, Max_dim_, false, true> : LA { + typedef typename LA::NT NT; + typedef typename LA::Vector Vector; + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef typename LA::template Rebind_dimension<D2,D3> LA2; + typedef Add_determinant_of_iterator_to_points_from_points<LA2> Other; + }; + template<class P,class=void> struct Property : LA::template Property<P> {}; + template<class D> struct Property<Has_determinant_of_iterator_to_points_tag, D> : + boost::true_type {}; + + template<class Iter> + static NT determinant_of_iterator_to_points(Iter const&first, Iter const&end){ + Vector const&a=*first; ++first; + Vector const&b=*first; ++first; + Vector const&c=*first; ++first; + Vector const&d=*first; ++first; + Vector const&e=*first; ++first; + Vector const&f=*first; CGAL_assertion(++first==end); + return LA::determinant_of_points(a,b,c,d,e,f); + } + template<class Iter> + static Sign sign_of_determinant_of_iterator_to_points(Iter const&first, Iter const&end){ + Vector const&a=*first; ++first; + Vector const&b=*first; ++first; + Vector const&c=*first; ++first; + Vector const&d=*first; ++first; + Vector const&e=*first; ++first; + Vector const&f=*first; CGAL_assertion(++first==end); + return LA::sign_of_determinant_of_points(a,b,c,d,e,f); + } +}; + +template <class LA, class Max_dim_> +struct Add_determinant_of_iterator_to_points_from_points +<LA, Dimension_tag<6>, Max_dim_, false, true> : LA { + typedef typename LA::NT NT; + typedef typename LA::Vector Vector; + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef typename LA::template Rebind_dimension<D2,D3> LA2; + typedef Add_determinant_of_iterator_to_points_from_points<LA2> Other; + }; + template<class P,class=void> struct Property : LA::template Property<P> {}; + template<class D> struct Property<Has_determinant_of_iterator_to_points_tag, D> : + boost::true_type {}; + + template<class Iter> + static NT determinant_of_iterator_to_points(Iter const&first, Iter const&end){ + Vector const&a=*first; ++first; + Vector const&b=*first; ++first; + Vector const&c=*first; ++first; + Vector const&d=*first; ++first; + Vector const&e=*first; ++first; + Vector const&f=*first; ++first; + Vector const&g=*first; CGAL_assertion(++first==end); + return LA::determinant_of_points(a,b,c,d,e,f,g); + } + template<class Iter> + static Sign sign_of_determinant_of_iterator_to_points(Iter const&first, Iter const&end){ + Vector const&a=*first; ++first; + Vector const&b=*first; ++first; + Vector const&c=*first; ++first; + Vector const&d=*first; ++first; + Vector const&e=*first; ++first; + Vector const&f=*first; ++first; + Vector const&g=*first; CGAL_assertion(++first==end); + return LA::sign_of_determinant_of_points(a,b,c,d,e,f,g); + } +}; + +} +#endif diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_iterator_to_vectors_from_vectors.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_iterator_to_vectors_from_vectors.h new file mode 100644 index 00000000..f096d6c7 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_iterator_to_vectors_from_vectors.h @@ -0,0 +1,201 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_VECTOR_DET_ITER_VEC_VEC_H +#define CGAL_VECTOR_DET_ITER_VEC_VEC_H +#include <CGAL/NewKernel_d/functor_tags.h> +#include <CGAL/Dimension.h> + +namespace CGAL { + +template <class LA, class Dim_=typename LA::Dimension, + class Max_dim_=typename LA::Max_dimension, + bool = LA::template Property<Has_determinant_of_iterator_to_vectors_tag>::value, + bool = LA::template Property<Has_determinant_of_vectors_tag>::value> +struct Add_determinant_of_iterator_to_vectors_from_vectors : LA { + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef typename LA::template Rebind_dimension<D2,D3> LA2; + typedef Add_determinant_of_iterator_to_vectors_from_vectors<LA2> Other; + }; +}; + +//FIXME: Use variadics and boost so it works in any dimension. +template <class LA, class Max_dim_> +struct Add_determinant_of_iterator_to_vectors_from_vectors +<LA, Dimension_tag<2>, Max_dim_, false, true> : LA { + typedef typename LA::NT NT; + typedef typename LA::Vector Vector; + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef typename LA::template Rebind_dimension<D2,D3> LA2; + typedef Add_determinant_of_iterator_to_vectors_from_vectors<LA2> Other; + }; + template<class P,class=void> struct Property : LA::template Property<P> {}; + template<class D> struct Property<Has_determinant_of_iterator_to_vectors_tag, D> : + boost::true_type {}; + + template<class Iter> + static NT determinant_of_iterator_to_vectors(Iter const&first, Iter const&end){ + Vector const&a=*first; ++first; + Vector const&b=*first; CGAL_assertion(++first==end); + return LA::determinant_of_vectors(a,b); + } + template<class Iter> + static Sign sign_of_determinant_of_iterator_to_vectors(Iter const&first, Iter const&end){ + Vector const&a=*first; ++first; + Vector const&b=*first; CGAL_assertion(++first==end); + return LA::sign_of_determinant_of_vectors(a,b); + } +}; + +template <class LA, class Max_dim_> +struct Add_determinant_of_iterator_to_vectors_from_vectors +<LA, Dimension_tag<3>, Max_dim_, false, true> : LA { + typedef typename LA::NT NT; + typedef typename LA::Vector Vector; + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef typename LA::template Rebind_dimension<D2,D3> LA2; + typedef Add_determinant_of_iterator_to_vectors_from_vectors<LA2> Other; + }; + template<class P,class=void> struct Property : LA::template Property<P> {}; + template<class D> struct Property<Has_determinant_of_iterator_to_vectors_tag, D> : + boost::true_type {}; + + template<class Iter> + static NT determinant_of_iterator_to_vectors(Iter const&first, Iter const&end){ + Vector const&a=*first; ++first; + Vector const&b=*first; ++first; + Vector const&c=*first; CGAL_assertion(++first==end); + return LA::determinant_of_vectors(a,b,c); + } + template<class Iter> + static Sign sign_of_determinant_of_iterator_to_vectors(Iter const&first, Iter const&end){ + Vector const&a=*first; ++first; + Vector const&b=*first; ++first; + Vector const&c=*first; CGAL_assertion(++first==end); + return LA::sign_of_determinant_of_vectors(a,b,c); + } +}; + +template <class LA, class Max_dim_> +struct Add_determinant_of_iterator_to_vectors_from_vectors +<LA, Dimension_tag<4>, Max_dim_, false, true> : LA { + typedef typename LA::NT NT; + typedef typename LA::Vector Vector; + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef typename LA::template Rebind_dimension<D2,D3> LA2; + typedef Add_determinant_of_iterator_to_vectors_from_vectors<LA2> Other; + }; + template<class P,class=void> struct Property : LA::template Property<P> {}; + template<class D> struct Property<Has_determinant_of_iterator_to_vectors_tag, D> : + boost::true_type {}; + + template<class Iter> + static NT determinant_of_iterator_to_vectors(Iter const&first, Iter const&end){ + Vector const&a=*first; ++first; + Vector const&b=*first; ++first; + Vector const&c=*first; ++first; + Vector const&d=*first; CGAL_assertion(++first==end); + return LA::determinant_of_vectors(a,b,c,d); + } + template<class Iter> + static Sign sign_of_determinant_of_iterator_to_vectors(Iter const&first, Iter const&end){ + Vector const&a=*first; ++first; + Vector const&b=*first; ++first; + Vector const&c=*first; ++first; + Vector const&d=*first; CGAL_assertion(++first==end); + return LA::sign_of_determinant_of_vectors(a,b,c,d); + } +}; + +template <class LA, class Max_dim_> +struct Add_determinant_of_iterator_to_vectors_from_vectors +<LA, Dimension_tag<5>, Max_dim_, false, true> : LA { + typedef typename LA::NT NT; + typedef typename LA::Vector Vector; + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef typename LA::template Rebind_dimension<D2,D3> LA2; + typedef Add_determinant_of_iterator_to_vectors_from_vectors<LA2> Other; + }; + template<class P,class=void> struct Property : LA::template Property<P> {}; + template<class D> struct Property<Has_determinant_of_iterator_to_vectors_tag, D> : + boost::true_type {}; + + template<class Iter> + static NT determinant_of_iterator_to_vectors(Iter const&first, Iter const&end){ + Vector const&a=*first; ++first; + Vector const&b=*first; ++first; + Vector const&c=*first; ++first; + Vector const&d=*first; ++first; + Vector const&e=*first; CGAL_assertion(++first==end); + return LA::determinant_of_vectors(a,b,c,d,e); + } + template<class Iter> + static Sign sign_of_determinant_of_iterator_to_vectors(Iter const&first, Iter const&end){ + Vector const&a=*first; ++first; + Vector const&b=*first; ++first; + Vector const&c=*first; ++first; + Vector const&d=*first; ++first; + Vector const&e=*first; CGAL_assertion(++first==end); + return LA::sign_of_determinant_of_vectors(a,b,c,d,e); + } +}; + +template <class LA, class Max_dim_> +struct Add_determinant_of_iterator_to_vectors_from_vectors +<LA, Dimension_tag<6>, Max_dim_, false, true> : LA { + typedef typename LA::NT NT; + typedef typename LA::Vector Vector; + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef typename LA::template Rebind_dimension<D2,D3> LA2; + typedef Add_determinant_of_iterator_to_vectors_from_vectors<LA2> Other; + }; + template<class P,class=void> struct Property : LA::template Property<P> {}; + template<class D> struct Property<Has_determinant_of_iterator_to_vectors_tag, D> : + boost::true_type {}; + + template<class Iter> + static NT determinant_of_iterator_to_vectors(Iter const&first, Iter const&end){ + Vector const&a=*first; ++first; + Vector const&b=*first; ++first; + Vector const&c=*first; ++first; + Vector const&d=*first; ++first; + Vector const&e=*first; ++first; + Vector const&f=*first; CGAL_assertion(++first==end); + return LA::determinant_of_vectors(a,b,c,d,e,f); + } + template<class Iter> + static Sign sign_of_determinant_of_iterator_to_vectors(Iter const&first, Iter const&end){ + Vector const&a=*first; ++first; + Vector const&b=*first; ++first; + Vector const&c=*first; ++first; + Vector const&d=*first; ++first; + Vector const&e=*first; ++first; + Vector const&f=*first; CGAL_assertion(++first==end); + return LA::sign_of_determinant_of_vectors(a,b,c,d,e,f); + } +}; + +} +#endif diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_points_from_vectors.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_points_from_vectors.h new file mode 100644 index 00000000..7ddb73c3 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_points_from_vectors.h @@ -0,0 +1,164 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_VECTOR_DETPTS_H +#define CGAL_VECTOR_DETPTS_H +#include <CGAL/NewKernel_d/functor_tags.h> +#include <CGAL/Dimension.h> + +namespace CGAL { + +template <class LA, class Dim_=typename LA::Dimension, + class Max_dim_=typename LA::Max_dimension, + bool = LA::template Property<Has_determinant_of_points_tag>::value, + bool = LA::template Property<Has_determinant_of_vectors_tag>::value + && LA::template Property<Has_vector_plus_minus_tag>::value> +struct Add_determinant_of_points_from_vectors_and_minus : LA { + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef typename LA::template Rebind_dimension<D2,D3> LA2; + typedef Add_determinant_of_points_from_vectors_and_minus<LA2> Other; + }; +}; + +//FIXME: Use variadics and boost so it works in any dimension. +template <class LA, class Max_dim_> +struct Add_determinant_of_points_from_vectors_and_minus +<LA, Dimension_tag<2>, Max_dim_, false, true> : LA { + typedef typename LA::NT NT; + typedef typename LA::Vector Vector; + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef typename LA::template Rebind_dimension<D2,D3> LA2; + typedef Add_determinant_of_points_from_vectors_and_minus<LA2> Other; + }; + template<class P,class=void> struct Property : LA::template Property<P> {}; + template<class D> struct Property<Has_determinant_of_points_tag, D> : + boost::true_type {}; + + static NT determinant_of_points(Vector const&a, Vector const&b, + Vector const&c){ + return LA::determinant_of_vectors(b-a,c-a); + } + static Sign sign_of_determinant_of_points(Vector const&a, Vector const&b, + Vector const&c){ + return LA::sign_of_determinant_of_vectors(b-a,c-a); + } +}; + +template <class LA, class Max_dim_> +struct Add_determinant_of_points_from_vectors_and_minus +<LA, Dimension_tag<3>, Max_dim_, false, true> : LA { + typedef typename LA::NT NT; + typedef typename LA::Vector Vector; + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef typename LA::template Rebind_dimension<D2,D3> LA2; + typedef Add_determinant_of_points_from_vectors_and_minus<LA2> Other; + }; + template<class P,class=void> struct Property : LA::template Property<P> {}; + template<class D> struct Property<Has_determinant_of_points_tag, D> : + boost::true_type {}; + + static NT determinant_of_points(Vector const&a, Vector const&b, + Vector const&c, Vector const&d){ + return LA::determinant_of_vectors(b-a,c-a,d-a); + } + static Sign sign_of_determinant_of_points(Vector const&a, Vector const&b, + Vector const&c, Vector const&d){ + return LA::sign_of_determinant_of_vectors(b-a,c-a,d-a); + } +}; + +template <class LA, class Max_dim_> +struct Add_determinant_of_points_from_vectors_and_minus +<LA, Dimension_tag<4>, Max_dim_, false, true> : LA { + typedef typename LA::NT NT; + typedef typename LA::Vector Vector; + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef typename LA::template Rebind_dimension<D2,D3> LA2; + typedef Add_determinant_of_points_from_vectors_and_minus<LA2> Other; + }; + template<class P,class=void> struct Property : LA::template Property<P> {}; + template<class D> struct Property<Has_determinant_of_points_tag, D> : + boost::true_type {}; + + static NT determinant_of_points(Vector const&a, Vector const&b, + Vector const&c, Vector const&d, Vector const&e){ + return LA::determinant_of_vectors(b-a,c-a,d-a,e-a); + } + static Sign sign_of_determinant_of_points(Vector const&a, Vector const&b, + Vector const&c, Vector const&d, Vector const&e){ + return LA::sign_of_determinant_of_vectors(b-a,c-a,d-a,e-a); + } +}; + +template <class LA, class Max_dim_> +struct Add_determinant_of_points_from_vectors_and_minus +<LA, Dimension_tag<5>, Max_dim_, false, true> : LA { + typedef typename LA::NT NT; + typedef typename LA::Vector Vector; + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef typename LA::template Rebind_dimension<D2,D3> LA2; + typedef Add_determinant_of_points_from_vectors_and_minus<LA2> Other; + }; + template<class P,class=void> struct Property : LA::template Property<P> {}; + template<class D> struct Property<Has_determinant_of_points_tag, D> : + boost::true_type {}; + + static NT determinant_of_points(Vector const&a, Vector const&b, + Vector const&c, Vector const&d, Vector const&e, Vector const&f){ + return LA::determinant_of_vectors(b-a,c-a,d-a,e-a,f-a); + } + static Sign sign_of_determinant_of_points(Vector const&a, Vector const&b, + Vector const&c, Vector const&d, Vector const&e, Vector const&f){ + return LA::sign_of_determinant_of_vectors(b-a,c-a,d-a,e-a,f-a); + } +}; + +template <class LA, class Max_dim_> +struct Add_determinant_of_points_from_vectors_and_minus +<LA, Dimension_tag<6>, Max_dim_, false, true> : LA { + typedef typename LA::NT NT; + typedef typename LA::Vector Vector; + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef typename LA::template Rebind_dimension<D2,D3> LA2; + typedef Add_determinant_of_points_from_vectors_and_minus<LA2> Other; + }; + template<class P,class=void> struct Property : LA::template Property<P> {}; + template<class D> struct Property<Has_determinant_of_points_tag, D> : + boost::true_type {}; + + static NT determinant_of_points(Vector const&a, Vector const&b, + Vector const&c, Vector const&d, Vector const&e, Vector const&f, + Vector const&g){ + return LA::determinant_of_vectors(b-a,c-a,d-a,e-a,f-a,g-a); + } + static Sign sign_of_determinant_of_points(Vector const&a, Vector const&b, + Vector const&c, Vector const&d, Vector const&e, Vector const&f, + Vector const&g){ + return LA::sign_of_determinant_of_vectors(b-a,c-a,d-a,e-a,f-a,g-a); + } +}; + +} +#endif diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim.h new file mode 100644 index 00000000..64eafe69 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim.h @@ -0,0 +1,58 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_VECTOR_DETVEC_SMALL_H +#define CGAL_VECTOR_DETVEC_SMALL_H +#include <CGAL/NewKernel_d/functor_tags.h> +#include <CGAL/Dimension.h> +#include <CGAL/determinant_of_vectors.h> + +#define CGAL_ALLOWED_INCLUSION 1 + +#define CGAL_CLASS Add_determinant_of_vectors_small_dim +#define CGAL_TAG Has_determinant_of_vectors_tag +#define CGAL_FUNC determinant_of_vectors +#define CGAL_SIGN_FUNC sign_of_determinant_of_vectors +#define CGAL_SHIFT 0 + +#include <CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim_internal.h> + +#undef CGAL_CLASS +#undef CGAL_TAG +#undef CGAL_FUNC +#undef CGAL_SIGN_FUNC +#undef CGAL_SHIFT + +#define CGAL_CLASS Add_determinant_of_vectors_omit_last_small_dim +#define CGAL_TAG Has_determinant_of_vectors_omit_last_tag +#define CGAL_FUNC determinant_of_vectors_omit_last +#define CGAL_SIGN_FUNC sign_of_determinant_of_vectors_omit_last +#define CGAL_SHIFT 1 + +#include <CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim_internal.h> + +#undef CGAL_CLASS +#undef CGAL_TAG +#undef CGAL_FUNC +#undef CGAL_SIGN_FUNC +#undef CGAL_SHIFT + +#undef CGAL_ALLOWED_INCLUSION + +#endif diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim_internal.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim_internal.h new file mode 100644 index 00000000..b4856742 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/determinant_of_vectors_small_dim_internal.h @@ -0,0 +1,164 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_ALLOWED_INCLUSION +#error Must not include this header directly +#endif +#if !defined(CGAL_TAG) \ + || ! defined(CGAL_CLASS) \ + || ! defined(CGAL_FUNC) \ + || ! defined(CGAL_SIGN_FUNC) \ + || ! defined(CGAL_SHIFT) + +#error Forgot one macro +#endif + +namespace CGAL { + +template <class LA, class Dim_=typename LA::Dimension, + class Max_dim_=typename LA::Max_dimension, + bool=LA::template Property<CGAL_TAG>::value> +struct CGAL_CLASS : LA { + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef typename LA::template Rebind_dimension<D2,D3> LA2; + typedef CGAL_CLASS<LA2> Other; + }; +}; + +template <class LA, class Max_dim_> +struct CGAL_CLASS +<LA, Dimension_tag<2+CGAL_SHIFT>, Max_dim_, false> : LA { + typedef typename LA::NT NT; + typedef typename LA::Vector Vector; + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef typename LA::template Rebind_dimension<D2,D3> LA2; + typedef CGAL_CLASS<LA2> Other; + }; + template<class P,class=void> struct Property : LA::template Property<P> {}; + template<class D> struct Property<CGAL_TAG, D> : + boost::true_type {}; + + static NT CGAL_FUNC(Vector const&a, Vector const&b){ + return CGAL::determinant_of_vectors<NT>(a,b); + } + template <class V1, class V2> + static Sign CGAL_SIGN_FUNC(V1 const&a, V2 const&b){ + return CGAL::sign_of_determinant_of_vectors<NT>(a,b); + } +}; + +template <class LA, class Max_dim_> +struct CGAL_CLASS +<LA, Dimension_tag<3+CGAL_SHIFT>, Max_dim_, false> : LA { + typedef typename LA::NT NT; + typedef typename LA::Vector Vector; + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef typename LA::template Rebind_dimension<D2,D3> LA2; + typedef CGAL_CLASS<LA2> Other; + }; + template<class P,class=void> struct Property : LA::template Property<P> {}; + template<class D> struct Property<CGAL_TAG, D> : + boost::true_type {}; + + static NT CGAL_FUNC(Vector const&a, Vector const&b, + Vector const&c){ + return CGAL::determinant_of_vectors<NT>(a,b,c); + } + static Sign CGAL_SIGN_FUNC(Vector const&a, Vector const&b, + Vector const&c){ + return CGAL::sign_of_determinant_of_vectors<NT>(a,b,c); + } +}; + +template <class LA, class Max_dim_> +struct CGAL_CLASS +<LA, Dimension_tag<4+CGAL_SHIFT>, Max_dim_, false> : LA { + typedef typename LA::NT NT; + typedef typename LA::Vector Vector; + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef typename LA::template Rebind_dimension<D2,D3> LA2; + typedef CGAL_CLASS<LA2> Other; + }; + template<class P,class=void> struct Property : LA::template Property<P> {}; + template<class D> struct Property<CGAL_TAG, D> : + boost::true_type {}; + + static NT CGAL_FUNC(Vector const&a, Vector const&b, + Vector const&c, Vector const&d){ + return CGAL::determinant_of_vectors<NT>(a,b,c,d); + } + static Sign CGAL_SIGN_FUNC(Vector const&a, Vector const&b, + Vector const&c, Vector const&d){ + return CGAL::sign_of_determinant_of_vectors<NT>(a,b,c,d); + } +}; + +template <class LA, class Max_dim_> +struct CGAL_CLASS +<LA, Dimension_tag<5+CGAL_SHIFT>, Max_dim_, false> : LA { + typedef typename LA::NT NT; + typedef typename LA::Vector Vector; + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef typename LA::template Rebind_dimension<D2,D3> LA2; + typedef CGAL_CLASS<LA2> Other; + }; + template<class P,class=void> struct Property : LA::template Property<P> {}; + template<class D> struct Property<CGAL_TAG, D> : + boost::true_type {}; + + static NT CGAL_FUNC(Vector const&a, Vector const&b, + Vector const&c, Vector const&d, Vector const&e){ + return CGAL::determinant_of_vectors<NT>(a,b,c,d,e); + } + static Sign CGAL_SIGN_FUNC(Vector const&a, Vector const&b, + Vector const&c, Vector const&d, Vector const&e){ + return CGAL::sign_of_determinant_of_vectors<NT>(a,b,c,d,e); + } +}; + +template <class LA, class Max_dim_> +struct CGAL_CLASS +<LA, Dimension_tag<6+CGAL_SHIFT>, Max_dim_, false> : LA { + typedef typename LA::NT NT; + typedef typename LA::Vector Vector; + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef typename LA::template Rebind_dimension<D2,D3> LA2; + typedef CGAL_CLASS<LA2> Other; + }; + template<class P,class=void> struct Property : LA::template Property<P> {}; + template<class D> struct Property<CGAL_TAG, D> : + boost::true_type {}; + + static NT CGAL_FUNC(Vector const&a, Vector const&b, + Vector const&c, Vector const&d, Vector const&e, Vector const&f){ + return CGAL::determinant_of_vectors<NT>(a,b,c,d,e,f); + } + static Sign CGAL_SIGN_FUNC(Vector const&a, Vector const&b, + Vector const&c, Vector const&d, Vector const&e, Vector const&f){ + return CGAL::sign_of_determinant_of_vectors<NT>(a,b,c,d,e,f); + } +}; + +} diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/mix.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/mix.h new file mode 100644 index 00000000..d4cfeeb1 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/mix.h @@ -0,0 +1,46 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KD_MIX_VECTOR_H +#define CGAL_KD_MIX_VECTOR_H +#include <CGAL/Dimension.h> +namespace CGAL { + +template <class Static_, class Dynamic_, class NT_ ,class Dim_, class Max_dim_ = Dim_> +struct Mix_vector +: Dynamic_::template Rebind_dimension<Dim_, Max_dim_>::Other +{ + template <class D2, class D3 = D2> + struct Rebind_dimension { + typedef Mix_vector<Static_, Dynamic_, NT_, D2, D3> Other; + }; +}; + +template <class Static_, class Dynamic_, class NT_, int d, class Max_dim_> +struct Mix_vector<Static_, Dynamic_, NT_, Dimension_tag<d>, Max_dim_> +: Static_::template Rebind_dimension<Dimension_tag<d>, Max_dim_>::Other +{ + template <class D2, class D3 = D2> + struct Rebind_dimension { + typedef Mix_vector<Static_, Dynamic_, NT_, D2, D3> Other; + }; +}; +} +#endif + diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/sse2.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/sse2.h new file mode 100644 index 00000000..2a75385c --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/sse2.h @@ -0,0 +1,145 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_VECTOR_SSE2_H +#define CGAL_VECTOR_SSE2_H + +// Check what needs adapting for clang, intel and microsoft +#if !defined __SSE2__ || (__GNUC__ * 100 + __GNUC_MINOR__ < 408) +#error Requires SSE2 and gcc 4.8+ +#endif +#include <x86intrin.h> // FIXME: other platforms call it differently + +#include <CGAL/NewKernel_d/functor_tags.h> +#include <CGAL/Dimension.h> +#include <CGAL/enum.h> // CGAL::Sign +#include <CGAL/number_utils.h> // CGAL::sign + + + +namespace CGAL { + + struct Sse_vector_2 { + typedef double NT; + typedef Dimension_tag<2> Dimension; + typedef Dimension_tag<2> Max_dimension; + // No Rebind_dimension, this is a building block + template<class,bool=true> struct Property : boost::false_type {}; + template<bool b> struct Property<Has_vector_plus_minus_tag,b> + : boost::true_type {}; + /* MAYBE? + template<bool b> struct Property<Has_vector_scalar_ops_tag,b> + : boost::true_type {}; + */ + template<bool b> struct Property<Has_determinant_of_vectors_tag,b> + : boost::true_type {}; + template<bool b> struct Property<Has_dot_product_tag,b> + : boost::true_type {}; + + typedef __m128d Vector; + struct Construct_vector { + struct Dimension { + // Initialize with NaN? + Vector operator()(unsigned d) const { + CGAL_assertion(d==2); + return Vector(); + } + }; + + struct Iterator { + template<typename Iter> + Vector operator()(unsigned d,Iter const& f,Iter const& e) const { + CGAL_assertion(d==2); + double x0 = *f; + double x1 = *++f; + CGAL_assertion(++f==e); + Vector a = { x0, x1 }; + return a; + } + }; + + struct Iterator_and_last { + template<typename Iter,typename T> + Vector operator()(unsigned d,Iter const& f,Iter const& e,double t) const { + CGAL_assertion(d==2); + Vector a = { *f, t }; + CGAL_assertion(++f==e); + return a; + } + }; + + struct Values { + Vector operator()(double a,double b) const { + Vector r = { a, b }; + return r; + } + }; + + struct Values_divide { + Vector operator()(double h,double a,double b) const { + // {a,b}/{h,h} is probably slower + Vector r = { a/h, b/h }; + return r; + } + }; + }; + + typedef double const* Vector_const_iterator; + static inline Vector_const_iterator vector_begin(Vector const&a){ + return (Vector_const_iterator)(&a); + } + static inline Vector_const_iterator vector_end(Vector const&a){ + return (Vector_const_iterator)(&a)+2; + } + static inline unsigned size_of_vector(Vector){ + return 2; + } + public: + + static double determinant_of_vectors(Vector a, Vector b) { + __m128d c = _mm_shuffle_pd (b, b, 1); // b1, b0 + __m128d d = a * c; // a0*b1, a1*b0 +#ifdef __SSE3__ + __m128d e = _mm_hsub_pd (d, d); + return e[0]; +#else + return d[0]-d[1]; +#endif + } + static CGAL::Sign sign_of_determinant_of_vectors(Vector a, Vector b) { + return CGAL::sign(determinant_of_vectors(a,b)); + } + + static double dot_product(Vector a,Vector b){ +#ifdef __SSE4_1__ + return _mm_dp_pd (a, b, 1+16+32)[0]; +#else + __m128d p = a * b; +#if defined __SSE3__ + __m128d s = _mm_hadd_pd (p, p); + return s[0]; +#else + return p[0]+p[1]; +#endif +#endif + }; + }; + +} +#endif diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/v2int.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/v2int.h new file mode 100644 index 00000000..b85a3734 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/v2int.h @@ -0,0 +1,181 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_VECTOR_2INT_H +#define CGAL_VECTOR_2INT_H + +#include <stdint.h> +#include <cmath> +#include <CGAL/array.h> +#include <CGAL/Dimension.h> +#include <CGAL/enum.h> +#include <CGAL/number_utils.h> +#include <CGAL/NT_converter.h> +#include <CGAL/transforming_iterator.h> +#include <CGAL/determinant_of_vectors.h> +#include <CGAL/NewKernel_d/functor_tags.h> + + +// What are the pros and cons of having NT be int vs double? + +namespace CGAL { + struct Vector_2_int_prop1 { + typedef double NT; // try lying a bit + typedef int32_t NT1; // what is really stored + typedef int32_t NT1b; // slightly longer + typedef int_fast64_t NT2; // longer type for computations + typedef int_fast64_t NT2b; // slightly longer + bool check_limits(int32_t x){return std::abs(x)<(1<<30);} + // TODO: find nice bounds + }; +#ifdef __SIZEOF_INT128__ + struct Vector_2_int_prop2 { + typedef double NT; + typedef int32_t NT1; + typedef int_fast64_t NT1b; + typedef int_fast64_t NT2; + typedef __int128 NT2b; + bool check_limits(int32_t){return true;} + // take a template/int64_t input and still check the limits? + }; + struct Vector_2_int_prop3 { + typedef long double NT; + typedef int64_t NT1; + typedef int64_t NT1b; + typedef __int128 NT2; + typedef __int128 NT2b; + enum { has_limit=true }; + bool check_limits(int32_t x){return std::abs(x)<(1L<<62);} + // TODO: find nice bounds + }; +#endif + + template<class Prop=Vector_2_int_prop1> + struct Vector_2_int : Prop { + using typename Prop::NT; + using typename Prop::NT1; + using typename Prop::NT1b; + using typename Prop::NT2; + using typename Prop::NT2b; + using Prop::check_limits; + + typedef Dimension_tag<2> Dimension; + typedef Dimension_tag<2> Max_dimension; + // No Rebind_dimension, this is a building block + template<class,bool=true> struct Property : boost::false_type {}; + //template<bool b> struct Property<Has_vector_plus_minus_tag,b> + // : boost::true_type {}; + template<bool b> struct Property<Has_determinant_of_vectors_tag,b> + : boost::true_type {}; + //template<bool b> struct Property<Has_determinant_of_points_tag,b> + // : boost::true_type {}; + // Advertise somehow that the sign_of_determinant* are exact? + + typedef cpp0x::array<NT1,2> Vector; + struct Construct_vector { + struct Dimension { + Vector operator()(unsigned d) const { + CGAL_assertion(d==2); + return Vector(); + } + }; + + // TODO (for all constructors): check that input fits in NT1... + struct Iterator { + template<typename Iter> + Vector operator()(unsigned d,Iter const& f,Iter const& e) const { + CGAL_assertion(d==2); + NT1 x0 = *f; + NT1 x1 = *++f; + CGAL_assertion (++f == e); + CGAL_assertion (check_limits(x0) && check_limits(x1)); + Vector a = { x0, x1 }; + return a; + } + }; + + struct Iterator_and_last { + template<typename Iter,typename T> + Vector operator()(unsigned d,Iter const& f,Iter const& e,double t) const { + CGAL_assertion(d==2); + NT1 x = *f; + CGAL_assertion (++f == e); + CGAL_assertion (check_limits(x) && check_limits(t)); + Vector a = { x, t }; + return a; + } + }; + + struct Values { + Vector operator()(NT1 a,NT1 b) const { + CGAL_assertion (check_limits(a) && check_limits(b)); + Vector r = { a, b }; + return r; + } + }; + + /* + // Maybe safer not to provide it + struct Values_divide { + Vector operator()(double h,double a,double b) const { + Vector r = { a/h, b/h }; + return r; + } + }; + */ + }; + + // Since we lie about NT, be consistent about it + typedef transforming_iterator<NT_converter<NT1,NT>,NT1 const*> Vector_const_iterator; + static inline Vector_const_iterator vector_begin(Vector const&a){ + return Vector_const_iterator(a.begin()); + } + static inline Vector_const_iterator vector_end(Vector const&a){ + return Vector_const_iterator(a.end()); + } + static inline unsigned size_of_vector(Vector){ + return 2; + } + + // for unsigned NT1, check what changes to do. + // return NT or NT2? + static NT determinant_of_vectors(Vector a, Vector b) { + return CGAL::determinant_of_vectors<NT2>(a,b); + } + static CGAL::Sign sign_of_determinant_of_vectors(Vector a, Vector b) { + return CGAL::sign_of_determinant_of_vectors<NT2>(a,b); + } + + static NT determinant_of_points(Vector a, Vector b, Vector c) { + // could be faster to convert to NT directly + NT1b a0=a[0]; NT1b a1=a[1]; + NT1b x0=b[0]-a0; NT1b x1=b[1]-a1; + NT1b y0=c[0]-a0; NT1b y1=c[1]-a1; + return CGAL::determinant<NT>(x0,x1,y0,y1); + } + static CGAL::Sign sign_of_determinant_of_points(Vector a, Vector b, Vector c) { + NT1b a0=a[0]; NT1b a1=a[1]; + NT1b x0=b[0]-a0; NT1b x1=b[1]-a1; + NT2b y0=c[0]-a0; NT2b y1=c[1]-a1; + return CGAL::compare(x0*y1,x1*y0); + } + }; + +} +#endif diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/vector.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/vector.h new file mode 100644 index 00000000..f9cc4e3c --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Vector/vector.h @@ -0,0 +1,167 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_VECTOR_VECTOR_H +#define CGAL_VECTOR_VECTOR_H +#include <boost/type_traits/is_arithmetic.hpp> +#include <boost/utility/enable_if.hpp> +#include <CGAL/Dimension.h> +#include <CGAL/NewKernel_d/utils.h> +#include <vector> +#include <boost/preprocessor/repetition.hpp> +#include <boost/preprocessor/repetition/enum.hpp> +namespace CGAL { + +//Derive from a class that doesn't depend on Dim, or still use Dim for checking? +template<class NT_,class Dim_,class Max_dim_=Dim_> struct Vector_vector { + typedef NT_ NT; + typedef Dim_ Dimension; + typedef Max_dim_ Max_dimension; + typedef std::vector<NT> Vector; + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef Vector_vector< NT, D2, D3 > Other; + }; + template<class> struct Property : boost::false_type {}; + + struct Construct_vector { + struct Dimension { + Vector operator()(int d) const { + return Vector(d); + } + }; + + struct Iterator { + template<typename Iter> + Vector operator()(int CGAL_assertion_code(d),Iter const& f,Iter const& e) const { + CGAL_assertion(d==std::distance(f,e)); + return Vector(f,e); + } + }; + + // unneeded thanks to Iterator_and_last? +#if 0 + struct Iterator_add_one { + template<typename Iter> + Vector operator()(int CGAL_assertion_code(d),Iter const& f,Iter const& e) const { + CGAL_assertion(d==std::distance(f,e)+1); + Vector a; + a.reserve(d+1); + a.insert(a.end(),f,e); + a.push_back(1); + return a; + } + }; +#endif + + struct Iterator_and_last { + template<typename Iter,typename T> + Vector operator()(int d,Iter const& f,Iter const& e,CGAL_FORWARDABLE(T) t) const { + CGAL_assertion(d==std::distance(f,e)+1); + Vector a; + a.reserve(d+1); + a.insert(a.end(),f,e); + a.push_back(CGAL_FORWARD(T,t)); + return a; + } + }; + + // useless, use a transform_iterator? +#if 0 + struct Iterator_and_last_divide { + template<typename Iter,typename T> + Vector operator()(int d,Iter f,Iter const& e,T const&t) const { + CGAL_assertion(d==std::distance(f,e)+1); + Vector a; + a.reserve(d+1); + for(;f!=e;++f){ + a.push_back(*f/t); + } + return a; + } + }; +#endif + + struct Values { +#ifdef CGAL_CXX11 + template<class...U> + Vector operator()(U&&...u) const { + //TODO: check the right number of {}, g++ accepts one and two + Vector a={forward_safe<NT,U>(u)...}; + return a; + } +#else + +#define CGAL_VAR(Z,N,_) a.push_back(t##N); +#define CGAL_CODE(Z,N,_) Vector operator()(BOOST_PP_ENUM_PARAMS(N,NT const& t)) const { \ + Vector a; \ + a.reserve(N); \ + BOOST_PP_REPEAT(N,CGAL_VAR,) \ + return a; \ +} +BOOST_PP_REPEAT_FROM_TO(1, 11, CGAL_CODE, _ ) +#undef CGAL_CODE +#undef CGAL_VAR + +#endif + }; + + struct Values_divide { +#ifdef CGAL_CXX11 + template<class H,class...U> + Vector operator()(H const&h,U&&...u) const { + //TODO: do we want to cast at some point? + //e.g. to avoid 1/2 in integers + // ==> use Rational_traits<NT>().make_rational(x,y) ? + Vector a={Rational_traits<NT>().make_rational(std::forward<U>(u),h)...}; + return a; + } +#else + +#define CGAL_VAR(Z,N,_) a.push_back(Rational_traits<NT>().make_rational( t##N ,h)); +#define CGAL_CODE(Z,N,_) template<class H> Vector \ + operator()(H const&h, BOOST_PP_ENUM_PARAMS(N,NT const& t)) const { \ + Vector a; \ + a.reserve(N); \ + BOOST_PP_REPEAT(N,CGAL_VAR,) \ + return a; \ + } + BOOST_PP_REPEAT_FROM_TO(1, 11, CGAL_CODE, _ ) +#undef CGAL_CODE +#undef CGAL_VAR + +#endif + }; + }; + typedef typename Vector::const_iterator Vector_const_iterator; + static Vector_const_iterator vector_begin(Vector const&a){ + return a.begin(); + } + static Vector_const_iterator vector_end(Vector const&a){ + return a.end(); + } + static int size_of_vector(Vector const&a){ + return (int)a.size(); + } +}; + + +} +#endif + diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h new file mode 100644 index 00000000..44e9aa96 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h @@ -0,0 +1,305 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KERNEL_D_CARTESIAN_WRAP_H +#define CGAL_KERNEL_D_CARTESIAN_WRAP_H + +#include <CGAL/basic.h> +#include <CGAL/is_iterator.h> + +#if defined(BOOST_MSVC) +# pragma warning(push) +# pragma warning(disable:4003) // not enough actual parameters for macro 'BOOST_PP_EXPAND_I' + // http://lists.boost.org/boost-users/2014/11/83291.php +#endif +#include <CGAL/NewKernel_d/Wrapper/Point_d.h> +#include <CGAL/NewKernel_d/Wrapper/Vector_d.h> +#include <CGAL/NewKernel_d/Wrapper/Segment_d.h> +#include <CGAL/NewKernel_d/Wrapper/Sphere_d.h> +#include <CGAL/NewKernel_d/Wrapper/Hyperplane_d.h> +#include <CGAL/NewKernel_d/Wrapper/Weighted_point_d.h> + +#include <CGAL/NewKernel_d/Wrapper/Ref_count_obj.h> + +#include <boost/mpl/or.hpp> +#include <boost/mpl/contains.hpp> +#include <boost/mpl/vector.hpp> + +//TODO: do we want to store the kernel ref in the Object wrappers? It would allow for additions and operator[] and things like that to work, but objects would still need to be created by functors. + +namespace CGAL { +namespace internal { +BOOST_MPL_HAS_XXX_TRAIT_DEF(Is_wrapper) +template<class T,bool=has_Is_wrapper<T>::value> struct Is_wrapper { + enum { value=false }; + typedef Tag_false type; +}; +template<class T> struct Is_wrapper<T,true> { + typedef typename T::Is_wrapper type; + enum { value=type::value }; +}; + +template<class T,bool=is_iterator_type<T,std::input_iterator_tag>::value> struct Is_wrapper_iterator { + enum { value=false }; + typedef Tag_false type; +}; +template<class T> struct Is_wrapper_iterator<T,true> : + Is_wrapper<typename std::iterator_traits<typename CGAL::decay<T>::type>::value_type> +{ }; + +struct Forward_rep { +//TODO: make a good C++0X version with perfect forwarding +//#ifdef CGAL_CXX11 +//template <class T,class=typename std::enable_if<!Is_wrapper<typename std::decay<T>::type>::value&&!Is_wrapper_iterator<typename std::decay<T>::type>::value>::type> +//T&& operator()(typename std::remove_reference<T>::type&& t) const {return static_cast<T&&>(t);}; +//template <class T,class=typename std::enable_if<!Is_wrapper<typename std::decay<T>::type>::value&&!Is_wrapper_iterator<typename std::decay<T>::type>::value>::type> +//T&& operator()(typename std::remove_reference<T>::type& t) const {return static_cast<T&&>(t);}; +// +//template <class T,class=typename std::enable_if<Is_wrapper<typename std::decay<T>::type>::value>::type> +//typename Type_copy_cvref<T,typename std::decay<T>::type::Rep>::type&& +//operator()(T&& t) const { +// return static_cast<typename Type_copy_cvref<T,typename std::decay<T>::type::Rep>::type&&>(t.rep()); +//}; +// +//template <class T,class=typename std::enable_if<Is_wrapper_iterator<typename std::decay<T>::type>::value>::type> +//transforming_iterator<Forward_rep,typename std::decay<T>::type> +//operator()(T&& t) const { +// return make_transforming_iterator(std::forward<T>(t),Forward_rep()); +//}; +//#else +template <class T,bool=Is_wrapper<T>::value,bool=Is_wrapper_iterator<T>::value> struct result_; +template <class T> struct result_<T,false,false>{typedef T const& type;}; +template <class T> struct result_<T,true,false>{typedef typename decay<T>::type::Rep const& type;}; +template <class T> struct result_<T,false,true>{typedef transforming_iterator<Forward_rep,typename decay<T>::type> type;}; +template<class> struct result; +template<class T> struct result<Forward_rep(T)> : result_<T> {}; + +template <class T> typename boost::disable_if<boost::mpl::or_<Is_wrapper<T>,Is_wrapper_iterator<T> >,T>::type const& operator()(T const& t) const {return t;} +template <class T> typename boost::disable_if<boost::mpl::or_<Is_wrapper<T>,Is_wrapper_iterator<T> >,T>::type& operator()(T& t) const {return t;} + +template <class T> typename T::Rep const& operator()(T const& t, typename boost::enable_if<Is_wrapper<T> >::type* = 0) const {return t.rep();} + +template <class T> transforming_iterator<Forward_rep,typename boost::enable_if<Is_wrapper_iterator<T>,T>::type> operator()(T const& t) const {return make_transforming_iterator(t,Forward_rep());} +//#endif +}; +} + +template <class B, class K, class T, bool = Provides_type<B, T>::value> +struct Map_wrapping_type : Get_type<B, T> {}; +#define CGAL_REGISTER_OBJECT_WRAPPER(X) \ + template <class B, class K> \ + struct Map_wrapping_type <B, K, X##_tag, true> { \ + typedef Wrap::X##_d<K> type; \ + } +CGAL_REGISTER_OBJECT_WRAPPER(Point); +CGAL_REGISTER_OBJECT_WRAPPER(Vector); +CGAL_REGISTER_OBJECT_WRAPPER(Segment); +CGAL_REGISTER_OBJECT_WRAPPER(Sphere); +CGAL_REGISTER_OBJECT_WRAPPER(Hyperplane); +CGAL_REGISTER_OBJECT_WRAPPER(Weighted_point); +#undef CGAL_REGISTER_OBJECT_WRAPPER + +// Note: this tends to be an all or nothing thing currently, wrapping +// only some types breaks, probably because we don't check whether the +// return type is indeed wrapped. +template < typename Base_ , typename Derived_ = Default > +struct Cartesian_wrap : public Base_ +{ + CGAL_CONSTEXPR Cartesian_wrap(){} + CGAL_CONSTEXPR Cartesian_wrap(int d):Base_(d){} + typedef Base_ Kernel_base; + typedef Cartesian_wrap Self; + // TODO: pass the 2 types Self and Derived to the wrappers, they can use Self for most purposes and Derived only for Kernel_traits' typedef R. + typedef typename Default::Get<Derived_, Self>::type Derived; + // FIXME: The list doesn't belong here. + typedef boost::mpl::vector<Point_tag,Segment_tag,Sphere_tag,Vector_tag,Hyperplane_tag> Wrapped_list; + + template <class T> + struct Type : Map_wrapping_type<Base_, Derived, T> {}; + + //Translate the arguments + template <class T, class D = void, + class=typename Get_functor_category<Derived,T>::type, + bool=Provides_functor<Kernel_base, T>::value, + bool=boost::mpl::contains<Wrapped_list,typename map_result_tag<T>::type>::type::value> + struct Functor { + typedef typename Get_functor<Kernel_base, T>::type B; + struct type { + B b; + type(){} + type(Self const&k):b(k){} + typedef typename B::result_type result_type; +#ifdef CGAL_CXX11 + template<class...U> result_type operator()(U&&...u)const{ + return b(internal::Forward_rep()(u)...); + } +#else +#define CGAL_VAR(Z,N,_) internal::Forward_rep()(u##N) +#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class U)> result_type \ + operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,U,const&u))const{ \ + return b(BOOST_PP_ENUM(N,CGAL_VAR,)); \ + } + BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_) +#undef CGAL_CODE +#undef CGAL_VAR +// In case the last argument needs to be non-const. Fragile... +#define CGAL_VAR(Z,N,_) internal::Forward_rep()(u##N) +#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class U),class V> result_type \ + operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,U,const&u),V&v)const{ \ + return b(BOOST_PP_ENUM(N,CGAL_VAR,),internal::Forward_rep()(v)); \ + } + BOOST_PP_REPEAT_FROM_TO(1,8,CGAL_CODE,_) +#undef CGAL_CODE +#undef CGAL_VAR +#endif + }; + }; + + // Preserve the difference between Null_functor and nothing. + template <class T, class D, class C, bool b> + struct Functor <T, D, C, false, b> + : Get_functor <Kernel_base, T> {}; + + //Translate both the arguments and the result + //TODO: Check Is_wrapper instead of relying on map_result_tag? + template<class T,class D> struct Functor<T,D,Construct_tag,true,true> { + typedef typename Get_functor<Kernel_base, T>::type B; + struct type { + B b; + type(){} + type(Self const&k):b(k){} + typedef typename map_result_tag<T>::type result_tag; + // FIXME: Self or Derived? + typedef typename Get_type<Self,result_tag>::type result_type; +#ifdef CGAL_CXX11 + template<class...U> result_type operator()(U&&...u)const{ + return result_type(Eval_functor(),b,internal::Forward_rep()(u)...); + } +#else +#define CGAL_VAR(Z,N,_) internal::Forward_rep()(u##N) +#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class U)> result_type \ + operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,U,const&u))const{ \ + return result_type(Eval_functor(),b,BOOST_PP_ENUM(N,CGAL_VAR,)); \ + } + BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_) +#undef CGAL_CODE +#undef CGAL_VAR +#endif + }; + }; + +}; + +template < typename Base_ > +struct Cartesian_refcount : public Base_ +{ + CGAL_CONSTEXPR Cartesian_refcount(){} + CGAL_CONSTEXPR Cartesian_refcount(int d):Base_(d){} + typedef Base_ Kernel_base; + typedef Cartesian_refcount Self; + + // FIXME: Use object_list, or a list passed as argument, or anything + // automatic. + template <class T, class=void> struct Type : Get_type<Base_, T> {}; +#define CGAL_Kernel_obj(X,Y) \ + template <class D> struct Type<X##_tag, D> { typedef Ref_count_obj<Cartesian_refcount, X##_tag> type; }; + + CGAL_Kernel_obj(Point,point) + CGAL_Kernel_obj(Vector,vector) +#undef CGAL_Kernel_obj + + template<class T> struct Dispatch { + //typedef typename map_functor_type<T>::type f_t; + typedef typename map_result_tag<T>::type r_t; + enum { + is_nul = boost::is_same<typename Get_functor<Kernel_base, T>::type,Null_functor>::value, + ret_rcobj = boost::is_same<r_t,Point_tag>::value || boost::is_same<r_t,Vector_tag>::value + }; + }; + + //Translate the arguments + template<class T,class D=void,bool=Dispatch<T>::is_nul,bool=Dispatch<T>::ret_rcobj> struct Functor { + typedef typename Get_functor<Kernel_base, T>::type B; + struct type { + B b; + type(){} + type(Self const&k):b(k){} + typedef typename B::result_type result_type; +#ifdef CGAL_CXX11 + template<class...U> result_type operator()(U&&...u)const{ + return b(internal::Forward_rep()(u)...); + } +#else + result_type operator()()const{ + return b(); + } +#define CGAL_VAR(Z,N,_) internal::Forward_rep()(u##N) +#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class U)> result_type \ + operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,U,const&u))const{ \ + return b(BOOST_PP_ENUM(N,CGAL_VAR,)); \ + } + BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_) +#undef CGAL_CODE +#undef CGAL_VAR +#endif + }; + }; + + //Translate both the arguments and the result + template<class T,class D,bool b> struct Functor<T,D,true,b> { + typedef Null_functor type; + }; + + template<class T,class D> struct Functor<T,D,false,true> { + typedef typename Get_functor<Kernel_base, T>::type B; + struct type { + B b; + type(){} + type(Self const&k):b(k){} + typedef typename map_result_tag<T>::type result_tag; + typedef typename Get_type<Self,result_tag>::type result_type; +#ifdef CGAL_CXX11 + template<class...U> result_type operator()(U&&...u)const{ + return result_type(Eval_functor(),b,internal::Forward_rep()(u)...); + } +#else + result_type operator()()const{ + return result_type(Eval_functor(),b); + } +#define CGAL_VAR(Z,N,_) internal::Forward_rep()(u##N) +#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class U)> result_type \ + operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,U,const&u))const{ \ + return result_type(Eval_functor(),b,BOOST_PP_ENUM(N,CGAL_VAR,)); \ + } + BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_) +#undef CGAL_CODE +#undef CGAL_VAR +#endif + }; + }; + +}; + +} //namespace CGAL + +#if defined(BOOST_MSVC) +# pragma warning(pop) +#endif + +#endif // CGAL_KERNEL_D_CARTESIAN_WRAP_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Hyperplane_d.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Hyperplane_d.h new file mode 100644 index 00000000..54fd50bd --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Hyperplane_d.h @@ -0,0 +1,131 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_WRAPPER_HYPERPLANE_D_H +#define CGAL_WRAPPER_HYPERPLANE_D_H + +#include <CGAL/representation_tags.h> +#include <CGAL/assertions.h> +#include <boost/type_traits.hpp> +#include <CGAL/Kernel/Return_base_tag.h> +#include <CGAL/Dimension.h> +#ifndef CGAL_CXX11 +#include <boost/preprocessor/repetition.hpp> +#endif +#include <boost/utility/result_of.hpp> + +namespace CGAL { +namespace Wrap { + +template <class R_> +class Hyperplane_d : public Get_type<typename R_::Kernel_base, Hyperplane_tag>::type +{ + typedef typename Get_type<R_, FT_tag>::type FT_; + typedef typename R_::Kernel_base Kbase; + typedef typename Get_type<R_, Vector_tag>::type Vector_; + typedef typename Get_functor<Kbase, Construct_ttag<Hyperplane_tag> >::type CHBase; + typedef typename Get_functor<Kbase, Orthogonal_vector_tag>::type OVBase; + typedef typename Get_functor<Kbase, Hyperplane_translation_tag>::type HTBase; + + typedef Hyperplane_d Self; + CGAL_static_assertion((boost::is_same<Self, typename Get_type<R_, Hyperplane_tag>::type>::value)); + +public: + + typedef Tag_true Is_wrapper; + typedef typename R_::Default_ambient_dimension Ambient_dimension; + typedef typename Increment_dimension<Ambient_dimension,-1>::type Feature_dimension; + + typedef typename Get_type<Kbase, Hyperplane_tag>::type Rep; + + const Rep& rep() const + { + return *this; + } + + Rep& rep() + { + return *this; + } + + typedef R_ R; + +#ifdef CGAL_CXX11 + template<class...U,class=typename std::enable_if<!std::is_same<std::tuple<typename std::decay<U>::type...>,std::tuple<Hyperplane_d> >::value>::type> explicit Hyperplane_d(U&&...u) + : Rep(CHBase()(std::forward<U>(u)...)){} + +// // called from Construct_point_d +// template<class...U> explicit Point_d(Eval_functor&&,U&&...u) +// : Rep(Eval_functor(), std::forward<U>(u)...){} + template<class F,class...U> explicit Hyperplane_d(Eval_functor&&,F&&f,U&&...u) + : Rep(std::forward<F>(f)(std::forward<U>(u)...)){} + +#if 0 + // the new standard may make this necessary + Point_d(Point_d const&)=default; + Point_d(Point_d &);//=default; + Point_d(Point_d &&)=default; +#endif + + // try not to use these + Hyperplane_d(Rep const& v) : Rep(v) {} + Hyperplane_d(Rep& v) : Rep(static_cast<Rep const&>(v)) {} + Hyperplane_d(Rep&& v) : Rep(std::move(v)) {} + +#else + + Hyperplane_d() : Rep(CHBase()()) {} + + Hyperplane_d(Rep const& v) : Rep(v) {} // try not to use it + +#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class T)> \ + explicit Hyperplane_d(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \ + : Rep(CHBase()( \ + BOOST_PP_ENUM_PARAMS(N,t))) {} \ + \ + template<class F,BOOST_PP_ENUM_PARAMS(N,class T)> \ + Hyperplane_d(Eval_functor,F const& f,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \ + : Rep(f(BOOST_PP_ENUM_PARAMS(N,t))) {} + /* + template<BOOST_PP_ENUM_PARAMS(N,class T)> \ + Point_d(Eval_functor,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \ + : Rep(Eval_functor(), BOOST_PP_ENUM_PARAMS(N,t)) {} + */ + + BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_) +#undef CGAL_CODE + +#endif + + //TODO: if OVBase returns a reference to a base vector, cast it to a + //reference to a wrapper vector. Ugly but should be safe. + Vector_ orthogonal_vector()const{ + return Vector_(Eval_functor(),OVBase(),rep()); + } + FT_ translation()const{ + return HTBase()(rep()); + } + + +}; + +} //namespace Wrap +} //namespace CGAL + +#endif // CGAL_WRAPPER_SPHERE_D_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Point_d.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Point_d.h new file mode 100644 index 00000000..0718c947 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Point_d.h @@ -0,0 +1,284 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_WRAPPER_POINT_D_H +#define CGAL_WRAPPER_POINT_D_H + +#include <ostream> +#include <CGAL/Origin.h> +#include <CGAL/Kernel/mpl.h> +#include <CGAL/representation_tags.h> +#include <CGAL/assertions.h> +#include <boost/type_traits.hpp> +#include <CGAL/Kernel/Return_base_tag.h> +#include <CGAL/Dimension.h> +#ifndef CGAL_CXX11 +#include <boost/preprocessor/repetition.hpp> +#endif +#include <boost/utility/result_of.hpp> + +namespace CGAL { +namespace Wrap { + +template <class R_> +class Point_d : public Get_type<typename R_::Kernel_base, Point_tag>::type + // Deriving won't work if the point is just a __m256d. + // Test boost/std::is_class for instance +{ + typedef typename Get_type<R_, RT_tag>::type RT_; + typedef typename Get_type<R_, FT_tag>::type FT_; + typedef typename R_::Kernel_base Kbase; + typedef typename Get_type<R_, Vector_tag>::type Vector_; + typedef typename Get_functor<Kbase, Construct_ttag<Point_tag> >::type CPBase; + typedef typename Get_functor<Kbase, Compute_point_cartesian_coordinate_tag>::type CCBase; + typedef typename Get_functor<Kbase, Construct_ttag<Point_cartesian_const_iterator_tag> >::type CPI; + + + typedef Point_d Self; + CGAL_static_assertion((boost::is_same<Self, typename Get_type<R_, Point_tag>::type>::value)); + +public: + + typedef Tag_true Is_wrapper; + typedef typename R_::Default_ambient_dimension Ambient_dimension; + typedef Dimension_tag<0> Feature_dimension; + + typedef typename Get_type<Kbase, Point_tag>::type Rep; + //typedef typename CGAL::decay<typename boost::result_of<CPI(Rep,Begin_tag)>::type>::type Cartesian_const_iterator; + + const Rep& rep() const + { + return *this; + } + + Rep& rep() + { + return *this; + } + + typedef R_ R; + +#ifdef CGAL_CXX11 + template<class...U,class=typename std::enable_if<!std::is_same<std::tuple<typename std::decay<U>::type...>,std::tuple<Point_d> >::value>::type> explicit Point_d(U&&...u) + : Rep(CPBase()(std::forward<U>(u)...)){} + +// // called from Construct_point_d +// template<class...U> explicit Point_d(Eval_functor&&,U&&...u) +// : Rep(Eval_functor(), std::forward<U>(u)...){} + template<class F,class...U> explicit Point_d(Eval_functor&&,F&&f,U&&...u) + : Rep(std::forward<F>(f)(std::forward<U>(u)...)){} + +#if 0 + // the new standard may make this necessary + Point_d(Point_d const&)=default; + Point_d(Point_d &);//=default; + Point_d(Point_d &&)=default; +#endif + + // try not to use these + Point_d(Rep const& v) : Rep(v) {} + Point_d(Rep& v) : Rep(static_cast<Rep const&>(v)) {} + Point_d(Rep&& v) : Rep(std::move(v)) {} + + // this one should be implicit + Point_d(Origin const& v) + : Rep(CPBase()(v)) {} + Point_d(Origin& v) + : Rep(CPBase()(v)) {} + Point_d(Origin&& v) + : Rep(CPBase()(std::move(v))) {} + +#else + + Point_d() : Rep(CPBase()()) {} + + Point_d(Rep const& v) : Rep(v) {} // try not to use it + +#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class T)> \ + explicit Point_d(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \ + : Rep(CPBase()( \ + BOOST_PP_ENUM_PARAMS(N,t))) {} \ + \ + template<class F,BOOST_PP_ENUM_PARAMS(N,class T)> \ + Point_d(Eval_functor,F const& f,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \ + : Rep(f(BOOST_PP_ENUM_PARAMS(N,t))) {} + /* + template<BOOST_PP_ENUM_PARAMS(N,class T)> \ + Point_d(Eval_functor,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \ + : Rep(Eval_functor(), BOOST_PP_ENUM_PARAMS(N,t)) {} + */ + + BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_) +#undef CGAL_CODE + + // this one should be implicit + Point_d(Origin const& o) + : Rep(CPBase()(o)) {} + +#endif + + typename boost::result_of<CCBase(Rep,int)>::type cartesian(int i)const{ + return CCBase()(rep(),i); + } + typename boost::result_of<CCBase(Rep,int)>::type operator[](int i)const{ + return CCBase()(rep(),i); + } + + typename boost::result_of<CPI(Rep,Begin_tag)>::type cartesian_begin()const{ + return CPI()(rep(),Begin_tag()); + } + + typename boost::result_of<CPI(Rep,End_tag)>::type cartesian_end()const{ + return CPI()(rep(),End_tag()); + } + + int dimension() const { + typedef typename Get_functor<Kbase, Point_dimension_tag>::type PDBase; + return PDBase()(rep()); + } + + /* + Direction_d direction() const + { + return R().construct_direction_d_object()(*this); + } + + Vector_d transform(const Aff_transformation_d &t) const + { + return t.transform(*this); + } + + Vector_d operator/(const RT& c) const + { + return R().construct_divided_vector_d_object()(*this,c); + } + + Vector_d operator/(const typename First_if_different<FT_,RT>::Type & c) const + { + return R().construct_divided_vector_d_object()(*this,c); + } + + typename Qualified_result_of<typename R::Compute_x_3, Vector_3>::type + x() const + { + return R().compute_x_3_object()(*this); + } + + typename Qualified_result_of<typename R::Compute_y_3, Vector_3>::type + y() const + { + return R().compute_y_3_object()(*this); + } + + typename Qualified_result_of<typename R::Compute_z_3, Vector_3>::type + z() const + { + return R().compute_z_3_object()(*this); + } + + typename Qualified_result_of<typename R::Compute_hx_3, Vector_3>::type + hx() const + { + return R().compute_hx_3_object()(*this); + } + + typename Qualified_result_of<typename R::Compute_hy_3, Vector_3>::type + hy() const + { + return R().compute_hy_3_object()(*this); + } + + typename Qualified_result_of<typename R::Compute_hz_3, Vector_3>::type + hz() const + { + return R().compute_hz_3_object()(*this); + } + + typename Qualified_result_of<typename R::Compute_hw_3, Vector_3>::type + hw() const + { + return R().compute_hw_3_object()(*this); + } + + typename Qualified_result_of<typename R::Compute_x_3, Vector_3>::type + cartesian(int i) const + { + CGAL_kernel_precondition( (i == 0) || (i == 1) || (i == 2) ); + if (i==0) return x(); + if (i==1) return y(); + return z(); + } + + typename Qualified_result_of<typename R::Compute_hw_3, Vector_3>::type + homogeneous(int i) const + { + CGAL_kernel_precondition( (i >= 0) || (i <= 3) ); + if (i==0) return hx(); + if (i==1) return hy(); + if (i==2) return hz(); + return hw(); + } + + typename Qualified_result_of<typename R::Compute_squared_length_3, Vector_3>::type + squared_length() const + { + return R().compute_squared_length_3_object()(*this); + } +*/ +}; +#if 0 +template <class R_> Point_d<R_>::Point_d(Point_d &)=default; +#endif + +//TODO: IO + +template <class R_> +std::ostream& operator <<(std::ostream& os, const Point_d<R_>& p) +{ + typedef typename R_::Kernel_base Kbase; + typedef typename Get_functor<Kbase, Construct_ttag<Point_cartesian_const_iterator_tag> >::type CPI; + // Should just be "auto"... + typename CGAL::decay<typename boost::result_of< + CPI(typename Point_d<R_>::Rep,Begin_tag) + >::type>::type + b = p.cartesian_begin(), + e = p.cartesian_end(); + os << p.dimension(); + for(; b != e; ++b){ + os << " " << *b; + } + return os; +} + +//template <class R_> +//Vector_d<R_> operator+(const Vector_d<R_>& v,const Vector_d<R_>& w) const +//{ +// return typename R::template Construct<Sum_of_vectors_tag>::type()(v,w); +//} +// +//template <class R_> +//Vector_d<R_> operator-(const Vector_d<R_>& v,const Vector_d<R_>& w) const +//{ +// return typename R::template Construct<Difference_of_vectors_tag>::type()(v,w); +//} + +} //namespace Wrap +} //namespace CGAL + +#endif // CGAL_WRAPPER_POINT_D_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Ref_count_obj.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Ref_count_obj.h new file mode 100644 index 00000000..f33e14c0 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Ref_count_obj.h @@ -0,0 +1,120 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_WRAPPER_REF_COUNT_OBJ_H +#define CGAL_WRAPPER_REF_COUNT_OBJ_H + +#include <CGAL/Origin.h> +#include <CGAL/Handle_for.h> +#include <CGAL/Kernel/mpl.h> +#include <CGAL/representation_tags.h> +#include <CGAL/assertions.h> +#include <boost/type_traits.hpp> +#include <CGAL/Kernel/Return_base_tag.h> +#include <CGAL/Dimension.h> +#ifndef CGAL_CXX11 +#include <boost/preprocessor/repetition.hpp> +#endif +#include <boost/utility/result_of.hpp> + +// no need for a fancy interface here, people can use the Point_d wrapper on +// top. + +namespace CGAL { + +template <class R_, class Tag_> +class Ref_count_obj +{ + typedef typename R_::Kernel_base Kbase; + typedef typename Get_functor<Kbase, Construct_ttag<Tag_> >::type CBase; + + typedef Ref_count_obj Self; + CGAL_static_assertion((boost::is_same<Self, typename Get_type<R_, Tag_>::type>::value)); + +public: + typedef R_ R; + + typedef Tag_true Is_wrapper; + typedef typename R_::Default_ambient_dimension Ambient_dimension; + //typedef Dimension_tag<0> Feature_dimension; + + typedef typename Get_type<Kbase, Tag_>::type Rep; + typedef Handle_for<Rep> Data; + +private: + Data data; +public: + + const Rep& rep() const + { + return CGAL::get_pointee_or_identity(data); + } + +#ifdef CGAL_CXX11 + template<class...U,class=typename std::enable_if<!std::is_same<std::tuple<typename std::decay<U>::type...>,std::tuple<Ref_count_obj> >::value>::type> explicit Ref_count_obj(U&&...u) + : data(Eval_functor(),CBase(),std::forward<U>(u)...){} + + template<class F,class...U> explicit Ref_count_obj(Eval_functor&&,F&&f,U&&...u) + : data(Eval_functor(),std::forward<F>(f),std::forward<U>(u)...){} + + // try not to use these + Ref_count_obj(Rep const& v) : data(v) {} + Ref_count_obj(Rep& v) : data(static_cast<Rep const&>(v)) {} + Ref_count_obj(Rep&& v) : data(std::move(v)) {} + + // Do we really need this for point? +// // this one should be implicit +// Ref_count_obj(Origin const& v) +// : data(Eval_functor(),CBase(),v) {} +// Ref_count_obj(Origin& v) +// : data(Eval_functor(),CBase(),v) {} +// Ref_count_obj(Origin&& v) +// : data(Eval_functor(),CBase(),std::move(v)) {} + +#else + + Ref_count_obj() : data(Eval_functor(),CBase()) {} + + Ref_count_obj(Rep const& v) : data(v) {} // try not to use it + +#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class T)> \ + explicit Ref_count_obj(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \ + : data(Eval_functor(),CBase(),BOOST_PP_ENUM_PARAMS(N,t)) {} \ + \ + template<class F,BOOST_PP_ENUM_PARAMS(N,class T)> \ + Ref_count_obj(Eval_functor,F const& f,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \ + : data(Eval_functor(),f,BOOST_PP_ENUM_PARAMS(N,t)) {} + + BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_) +#undef CGAL_CODE + template<class F> + Ref_count_obj(Eval_functor,F const& f) + : data(Eval_functor(),f) {} + +// // this one should be implicit +// Ref_count_obj(Origin const& o) +// : data(Eval_functor(),CBase(),o) {} + +#endif + +}; + +} //namespace CGAL + +#endif diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Segment_d.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Segment_d.h new file mode 100644 index 00000000..bfb20a77 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Segment_d.h @@ -0,0 +1,133 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_WRAPPER_SEGMENT_D_H +#define CGAL_WRAPPER_SEGMENT_D_H + +#include <CGAL/Origin.h> +#include <CGAL/Kernel/mpl.h> +#include <CGAL/representation_tags.h> +#include <CGAL/assertions.h> +#include <boost/type_traits.hpp> +#include <CGAL/Kernel/Return_base_tag.h> +#include <CGAL/Dimension.h> +#ifndef CGAL_CXX11 +#include <boost/preprocessor/repetition.hpp> +#endif +#include <boost/utility/result_of.hpp> + +namespace CGAL { +namespace Wrap { + +template <class R_> +class Segment_d : public Get_type<typename R_::Kernel_base, Segment_tag>::type +{ + typedef typename Get_type<R_, RT_tag>::type RT_; + typedef typename Get_type<R_, FT_tag>::type FT_; + typedef typename R_::Kernel_base Kbase; + typedef typename Get_type<R_, Point_tag>::type Point_; + typedef typename Get_functor<Kbase, Construct_ttag<Point_tag> >::type CPBase; + typedef typename Get_functor<Kbase, Construct_ttag<Segment_tag> >::type CSBase; + typedef typename Get_functor<Kbase, Segment_extremity_tag>::type CSEBase; + + typedef Segment_d Self; + CGAL_static_assertion((boost::is_same<Self, typename Get_type<R_, Segment_tag>::type>::value)); + +public: + + typedef Tag_true Is_wrapper; + typedef typename R_::Default_ambient_dimension Ambient_dimension; + typedef Dimension_tag<1> Feature_dimension; + + typedef typename Get_type<Kbase, Segment_tag>::type Rep; + + const Rep& rep() const + { + return *this; + } + + Rep& rep() + { + return *this; + } + + typedef R_ R; + +#ifdef CGAL_CXX11 + template<class...U,class=typename std::enable_if<!std::is_same<std::tuple<typename std::decay<U>::type...>,std::tuple<Segment_d> >::value>::type> explicit Segment_d(U&&...u) + : Rep(CSBase()(std::forward<U>(u)...)){} + +// // called from Construct_point_d +// template<class...U> explicit Point_d(Eval_functor&&,U&&...u) +// : Rep(Eval_functor(), std::forward<U>(u)...){} + template<class F,class...U> explicit Segment_d(Eval_functor&&,F&&f,U&&...u) + : Rep(std::forward<F>(f)(std::forward<U>(u)...)){} + +#if 0 + // the new standard may make this necessary + Point_d(Point_d const&)=default; + Point_d(Point_d &);//=default; + Point_d(Point_d &&)=default; +#endif + + // try not to use these + Segment_d(Rep const& v) : Rep(v) {} + Segment_d(Rep& v) : Rep(static_cast<Rep const&>(v)) {} + Segment_d(Rep&& v) : Rep(std::move(v)) {} + +#else + + Segment_d() : Rep(CSBase()()) {} + + Segment_d(Rep const& v) : Rep(v) {} // try not to use it + +#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class T)> \ + explicit Segment_d(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \ + : Rep(CSBase()( \ + BOOST_PP_ENUM_PARAMS(N,t))) {} \ + \ + template<class F,BOOST_PP_ENUM_PARAMS(N,class T)> \ + Segment_d(Eval_functor,F const& f,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \ + : Rep(f(BOOST_PP_ENUM_PARAMS(N,t))) {} + /* + template<BOOST_PP_ENUM_PARAMS(N,class T)> \ + Point_d(Eval_functor,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \ + : Rep(Eval_functor(), BOOST_PP_ENUM_PARAMS(N,t)) {} + */ + + BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_) +#undef CGAL_CODE + +#endif + + //TODO: if CSEBase returns a reference to a base point, cast it to a + //reference to a wrapper point. Ugly but should be safe. + Point_ source()const{ + return Point_(Eval_functor(),CSEBase(),rep(),0); + } + Point_ target()const{ + return Point_(Eval_functor(),CSEBase(),rep(),1); + } + +}; + +} //namespace Wrap +} //namespace CGAL + +#endif // CGAL_WRAPPER_SEGMENT_D_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Sphere_d.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Sphere_d.h new file mode 100644 index 00000000..87f0c66e --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Sphere_d.h @@ -0,0 +1,130 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_WRAPPER_SPHERE_D_H +#define CGAL_WRAPPER_SPHERE_D_H + +#include <CGAL/representation_tags.h> +#include <CGAL/assertions.h> +#include <boost/type_traits.hpp> +#include <CGAL/Kernel/Return_base_tag.h> +#include <CGAL/Dimension.h> +#ifndef CGAL_CXX11 +#include <boost/preprocessor/repetition.hpp> +#endif +#include <boost/utility/result_of.hpp> + +namespace CGAL { +namespace Wrap { + +template <class R_> +class Sphere_d : public Get_type<typename R_::Kernel_base, Sphere_tag>::type +{ + typedef typename Get_type<R_, FT_tag>::type FT_; + typedef typename R_::Kernel_base Kbase; + typedef typename Get_type<R_, Point_tag>::type Point_; + typedef typename Get_functor<Kbase, Construct_ttag<Sphere_tag> >::type CSBase; + typedef typename Get_functor<Kbase, Center_of_sphere_tag>::type COSBase; + typedef typename Get_functor<Kbase, Squared_radius_tag>::type SRBase; + + typedef Sphere_d Self; + CGAL_static_assertion((boost::is_same<Self, typename Get_type<R_, Sphere_tag>::type>::value)); + +public: + + typedef Tag_true Is_wrapper; + typedef typename R_::Default_ambient_dimension Ambient_dimension; + typedef typename Increment_dimension<Ambient_dimension,-1>::type Feature_dimension; + + typedef typename Get_type<Kbase, Sphere_tag>::type Rep; + + const Rep& rep() const + { + return *this; + } + + Rep& rep() + { + return *this; + } + + typedef R_ R; + +#ifdef CGAL_CXX11 + template<class...U,class=typename std::enable_if<!std::is_same<std::tuple<typename std::decay<U>::type...>,std::tuple<Sphere_d> >::value>::type> explicit Sphere_d(U&&...u) + : Rep(CSBase()(std::forward<U>(u)...)){} + +// // called from Construct_point_d +// template<class...U> explicit Point_d(Eval_functor&&,U&&...u) +// : Rep(Eval_functor(), std::forward<U>(u)...){} + template<class F,class...U> explicit Sphere_d(Eval_functor&&,F&&f,U&&...u) + : Rep(std::forward<F>(f)(std::forward<U>(u)...)){} + +#if 0 + // the new standard may make this necessary + Point_d(Point_d const&)=default; + Point_d(Point_d &);//=default; + Point_d(Point_d &&)=default; +#endif + + // try not to use these + Sphere_d(Rep const& v) : Rep(v) {} + Sphere_d(Rep& v) : Rep(static_cast<Rep const&>(v)) {} + Sphere_d(Rep&& v) : Rep(std::move(v)) {} + +#else + + Sphere_d() : Rep(CSBase()()) {} + + Sphere_d(Rep const& v) : Rep(v) {} // try not to use it + +#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class T)> \ + explicit Sphere_d(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \ + : Rep(CSBase()( \ + BOOST_PP_ENUM_PARAMS(N,t))) {} \ + \ + template<class F,BOOST_PP_ENUM_PARAMS(N,class T)> \ + Sphere_d(Eval_functor,F const& f,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \ + : Rep(f(BOOST_PP_ENUM_PARAMS(N,t))) {} + /* + template<BOOST_PP_ENUM_PARAMS(N,class T)> \ + Point_d(Eval_functor,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \ + : Rep(Eval_functor(), BOOST_PP_ENUM_PARAMS(N,t)) {} + */ + + BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_) +#undef CGAL_CODE + +#endif + + //TODO: if COSBase returns a reference to a base point, cast it to a + //reference to a wrapper point. Ugly but should be safe. + Point_ center()const{ + return Point_(Eval_functor(),COSBase(),rep()); + } + FT_ squared_radius()const{ + return SRBase()(rep()); + } + +}; + +} //namespace Wrap +} //namespace CGAL + +#endif // CGAL_WRAPPER_SPHERE_D_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Vector_d.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Vector_d.h new file mode 100644 index 00000000..b7d1f0d0 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Vector_d.h @@ -0,0 +1,266 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_WRAPPER_VECTOR_D_H +#define CGAL_WRAPPER_VECTOR_D_H + +#include <CGAL/Origin.h> +#include <CGAL/Kernel/mpl.h> +#include <CGAL/representation_tags.h> +#include <CGAL/assertions.h> +#include <boost/type_traits.hpp> +#include <CGAL/Kernel/Return_base_tag.h> +#include <CGAL/Dimension.h> +#ifndef CGAL_CXX11 +#include <boost/preprocessor/repetition.hpp> +#endif +#include <boost/utility/result_of.hpp> + +namespace CGAL { +namespace Wrap { + +template <class R_> +class Vector_d : public Get_type<typename R_::Kernel_base, Vector_tag>::type +{ + typedef typename Get_type<R_, RT_tag>::type RT_; + typedef typename Get_type<R_, FT_tag>::type FT_; + typedef typename R_::Kernel_base Kbase; + typedef typename Get_type<R_, Point_tag>::type Point_; + typedef typename Get_functor<Kbase, Construct_ttag<Vector_tag> >::type CVBase; + typedef typename Get_functor<Kbase, Compute_vector_cartesian_coordinate_tag>::type CCBase; + typedef typename Get_functor<Kbase, Construct_ttag<Vector_cartesian_const_iterator_tag> >::type CVI; + typedef typename Get_functor<Kbase, Squared_length_tag>::type SLBase; + + typedef Vector_d Self; + CGAL_static_assertion((boost::is_same<Self, typename Get_type<R_, Vector_tag>::type>::value)); + +public: + + typedef Tag_true Is_wrapper; + typedef typename R_::Default_ambient_dimension Ambient_dimension; + typedef Dimension_tag<0> Feature_dimension; + + //typedef typename R_::Vector_cartesian_const_iterator Cartesian_const_iterator; + typedef typename Get_type<Kbase, Vector_tag>::type Rep; + + const Rep& rep() const + { + return *this; + } + + Rep& rep() + { + return *this; + } + + typedef R_ R; + +#ifdef CGAL_CXX11 + template<class...U,class=typename std::enable_if<!std::is_same<std::tuple<typename std::decay<U>::type...>,std::tuple<Vector_d> >::value>::type> explicit Vector_d(U&&...u) + : Rep(CVBase()(std::forward<U>(u)...)){} + +// // called from Construct_vector_d +// template<class...U> explicit Vector_d(Eval_functor&&,U&&...u) +// : Rep(Eval_functor(), std::forward<U>(u)...){} + template<class F,class...U> explicit Vector_d(Eval_functor&&,F&&f,U&&...u) + : Rep(std::forward<F>(f)(std::forward<U>(u)...)){} + +#if 0 + // the new standard may make this necessary + Vector_d(Vector_d const&)=default; + Vector_d(Vector_d &);//=default; + Vector_d(Vector_d &&)=default; +#endif + + // try not to use these + Vector_d(Rep const& v) : Rep(v) {} + Vector_d(Rep& v) : Rep(static_cast<Rep const&>(v)) {} + Vector_d(Rep&& v) : Rep(std::move(v)) {} + + // this one should be implicit + Vector_d(Null_vector const& v) + : Rep(CVBase()(v)) {} + Vector_d(Null_vector& v) + : Rep(CVBase()(v)) {} + Vector_d(Null_vector&& v) + : Rep(CVBase()(std::move(v))) {} + +#else + + Vector_d() : Rep(CVBase()()) {} + + Vector_d(Rep const& v) : Rep(v) {} // try not to use it + +#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class T)> \ + explicit Vector_d(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \ + : Rep(CVBase()( \ + BOOST_PP_ENUM_PARAMS(N,t))) {} \ + \ + template<class F,BOOST_PP_ENUM_PARAMS(N,class T)> \ + Vector_d(Eval_functor,F const& f,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \ + : Rep(f(BOOST_PP_ENUM_PARAMS(N,t))) {} + /* + template<BOOST_PP_ENUM_PARAMS(N,class T)> \ + Vector_d(Eval_functor,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \ + : Rep(Eval_functor(), BOOST_PP_ENUM_PARAMS(N,t)) {} + */ + + BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_) +#undef CGAL_CODE + + // this one should be implicit + Vector_d(Null_vector const& v) + : Rep(CVBase()(v)) {} + +#endif + + typename boost::result_of<CCBase(Rep,int)>::type cartesian(int i)const{ + return CCBase()(rep(),i); + } + + typename boost::result_of<CCBase(Rep,int)>::type operator[](int i)const{ + return CCBase()(rep(),i); + } + + typename boost::result_of<CVI(Rep,Begin_tag)>::type cartesian_begin()const{ + return CVI()(rep(),Begin_tag()); + } + + typename boost::result_of<CVI(Rep,End_tag)>::type cartesian_end()const{ + return CVI()(rep(),End_tag()); + } + + Vector_d operator-() const + { + return typename Get_functor<R, Opposite_vector_tag>::type()(*this); + } + + /* + Direction_d direction() const + { + return R().construct_direction_d_object()(*this); + } + + Vector_d transform(const Aff_transformation_d &t) const + { + return t.transform(*this); + } + + Vector_d operator/(const RT& c) const + { + return R().construct_divided_vector_d_object()(*this,c); + } + + Vector_d operator/(const typename First_if_different<FT_,RT>::Type & c) const + { + return R().construct_divided_vector_d_object()(*this,c); + } + + typename Qualified_result_of<typename R::Compute_x_3, Vector_3>::type + x() const + { + return R().compute_x_3_object()(*this); + } + + typename Qualified_result_of<typename R::Compute_y_3, Vector_3>::type + y() const + { + return R().compute_y_3_object()(*this); + } + + typename Qualified_result_of<typename R::Compute_z_3, Vector_3>::type + z() const + { + return R().compute_z_3_object()(*this); + } + + typename Qualified_result_of<typename R::Compute_hx_3, Vector_3>::type + hx() const + { + return R().compute_hx_3_object()(*this); + } + + typename Qualified_result_of<typename R::Compute_hy_3, Vector_3>::type + hy() const + { + return R().compute_hy_3_object()(*this); + } + + typename Qualified_result_of<typename R::Compute_hz_3, Vector_3>::type + hz() const + { + return R().compute_hz_3_object()(*this); + } + + typename Qualified_result_of<typename R::Compute_hw_3, Vector_3>::type + hw() const + { + return R().compute_hw_3_object()(*this); + } + + typename Qualified_result_of<typename R::Compute_x_3, Vector_3>::type + cartesian(int i) const + { + CGAL_kernel_precondition( (i == 0) || (i == 1) || (i == 2) ); + if (i==0) return x(); + if (i==1) return y(); + return z(); + } + + typename Qualified_result_of<typename R::Compute_hw_3, Vector_3>::type + homogeneous(int i) const + { + CGAL_kernel_precondition( (i >= 0) || (i <= 3) ); + if (i==0) return hx(); + if (i==1) return hy(); + if (i==2) return hz(); + return hw(); + } + + int dimension() const // bad idea? + { + return rep.dimension(); + } +*/ + typename boost::result_of<SLBase(Rep)>::type squared_length()const{ + return SLBase()(rep()); + } +}; +#if 0 +template <class R_> Vector_d<R_>::Vector_d(Vector_d &)=default; +#endif + +//TODO: IO + +template <class R_> +Vector_d<R_> operator+(const Vector_d<R_>& v,const Vector_d<R_>& w) +{ + return typename Get_functor<R_, Sum_of_vectors_tag>::type()(v,w); +} + +template <class R_> +Vector_d<R_> operator-(const Vector_d<R_>& v,const Vector_d<R_>& w) +{ + return typename Get_functor<R_, Difference_of_vectors_tag>::type()(v,w); +} + +} //namespace Wrap +} //namespace CGAL + +#endif // CGAL_WRAPPER_VECTOR_D_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Weighted_point_d.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Weighted_point_d.h new file mode 100644 index 00000000..877eea21 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/Wrapper/Weighted_point_d.h @@ -0,0 +1,129 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_WRAPPER_WEIGHTED_POINT_D_H +#define CGAL_WRAPPER_WEIGHTED_POINT_D_H + +#include <CGAL/representation_tags.h> +#include <boost/static_assert.hpp> +#include <boost/type_traits.hpp> +#include <CGAL/Kernel/Return_base_tag.h> +#include <CGAL/Dimension.h> +#ifndef CGAL_CXX11 +#include <boost/preprocessor/repetition.hpp> +#endif +#include <boost/utility/result_of.hpp> + +namespace CGAL { +namespace Wrap { + +template <class R_> +class Weighted_point_d : public Get_type<typename R_::Kernel_base, Weighted_point_tag>::type +{ + typedef typename Get_type<R_, FT_tag>::type FT_; + typedef typename R_::Kernel_base Kbase; + typedef typename Get_type<R_, Point_tag>::type Point_; + typedef typename Get_functor<Kbase, Construct_ttag<Weighted_point_tag> >::type CWPBase; + typedef typename Get_functor<Kbase, Point_drop_weight_tag>::type PDWBase; + typedef typename Get_functor<Kbase, Point_weight_tag>::type PWBase; + + typedef Weighted_point_d Self; + BOOST_STATIC_ASSERT((boost::is_same<Self, typename Get_type<R_, Weighted_point_tag>::type>::value)); + +public: + + typedef Tag_true Is_wrapper; + typedef typename R_::Default_ambient_dimension Ambient_dimension; + typedef Dimension_tag<0> Feature_dimension; + + typedef typename Get_type<Kbase, Weighted_point_tag>::type Rep; + + const Rep& rep() const + { + return *this; + } + + Rep& rep() + { + return *this; + } + + typedef R_ R; + +#ifdef CGAL_CXX11 + template<class...U,class=typename std::enable_if<!std::is_same<std::tuple<typename std::decay<U>::type...>,std::tuple<Weighted_point_d> >::value>::type> explicit Weighted_point_d(U&&...u) + : Rep(CWPBase()(std::forward<U>(u)...)){} + +// // called from Construct_point_d +// template<class...U> explicit Point_d(Eval_functor&&,U&&...u) +// : Rep(Eval_functor(), std::forward<U>(u)...){} + template<class F,class...U> explicit Weighted_point_d(Eval_functor&&,F&&f,U&&...u) + : Rep(std::forward<F>(f)(std::forward<U>(u)...)){} + +#if 0 + // the new standard may make this necessary + Point_d(Point_d const&)=default; + Point_d(Point_d &);//=default; + Point_d(Point_d &&)=default; +#endif + + // try not to use these + Weighted_point_d(Rep const& v) : Rep(v) {} + Weighted_point_d(Rep& v) : Rep(static_cast<Rep const&>(v)) {} + Weighted_point_d(Rep&& v) : Rep(std::move(v)) {} + +#else + + Weighted_point_d() : Rep(CWPBase()()) {} + + Weighted_point_d(Rep const& v) : Rep(v) {} // try not to use it + +#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class T)> \ + explicit Weighted_point_d(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \ + : Rep(CWPBase()( \ + BOOST_PP_ENUM_PARAMS(N,t))) {} \ + \ + template<class F,BOOST_PP_ENUM_PARAMS(N,class T)> \ + Weighted_point_d(Eval_functor,F const& f,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \ + : Rep(f(BOOST_PP_ENUM_PARAMS(N,t))) {} + /* + template<BOOST_PP_ENUM_PARAMS(N,class T)> \ + Point_d(Eval_functor,BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t)) \ + : Rep(Eval_functor(), BOOST_PP_ENUM_PARAMS(N,t)) {} + */ + + BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_) +#undef CGAL_CODE + +#endif + + //TODO: use references? + Point_ point()const{ + return Point_(Eval_functor(),PDWBase(),rep()); + } + FT_ weight()const{ + return PWBase()(rep()); + } + +}; + +} //namespace Wrap +} //namespace CGAL + +#endif // CGAL_WRAPPER_SPHERE_D_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/function_objects_cartesian.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/function_objects_cartesian.h new file mode 100644 index 00000000..5a132ad2 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/function_objects_cartesian.h @@ -0,0 +1,1355 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_KERNEL_D_FUNCTION_OBJECTS_CARTESIAN_H +#define CGAL_KERNEL_D_FUNCTION_OBJECTS_CARTESIAN_H + +#include <CGAL/NewKernel_d/utils.h> +#include <CGAL/Dimension.h> +#include <CGAL/Uncertain.h> +#include <CGAL/NewKernel_d/store_kernel.h> +#include <CGAL/is_iterator.h> +#include <CGAL/iterator_from_indices.h> +#include <CGAL/number_utils.h> +#include <CGAL/Kernel/Return_base_tag.h> +#include <CGAL/transforming_iterator.h> +#include <CGAL/transforming_pair_iterator.h> +#include <CGAL/NewKernel_d/functor_tags.h> +#include <CGAL/NewKernel_d/functor_properties.h> +#include <CGAL/predicates/sign_of_determinant.h> +#include <functional> +#ifdef CGAL_CXX11 +#include <initializer_list> +#endif + +namespace CGAL { +namespace CartesianDKernelFunctors { +namespace internal { +template<class,int> struct Dimension_at_most { enum { value = false }; }; +template<int a,int b> struct Dimension_at_most<Dimension_tag<a>,b> { + enum { value = (a <= b) }; +}; +} + +template<class R_,class D_=typename R_::Default_ambient_dimension,bool=internal::Dimension_at_most<D_,6>::value> struct Orientation_of_points : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Orientation_of_points) + typedef R_ R; + typedef typename Get_type<R, Point_tag>::type Point; + typedef typename Get_type<R, Orientation_tag>::type result_type; + typedef typename R::LA::Square_matrix Matrix; + + template<class Iter> + result_type operator()(Iter f, Iter e)const{ + typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type c(this->kernel()); + typename Get_functor<R, Point_dimension_tag>::type pd(this->kernel()); + Point const& p0=*f++; + int d=pd(p0); + Matrix m(d,d); + // FIXME: this writes the vector coordinates in lines ? check all the other uses in this file, this may be wrong for some. + for(int i=0;f!=e;++f,++i) { + Point const& p=*f; + for(int j=0;j<d;++j){ + m(i,j)=c(p,j)-c(p0,j); + // should we cache the coordinates of p0 in case they are computed? + } + } + return R::LA::sign_of_determinant(CGAL_MOVE(m)); + } + +#ifdef CGAL_CXX11 + // Since the dimension is at least 2, there are at least 3 points and no ambiguity with iterators. + // template <class...U,class=typename std::enable_if<std::is_same<Dimension_tag<sizeof...(U)-1>,typename R::Default_ambient_dimension>::value>::type> + template <class...U,class=typename std::enable_if<(sizeof...(U)>=3)>::type> + result_type operator()(U&&...u) const { + return operator()({std::forward<U>(u)...}); + } + + template <class P> + result_type operator()(std::initializer_list<P> l) const { + return operator()(l.begin(),l.end()); + } +#else + //should we make it template to avoid instantiation for wrong dim? + //or iterate outside the class? +#define CGAL_VAR(Z,J,I) m(I,J)=c(p##I,J)-c(x,J); +#define CGAL_VAR2(Z,I,N) BOOST_PP_REPEAT(N,CGAL_VAR,I) +#define CGAL_CODE(Z,N,_) \ + result_type operator()(Point const&x, BOOST_PP_ENUM_PARAMS(N,Point const&p)) const { \ + typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type c(this->kernel()); \ + Matrix m(N,N); \ + BOOST_PP_REPEAT(N,CGAL_VAR2,N) \ + return R::LA::sign_of_determinant(CGAL_MOVE(m)); \ + } + +BOOST_PP_REPEAT_FROM_TO(7, 10, CGAL_CODE, _ ) + // No need to do it for <=6, since that uses a different code path +#undef CGAL_CODE +#undef CGAL_VAR2 +#undef CGAL_VAR +#endif +}; + +#ifdef CGAL_CXX11 +template<class R_,int d> struct Orientation_of_points<R_,Dimension_tag<d>,true> : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Orientation_of_points) + typedef R_ R; + typedef typename Get_type<R, RT_tag>::type RT; + typedef typename Get_type<R, Point_tag>::type Point; + typedef typename Get_type<R, Orientation_tag>::type result_type; + template<class>struct Help; + template<int...I>struct Help<Indices<I...> > { + template<class C,class P,class T> result_type operator()(C const&c,P const&x,T&&t)const{ + return sign_of_determinant<RT>(c(std::get<I/d>(t),I%d)-c(x,I%d)...); + } + }; + template<class P0,class...P> result_type operator()(P0 const&x,P&&...p)const{ + static_assert(d==sizeof...(P),"Wrong number of arguments"); + typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type c(this->kernel()); + return Help<typename N_increasing_indices<d*d>::type>()(c,x,std::forward_as_tuple(std::forward<P>(p)...)); + } + + + template<int N,class Iter,class...U> result_type help2(Dimension_tag<N>, Iter f, Iter const&e, U&&...u)const{ + auto const&p=*f; + return help2(Dimension_tag<N-1>(),++f,e,std::forward<U>(u)...,p); + } + template<class Iter,class...U> result_type help2(Dimension_tag<0>, Iter CGAL_assertion_code(f), Iter const& CGAL_assertion_code(e), U&&...u)const{ + CGAL_assertion(f==e); + return operator()(std::forward<U>(u)...); + } + template<class Iter> + result_type operator()(Iter f, Iter e)const{ + return help2(Dimension_tag<d+1>(),f,e); + } +}; +#else +#define CGAL_VAR(Z,J,I) c(p##I,J)-x##J +#define CGAL_VAR2(Z,I,N) BOOST_PP_ENUM(N,CGAL_VAR,I) +#define CGAL_VAR3(Z,N,_) Point const&p##N=*++f; +#define CGAL_VAR4(Z,N,_) RT const&x##N=c(x,N); +#define CGAL_CODE(Z,N,_) \ +template<class R_> struct Orientation_of_points<R_,Dimension_tag<N>,true> : private Store_kernel<R_> { \ + CGAL_FUNCTOR_INIT_STORE(Orientation_of_points) \ + typedef R_ R; \ + typedef typename Get_type<R, RT_tag>::type RT; \ + typedef typename Get_type<R, Point_tag>::type Point; \ + typedef typename Get_type<R, Orientation_tag>::type result_type; \ + result_type operator()(Point const&x, BOOST_PP_ENUM_PARAMS(N,Point const&p)) const { \ + typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type c(this->kernel()); \ + BOOST_PP_REPEAT(N,CGAL_VAR4,) \ + return sign_of_determinant<RT>(BOOST_PP_ENUM(N,CGAL_VAR2,N)); \ + } \ + template<class Iter> \ + result_type operator()(Iter f, Iter CGAL_assertion_code(e))const{ \ + Point const&x=*f; \ + BOOST_PP_REPEAT(N,CGAL_VAR3,) \ + CGAL_assertion(++f==e); \ + return operator()(x,BOOST_PP_ENUM_PARAMS(N,p)); \ + } \ +}; + + BOOST_PP_REPEAT_FROM_TO(2, 7, CGAL_CODE, _ ) +#undef CGAL_CODE +#undef CGAL_VAR4 +#undef CGAL_VAR3 +#undef CGAL_VAR2 +#undef CGAL_VAR + +#endif + +template<class R_> struct Orientation_of_points<R_,Dimension_tag<1>,true> : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Orientation_of_points) + typedef R_ R; + typedef typename Get_type<R, RT_tag>::type RT; + typedef typename Get_type<R, Point_tag>::type Point; + typedef typename Get_type<R, Orientation_tag>::type result_type; + result_type operator()(Point const&x, Point const&y) const { + typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type c(this->kernel()); + // No sign_of_determinant(RT) :-( + return CGAL::compare(c(y,0),c(x,0)); + } + template<class Iter> + result_type operator()(Iter f, Iter CGAL_assertion_code(e))const{ + Point const&x=*f; + Point const&y=*++f; + CGAL_assertion(++f==e); + return operator()(x,y); + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Orientation_of_points_tag,(CartesianDKernelFunctors::Orientation_of_points<K>),(Point_tag),(Point_dimension_tag,Compute_point_cartesian_coordinate_tag)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Orientation_of_vectors : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Orientation_of_vectors) + typedef R_ R; + typedef typename Get_type<R, Vector_tag>::type Vector; + typedef typename Get_type<R, Orientation_tag>::type result_type; + typedef typename R::LA::Square_matrix Matrix; + + template<class Iter> + result_type operator()(Iter f, Iter e)const{ + typename Get_functor<R, Compute_vector_cartesian_coordinate_tag>::type c(this->kernel()); + typename Get_functor<R, Point_dimension_tag>::type vd(this->kernel()); + // FIXME: Uh? Using it on a vector ?! + Vector const& v0=*f; + int d=vd(v0); + Matrix m(d,d); + for(int j=0;j<d;++j){ + m(0,j)=c(v0,j); + } + for(int i=1;++f!=e;++i) { + Vector const& v=*f; + for(int j=0;j<d;++j){ + m(i,j)=c(v,j); + } + } + return R::LA::sign_of_determinant(CGAL_MOVE(m)); + } + +#ifdef CGAL_CXX11 + template <class...U,class=typename std::enable_if<(sizeof...(U)>=3)>::type> + result_type operator()(U&&...u) const { + return operator()({std::forward<U>(u)...}); + } + + template <class V> + result_type operator()(std::initializer_list<V> l) const { + return operator()(l.begin(),l.end()); + } +#else + //TODO +#endif +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Orientation_of_vectors_tag,(CartesianDKernelFunctors::Orientation_of_vectors<K>),(Vector_tag),(Point_dimension_tag,Compute_vector_cartesian_coordinate_tag)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Linear_rank : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Linear_rank) + typedef R_ R; + typedef typename Get_type<R, Vector_tag>::type Vector; + // Computing a sensible Uncertain<int> is not worth it + typedef int result_type; + typedef typename R::LA::Dynamic_matrix Matrix; + + template<class Iter> + result_type operator()(Iter f, Iter e)const{ + typename Get_functor<R, Compute_vector_cartesian_coordinate_tag>::type c(this->kernel()); + typename Get_functor<R, Point_dimension_tag>::type vd(this->kernel()); + std::ptrdiff_t n=std::distance(f,e); + if (n==0) return 0; + Vector const& v0 = *f; + // FIXME: Uh? Using it on a vector ?! + int d=vd(v0); + Matrix m(d,n); + for(int j=0;j<d;++j){ + m(j,0)=c(v0,j); + } + for(int i=1; ++f!=e; ++i){ + Vector const& v = *f; + for(int j=0;j<d;++j){ + m(j,i)=c(v,j); + } + } + return R::LA::rank(CGAL_MOVE(m)); + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Linear_rank_tag,(CartesianDKernelFunctors::Linear_rank<K>),(Vector_tag),(Point_dimension_tag,Compute_vector_cartesian_coordinate_tag)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Linearly_independent : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Linearly_independent) + typedef R_ R; + typedef typename Get_type<R, Bool_tag>::type result_type; + + template<class Iter> + result_type operator()(Iter f, Iter e)const{ + typename Get_functor<R, Point_dimension_tag>::type vd(this->kernel()); + std::ptrdiff_t n=std::distance(f,e); + // FIXME: Uh? Using it on a vector ?! + int d=vd(*f); + if (n>d) return false; + typename Get_functor<R, Linear_rank_tag>::type lr(this->kernel()); + return lr(f,e) == n; + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Linearly_independent_tag,(CartesianDKernelFunctors::Linearly_independent<K>),(Vector_tag),(Point_dimension_tag,Linear_rank_tag)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Contained_in_linear_hull : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Contained_in_linear_hull) + typedef R_ R; + typedef typename Get_type<R, Vector_tag>::type Vector; + // Computing a sensible Uncertain<bool> is not worth it + typedef bool result_type; + typedef typename R::LA::Dynamic_matrix Matrix; + + template<class Iter,class V> + result_type operator()(Iter f, Iter e,V const&w)const{ + typename Get_functor<R, Compute_vector_cartesian_coordinate_tag>::type c(this->kernel()); + typename Get_functor<R, Point_dimension_tag>::type vd(this->kernel()); + std::ptrdiff_t n=std::distance(f,e); + if (n==0) return false; + // FIXME: Uh? Using it on a vector ?! + int d=vd(w); + Matrix m(d,n+1); + for(int i=0; f!=e; ++f,++i){ + Vector const& v = *f; + for(int j=0;j<d;++j){ + m(j,i)=c(v,j); + } + } + for(int j=0;j<d;++j){ + m(j,n)=c(w,j); + } + int r1 = R::LA::rank(m); + // FIXME: Don't use eigen directly, go through an interface in LA... + m.conservativeResize(Eigen::NoChange, n); + int r2 = R::LA::rank(CGAL_MOVE(m)); + return r1 == r2; + // TODO: This is very very far from optimal... + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Contained_in_linear_hull_tag,(CartesianDKernelFunctors::Contained_in_linear_hull<K>),(Vector_tag),(Point_dimension_tag,Compute_vector_cartesian_coordinate_tag)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Affine_rank : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Affine_rank) + typedef R_ R; + typedef typename Get_type<R, Point_tag>::type Point; + // Computing a sensible Uncertain<int> is not worth it + typedef int result_type; + typedef typename R::LA::Dynamic_matrix Matrix; + + template<class Iter> + result_type operator()(Iter f, Iter e)const{ + typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type c(this->kernel()); + typename Get_functor<R, Point_dimension_tag>::type pd(this->kernel()); + int n=(int)std::distance(f,e); + if (--n<=0) return n; + Point const& p0 = *f; + int d=pd(p0); + Matrix m(d,n); + for(int i=0; ++f!=e; ++i){ + Point const& p = *f; + for(int j=0;j<d;++j){ + m(j,i)=c(p,j)-c(p0,j); + // TODO: cache p0[j] in case it is computed? + } + } + return R::LA::rank(CGAL_MOVE(m)); + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Affine_rank_tag,(CartesianDKernelFunctors::Affine_rank<K>),(Point_tag),(Point_dimension_tag,Compute_point_cartesian_coordinate_tag)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Affinely_independent : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Affinely_independent) + typedef R_ R; + typedef typename Get_type<R, Bool_tag>::type result_type; + + template<class Iter> + result_type operator()(Iter f, Iter e)const{ + typename Get_functor<R, Point_dimension_tag>::type pd(this->kernel()); + std::ptrdiff_t n=std::distance(f,e); + int d=pd(*f); + if (--n>d) return false; + typename Get_functor<R, Affine_rank_tag>::type ar(this->kernel()); + return ar(f,e) == n; + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Affinely_independent_tag,(CartesianDKernelFunctors::Affinely_independent<K>),(Point_tag),(Point_dimension_tag,Affine_rank_tag)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Contained_in_simplex : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Contained_in_simplex) + typedef R_ R; + typedef typename Get_type<R, Point_tag>::type Point; + // Computing a sensible Uncertain<*> is not worth it + // typedef typename Get_type<R, Boolean_tag>::type result_type; + typedef bool result_type; + typedef typename Increment_dimension<typename R::Default_ambient_dimension>::type D1; + typedef typename Increment_dimension<typename R::Max_ambient_dimension>::type D2; + typedef typename R::LA::template Rebind_dimension<D1,D2>::Other LA; + typedef typename LA::Dynamic_matrix Matrix; + typedef typename LA::Dynamic_vector DynVec; + typedef typename LA::Vector Vec; + + template<class Iter, class P> + result_type operator()(Iter f, Iter e, P const&q)const{ + typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type c(this->kernel()); + typename Get_functor<R, Point_dimension_tag>::type pd(this->kernel()); + std::ptrdiff_t n=std::distance(f,e); + if (n==0) return false; + int d=pd(q); + Matrix m(d+1,n); + DynVec a(n); + // FIXME: Should use the proper vector constructor (Iterator_and_last) + Vec b(d+1); + for(int j=0;j<d;++j) b[j]=c(q,j); + b[d]=1; + + for(int i=0; f!=e; ++i,++f){ + Point const& p = *f; + for(int j=0;j<d;++j){ + m(j,i)=c(p,j); + } + m(d,i)=1; + } + // If the simplex has full dimension, there must be a solution, only the signs need to be checked. + if (n == d+1) + LA::solve(a,CGAL_MOVE(m),CGAL_MOVE(b)); + else if (!LA::solve_and_check(a,CGAL_MOVE(m),CGAL_MOVE(b))) + return false; + for(int i=0;i<n;++i){ + if (a[i]<0) return false; + } + return true; + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Contained_in_simplex_tag,(CartesianDKernelFunctors::Contained_in_simplex<K>),(Point_tag),(Point_dimension_tag,Compute_point_cartesian_coordinate_tag)); + +namespace CartesianDKernelFunctors { + namespace internal { + template<class Ref_> + struct Matrix_col_access { + typedef Ref_ result_type; + int col; + Matrix_col_access(int r):col(r){} + template<class Mat> Ref_ operator()(Mat const& m, std::ptrdiff_t row)const{ + return m(row,col); + } + }; + } +template<class R_> struct Linear_base : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Linear_base) + typedef R_ R; + typedef typename Get_type<R, Vector_tag>::type Vector; + typedef typename Get_type<R, FT_tag>::type FT; + typedef void result_type; + typedef typename R::LA::Dynamic_matrix Matrix; + + template<class Iter, class Oter> + result_type operator()(Iter f, Iter e, Oter&o)const{ + typename Get_functor<R, Compute_vector_cartesian_coordinate_tag>::type c(this->kernel()); + typename Get_functor<R, Point_dimension_tag>::type vd(this->kernel()); + typename Get_functor<R, Construct_ttag<Vector_tag> >::type cv(this->kernel()); + std::ptrdiff_t n=std::distance(f,e); + if (n==0) return; + Vector const& v0 = *f; + // FIXME: Uh? Using it on a vector ?! + int d=vd(v0); + Matrix m(d,n); + for(int j=0;j<d;++j){ + m(0,j)=c(v0,j); + } + for(int i=1; ++f!=e; ++i){ + Vector const& v = *f; + for(int j=0;j<d;++j){ + m(i,j)=c(v,j); + } + } + Matrix b = R::LA::basis(CGAL_MOVE(m)); + for(int i=0; i < R::LA::columns(b); ++i){ + //*o++ = Vector(b.col(i)); + typedef +#ifdef CGAL_CXX11 + decltype(std::declval<const Matrix>()(0,0)) +#else + FT +#endif + Ref; + typedef Iterator_from_indices<Matrix, FT, Ref, + internal::Matrix_col_access<Ref> > IFI; + *o++ = cv(IFI(b,0,i),IFI(b,d,i)); + } + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Linear_base_tag,(CartesianDKernelFunctors::Linear_base<K>),(Vector_tag),(Point_dimension_tag,Compute_vector_cartesian_coordinate_tag)); + +#if 0 +namespace CartesianDKernelFunctors { +template<class R_,bool=boost::is_same<typename R_::Point,typename R_::Vector>::value> struct Orientation : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Orientation) + typedef R_ R; + typedef typename Get_type<R, Vector_tag>::type Vector; + typedef typename Get_type<R, Point_tag>::type Point; + typedef typename Get_type<R, Orientation_tag>::type result_type; + typedef typename Get_functor<R, Orientation_of_points_tag>::type OP; + typedef typename Get_functor<R, Orientation_of_vectors_tag>::type OV; + + //FIXME!!! + //when Point and Vector are distinct types, the dispatch should be made + //in a way that doesn't instantiate a conversion from Point to Vector + template<class Iter> + result_type operator()(Iter const&f, Iter const& e)const{ + typename Get_functor<R, Point_dimension_tag>::type pd(this->kernel()); + typename std::iterator_traits<Iter>::difference_type d=std::distance(f,e); + int dim=pd(*f); // BAD + if(d==dim) return OV(this->kernel())(f,e); + CGAL_assertion(d==dim+1); + return OP(this->kernel())(f,e); + } + //TODO: version that takes objects directly instead of iterators +}; + +template<class R_> struct Orientation<R_,false> : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Orientation) + typedef R_ R; + typedef typename Get_type<R, Vector_tag>::type Vector; + typedef typename Get_type<R, Point_tag>::type Point; + typedef typename Get_type<R, Orientation_tag>::type result_type; + typedef typename Get_functor<R, Orientation_of_points_tag>::type OP; + typedef typename Get_functor<R, Orientation_of_vectors_tag>::type OV; + typedef typename R::LA::Square_matrix Matrix; + + //FIXME!!! + //when Point and Vector are distinct types, the dispatch should be made + //in a way that doesn't instantiate a conversion from Point to Vector + template<class Iter> + typename boost::enable_if<is_iterator_to<Iter,Point>,result_type>::type + operator()(Iter const&f, Iter const& e)const{ + return OP(this->kernel())(f,e); + } + template<class Iter> + typename boost::enable_if<is_iterator_to<Iter,Vector>,result_type>::type + operator()(Iter const&f, Iter const& e)const{ + return OV(this->kernel())(f,e); + } + //TODO: version that takes objects directly instead of iterators +}; +} +#endif + +namespace CartesianDKernelFunctors { +template<class R_> struct Power_side_of_power_sphere_raw : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Power_side_of_power_sphere_raw) + typedef R_ R; + typedef typename Get_type<R, RT_tag>::type RT; + typedef typename Get_type<R, FT_tag>::type FT; + typedef typename Get_type<R, Point_tag>::type Point; + typedef typename Get_type<R, Oriented_side_tag>::type result_type; + typedef typename Increment_dimension<typename R::Default_ambient_dimension>::type D1; + typedef typename Increment_dimension<typename R::Max_ambient_dimension>::type D2; + typedef typename R::LA::template Rebind_dimension<D1,D2>::Other LA; + typedef typename LA::Square_matrix Matrix; + + template<class IterP, class IterW, class Pt, class Wt> + result_type operator()(IterP f, IterP const& e, IterW fw, Pt const& p0, Wt const& w0) const { + typedef typename Get_functor<R, Squared_distance_to_origin_tag>::type Sqdo; + typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type c(this->kernel()); + typename Get_functor<R, Point_dimension_tag>::type pd(this->kernel()); + + int d=pd(p0); + Matrix m(d+1,d+1); + if(CGAL::Is_stored<Sqdo>::value) { + Sqdo sqdo(this->kernel()); + FT const& h0 = sqdo(p0) - w0; + for(int i=0;f!=e;++f,++fw,++i) { + Point const& p=*f; + for(int j=0;j<d;++j){ + RT const& x=c(p,j); + m(i,j)=x-c(p0,j); + } + m(i,d) = sqdo(p) - *fw - h0; + } + } else { + for(int i=0;f!=e;++f,++fw,++i) { + Point const& p=*f; + m(i,d) = w0 - *fw; + for(int j=0;j<d;++j){ + RT const& x=c(p,j); + m(i,j)=x-c(p0,j); + m(i,d)+=CGAL::square(m(i,j)); + } + } + } + if(d%2) + return -LA::sign_of_determinant(CGAL_MOVE(m)); + else + return LA::sign_of_determinant(CGAL_MOVE(m)); + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Power_side_of_power_sphere_raw_tag,(CartesianDKernelFunctors::Power_side_of_power_sphere_raw<K>),(Point_tag),(Point_dimension_tag,Squared_distance_to_origin_tag,Compute_point_cartesian_coordinate_tag)); + +// TODO: make Side_of_oriented_sphere call Power_side_of_power_sphere_raw +namespace CartesianDKernelFunctors { +template<class R_> struct Side_of_oriented_sphere : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Side_of_oriented_sphere) + typedef R_ R; + typedef typename Get_type<R, RT_tag>::type RT; + typedef typename Get_type<R, Point_tag>::type Point; + typedef typename Get_type<R, Oriented_side_tag>::type result_type; + typedef typename Increment_dimension<typename R::Default_ambient_dimension>::type D1; + typedef typename Increment_dimension<typename R::Max_ambient_dimension>::type D2; + typedef typename R::LA::template Rebind_dimension<D1,D2>::Other LA; + typedef typename LA::Square_matrix Matrix; + + template<class Iter> + result_type operator()(Iter f, Iter const& e)const{ + Point const& p0=*f++; // *--e ? + return this->operator()(f,e,p0); + } + + template<class Iter> + result_type operator()(Iter f, Iter const& e, Point const& p0) const { + typedef typename Get_functor<R, Squared_distance_to_origin_tag>::type Sqdo; + typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type c(this->kernel()); + typename Get_functor<R, Point_dimension_tag>::type pd(this->kernel()); + + int d=pd(p0); + Matrix m(d+1,d+1); + if(CGAL::Is_stored<Sqdo>::value) { + Sqdo sqdo(this->kernel()); + for(int i=0;f!=e;++f,++i) { + Point const& p=*f; + for(int j=0;j<d;++j){ + RT const& x=c(p,j); + m(i,j)=x-c(p0,j); + } + m(i,d) = sqdo(p) - sqdo(p0); + } + } else { + for(int i=0;f!=e;++f,++i) { + Point const& p=*f; + m(i,d) = 0; + for(int j=0;j<d;++j){ + RT const& x=c(p,j); + m(i,j)=x-c(p0,j); + m(i,d)+=CGAL::square(m(i,j)); + } + } + } + if(d%2) + return -LA::sign_of_determinant(CGAL_MOVE(m)); + else + return LA::sign_of_determinant(CGAL_MOVE(m)); + } + +#ifdef CGAL_CXX11 + template <class...U,class=typename std::enable_if<(sizeof...(U)>=4)>::type> + result_type operator()(U&&...u) const { + return operator()({std::forward<U>(u)...}); + } + + template <class P> + result_type operator()(std::initializer_list<P> l) const { + return operator()(l.begin(),l.end()); + } +#else + //TODO +#endif +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Side_of_oriented_sphere_tag,(CartesianDKernelFunctors::Side_of_oriented_sphere<K>),(Point_tag),(Point_dimension_tag,Squared_distance_to_origin_tag,Compute_point_cartesian_coordinate_tag)); + +namespace CartesianDKernelFunctors { +template <class R_> struct Construct_circumcenter : Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Construct_circumcenter) + typedef typename Get_type<R_, Point_tag>::type Point; + typedef Point result_type; + typedef typename Get_type<R_, FT_tag>::type FT; + template <class Iter> + result_type operator()(Iter f, Iter e)const{ + typedef typename Get_type<R_, Point_tag>::type Point; + typedef typename R_::LA LA; + typename Get_functor<R_, Compute_point_cartesian_coordinate_tag>::type c(this->kernel()); + typename Get_functor<R_, Construct_ttag<Point_tag> >::type cp(this->kernel()); + typename Get_functor<R_, Point_dimension_tag>::type pd(this->kernel()); + typename Get_functor<R_, Squared_distance_to_origin_tag>::type sdo(this->kernel()); + + Point const& p0=*f; + int d = pd(p0); + if (d+1 == std::distance(f,e)) + { + // 2*(x-y).c == x^2-y^2 + typedef typename LA::Square_matrix Matrix; + typedef typename LA::Vector Vec; + typedef typename LA::Construct_vector CVec; + FT const& n0 = sdo(p0); + Matrix m(d,d); + Vec b = typename CVec::Dimension()(d); + // Write the point coordinates in lines. + int i; + for(i=0; ++f!=e; ++i) { + Point const& p=*f; + for(int j=0;j<d;++j) { + m(i,j)=2*(c(p,j)-c(p0,j)); + b[i] = sdo(p) - n0; + } + } + CGAL_assertion (i == d); + Vec res = typename CVec::Dimension()(d);; + //std::cout << "Mat: " << m << "\n Vec: " << one << std::endl; + LA::solve(res, CGAL_MOVE(m), CGAL_MOVE(b)); + //std::cout << "Sol: " << res << std::endl; + return cp(d,LA::vector_begin(res),LA::vector_end(res)); + } + else + { + /* + * Matrix P=(p1, p2, ...) (each point as a column) + * Matrix Q=2*t(p2-p1,p3-p1, ...) (each vector as a line) + * Matrix M: QP, adding a line of 1 at the top + * Vector B: (1, p2^2-p1^2, p3^2-p1^2, ...) + * Solve ML=B, the center of the sphere is PL + * + * It would likely be faster to write P then transpose, multiply, + * etc instead of doing it by hand. + */ + // TODO: check for degenerate cases? + + typedef typename R_::Max_ambient_dimension D2; + typedef typename R_::LA::template Rebind_dimension<Dynamic_dimension_tag,D2>::Other LAd; + typedef typename LAd::Square_matrix Matrix; + typedef typename LAd::Vector Vec; + typename Get_functor<R_, Scalar_product_tag>::type sp(this->kernel()); + int k=static_cast<int>(std::distance(f,e)); + Matrix m(k,k); + Vec b(k); + Vec l(k); + int j,i=0; + for(Iter f2=f;f2!=e;++f2,++i){ + b(i)=m(i,i)=sdo(*f2); + j=0; + for(Iter f3=f;f3!=e;++f3,++j){ + m(j,i)=m(i,j)=sp(*f2,*f3); + } + } + for(i=1;i<k;++i){ + b(i)-=b(0); + for(j=0;j<k;++j){ + m(i,j)=2*(m(i,j)-m(0,j)); + } + } + for(j=0;j<k;++j) m(0,j)=1; + b(0)=1; + + LAd::solve(l,CGAL_MOVE(m),CGAL_MOVE(b)); + + typename LA::Vector center=typename LA::Construct_vector::Dimension()(d); + for(i=0;i<d;++i) center(i)=0; + j=0; + for(Iter f2=f;f2!=e;++f2,++j){ + for(i=0;i<d;++i){ + center(i)+=l(j)*c(*f2,i); + } + } + + return cp(LA::vector_begin(center),LA::vector_end(center)); + } + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Construct_circumcenter_tag,(CartesianDKernelFunctors::Construct_circumcenter<K>),(Point_tag),(Construct_ttag<Point_tag>,Compute_point_cartesian_coordinate_tag,Scalar_product_tag,Squared_distance_to_origin_tag,Point_dimension_tag)); + +namespace CartesianDKernelFunctors { +template <class R_> struct Squared_circumradius : Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Squared_circumradius) + typedef typename Get_type<R_, FT_tag>::type result_type; + template <class Iter> + result_type operator()(Iter f, Iter e)const{ + typename Get_functor<R_, Construct_circumcenter_tag>::type cc(this->kernel()); + typename Get_functor<R_, Squared_distance_tag>::type sd(this->kernel()); + return sd(cc(f, e), *f); + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Squared_circumradius_tag,(CartesianDKernelFunctors::Squared_circumradius<K>),(Point_tag),(Construct_circumcenter_tag,Squared_distance_tag)); + +namespace CartesianDKernelFunctors { +// TODO: implement it directly, it should be at least as fast as Side_of_oriented_sphere. +template<class R_> struct Side_of_bounded_sphere : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Side_of_bounded_sphere) + typedef R_ R; + typedef typename Get_type<R, Point_tag>::type Point; + typedef typename Get_type<R, Bounded_side_tag>::type result_type; + + template<class Iter> + result_type operator()(Iter f, Iter const& e) const { + Point const& p0 = *f++; // *--e ? + typename Get_functor<R, Point_dimension_tag>::type pd(this->kernel()); + //FIXME: Doesn't work for non-full dimension. + CGAL_assertion (std::distance(f,e) == pd(p0)+1); + return operator() (f, e, p0); + } + + template<class Iter> + result_type operator()(Iter const& f, Iter const& e, Point const& p0) const { + typename Get_functor<R, Side_of_oriented_sphere_tag>::type sos (this->kernel()); + typename Get_functor<R, Orientation_of_points_tag>::type op (this->kernel()); + // enum_cast is not very generic, but since this function isn't supposed to remain like this... + return enum_cast<Bounded_side> (sos (f, e, p0) * op (f, e)); + } + +#ifdef CGAL_CXX11 + template <class...U,class=typename std::enable_if<(sizeof...(U)>=4)>::type> + result_type operator()(U&&...u) const { + return operator()({std::forward<U>(u)...}); + } + + template <class P> + result_type operator()(std::initializer_list<P> l) const { + return operator()(l.begin(),l.end()); + } +#else + //TODO +#endif +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Side_of_bounded_sphere_tag,(CartesianDKernelFunctors::Side_of_bounded_sphere<K>),(Point_tag),(Side_of_oriented_sphere_tag,Orientation_of_points_tag)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Side_of_bounded_circumsphere : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Side_of_bounded_circumsphere) + typedef typename Get_type<R_, Bounded_side_tag>::type result_type; + + template<class Iter, class P> + result_type operator()(Iter f, Iter const& e, P const& p0) const { + // TODO: Special case when the dimension is full. + typename Get_functor<R_, Construct_circumcenter_tag>::type cc(this->kernel()); + typename Get_functor<R_, Compare_distance_tag>::type cd(this->kernel()); + + return enum_cast<Bounded_side>(cd(cc(f, e), *f, p0)); + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Side_of_bounded_circumsphere_tag,(CartesianDKernelFunctors::Side_of_bounded_circumsphere<K>),(Point_tag),(Squared_distance_tag,Construct_circumcenter_tag)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Point_to_vector : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Point_to_vector) + typedef R_ R; + typedef typename Get_type<R, RT_tag>::type RT; + typedef typename Get_type<R, Vector_tag>::type Vector; + typedef typename Get_type<R, Point_tag>::type Point; + typedef typename Get_functor<R, Construct_ttag<Vector_tag> >::type CV; + typedef typename Get_functor<R, Construct_ttag<Point_cartesian_const_iterator_tag> >::type CI; + typedef Vector result_type; + typedef Point argument_type; + result_type operator()(argument_type const&v)const{ + CI ci(this->kernel()); + return CV(this->kernel())(ci(v,Begin_tag()),ci(v,End_tag())); + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Point_to_vector_tag,(CartesianDKernelFunctors::Point_to_vector<K>),(Point_tag,Vector_tag),(Construct_ttag<Vector_tag>, Construct_ttag<Point_cartesian_const_iterator_tag>)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Vector_to_point : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Vector_to_point) + typedef R_ R; + typedef typename Get_type<R, RT_tag>::type RT; + typedef typename Get_type<R, Vector_tag>::type Vector; + typedef typename Get_type<R, Point_tag>::type Point; + typedef typename Get_functor<R, Construct_ttag<Point_tag> >::type CP; + typedef typename Get_functor<R, Construct_ttag<Vector_cartesian_const_iterator_tag> >::type CI; + typedef Point result_type; + typedef Vector argument_type; + result_type operator()(argument_type const&v)const{ + CI ci(this->kernel()); + return CP(this->kernel())(ci(v,Begin_tag()),ci(v,End_tag())); + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Vector_to_point_tag,(CartesianDKernelFunctors::Vector_to_point<K>),(Point_tag,Vector_tag),(Construct_ttag<Point_tag>, Construct_ttag<Vector_cartesian_const_iterator_tag>)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Opposite_vector : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Opposite_vector) + typedef R_ R; + typedef typename Get_type<R, RT_tag>::type RT; + typedef typename Get_type<R, Vector_tag>::type Vector; + typedef typename Get_functor<R, Construct_ttag<Vector_tag> >::type CV; + typedef typename Get_functor<R, Construct_ttag<Vector_cartesian_const_iterator_tag> >::type CI; + typedef Vector result_type; + typedef Vector argument_type; + result_type operator()(Vector const&v)const{ + CI ci(this->kernel()); + return CV(this->kernel())(make_transforming_iterator(ci(v,Begin_tag()),std::negate<RT>()),make_transforming_iterator(ci(v,End_tag()),std::negate<RT>())); + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Opposite_vector_tag,(CartesianDKernelFunctors::Opposite_vector<K>),(Vector_tag),(Construct_ttag<Vector_tag>, Construct_ttag<Vector_cartesian_const_iterator_tag>)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Scaled_vector : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Scaled_vector) + typedef R_ R; + typedef typename Get_type<R, FT_tag>::type FT; + typedef typename Get_type<R, Vector_tag>::type Vector; + typedef typename Get_functor<R, Construct_ttag<Vector_tag> >::type CV; + typedef typename Get_functor<R, Construct_ttag<Vector_cartesian_const_iterator_tag> >::type CI; + typedef Vector result_type; + typedef Vector first_argument_type; + typedef FT second_argument_type; + result_type operator()(Vector const&v,FT const& s)const{ + CI ci(this->kernel()); + return CV(this->kernel())(make_transforming_iterator(ci(v,Begin_tag()),Scale<FT>(s)),make_transforming_iterator(ci(v,End_tag()),Scale<FT>(s))); + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Scaled_vector_tag,(CartesianDKernelFunctors::Scaled_vector<K>),(Vector_tag),(Construct_ttag<Vector_tag>, Construct_ttag<Vector_cartesian_const_iterator_tag>)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Sum_of_vectors : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Sum_of_vectors) + typedef R_ R; + typedef typename Get_type<R, RT_tag>::type RT; + typedef typename Get_type<R, Vector_tag>::type Vector; + typedef typename Get_functor<R, Construct_ttag<Vector_tag> >::type CV; + typedef typename Get_functor<R, Construct_ttag<Vector_cartesian_const_iterator_tag> >::type CI; + typedef Vector result_type; + typedef Vector first_argument_type; + typedef Vector second_argument_type; + result_type operator()(Vector const&a, Vector const&b)const{ + CI ci(this->kernel()); + return CV(this->kernel())(make_transforming_pair_iterator(ci(a,Begin_tag()),ci(b,Begin_tag()),std::plus<RT>()),make_transforming_pair_iterator(ci(a,End_tag()),ci(b,End_tag()),std::plus<RT>())); + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Sum_of_vectors_tag,(CartesianDKernelFunctors::Sum_of_vectors<K>),(Vector_tag),(Construct_ttag<Vector_tag>, Construct_ttag<Vector_cartesian_const_iterator_tag>)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Difference_of_vectors : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Difference_of_vectors) + typedef R_ R; + typedef typename Get_type<R, RT_tag>::type RT; + typedef typename Get_type<R, Vector_tag>::type Vector; + typedef typename Get_functor<R, Construct_ttag<Vector_tag> >::type CV; + typedef typename Get_functor<R, Construct_ttag<Vector_cartesian_const_iterator_tag> >::type CI; + typedef Vector result_type; + typedef Vector first_argument_type; + typedef Vector second_argument_type; + result_type operator()(Vector const&a, Vector const&b)const{ + CI ci(this->kernel()); + return CV(this->kernel())(make_transforming_pair_iterator(ci(a,Begin_tag()),ci(b,Begin_tag()),std::minus<RT>()),make_transforming_pair_iterator(ci(a,End_tag()),ci(b,End_tag()),std::minus<RT>())); + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Difference_of_vectors_tag,(CartesianDKernelFunctors::Difference_of_vectors<K>),(Vector_tag),(Construct_ttag<Vector_tag>, Construct_ttag<Vector_cartesian_const_iterator_tag>)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Translated_point : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Translated_point) + typedef R_ R; + typedef typename Get_type<R, RT_tag>::type RT; + typedef typename Get_type<R, Vector_tag>::type Vector; + typedef typename Get_type<R, Point_tag>::type Point; + typedef typename Get_functor<R, Construct_ttag<Point_tag> >::type CP; + typedef typename Get_functor<R, Construct_ttag<Vector_cartesian_const_iterator_tag> >::type CVI; + typedef typename Get_functor<R, Construct_ttag<Point_cartesian_const_iterator_tag> >::type CPI; + typedef Point result_type; + typedef Point first_argument_type; + typedef Vector second_argument_type; + result_type operator()(Point const&a, Vector const&b)const{ + CVI cvi(this->kernel()); + CPI cpi(this->kernel()); + return CP(this->kernel())(make_transforming_pair_iterator(cpi(a,Begin_tag()),cvi(b,Begin_tag()),std::plus<RT>()),make_transforming_pair_iterator(cpi(a,End_tag()),cvi(b,End_tag()),std::plus<RT>())); + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Translated_point_tag,(CartesianDKernelFunctors::Translated_point<K>),(Point_tag, Vector_tag),(Construct_ttag<Point_tag>, Construct_ttag<Vector_cartesian_const_iterator_tag>, Construct_ttag<Point_cartesian_const_iterator_tag>)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Difference_of_points : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Difference_of_points) + typedef R_ R; + typedef typename Get_type<R, RT_tag>::type RT; + typedef typename Get_type<R, Point_tag>::type Point; + typedef typename Get_type<R, Vector_tag>::type Vector; + typedef typename Get_functor<R, Construct_ttag<Vector_tag> >::type CV; + typedef typename Get_functor<R, Construct_ttag<Point_cartesian_const_iterator_tag> >::type CI; + typedef Vector result_type; + typedef Point first_argument_type; + typedef Point second_argument_type; + result_type operator()(Point const&a, Point const&b)const{ + CI ci(this->kernel()); + return CV(this->kernel())(make_transforming_pair_iterator(ci(a,Begin_tag()),ci(b,Begin_tag()),std::minus<RT>()),make_transforming_pair_iterator(ci(a,End_tag()),ci(b,End_tag()),std::minus<RT>())); + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Difference_of_points_tag,(CartesianDKernelFunctors::Difference_of_points<K>),(Point_tag, Vector_tag),(Construct_ttag<Vector_tag>, Construct_ttag<Point_cartesian_const_iterator_tag>)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Midpoint : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Midpoint) + typedef R_ R; + typedef typename Get_type<R, FT_tag>::type FT; + typedef typename Get_type<R, RT_tag>::type RT; + typedef typename Get_type<R, Point_tag>::type Point; + typedef typename Get_functor<R, Construct_ttag<Point_tag> >::type CP; + typedef typename Get_functor<R, Construct_ttag<Point_cartesian_const_iterator_tag> >::type CI; + typedef Point result_type; + typedef Point first_argument_type; + typedef Point second_argument_type; + // There is a division, but it will be cast to RT afterwards anyway, so maybe we could use RT. + struct Average : std::binary_function<FT,RT,FT> { + FT operator()(FT const&a, RT const&b)const{ + return (a+b)/2; + } + }; + result_type operator()(Point const&a, Point const&b)const{ + CI ci(this->kernel()); + //Divide<FT,int> half(2); + //return CP(this->kernel())(make_transforming_iterator(make_transforming_pair_iterator(ci.begin(a),ci.begin(b),std::plus<FT>()),half),make_transforming_iterator(make_transforming_pair_iterator(ci.end(a),ci.end(b),std::plus<FT>()),half)); + return CP(this->kernel())(make_transforming_pair_iterator(ci(a,Begin_tag()),ci(b,Begin_tag()),Average()),make_transforming_pair_iterator(ci(a,End_tag()),ci(b,End_tag()),Average())); + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Midpoint_tag,(CartesianDKernelFunctors::Midpoint<K>),(Point_tag),(Construct_ttag<Point_tag>, Construct_ttag<Point_cartesian_const_iterator_tag>)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Squared_length : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Squared_length) + typedef R_ R; + typedef typename Get_type<R, RT_tag>::type RT; + typedef typename Get_type<R, Vector_tag>::type Vector; + typedef typename Get_functor<R, Construct_ttag<Vector_cartesian_const_iterator_tag> >::type CI; + typedef RT result_type; + typedef Vector argument_type; + result_type operator()(Vector const&a)const{ + CI ci(this->kernel()); + typename Algebraic_structure_traits<RT>::Square f; + // TODO: avoid this RT(0)+... + return std::accumulate(make_transforming_iterator(ci(a,Begin_tag()),f),make_transforming_iterator(ci(a,End_tag()),f),RT(0)); + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Squared_length_tag,(CartesianDKernelFunctors::Squared_length<K>),(Vector_tag),(Construct_ttag<Vector_cartesian_const_iterator_tag>)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Squared_distance_to_origin : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Squared_distance_to_origin) + typedef R_ R; + typedef typename Get_type<R, RT_tag>::type RT; + typedef typename Get_type<R, Point_tag>::type Point; + typedef typename Get_functor<R, Construct_ttag<Point_cartesian_const_iterator_tag> >::type CI; + typedef RT result_type; + typedef Point argument_type; + result_type operator()(Point const&a)const{ + CI ci(this->kernel()); + typename Algebraic_structure_traits<RT>::Square f; + // TODO: avoid this RT(0)+... + return std::accumulate(make_transforming_iterator(ci(a,Begin_tag()),f),make_transforming_iterator(ci(a,End_tag()),f),RT(0)); + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Squared_distance_to_origin_tag,(CartesianDKernelFunctors::Squared_distance_to_origin<K>),(Point_tag),(Construct_ttag<Point_cartesian_const_iterator_tag>)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Squared_distance : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Squared_distance) + typedef R_ R; + typedef typename Get_type<R, RT_tag>::type RT; + typedef typename Get_type<R, Point_tag>::type Point; + typedef typename Get_functor<R, Construct_ttag<Point_cartesian_const_iterator_tag> >::type CI; + typedef RT result_type; + typedef Point first_argument_type; + typedef Point second_argument_type; + struct Sq_diff : std::binary_function<RT,RT,RT> { + RT operator()(RT const&a, RT const&b)const{ + return CGAL::square(a-b); + } + }; + result_type operator()(Point const&a, Point const&b)const{ + CI ci(this->kernel()); + Sq_diff f; + // TODO: avoid this RT(0)+... + return std::accumulate(make_transforming_pair_iterator(ci(a,Begin_tag()),ci(b,Begin_tag()),f),make_transforming_pair_iterator(ci(a,End_tag()),ci(b,End_tag()),f),RT(0)); + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Squared_distance_tag,(CartesianDKernelFunctors::Squared_distance<K>),(Point_tag),(Construct_ttag<Point_cartesian_const_iterator_tag>)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Scalar_product : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Scalar_product) + typedef R_ R; + typedef typename Get_type<R, RT_tag>::type RT; + typedef typename Get_type<R, Vector_tag>::type Vector; + typedef typename Get_functor<R, Construct_ttag<Vector_cartesian_const_iterator_tag> >::type CI; + typedef RT result_type; + typedef Vector first_argument_type; + typedef Vector second_argument_type; + result_type operator()(Vector const&a, Vector const&b)const{ + CI ci(this->kernel()); + std::multiplies<RT> f; + // TODO: avoid this RT(0)+... + return std::accumulate( + make_transforming_pair_iterator(ci(a,Begin_tag()),ci(b,Begin_tag()),f), + make_transforming_pair_iterator(ci(a, End_tag()),ci(b, End_tag()),f), + RT(0)); + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Scalar_product_tag,(CartesianDKernelFunctors::Scalar_product<K>),(Vector_tag),(Construct_ttag<Vector_cartesian_const_iterator_tag>)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Compare_distance : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Compare_distance) + typedef R_ R; + typedef typename Get_type<R, Point_tag>::type Point; + typedef typename Get_functor<R, Squared_distance_tag>::type CSD; + typedef typename Get_type<R, Comparison_result_tag>::type result_type; + typedef Point first_argument_type; + typedef Point second_argument_type; + typedef Point third_argument_type; // why am I doing this already? + typedef Point fourth_argument_type; + result_type operator()(Point const&a, Point const&b, Point const&c)const{ + CSD csd(this->kernel()); + return CGAL_NTS compare(csd(a,b),csd(a,c)); + } + result_type operator()(Point const&a, Point const&b, Point const&c, Point const&d)const{ + CSD csd(this->kernel()); + return CGAL_NTS compare(csd(a,b),csd(c,d)); + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Compare_distance_tag,(CartesianDKernelFunctors::Compare_distance<K>),(Point_tag),(Squared_distance_tag)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Less_point_cartesian_coordinate : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Less_point_cartesian_coordinate) + typedef R_ R; + typedef typename Get_type<R, Bool_tag>::type result_type; + typedef typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type Cc; + // TODO: This is_exact thing should be reengineered. + // the goal is to have a way to tell: don't filter this + typedef typename CGAL::Is_exact<Cc> Is_exact; + + template<class V,class W,class I> + result_type operator()(V const&a, W const&b, I i)const{ + Cc c(this->kernel()); + return c(a,i)<c(b,i); + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Less_point_cartesian_coordinate_tag,(CartesianDKernelFunctors::Less_point_cartesian_coordinate<K>),(),(Compute_point_cartesian_coordinate_tag)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Compare_point_cartesian_coordinate : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Compare_point_cartesian_coordinate) + typedef R_ R; + typedef typename Get_type<R, Comparison_result_tag>::type result_type; + typedef typename Get_functor<R, Compute_point_cartesian_coordinate_tag>::type Cc; + // TODO: This is_exact thing should be reengineered. + // the goal is to have a way to tell: don't filter this + typedef typename CGAL::Is_exact<Cc> Is_exact; + + template<class V,class W,class I> + result_type operator()(V const&a, W const&b, I i)const{ + Cc c(this->kernel()); + return CGAL_NTS compare(c(a,i),c(b,i)); + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Compare_point_cartesian_coordinate_tag,(CartesianDKernelFunctors::Compare_point_cartesian_coordinate<K>),(),(Compute_point_cartesian_coordinate_tag)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Compare_lexicographically : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Compare_lexicographically) + typedef R_ R; + typedef typename Get_type<R, Comparison_result_tag>::type result_type; + typedef typename Get_functor<R, Construct_ttag<Point_cartesian_const_iterator_tag> >::type CI; + // TODO: This is_exact thing should be reengineered. + // the goal is to have a way to tell: don't filter this + typedef typename CGAL::Is_exact<CI> Is_exact; + + template<class V,class W> + result_type operator()(V const&a, W const&b)const{ + CI c(this->kernel()); +#ifdef CGAL_CXX11 + auto +#else + typename CI::result_type +#endif + a_begin=c(a,Begin_tag()), + b_begin=c(b,Begin_tag()), + a_end=c(a,End_tag()); + result_type res; + // can't we do slightly better for Uncertain<*> ? + // after res=...; if(is_uncertain(res))return indeterminate<result_type>(); + do res=CGAL_NTS compare(*a_begin++,*b_begin++); + while(a_begin!=a_end && res==EQUAL); + return res; + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Compare_lexicographically_tag,(CartesianDKernelFunctors::Compare_lexicographically<K>),(),(Construct_ttag<Point_cartesian_const_iterator_tag>)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Less_lexicographically : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Less_lexicographically) + typedef R_ R; + typedef typename Get_type<R, Bool_tag>::type result_type; + typedef typename Get_functor<R, Compare_lexicographically_tag>::type CL; + typedef typename CGAL::Is_exact<CL> Is_exact; + + template <class V, class W> + result_type operator() (V const&a, W const&b) const { + CL c (this->kernel()); + return c(a,b) < 0; + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Less_lexicographically_tag,(CartesianDKernelFunctors::Less_lexicographically<K>),(),(Compare_lexicographically_tag)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Less_or_equal_lexicographically : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Less_or_equal_lexicographically) + typedef R_ R; + typedef typename Get_type<R, Bool_tag>::type result_type; + typedef typename Get_functor<R, Compare_lexicographically_tag>::type CL; + typedef typename CGAL::Is_exact<CL> Is_exact; + + template <class V, class W> + result_type operator() (V const&a, W const&b) const { + CL c (this->kernel()); + return c(a,b) <= 0; + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Less_or_equal_lexicographically_tag,(CartesianDKernelFunctors::Less_or_equal_lexicographically<K>),(),(Compare_lexicographically_tag)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Equal_points : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Equal_points) + typedef R_ R; + typedef typename Get_type<R, Bool_tag>::type result_type; + typedef typename Get_functor<R, Construct_ttag<Point_cartesian_const_iterator_tag> >::type CI; + // TODO: This is_exact thing should be reengineered. + // the goal is to have a way to tell: don't filter this + typedef typename CGAL::Is_exact<CI> Is_exact; + + template<class V,class W> + result_type operator()(V const&a, W const&b)const{ + CI c(this->kernel()); +#ifdef CGAL_CXX11 + auto +#else + typename CI::result_type +#endif + a_begin=c(a,Begin_tag()), + b_begin=c(b,Begin_tag()), + a_end=c(a,End_tag()); + result_type res = true; + // Is using CGAL::possibly for Uncertain really an optimization? + do res = res & (*a_begin++ == *b_begin++); + while(a_begin!=a_end && possibly(res)); + return res; + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Equal_points_tag,(CartesianDKernelFunctors::Equal_points<K>),(),(Construct_ttag<Point_cartesian_const_iterator_tag>)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Oriented_side : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Oriented_side) + typedef R_ R; + typedef typename Get_type<R, Oriented_side_tag>::type result_type; + typedef typename Get_type<R, Point_tag>::type Point; + typedef typename Get_type<R, Hyperplane_tag>::type Hyperplane; + typedef typename Get_type<R, Sphere_tag>::type Sphere; + typedef typename Get_functor<R, Value_at_tag>::type VA; + typedef typename Get_functor<R, Hyperplane_translation_tag>::type HT; + typedef typename Get_functor<R, Squared_distance_tag>::type SD; + typedef typename Get_functor<R, Squared_radius_tag>::type SR; + typedef typename Get_functor<R, Center_of_sphere_tag>::type CS; + + result_type operator()(Hyperplane const&h, Point const&p)const{ + HT ht(this->kernel()); + VA va(this->kernel()); + return CGAL::compare(va(h,p),ht(h)); + } + result_type operator()(Sphere const&s, Point const&p)const{ + SD sd(this->kernel()); + SR sr(this->kernel()); + CS cs(this->kernel()); + return CGAL::compare(sd(cs(s),p),sr(s)); + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Oriented_side_tag,(CartesianDKernelFunctors::Oriented_side<K>),(Point_tag,Sphere_tag,Hyperplane_tag),(Value_at_tag,Hyperplane_translation_tag,Squared_distance_tag,Squared_radius_tag,Center_of_sphere_tag)); + +namespace CartesianDKernelFunctors { +template<class R_> struct Has_on_positive_side : private Store_kernel<R_> { + CGAL_FUNCTOR_INIT_STORE(Has_on_positive_side) + typedef R_ R; + typedef typename Get_type<R, Bool_tag>::type result_type; + typedef typename Get_functor<R, Oriented_side_tag>::type OS; + + template <class Obj, class Pt> + result_type operator()(Obj const&o, Pt const&p)const{ + OS os(this->kernel()); + return os(o,p) == ON_POSITIVE_SIDE; + } +}; +} + +CGAL_KD_DEFAULT_FUNCTOR(Has_on_positive_side_tag,(CartesianDKernelFunctors::Has_on_positive_side<K>),(),(Oriented_side_tag)); + +} +#include <CGAL/NewKernel_d/Coaffine.h> +#endif // CGAL_KERNEL_D_FUNCTION_OBJECTS_CARTESIAN_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/functor_properties.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/functor_properties.h new file mode 100644 index 00000000..c25c4e2b --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/functor_properties.h @@ -0,0 +1,40 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_EXACTNESS_H +#define CGAL_EXACTNESS_H +#include <boost/mpl/has_xxx.hpp> +#include <CGAL/tags.h> +namespace CGAL { + +#define CGAL_STRAWBERRY(Is_pretty) \ + namespace internal { \ + BOOST_MPL_HAS_XXX_TRAIT_DEF(Is_pretty) \ + } \ + template<class T,bool=internal::has_##Is_pretty<T>::value> \ + struct Is_pretty : boost::false_type {}; \ + template<class T> \ + struct Is_pretty<T,true> : T::Is_pretty {} + +CGAL_STRAWBERRY(Is_exact); +CGAL_STRAWBERRY(Is_fast); +CGAL_STRAWBERRY(Is_stored); +#undef CGAL_STRAWBERRY +} +#endif // CGAL_EXACTNESS_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/functor_tags.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/functor_tags.h new file mode 100644 index 00000000..b8e17886 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/functor_tags.h @@ -0,0 +1,363 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_FUNCTOR_TAGS_H +#define CGAL_FUNCTOR_TAGS_H +#include <CGAL/tags.h> // for Null_tag +#include <CGAL/NewKernel_d/utils.h> +#ifdef CGAL_CXX11 +#include <type_traits> +#include <utility> +#endif +#include <boost/type_traits.hpp> +#include <boost/mpl/has_xxx.hpp> +#include <boost/mpl/not.hpp> +#include <boost/mpl/if.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/mpl/empty.hpp> +#include <boost/mpl/front.hpp> +#include <boost/mpl/pop_front.hpp> +namespace CGAL { + + // Find a better place for this later + + template <class K, class T, class=void> struct Get_type + : K::template Type<T> {}; + template <class K, class F, class O=void, class=void> struct Get_functor + : K::template Functor<F, O> {}; +#ifdef CGAL_CXX11 + template <class K, class T> using Type = typename Get_type<K, T>::type; + template <class K, class T> using Functor = typename Get_functor<K, T>::type; +#endif + + class Null_type {~Null_type();}; // no such object should be created + + // To construct iterators + struct Begin_tag {}; + struct End_tag {}; + + // Functor category + struct Predicate_tag {}; + struct Construct_tag {}; + struct Construct_iterator_tag {}; + struct Compute_tag {}; + struct Misc_tag {}; + + struct No_filter_tag {}; + + template<class>struct Construct_ttag {}; + template<class>struct Convert_ttag {}; + + template <class K, class F, class=void, class=void> struct Get_functor_category { typedef Misc_tag type; }; + template<class Tg, class Obj, class Base> struct Typedef_tag_type; + //template<class Kernel, class Tg> struct Read_tag_type {}; + + template<class Kernel, class Tg> + struct Provides_type + : Has_type_different_from<Get_type<Kernel, Tg>, Null_type> {}; + + template<class Kernel, class Tg, class O=void> + struct Provides_functor + : Has_type_different_from<Get_functor<Kernel, Tg, O>, Null_functor> {}; + + template<class K, class List, bool=boost::mpl::empty<List>::type::value> + struct Provides_functors : boost::mpl::and_ < + Provides_functor<K, typename boost::mpl::front<List>::type>, + Provides_functors<K, typename boost::mpl::pop_front<List>::type> > {}; + template<class K, class List> + struct Provides_functors<K, List, true> : boost::true_type {}; + + template<class K, class List, bool=boost::mpl::empty<List>::type::value> + struct Provides_types : boost::mpl::and_ < + Provides_type<K, typename boost::mpl::front<List>::type>, + Provides_types<K, typename boost::mpl::pop_front<List>::type> > {}; + template<class K, class List> + struct Provides_types<K, List, true> : boost::true_type {}; + + namespace internal { BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_Type,template Type<Null_tag>,false) } + template<class Kernel, class Tg, + bool = internal::has_Type<Kernel>::value /* false */> + struct Provides_type_i : boost::false_type {}; + template<class Kernel, class Tg> + struct Provides_type_i <Kernel, Tg, true> + : Has_type_different_from<typename Kernel::template Type<Tg>, Null_type> {}; + + //// This version does not like Functor<T,bool=false> + //namespace internal { BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF(has_Functor,Functor,false) } + // This version lets us use non-type template parameters, but fails with older EDG-based compilers (Intel 14). + namespace internal { BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_Functor,template Functor<Null_tag>,false) } + + template<class Kernel, class Tg, class O=void, + bool = internal::has_Functor<Kernel>::value /* false */> + struct Provides_functor_i : boost::false_type {}; + template<class Kernel, class Tg, class O> + struct Provides_functor_i <Kernel, Tg, O, true> + : Has_type_different_from<typename Kernel::template Functor<Tg, O>, Null_functor> {}; + + // TODO: Refine this a bit. + template <class K, class T, class D=void, + //bool=Provides_functor<K,T>::value, + //bool=Provides_functor_i<K,T>::value, + bool = internal::has_Functor<K>::value + > + struct Inherit_functor : K::template Functor<T> {}; + template <class K, class T, class D> + struct Inherit_functor <K, T, D, false> {}; + + template <class K, class T, bool=internal::has_Type<K>::value> + struct Inherit_type : K::template Type<T> {}; + template <class K, class T> + struct Inherit_type <K, T, false> {}; + + struct Number_tag {}; + struct Discrete_tag {}; + struct Object_tag {}; + template <class K, class T, class=void> struct Get_type_category { + // The lazy kernel uses it too eagerly, + // so it currently needs a default. + typedef Null_tag type; + }; + +#define CGAL_DECL_OBJ_(X,Y) \ + template<class Obj,class Base> \ + struct Typedef_tag_type<X##_tag, Obj, Base> : Base { typedef Obj X; }; \ + template<class K, class D> \ + struct Get_type_category <K, X##_tag, D> { typedef Y##_tag type; } +#define CGAL_DECL_OBJ(X,Y) struct X##_tag {}; \ + CGAL_DECL_OBJ_(X,Y) + + //namespace has_object { BOOST_MPL_HAS_XXX_TRAIT_DEF(X) } + //template<class Kernel> + //struct Provides_tag_type<Kernel, X##_tag> : has_object::has_##X<Kernel> {}; + //template<class Kernel> + //struct Read_tag_type<Kernel, X##_tag> { typedef typename Kernel::X type; } + + // Not exactly objects, but the extras can't hurt. + CGAL_DECL_OBJ(FT, Number); + CGAL_DECL_OBJ(RT, Number); + + CGAL_DECL_OBJ(Bool, Discrete); // Boolean_tag is already taken, and is a template :-( + CGAL_DECL_OBJ(Comparison_result, Discrete); + CGAL_DECL_OBJ(Sign, Discrete); + CGAL_DECL_OBJ(Orientation, Discrete); // Note: duplicate with the functor tag! + CGAL_DECL_OBJ(Oriented_side, Discrete); + CGAL_DECL_OBJ(Bounded_side, Discrete); + CGAL_DECL_OBJ(Angle, Discrete); + CGAL_DECL_OBJ(Flat_orientation, Discrete); + + CGAL_DECL_OBJ(Vector, Object); + CGAL_DECL_OBJ(Point, Object); + CGAL_DECL_OBJ(Segment, Object); + CGAL_DECL_OBJ(Sphere, Object); + CGAL_DECL_OBJ(Line, Object); + CGAL_DECL_OBJ(Direction, Object); + CGAL_DECL_OBJ(Hyperplane, Object); + CGAL_DECL_OBJ(Ray, Object); + CGAL_DECL_OBJ(Iso_box, Object); + CGAL_DECL_OBJ(Bbox, Object); + CGAL_DECL_OBJ(Aff_transformation, Object); + CGAL_DECL_OBJ(Weighted_point, Object); +#undef CGAL_DECL_OBJ_ +#undef CGAL_DECL_OBJ + +// Intel fails with those, and they are not so useful. +// CGAL_KD_DEFAULT_TYPE(RT_tag,(typename Get_type<K, FT_tag>::type),(),()); +// CGAL_KD_DEFAULT_TYPE(FT_tag,(CGAL::Quotient<typename Get_type<K, RT_tag>::type>),(),()); + +#define CGAL_SMURF2(A,B) CGAL_KD_DEFAULT_TYPE(A##_tag,(typename Same_uncertainty_nt<B, typename Get_type<K,RT_tag>::type>::type),(RT_tag),()) +#define CGAL_SMURF1(A) CGAL_SMURF2(A,CGAL::A) + CGAL_SMURF2(Bool, bool); + CGAL_SMURF1(Sign); + CGAL_SMURF1(Comparison_result); + CGAL_SMURF1(Orientation); + CGAL_SMURF1(Oriented_side); + CGAL_SMURF1(Bounded_side); + CGAL_SMURF1(Angle); +#undef CGAL_SMURF1 +#undef CGAL_SMURF2 + + // TODO: replace with Get_type_category + template<class> struct is_NT_tag { enum { value = false }; }; + template<> struct is_NT_tag<FT_tag> { enum { value = true }; }; + template<> struct is_NT_tag<RT_tag> { enum { value = true }; }; + + template<class> struct iterator_tag_traits { + enum { is_iterator = false, has_nth_element = false }; + typedef Null_tag value_tag; + }; + +#define CGAL_DECL_COMPUTE(X) struct X##_tag {}; \ + template<class A,class B,class C>struct Get_functor_category<A,X##_tag,B,C>{typedef Compute_tag type;} + CGAL_DECL_COMPUTE(Compute_point_cartesian_coordinate); + CGAL_DECL_COMPUTE(Compute_vector_cartesian_coordinate); + CGAL_DECL_COMPUTE(Compute_homogeneous_coordinate); + CGAL_DECL_COMPUTE(Squared_distance); + CGAL_DECL_COMPUTE(Squared_distance_to_origin); + CGAL_DECL_COMPUTE(Squared_length); + CGAL_DECL_COMPUTE(Squared_radius); + CGAL_DECL_COMPUTE(Squared_circumradius); + CGAL_DECL_COMPUTE(Scalar_product); + CGAL_DECL_COMPUTE(Hyperplane_translation); + CGAL_DECL_COMPUTE(Value_at); + CGAL_DECL_COMPUTE(Point_weight); + CGAL_DECL_COMPUTE(Power_distance); + CGAL_DECL_COMPUTE(Power_distance_to_point); +#undef CGAL_DECL_COMPUTE + +#define CGAL_DECL_ITER_OBJ(X,Y,Z,C) struct X##_tag {}; \ + template<>struct iterator_tag_traits<X##_tag> { \ + enum { is_iterator = true, has_nth_element = true }; \ + typedef Y##_tag value_tag; \ + typedef Z##_tag nth_element; \ + typedef C##_tag container; \ + }; \ + template<class Obj,class Base> \ + struct Typedef_tag_type<X##_tag, Obj, Base> : Base { typedef Obj X; } + + //namespace has_object { BOOST_MPL_HAS_XXX_TRAIT_DEF(X) } + //template<class Kernel> + //struct Provides_tag_type<Kernel, X##_tag> : has_object::has_##X<Kernel> {}; + //template<class Kernel> + //struct Read_tag_type<Kernel, X##_tag> { typedef typename Kernel::X type; } + + CGAL_DECL_ITER_OBJ(Vector_cartesian_const_iterator, FT, Compute_vector_cartesian_coordinate, Vector); + CGAL_DECL_ITER_OBJ(Point_cartesian_const_iterator, FT, Compute_point_cartesian_coordinate, Point); +#undef CGAL_DECL_ITER_OBJ + + template<class>struct map_result_tag{typedef Null_type type;}; + template<class T>struct map_result_tag<Construct_ttag<T> >{typedef T type;}; + + template<class A,class T,class B,class C>struct Get_functor_category<A,Construct_ttag<T>,B,C> : + boost::mpl::if_c<iterator_tag_traits<T>::is_iterator, + Construct_iterator_tag, + Construct_tag> {}; + + // Really? + template<class A,class T,class B,class C>struct Get_functor_category<A,Convert_ttag<T>,B,C>{typedef Misc_tag type;}; + +#define CGAL_DECL_CONSTRUCT(X,Y) struct X##_tag {}; \ + template<>struct map_result_tag<X##_tag>{typedef Y##_tag type;}; \ + template<class A,class B,class C>struct Get_functor_category<A,X##_tag,B,C>{typedef Construct_tag type;} + CGAL_DECL_CONSTRUCT(Midpoint,Point); + CGAL_DECL_CONSTRUCT(Center_of_sphere,Point); + CGAL_DECL_CONSTRUCT(Point_of_sphere,Point); + CGAL_DECL_CONSTRUCT(Segment_extremity,Point); + CGAL_DECL_CONSTRUCT(Sum_of_vectors,Vector); + CGAL_DECL_CONSTRUCT(Difference_of_vectors,Vector); + CGAL_DECL_CONSTRUCT(Opposite_vector,Vector); + CGAL_DECL_CONSTRUCT(Scaled_vector,Vector); + CGAL_DECL_CONSTRUCT(Orthogonal_vector,Vector); + CGAL_DECL_CONSTRUCT(Difference_of_points,Vector); + CGAL_DECL_CONSTRUCT(Translated_point,Point); + CGAL_DECL_CONSTRUCT(Point_to_vector,Vector); + CGAL_DECL_CONSTRUCT(Vector_to_point,Point); + CGAL_DECL_CONSTRUCT(Construct_min_vertex,Point); + CGAL_DECL_CONSTRUCT(Construct_max_vertex,Point); + CGAL_DECL_CONSTRUCT(Construct_circumcenter,Point); + CGAL_DECL_CONSTRUCT(Point_drop_weight,Point); + CGAL_DECL_CONSTRUCT(Power_center,Weighted_point); +#undef CGAL_DECL_CONSTRUCT +#if 0 +#define CGAL_DECL_ITER_CONSTRUCT(X,Y) struct X##_tag {}; \ + template<>struct map_result_tag<X##_tag>{typedef Y##_tag type;}; \ + template<>struct map_functor_type<X##_tag>{typedef Construct_iterator_tag type;} + CGAL_DECL_ITER_CONSTRUCT(Construct_point_cartesian_const_iterator,Point_cartesian_const_iterator); + CGAL_DECL_ITER_CONSTRUCT(Construct_vector_cartesian_const_iterator,Vector_cartesian_const_iterator); +#undef CGAL_DECL_ITER_CONSTRUCT +#endif + + //FIXME: choose a convention: prefix with Predicate_ ? +#define CGAL_DECL_PREDICATE_(X) \ + template<class A,class B,class C>struct Get_functor_category<A,X##_tag,B,C>{typedef Predicate_tag type;} +#define CGAL_DECL_PREDICATE(X) struct X##_tag {}; \ + CGAL_DECL_PREDICATE_(X) + CGAL_DECL_PREDICATE(Less_point_cartesian_coordinate); + CGAL_DECL_PREDICATE(Compare_point_cartesian_coordinate); + CGAL_DECL_PREDICATE(Compare_distance); + CGAL_DECL_PREDICATE(Compare_lexicographically); + CGAL_DECL_PREDICATE(Less_lexicographically); + CGAL_DECL_PREDICATE(Less_or_equal_lexicographically); + CGAL_DECL_PREDICATE(Equal_points); + CGAL_DECL_PREDICATE(Has_on_positive_side); + CGAL_DECL_PREDICATE_(Orientation); // duplicate with the type + CGAL_DECL_PREDICATE_(Oriented_side); // duplicate with the type + CGAL_DECL_PREDICATE(Orientation_of_points); + CGAL_DECL_PREDICATE(Orientation_of_vectors); + CGAL_DECL_PREDICATE(Side_of_oriented_sphere); + CGAL_DECL_PREDICATE(Side_of_bounded_sphere); + CGAL_DECL_PREDICATE(Side_of_bounded_circumsphere); + CGAL_DECL_PREDICATE(Contained_in_affine_hull); + CGAL_DECL_PREDICATE(In_flat_orientation); + CGAL_DECL_PREDICATE(In_flat_side_of_oriented_sphere); + CGAL_DECL_PREDICATE(Construct_flat_orientation); // Making it a predicate is a questionable choice, it should be possible to let it be a construction for some implementations. Not sure how to do that... TODO + CGAL_DECL_PREDICATE(Linear_rank); + CGAL_DECL_PREDICATE(Affine_rank); + CGAL_DECL_PREDICATE(Linearly_independent); + CGAL_DECL_PREDICATE(Affinely_independent); + CGAL_DECL_PREDICATE(Contained_in_linear_hull); + CGAL_DECL_PREDICATE(Contained_in_simplex); + CGAL_DECL_PREDICATE(Power_side_of_power_sphere_raw); + CGAL_DECL_PREDICATE(Power_side_of_power_sphere); + CGAL_DECL_PREDICATE(In_flat_power_side_of_power_sphere_raw); + CGAL_DECL_PREDICATE(In_flat_power_side_of_power_sphere); +#undef CGAL_DECL_PREDICATE + +#define CGAL_DECL_MISC(X) struct X##_tag {}; \ + template<class A,class B,class C>struct Get_functor_category<A,X##_tag,B,C>{typedef Misc_tag type;} + //TODO: split into _begin and _end ? + //CGAL_DECL_MISC(Construct_point_cartesian_const_iterator); + //CGAL_DECL_MISC(Construct_vector_cartesian_const_iterator); + CGAL_DECL_MISC(Point_dimension); + CGAL_DECL_MISC(Vector_dimension); + CGAL_DECL_MISC(Linear_base); // Find a more appropriate category? +#undef CGAL_DECL_MISC + + + // Properties for LA + struct Has_extra_dimension_tag {}; + struct Has_vector_plus_minus_tag {}; + struct Has_vector_scalar_ops_tag {}; + struct Has_dot_product_tag {}; + struct Has_determinant_of_vectors_tag {}; + struct Has_determinant_of_points_tag {}; + struct Has_determinant_of_iterator_to_vectors_tag {}; + struct Has_determinant_of_iterator_to_points_tag {}; + struct Has_determinant_of_vectors_omit_last_tag {}; + struct Stores_squared_norm_tag {}; + + template<class> struct Preserved_by_non_linear_extra_coordinate + : boost::false_type {}; + template<> struct Preserved_by_non_linear_extra_coordinate + <Has_extra_dimension_tag> : boost::true_type {}; + template<> struct Preserved_by_non_linear_extra_coordinate + <Has_determinant_of_vectors_tag> : boost::true_type {}; + template<> struct Preserved_by_non_linear_extra_coordinate + <Has_determinant_of_points_tag> : boost::true_type {}; + template<> struct Preserved_by_non_linear_extra_coordinate + <Has_determinant_of_iterator_to_vectors_tag> : boost::true_type {}; + template<> struct Preserved_by_non_linear_extra_coordinate + <Has_determinant_of_iterator_to_points_tag> : boost::true_type {}; + template<> struct Preserved_by_non_linear_extra_coordinate + <Has_determinant_of_vectors_omit_last_tag> : boost::true_type {}; + + // Kernel properties + struct Point_stores_squared_distance_to_origin_tag {}; + +} +#endif // CGAL_FUNCTOR_TAGS_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/static_int.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/static_int.h new file mode 100644 index 00000000..21858804 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/static_int.h @@ -0,0 +1,61 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_STATIC_INT_H +#define CGAL_STATIC_INT_H +#include <CGAL/constant.h> + +namespace CGAL { +template <class NT> struct static_zero { + operator NT() const { return constant<NT,0>(); } +}; +template <class NT> struct static_one { + operator NT() const { return constant<NT,1>(); } +}; + +template <class NT> static_zero<NT> operator-(static_zero<NT>) { return static_zero<NT>(); } + +template <class NT> NT operator+(NT const& x, static_zero<NT>) { return x; } +template <class NT> NT operator+(static_zero<NT>, NT const& x) { return x; } +template <class NT> static_zero<NT> operator+(static_zero<NT>, static_zero<NT>) { return static_zero<NT>(); } +template <class NT> static_one<NT> operator+(static_zero<NT>, static_one<NT>) { return static_one<NT>(); } +template <class NT> static_one<NT> operator+(static_one<NT>, static_zero<NT>) { return static_one<NT>(); } + +template <class NT> NT operator-(NT const& x, static_zero<NT>) { return x; } +template <class NT> NT operator-(static_zero<NT>, NT const& x) { return -x; } +template <class NT> static_zero<NT> operator-(static_zero<NT>, static_zero<NT>) { return static_zero<NT>(); } +template <class NT> static_zero<NT> operator-(static_one<NT>, static_one<NT>) { return static_zero<NT>(); } +template <class NT> static_one<NT> operator-(static_one<NT>, static_zero<NT>) { return static_one<NT>(); } + +template <class NT> NT operator*(NT const& x, static_one<NT>) { return x; } +template <class NT> NT operator*(static_one<NT>, NT const& x) { return x; } +template <class NT> static_zero<NT> operator*(NT const&, static_zero<NT>) { return static_zero<NT>(); } +template <class NT> static_zero<NT> operator*(static_zero<NT>, NT const&) { return static_zero<NT>(); } +template <class NT> static_zero<NT> operator*(static_zero<NT>, static_zero<NT>) { return static_zero<NT>(); } +template <class NT> static_one<NT> operator*(static_one<NT>, static_one<NT>) { return static_one<NT>(); } +template <class NT> static_zero<NT> operator*(static_zero<NT>, static_one<NT>) { return static_zero<NT>(); } +template <class NT> static_zero<NT> operator*(static_one<NT>, static_zero<NT>) { return static_zero<NT>(); } + +template <class NT> NT operator/(NT const& x, static_one<NT>) { return x; } +template <class NT> static_zero<NT> operator/(static_zero<NT>, NT const&) { return static_zero<NT>(); } +template <class NT> static_zero<NT> operator/(static_zero<NT>, static_one<NT>) { return static_zero<NT>(); } +template <class NT> static_one<NT> operator/(static_one<NT>, static_one<NT>) { return static_one<NT>(); } + +} +#endif // CGAL_STATIC_INT_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/store_kernel.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/store_kernel.h new file mode 100644 index 00000000..253e1282 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/store_kernel.h @@ -0,0 +1,104 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_STORE_KERNEL_H +#define CGAL_STORE_KERNEL_H + +#include <CGAL/assertions.h> +#include <boost/type_traits/is_empty.hpp> + +namespace CGAL { +namespace internal { +BOOST_MPL_HAS_XXX_TRAIT_DEF(Do_not_store_kernel) +template<class T,bool=boost::is_empty<T>::value,bool=has_Do_not_store_kernel<T>::value> struct Do_not_store_kernel { + enum { value=false }; + typedef Tag_false type; +}; +template<class T> struct Do_not_store_kernel<T,true,false> { + enum { value=true }; + typedef Tag_true type; +}; +template<class T,bool b> struct Do_not_store_kernel<T,b,true> { + typedef typename T::Do_not_store_kernel type; + enum { value=type::value }; +}; +} + +template<class R_,bool=internal::Do_not_store_kernel<R_>::value> +struct Store_kernel { + Store_kernel(){} + Store_kernel(R_ const&){} + enum { kernel_is_stored = false }; + R_ kernel()const{return R_();} + typedef R_ reference_type; + void set_kernel(R_ const&){} +}; +template<class R_> +struct Store_kernel<R_,false> { + Store_kernel():rp(0){ + CGAL_warning_msg(true,"I should know my kernel"); + } + Store_kernel(R_ const& r):rp(&r){} + enum { kernel_is_stored = true }; + R_ const& kernel()const{ + CGAL_warning_msg(rp!=0,"I should know my kernel"); + return *rp; + } + typedef R_ const& reference_type; + void set_kernel(R_ const&r){rp=&r;} + private: + R_ const* rp; +}; + +//For a second kernel. TODO: find something more elegant +template<class R_,bool=internal::Do_not_store_kernel<R_>::value> +struct Store_kernel2 { + Store_kernel2(){} + Store_kernel2(R_ const&){} + enum { kernel2_is_stored = false }; + R_ kernel2()const{return R_();} + typedef R_ reference2_type; + void set_kernel2(R_ const&){} +}; +template<class R_> +struct Store_kernel2<R_,false> { + Store_kernel2(){ + //CGAL_warning_msg(true,"I should know my kernel"); + } + Store_kernel2(R_ const& r):rp(&r){} + enum { kernel2_is_stored = true }; + R_ const& kernel2()const{ + CGAL_warning_msg(rp==0,"I should know my kernel"); + return *rp; + } + typedef R_ const& reference2_type; + void set_kernel2(R_ const&r){rp=&r;} + private: + R_ const* rp; +}; +} +#define CGAL_BASE_INIT(X,Y) \ + X():Y(){} \ + X(R_ const&r):Y(r){} +#define CGAL_FUNCTOR_INIT_STORE(X) CGAL_BASE_INIT(X,Store_kernel<R_>) +#define CGAL_FUNCTOR_INIT_IGNORE(X) \ + X(){} \ + X(R_ const&){} + +#endif // CGAL_STORE_KERNEL_H diff --git a/src/common/include/gudhi_patches/CGAL/NewKernel_d/utils.h b/src/common/include/gudhi_patches/CGAL/NewKernel_d/utils.h new file mode 100644 index 00000000..238a2230 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/NewKernel_d/utils.h @@ -0,0 +1,306 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_MARCUTILS +#define CGAL_MARCUTILS + +#include <CGAL/config.h> + +#if defined(BOOST_MSVC) +# pragma warning(push) +# pragma warning(disable:4003) // not enough actual parameters for macro 'BOOST_PP_EXPAND_I' + // http://lists.boost.org/boost-users/2014/11/83291.php +#endif + +#ifdef CGAL_CXX11 +#include <type_traits> +#include <utility> +#define CGAL_FORWARDABLE(T) T&& +#define CGAL_FORWARD(T,t) std::forward<T>(t) +#define CGAL_MOVE(t) std::move(t) +#define CGAL_CONSTEXPR constexpr +#else +#define CGAL_FORWARDABLE(T) T const& +#define CGAL_FORWARD(T,t) t +#define CGAL_MOVE(t) t +#define CGAL_CONSTEXPR +#endif +#include <boost/utility/enable_if.hpp> +#include <boost/preprocessor/repetition.hpp> +#include <CGAL/Rational_traits.h> +#include <CGAL/tuple.h> +#include <boost/mpl/has_xxx.hpp> +#include <boost/mpl/not.hpp> +#include <boost/type_traits.hpp> + +#ifdef CGAL_CXX11 +#define CGAL_BOOSTD std:: +#else +#define CGAL_BOOSTD boost:: +#endif + +namespace CGAL { +namespace internal { + BOOST_MPL_HAS_XXX_TRAIT_DEF(type) +} + +template <class T, class No, bool=internal::has_type<T>::value /*false*/> +struct Has_type_different_from : boost::false_type {}; +template <class T, class No> +struct Has_type_different_from <T, No, true> +: boost::mpl::not_<boost::is_same<typename T::type, No> > {}; + + + template <class T> struct Wrap_type { typedef T type; }; + + // tell a function f(a,b,c) that its real argument is a(b,c) + struct Eval_functor {}; + + // forget the first argument. Useful to make something dependant + // (and thus usable in SFINAE), although that's not a great design. + template<class A,class B> struct Second_arg { + typedef B type; + }; + + // like std::forward, except for basic types where it does a cast, to + // avoid issues with narrowing conversions +#ifdef CGAL_CXX11 + template<class T,class U,class V> inline + typename std::conditional<std::is_arithmetic<T>::value&&std::is_arithmetic<typename std::remove_reference<U>::type>::value,T,U&&>::type + forward_safe(V&& u) { return std::forward<U>(u); } +#else + template<class T,class U> inline U const& forward_safe(U const& u) { + return u; + } +#endif + +#ifdef CGAL_CXX11 + template<class...> struct Constructible_from_each; + template<class To,class From1,class...From> struct Constructible_from_each<To,From1,From...>{ + enum { value=std::is_convertible<From1,To>::value&&Constructible_from_each<To,From...>::value }; + }; + template<class To> struct Constructible_from_each<To>{ + enum { value=true }; + }; +#else +// currently only used in C++0X code +#endif + + template<class T> struct Scale { +#ifndef CGAL_CXX11 + template<class> struct result; + template<class FT> struct result<Scale(FT)> { + typedef FT type; + }; +#endif + T const& scale; + Scale(T const& t):scale(t){} + template<class FT> +#ifdef CGAL_CXX11 + auto operator()(FT&& x)const->decltype(scale*std::forward<FT>(x)) +#else + FT operator()(FT const& x)const +#endif + { + return scale*CGAL_FORWARD(FT,x); + } + }; + template<class NT,class T> struct Divide { +#if !defined(CGAL_CXX11) || !defined(BOOST_RESULT_OF_USE_DECLTYPE) + // requires boost > 1.44 + // shouldn't be needed with C++0X + //template<class> struct result; + //template<class FT> struct result<Divide(FT)> { + // typedef FT type; + //}; + typedef NT result_type; +#endif + T const& scale; + Divide(T const& t):scale(t){} + template<class FT> +#ifdef CGAL_CXX11 + //FIXME: gcc complains for Gmpq + //auto operator()(FT&& x)const->decltype(Rational_traits<NT>().make_rational(std::forward<FT>(x),scale)) + NT operator()(FT&& x)const +#else + NT operator()(FT const& x)const +#endif + { + return Rational_traits<NT>(). + make_rational(CGAL_FORWARD(FT,x),scale); + } + }; + + template <class NT> struct has_cheap_constructor : boost::is_arithmetic<NT>{}; + template <bool p> struct has_cheap_constructor<Interval_nt<p> > { + enum { value=true }; + }; + + // like std::multiplies but allows mixing types + // in C++11 in doesn't need to be a template + template < class Ret > + struct multiplies { + template<class A,class B> +#ifdef CGAL_CXX11 + auto operator()(A&&a,B&&b)const->decltype(std::forward<A>(a)*std::forward<B>(b)) +#else + Ret operator()(A const& a, B const& b)const +#endif + { + return CGAL_FORWARD(A,a)*CGAL_FORWARD(B,b); + } + }; + template < class Ret > + struct division { + template<class A,class B> +#ifdef CGAL_CXX11 + auto operator()(A&&a,B&&b)const->decltype(std::forward<A>(a)/std::forward<B>(b)) +#else + Ret operator()(A const& a, B const& b)const +#endif + { + return CGAL_FORWARD(A,a)/CGAL_FORWARD(B,b); + } + }; + +#ifdef CGAL_CXX11 + using std::decay; +#else + template<class T> struct decay : boost::remove_cv<typename boost::decay<T>::type> {}; +#endif + + template<class T,class U> struct Type_copy_ref { typedef U type; }; + template<class T,class U> struct Type_copy_ref<T&,U> { typedef U& type; }; +#ifdef CGAL_CXX11 + template<class T,class U> struct Type_copy_ref<T&&,U> { typedef U&& type; }; +#endif + template<class T,class U> struct Type_copy_cv { typedef U type; }; + template<class T,class U> struct Type_copy_cv<T const,U> { typedef U const type; }; + template<class T,class U> struct Type_copy_cv<T volatile,U> { typedef U volatile type; }; + template<class T,class U> struct Type_copy_cv<T const volatile,U> { typedef U const volatile type; }; + + template<class T,class U> struct Type_copy_cvref : + Type_copy_ref<T,typename Type_copy_cv<typename boost::remove_reference<T>::type,U>::type> {}; + + struct Dereference_functor { + template<class> struct result{}; + template<class It> struct result<Dereference_functor(It)> { + typedef typename std::iterator_traits<It>::reference type; + }; + template<class It> typename result<Dereference_functor(It)>::type + operator()(It const&i)const{ + return *i; + } + }; + +#ifdef CGAL_CXX11 + template<int...> struct Indices{}; + template<class> struct Next_increasing_indices; + template<int...I> struct Next_increasing_indices<Indices<I...> > { + typedef Indices<I...,sizeof...(I)> type; + }; + template<int N> struct N_increasing_indices { + typedef typename Next_increasing_indices<typename N_increasing_indices<N-1>::type>::type type; + }; + template<> struct N_increasing_indices<0> { typedef Indices<> type; }; + namespace internal { + template<class F,class...U,int...I> inline typename std::result_of<F&&(U...)>::type + do_call_on_tuple_elements(F&&f, std::tuple<U...>&&t, Indices<I...>&&) { + return f(std::get<I>(std::move(t))...); + } + } // internal + template<class/*result type, ignored*/,class F,class...U> + inline typename std::result_of<F&&(U...)>::type + call_on_tuple_elements(F&&f, std::tuple<U...>&&t) { + return internal::do_call_on_tuple_elements(std::forward<F>(f),std::move(t), + typename N_increasing_indices<sizeof...(U)>::type()); + } +#else +#define CGAL_VAR(Z,N,_) cpp0x::get<N>(t) +#define CGAL_CODE(Z,N,_) template<class Res, class F BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_PARAMS(N,class U)> \ + inline Res call_on_tuple_elements(F const&f, \ + cpp0x::tuple<BOOST_PP_ENUM_PARAMS(N,U)> const&t) { \ + return f(BOOST_PP_ENUM(N,CGAL_VAR,)); \ + } + template<class Res, class F> + inline Res call_on_tuple_elements(F const&f, cpp0x::tuple<>) { + return f(); + } +BOOST_PP_REPEAT_FROM_TO(1, 8, CGAL_CODE, _ ) +#undef CGAL_CODE +#undef CGAL_VAR +#endif + + template<class A> struct Factory { + typedef A result_type; +#ifdef CGAL_CXX11 + template<class...U> result_type operator()(U&&...u)const{ + return A(std::forward<U>(u)...); + } +#else + result_type operator()()const{ + return A(); + } +#define CGAL_CODE(Z,N,_) template<BOOST_PP_ENUM_PARAMS(N,class U)> \ + result_type operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,U,const&u))const{ \ + return A(BOOST_PP_ENUM_PARAMS(N,u)); \ + } +BOOST_PP_REPEAT_FROM_TO(1, 8, CGAL_CODE, _ ) +#undef CGAL_CODE +#endif + }; +} + +// TODO: make a Cartesian-only variant +// WARNING: do not use the Req* parameters too much, they can cause circular instanciations and are only useful for dispatching. +#define CGAL_STRIP_PAREN_(...) __VA_ARGS__ +#define CGAL_STRIP_PAREN(...) CGAL_STRIP_PAREN_ __VA_ARGS__ +// What to do with O? pass it down to other functors or drop it? +#define CGAL_KD_DEFAULT_FUNCTOR(Tg,Name,ReqTyp,ReqFun) \ + template <class K, class O> \ + struct Get_functor<K, Tg, O, \ + typename boost::mpl::if_c< \ + Provides_functor_i<K, Tg, O>::value \ + || !Provides_types<K, boost::mpl::vector<CGAL_STRIP_PAREN_ ReqTyp> >::value \ + || !Provides_functors<K, boost::mpl::vector<CGAL_STRIP_PAREN_ ReqFun> >::value \ + , int, void>::type> \ + { \ + typedef CGAL_STRIP_PAREN_ Name type; \ + typedef K Bound_kernel; \ + } + +// Not used yet, may need some changes. +#define CGAL_KD_DEFAULT_TYPE(Tg,Name,ReqTyp,ReqFun) \ + template <class K> \ + struct Get_type<K, Tg, \ + typename boost::mpl::if_c< \ + Provides_type_i<K, Tg>::value \ + || !Provides_types<K, boost::mpl::vector<CGAL_STRIP_PAREN_ ReqTyp> >::value \ + || !Provides_functors<K, boost::mpl::vector<CGAL_STRIP_PAREN_ ReqFun> >::value \ + , int, void>::type> \ + { \ + typedef CGAL_STRIP_PAREN_ Name type; \ + typedef K Bound_kernel; \ + } + +#if defined(BOOST_MSVC) +# pragma warning(pop) +#endif + +#endif diff --git a/src/common/include/gudhi_patches/CGAL/Regular_triangulation.h b/src/common/include/gudhi_patches/CGAL/Regular_triangulation.h new file mode 100644 index 00000000..111c6ac9 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/Regular_triangulation.h @@ -0,0 +1,1169 @@ +// Copyright (c) 2014 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Clement Jamin + +#ifndef CGAL_REGULAR_TRIANGULATION_H +#define CGAL_REGULAR_TRIANGULATION_H + +#include <CGAL/Triangulation.h> +#include <CGAL/Dimension.h> +#include <CGAL/Default.h> +#include <CGAL/spatial_sort.h> +#include <CGAL/Regular_triangulation_traits_adapter.h> + +#include <boost/property_map/function_property_map.hpp> + +namespace CGAL { + +template< typename Traits_, typename TDS_ = Default > +class Regular_triangulation +: public Triangulation< + Regular_triangulation_traits_adapter<Traits_>, + typename Default::Get< + TDS_, + Triangulation_data_structure< + typename Regular_triangulation_traits_adapter<Traits_>::Dimension, + Triangulation_vertex<Regular_triangulation_traits_adapter<Traits_> >, + Triangulation_full_cell<Regular_triangulation_traits_adapter<Traits_> > + > + >::type> +{ + typedef Regular_triangulation_traits_adapter<Traits_> RTTraits; + typedef typename RTTraits::Dimension Maximal_dimension_; + typedef typename Default::Get< + TDS_, + Triangulation_data_structure< + Maximal_dimension_, + Triangulation_vertex<RTTraits>, + Triangulation_full_cell<RTTraits> + > >::type TDS; + typedef Triangulation<RTTraits, TDS> Base; + typedef Regular_triangulation<Traits_, TDS_> Self; + + typedef typename RTTraits::Orientation_d Orientation_d; + typedef typename RTTraits::Power_side_of_power_sphere_d Power_side_of_power_sphere_d; + typedef typename RTTraits::In_flat_power_side_of_power_sphere_d + In_flat_power_side_of_power_sphere_d; + typedef typename RTTraits::Flat_orientation_d Flat_orientation_d; + typedef typename RTTraits::Construct_flat_orientation_d Construct_flat_orientation_d; + +public: // PUBLIC NESTED TYPES + + typedef RTTraits Geom_traits; + typedef typename Base::Triangulation_ds Triangulation_ds; + + typedef typename Base::Vertex Vertex; + typedef typename Base::Full_cell Full_cell; + typedef typename Base::Facet Facet; + typedef typename Base::Face Face; + + typedef Maximal_dimension_ Maximal_dimension; + typedef typename RTTraits::Bare_point_d Bare_point; + typedef typename RTTraits::Weighted_point_d Weighted_point; + + typedef typename Base::Point_const_iterator Point_const_iterator; + typedef typename Base::Vertex_handle Vertex_handle; + typedef typename Base::Vertex_iterator Vertex_iterator; + typedef typename Base::Vertex_const_handle Vertex_const_handle; + typedef typename Base::Vertex_const_iterator Vertex_const_iterator; + + typedef typename Base::Full_cell_handle Full_cell_handle; + typedef typename Base::Full_cell_iterator Full_cell_iterator; + typedef typename Base::Full_cell_const_handle Full_cell_const_handle; + typedef typename Base::Full_cell_const_iterator Full_cell_const_iterator; + typedef typename Base::Finite_full_cell_const_iterator + Finite_full_cell_const_iterator; + + typedef typename Base::size_type size_type; + typedef typename Base::difference_type difference_type; + + typedef typename Base::Locate_type Locate_type; + + //Tag to distinguish Delaunay from Regular triangulations + typedef Tag_true Weighted_tag; + +protected: // DATA MEMBERS + + +public: + + using typename Base::Rotor; + using Base::maximal_dimension; + using Base::are_incident_full_cells_valid; + using Base::coaffine_orientation_predicate; + using Base::reset_flat_orientation; + using Base::current_dimension; + using Base::geom_traits; + using Base::index_of_covertex; + //using Base::index_of_second_covertex; + using Base::rotate_rotor; + using Base::infinite_vertex; + using Base::insert_in_hole; + using Base::is_infinite; + using Base::locate; + using Base::points_begin; + using Base::set_neighbors; + using Base::new_full_cell; + using Base::number_of_vertices; + using Base::orientation; + using Base::tds; + using Base::reorient_full_cells; + using Base::full_cell; + using Base::full_cells_begin; + using Base::full_cells_end; + using Base::finite_full_cells_begin; + using Base::finite_full_cells_end; + using Base::vertices_begin; + using Base::vertices_end; + +private: + + // Wrapper + struct Power_side_of_power_sphere_for_non_maximal_dim_d + { + boost::optional<Flat_orientation_d>* fop; + Construct_flat_orientation_d cfo; + In_flat_power_side_of_power_sphere_d ifpt; + + Power_side_of_power_sphere_for_non_maximal_dim_d( + boost::optional<Flat_orientation_d>& x, + Construct_flat_orientation_d const&y, + In_flat_power_side_of_power_sphere_d const&z) + : fop(&x), cfo(y), ifpt(z) {} + + template<class Iter> + CGAL::Orientation operator()(Iter a, Iter b, const Weighted_point & p)const + { + if(!*fop) + *fop=cfo(a,b); + return ifpt(fop->get(),a,b,p); + } + }; + +public: + +// - - - - - - - - - - - - - - - - - - - - - - - - - - CREATION / CONSTRUCTORS + + Regular_triangulation(int dim, const Geom_traits &k = Geom_traits()) + : Base(dim, k) + { + } + + // With this constructor, + // the user can specify a Flat_orientation_d object to be used for + // orienting simplices of a specific dimension + // (= preset_flat_orientation_.first) + // It it used by the dark triangulations created by DT::remove + Regular_triangulation( + int dim, + const std::pair<int, const Flat_orientation_d *> &preset_flat_orientation, + const Geom_traits &k = Geom_traits()) + : Base(dim, preset_flat_orientation, k) + { + } + + ~Regular_triangulation() {} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ACCESS + + // Not Documented + Power_side_of_power_sphere_for_non_maximal_dim_d power_side_of_power_sphere_for_non_maximal_dim_predicate() const + { + return Power_side_of_power_sphere_for_non_maximal_dim_d ( + flat_orientation_, + geom_traits().construct_flat_orientation_d_object(), + geom_traits().in_flat_power_side_of_power_sphere_d_object() + ); + } + + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS + + // Warning: these functions are not correct since they do not restore hidden + // vertices + + Full_cell_handle remove(Vertex_handle); + Full_cell_handle remove(const Weighted_point & p, Full_cell_handle hint = Full_cell_handle()) + { + Locate_type lt; + Face f(maximal_dimension()); + Facet ft; + Full_cell_handle s = locate(p, lt, f, ft, hint); + if( Base::ON_VERTEX == lt ) + { + return remove(s->vertex(f.index(0))); + } + return Full_cell_handle(); + } + + template< typename ForwardIterator > + void remove(ForwardIterator start, ForwardIterator end) + { + while( start != end ) + remove(*start++); + } + + // Not documented + void remove_decrease_dimension(Vertex_handle); + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INSERTIONS + + template< typename ForwardIterator > + std::ptrdiff_t insert(ForwardIterator start, ForwardIterator end) + { + size_type n = number_of_vertices(); + typedef std::vector<Weighted_point> WP_vec; + WP_vec points(start, end); + + spatial_sort(points.begin(), points.end(), geom_traits()); + + Full_cell_handle hint; + for(typename WP_vec::const_iterator p = points.begin(); p != points.end(); ++p ) + { + Locate_type lt; + Face f(maximal_dimension()); + Facet ft; + Full_cell_handle c = locate (*p, lt, f, ft, hint); + Vertex_handle v = insert (*p, lt, f, ft, c); + + hint = v == Vertex_handle() ? c : v->full_cell(); + } + return number_of_vertices() - n; + } + + Vertex_handle insert(const Weighted_point &, + Locate_type, + const Face &, + const Facet &, + Full_cell_handle); + + Vertex_handle insert(const Weighted_point & p, + Full_cell_handle start = Full_cell_handle()) + { + Locate_type lt; + Face f(maximal_dimension()); + Facet ft; + Full_cell_handle s = locate(p, lt, f, ft, start); + return insert(p, lt, f, ft, s); + } + + Vertex_handle insert(const Weighted_point & p, Vertex_handle hint) + { + CGAL_assertion( Vertex_handle() != hint ); + return insert(p, hint->full_cell()); + } + + Vertex_handle insert_outside_affine_hull(const Weighted_point &); + Vertex_handle insert_in_conflicting_cell( + const Weighted_point &, Full_cell_handle, + Vertex_handle only_if_this_vertex_is_in_the_cz = Vertex_handle()); + + Vertex_handle insert_if_in_star(const Weighted_point &, + Vertex_handle, + Locate_type, + const Face &, + const Facet &, + Full_cell_handle); + + Vertex_handle insert_if_in_star( + const Weighted_point & p, Vertex_handle star_center, + Full_cell_handle start = Full_cell_handle()) + { + Locate_type lt; + Face f(maximal_dimension()); + Facet ft; + Full_cell_handle s = locate(p, lt, f, ft, start); + return insert_if_in_star(p, star_center, lt, f, ft, s); + } + + Vertex_handle insert_if_in_star( + const Weighted_point & p, Vertex_handle star_center, + Vertex_handle hint) + { + CGAL_assertion( Vertex_handle() != hint ); + return insert_if_in_star(p, star_center, hint->full_cell()); + } + +// - - - - - - - - - - - - - - - - - - - - - - - - - GATHERING CONFLICTING SIMPLICES + + bool is_in_conflict(const Weighted_point &, Full_cell_const_handle) const; + + template< class OrientationPredicate > + Oriented_side perturbed_power_side_of_power_sphere(const Weighted_point &, + Full_cell_const_handle, const OrientationPredicate &) const; + + template< typename OutputIterator > + Facet compute_conflict_zone(const Weighted_point &, Full_cell_handle, OutputIterator) const; + + template < typename OrientationPredicate, typename PowerTestPredicate > + class Conflict_predicate + { + const Self & rt_; + const Weighted_point & p_; + OrientationPredicate ori_; + PowerTestPredicate power_side_of_power_sphere_; + int cur_dim_; + public: + Conflict_predicate( + const Self & rt, + const Weighted_point & p, + const OrientationPredicate & ori, + const PowerTestPredicate & power_side_of_power_sphere) + : rt_(rt), p_(p), ori_(ori), power_side_of_power_sphere_(power_side_of_power_sphere), cur_dim_(rt.current_dimension()) {} + + inline + bool operator()(Full_cell_const_handle s) const + { + bool ok; + if( ! rt_.is_infinite(s) ) + { + Oriented_side power_side_of_power_sphere = power_side_of_power_sphere_(rt_.points_begin(s), rt_.points_begin(s) + cur_dim_ + 1, p_); + if( ON_POSITIVE_SIDE == power_side_of_power_sphere ) + ok = true; + else if( ON_NEGATIVE_SIDE == power_side_of_power_sphere ) + ok = false; + else + ok = ON_POSITIVE_SIDE == rt_.perturbed_power_side_of_power_sphere<OrientationPredicate>(p_, s, ori_); + } + else + { + typedef typename Full_cell::Vertex_handle_const_iterator VHCI; + typedef Substitute_point_in_vertex_iterator<VHCI> F; + F spivi(rt_.infinite_vertex(), &p_); + + Orientation o = ori_( + boost::make_transform_iterator(s->vertices_begin(), spivi), + boost::make_transform_iterator(s->vertices_begin() + cur_dim_ + 1, + spivi)); + + if( POSITIVE == o ) + ok = true; + else if( o == NEGATIVE ) + ok = false; + else + ok = (*this)(s->neighbor( s->index( rt_.infinite_vertex() ) )); + } + return ok; + } + }; + + template < typename ConflictPredicate > + class Conflict_traversal_predicate + { + const Self & rt_; + const ConflictPredicate & pred_; + public: + Conflict_traversal_predicate(const Self & rt, const ConflictPredicate & pred) + : rt_(rt), pred_(pred) + {} + inline + bool operator()(const Facet & f) const + { + return pred_(rt_.full_cell(f)->neighbor(rt_.index_of_covertex(f))); + } + }; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY + + bool is_valid(bool verbose = false, int level = 0) const; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MISC + + std::size_t number_of_hidden_vertices() const + { + return m_hidden_points.size(); + } + +private: + + template<typename InputIterator> + bool + does_cell_range_contain_vertex(InputIterator cz_begin, InputIterator cz_end, + Vertex_handle vh) const + { + // Check all vertices + while(cz_begin != cz_end) + { + Full_cell_handle fch = *cz_begin; + for (int i = 0 ; i <= current_dimension() ; ++i) + { + if (fch->vertex(i) == vh) + return true; + } + ++cz_begin; + } + return false; + } + + template<typename InputIterator, typename OutputIterator> + void + process_conflict_zone(InputIterator cz_begin, InputIterator cz_end, + OutputIterator vertices_out) const + { + // Get all vertices + while(cz_begin != cz_end) + { + Full_cell_handle fch = *cz_begin; + for (int i = 0 ; i <= current_dimension() ; ++i) + { + Vertex_handle vh = fch->vertex(i); + if (vh->full_cell() != Full_cell_handle()) + { + (*vertices_out++) = vh; + vh->set_full_cell(Full_cell_handle()); + } + } + ++cz_begin; + } + } + + + template<typename InputIterator> + void + process_cz_vertices_after_insertion(InputIterator vertices_begin, + InputIterator vertices_end) + { + // Get all vertices + while(vertices_begin != vertices_end) + { + Vertex_handle vh = *vertices_begin; + if (vh->full_cell() == Full_cell_handle()) + { + m_hidden_points.push_back(vh->point()); + tds().delete_vertex(vh); + } + ++vertices_begin; + } + } + +private: + // Some internal types to shorten notation + using typename Base::Coaffine_orientation_d; + using Base::flat_orientation_; + typedef Conflict_predicate<Coaffine_orientation_d, Power_side_of_power_sphere_for_non_maximal_dim_d> + Conflict_pred_in_subspace; + typedef Conflict_predicate<Orientation_d, Power_side_of_power_sphere_d> + Conflict_pred_in_fullspace; + typedef Conflict_traversal_predicate<Conflict_pred_in_subspace> + Conflict_traversal_pred_in_subspace; + typedef Conflict_traversal_predicate<Conflict_pred_in_fullspace> + Conflict_traversal_pred_in_fullspace; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MEMBER VARIABLES + std::vector<Weighted_point> m_hidden_points; + +}; // class Regular_triangulation + + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +// FUNCTIONS THAT ARE MEMBER METHODS: + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS + + +// Warning: this function is not correct since it does not restore hidden +// vertices +template< typename Traits, typename TDS > +typename Regular_triangulation<Traits, TDS>::Full_cell_handle +Regular_triangulation<Traits, TDS> +::remove( Vertex_handle v ) +{ + CGAL_precondition( ! is_infinite(v) ); + CGAL_expensive_precondition( is_vertex(v) ); + + // THE CASE cur_dim == 0 + if( 0 == current_dimension() ) + { + remove_decrease_dimension(v); + return Full_cell_handle(); + } + else if( 1 == current_dimension() ) + { // THE CASE cur_dim == 1 + if( 2 == number_of_vertices() ) + { + remove_decrease_dimension(v); + return Full_cell_handle(); + } + Full_cell_handle left = v->full_cell(); + if( 0 == left->index(v) ) + left = left->neighbor(1); + CGAL_assertion( 1 == left->index(v) ); + Full_cell_handle right = left->neighbor(0); + tds().associate_vertex_with_full_cell(left, 1, right->vertex(1)); + set_neighbors(left, 0, right->neighbor(0), right->mirror_index(0)); + tds().delete_vertex(v); + tds().delete_full_cell(right); + return left; + } + + // THE CASE cur_dim >= 2 + // Gather the finite vertices sharing an edge with |v| + typedef typename Base::template Full_cell_set<Full_cell_handle> Simplices; + Simplices simps; + std::back_insert_iterator<Simplices> out(simps); + tds().incident_full_cells(v, out); + typedef std::set<Vertex_handle> Vertex_set; + Vertex_set verts; + Vertex_handle vh; + for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it ) + for( int i = 0; i <= current_dimension(); ++i ) + { + vh = (*it)->vertex(i); + if( is_infinite(vh) ) + continue; + if( vh == v ) + continue; + verts.insert(vh); + } + + // After gathering finite neighboring vertices, create their Dark Delaunay triangulation + typedef Triangulation_vertex<Geom_traits, Vertex_handle> Dark_vertex_base; + typedef Triangulation_full_cell< + Geom_traits, + internal::Triangulation::Dark_full_cell_data<TDS> > Dark_full_cell_base; + typedef Triangulation_data_structure<Maximal_dimension, + Dark_vertex_base, + Dark_full_cell_base + > Dark_tds; + typedef Regular_triangulation<Traits, Dark_tds> Dark_triangulation; + typedef typename Dark_triangulation::Face Dark_face; + typedef typename Dark_triangulation::Facet Dark_facet; + typedef typename Dark_triangulation::Vertex_handle Dark_v_handle; + typedef typename Dark_triangulation::Full_cell_handle Dark_s_handle; + + // If flat_orientation_ is defined, we give it the Dark triangulation + // so that the orientation it uses for "current_dimension()"-simplices is + // coherent with the global triangulation + Dark_triangulation dark_side( + maximal_dimension(), + flat_orientation_ ? + std::pair<int, const Flat_orientation_d *>(current_dimension(), flat_orientation_.get_ptr()) + : std::pair<int, const Flat_orientation_d *>(std::numeric_limits<int>::max(), NULL) ); + + Dark_s_handle dark_s; + Dark_v_handle dark_v; + typedef std::map<Vertex_handle, Dark_v_handle> Vertex_map; + Vertex_map light_to_dark; + typename Vertex_set::iterator vit = verts.begin(); + while( vit != verts.end() ) + { + dark_v = dark_side.insert((*vit)->point(), dark_s); + dark_s = dark_v->full_cell(); + dark_v->data() = *vit; + light_to_dark[*vit] = dark_v; + ++vit; + } + + if( dark_side.current_dimension() != current_dimension() ) + { + CGAL_assertion( dark_side.current_dimension() + 1 == current_dimension() ); + // Here, the finite neighbors of |v| span a affine subspace of + // dimension one less than the current dimension. Two cases are possible: + if( (size_type)(verts.size() + 1) == number_of_vertices() ) + { + remove_decrease_dimension(v); + return Full_cell_handle(); + } + else + { // |v| is strictly outside the convex hull of the rest of the points. This is an + // easy case: first, modify the finite full_cells, then, delete the infinite ones. + // We don't even need the Dark triangulation. + Simplices infinite_simps; + { + Simplices finite_simps; + for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it ) + if( is_infinite(*it) ) + infinite_simps.push_back(*it); + else + finite_simps.push_back(*it); + simps.swap(finite_simps); + } // now, simps only contains finite simplices + // First, modify the finite full_cells: + for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it ) + { + int v_idx = (*it)->index(v); + tds().associate_vertex_with_full_cell(*it, v_idx, infinite_vertex()); + } + // Make the handles to infinite full cells searchable + infinite_simps.make_searchable(); + // Then, modify the neighboring relation + for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it ) + { + for( int i = 0 ; i <= current_dimension(); ++i ) + { + if (is_infinite((*it)->vertex(i))) + continue; + (*it)->vertex(i)->set_full_cell(*it); + Full_cell_handle n = (*it)->neighbor(i); + // Was |n| a finite full cell prior to removing |v| ? + if( ! infinite_simps.contains(n) ) + continue; + int n_idx = n->index(v); + set_neighbors(*it, i, n->neighbor(n_idx), n->neighbor(n_idx)->index(n)); + } + } + Full_cell_handle ret_s; + // Then, we delete the infinite full_cells + for( typename Simplices::iterator it = infinite_simps.begin(); it != infinite_simps.end(); ++it ) + tds().delete_full_cell(*it); + tds().delete_vertex(v); + return simps.front(); + } + } + else // From here on, dark_side.current_dimension() == current_dimension() + { + dark_side.infinite_vertex()->data() = infinite_vertex(); + light_to_dark[infinite_vertex()] = dark_side.infinite_vertex(); + } + + // Now, compute the conflict zone of v->point() in + // the dark side. This is precisely the set of full_cells + // that we have to glue back into the light side. + Dark_face dark_f(dark_side.maximal_dimension()); + Dark_facet dark_ft; + typename Dark_triangulation::Locate_type lt; + dark_s = dark_side.locate(v->point(), lt, dark_f, dark_ft); + CGAL_assertion( lt != Dark_triangulation::ON_VERTEX + && lt != Dark_triangulation::OUTSIDE_AFFINE_HULL ); + + // |ret_s| is the full_cell that we return + Dark_s_handle dark_ret_s = dark_s; + Full_cell_handle ret_s; + + typedef typename Base::template Full_cell_set<Dark_s_handle> Dark_full_cells; + Dark_full_cells conflict_zone; + std::back_insert_iterator<Dark_full_cells> dark_out(conflict_zone); + + dark_ft = dark_side.compute_conflict_zone(v->point(), dark_s, dark_out); + // Make the dark simplices in the conflict zone searchable + conflict_zone.make_searchable(); + + // THE FOLLOWING SHOULD MAYBE GO IN TDS. + // Here is the plan: + // 1. Pick any Facet from boundary of the light zone + // 2. Find corresponding Facet on boundary of dark zone + // 3. stitch. + + // 1. Build a facet on the boudary of the light zone: + Full_cell_handle light_s = *simps.begin(); + Facet light_ft(light_s, light_s->index(v)); + + // 2. Find corresponding Dark_facet on boundary of the dark zone + Dark_full_cells dark_incident_s; + for( int i = 0; i <= current_dimension(); ++i ) + { + if( index_of_covertex(light_ft) == i ) + continue; + Dark_v_handle dark_v = light_to_dark[full_cell(light_ft)->vertex(i)]; + dark_incident_s.clear(); + dark_out = std::back_inserter(dark_incident_s); + dark_side.tds().incident_full_cells(dark_v, dark_out); + for(typename Dark_full_cells::iterator it = dark_incident_s.begin(); + it != dark_incident_s.end(); + ++it) + { + (*it)->data().count_ += 1; + } + } + + for( typename Dark_full_cells::iterator it = dark_incident_s.begin(); it != dark_incident_s.end(); ++it ) + { + if( current_dimension() != (*it)->data().count_ ) + continue; + if( ! conflict_zone.contains(*it) ) + continue; + // We found a full_cell incident to the dark facet corresponding to the light facet |light_ft| + int ft_idx = 0; + while( light_s->has_vertex( (*it)->vertex(ft_idx)->data() ) ) + ++ft_idx; + dark_ft = Dark_facet(*it, ft_idx); + break; + } + // Pre-3. Now, we are ready to traverse both boundary and do the stiching. + + // But first, we create the new full_cells in the light triangulation, + // with as much adjacency information as possible. + + // Create new full_cells with vertices + for( typename Dark_full_cells::iterator it = conflict_zone.begin(); it != conflict_zone.end(); ++it ) + { + Full_cell_handle new_s = new_full_cell(); + (*it)->data().light_copy_ = new_s; + for( int i = 0; i <= current_dimension(); ++i ) + tds().associate_vertex_with_full_cell(new_s, i, (*it)->vertex(i)->data()); + if( dark_ret_s == *it ) + ret_s = new_s; + } + + // Setup adjacencies inside the hole + for( typename Dark_full_cells::iterator it = conflict_zone.begin(); it != conflict_zone.end(); ++it ) + { + Full_cell_handle new_s = (*it)->data().light_copy_; + for( int i = 0; i <= current_dimension(); ++i ) + if( conflict_zone.contains((*it)->neighbor(i)) ) + tds().set_neighbors(new_s, i, (*it)->neighbor(i)->data().light_copy_, (*it)->mirror_index(i)); + } + + // 3. Stitch + simps.make_searchable(); + typedef std::queue<std::pair<Facet, Dark_facet> > Queue; + Queue q; + q.push(std::make_pair(light_ft, dark_ft)); + dark_s = dark_side.full_cell(dark_ft); + int dark_i = dark_side.index_of_covertex(dark_ft); + // mark dark_ft as visited: + // TODO try by marking with Dark_v_handle (vertex) + dark_s->neighbor(dark_i)->set_neighbor(dark_s->mirror_index(dark_i), Dark_s_handle()); + while( ! q.empty() ) + { + std::pair<Facet, Dark_facet> p = q.front(); + q.pop(); + light_ft = p.first; + dark_ft = p.second; + light_s = full_cell(light_ft); + int light_i = index_of_covertex(light_ft); + dark_s = dark_side.full_cell(dark_ft); + int dark_i = dark_side.index_of_covertex(dark_ft); + Full_cell_handle light_n = light_s->neighbor(light_i); + set_neighbors(dark_s->data().light_copy_, dark_i, light_n, light_s->mirror_index(light_i)); + for( int di = 0; di <= current_dimension(); ++di ) + { + if( di == dark_i ) + continue; + int li = light_s->index(dark_s->vertex(di)->data()); + Rotor light_r(light_s, li, light_i); + typename Dark_triangulation::Rotor dark_r(dark_s, di, dark_i); + + while( simps.contains(cpp11::get<0>(light_r)->neighbor(cpp11::get<1>(light_r))) ) + light_r = rotate_rotor(light_r); + + while( conflict_zone.contains(cpp11::get<0>(dark_r)->neighbor(cpp11::get<1>(dark_r))) ) + dark_r = dark_side.rotate_rotor(dark_r); + + Dark_s_handle dark_ns = cpp11::get<0>(dark_r); + int dark_ni = cpp11::get<1>(dark_r); + Full_cell_handle light_ns = cpp11::get<0>(light_r); + int light_ni = cpp11::get<1>(light_r); + // mark dark_r as visited: + // TODO try by marking with Dark_v_handle (vertex) + Dark_s_handle outside = dark_ns->neighbor(dark_ni); + Dark_v_handle mirror = dark_ns->mirror_vertex(dark_ni, current_dimension()); + int dn = outside->index(mirror); + if( Dark_s_handle() == outside->neighbor(dn) ) + continue; + outside->set_neighbor(dn, Dark_s_handle()); + q.push(std::make_pair(Facet(light_ns, light_ni), Dark_facet(dark_ns, dark_ni))); + } + } + tds().delete_full_cells(simps.begin(), simps.end()); + tds().delete_vertex(v); + return ret_s; +} + +template< typename Traits, typename TDS > +void +Regular_triangulation<Traits, TDS> +::remove_decrease_dimension(Vertex_handle v) +{ + CGAL_precondition( current_dimension() >= 0 ); + tds().remove_decrease_dimension(v, infinite_vertex()); + // reset the predicates: + reset_flat_orientation(); + if( 1 <= current_dimension() ) + { + Full_cell_handle inf_v_cell = infinite_vertex()->full_cell(); + int inf_v_index = inf_v_cell->index(infinite_vertex()); + Full_cell_handle s = inf_v_cell->neighbor(inf_v_index); + Orientation o = orientation(s); + CGAL_assertion( ZERO != o ); + if( NEGATIVE == o ) + reorient_full_cells(); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INSERTIONS + +template< typename Traits, typename TDS > +typename Regular_triangulation<Traits, TDS>::Vertex_handle +Regular_triangulation<Traits, TDS> +::insert(const Weighted_point & p, Locate_type lt, const Face & f, const Facet & ft, Full_cell_handle s) +{ + switch( lt ) + { + case Base::OUTSIDE_AFFINE_HULL: + return insert_outside_affine_hull(p); + break; + case Base::ON_VERTEX: + { + Vertex_handle v = s->vertex(f.index(0)); + typename RTTraits::Compute_weight_d pw = + geom_traits().compute_weight_d_object(); + + if (pw(p) == pw(v->point())) + return v; + // If dim == 0 and the new point has a bigger weight, + // we just replace the point, and the former point gets hidden + else if (current_dimension() == 0) + { + if (pw(p) > pw(v->point())) + { + m_hidden_points.push_back(v->point()); + v->set_point(p); + return v; + } + // Otherwise, the new point is hidden + else + { + m_hidden_points.push_back(p); + return Vertex_handle(); + } + } + // Otherwise, we apply the "normal" algorithm + + // !NO break here! + } + default: + return insert_in_conflicting_cell(p, s); + } +} + +/* +Inserts the point `p` in the regular triangulation. Returns a handle to the +newly created vertex at that position. +\pre The point `p` +must lie outside the affine hull of the regular triangulation. This implies that +`rt`.`current_dimension()` must be smaller than `rt`.`maximal_dimension()`. +*/ +template< typename Traits, typename TDS > +typename Regular_triangulation<Traits, TDS>::Vertex_handle +Regular_triangulation<Traits, TDS> +::insert_outside_affine_hull(const Weighted_point & p) +{ + // we don't use Base::insert_outside_affine_hull(...) because here, we + // also need to reset the side_of_oriented_subsphere functor. + CGAL_precondition( current_dimension() < maximal_dimension() ); + Vertex_handle v = tds().insert_increase_dimension(infinite_vertex()); + // reset the predicates: + reset_flat_orientation(); + v->set_point(p); + if( current_dimension() >= 1 ) + { + Full_cell_handle inf_v_cell = infinite_vertex()->full_cell(); + int inf_v_index = inf_v_cell->index(infinite_vertex()); + Full_cell_handle s = inf_v_cell->neighbor(inf_v_index); + Orientation o = orientation(s); + CGAL_assertion( ZERO != o ); + if( NEGATIVE == o ) + reorient_full_cells(); + + // We just inserted the second finite point and the right infinite + // cell is like : (inf_v, v), but we want it to be (v, inf_v) to be + // consistent with the rest of the cells + if (current_dimension() == 1) + { + // Is "inf_v_cell" the right infinite cell? Then inf_v_index should be 1 + if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0 + && inf_v_index == 0) + { + inf_v_cell->swap_vertices(current_dimension() - 1, current_dimension()); + } + else + { + inf_v_cell = inf_v_cell->neighbor((inf_v_index + 1) % 2); + inf_v_index = inf_v_cell->index(infinite_vertex()); + // Is "inf_v_cell" the right infinite cell? Then inf_v_index should be 1 + if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0 + && inf_v_index == 0) + { + inf_v_cell->swap_vertices(current_dimension() - 1, current_dimension()); + } + } + } + } + return v; +} + +template< typename Traits, typename TDS > +typename Regular_triangulation<Traits, TDS>::Vertex_handle +Regular_triangulation<Traits, TDS> +::insert_if_in_star(const Weighted_point & p, + Vertex_handle star_center, + Locate_type lt, + const Face & f, + const Facet & ft, + Full_cell_handle s) +{ + switch( lt ) + { + case Base::OUTSIDE_AFFINE_HULL: + return insert_outside_affine_hull(p); + break; + case Base::ON_VERTEX: + { + Vertex_handle v = s->vertex(f.index(0)); + typename RTTraits::Compute_weight_d pw = + geom_traits().compute_weight_d_object(); + if (pw(p) == pw(v->point())) + return v; + // If dim == 0 and the new point has a bigger weight, + // we replace the point + else if (current_dimension() == 0) + { + if (pw(p) > pw(v->point())) + v->set_point(p); + else + return v; + } + // Otherwise, we apply the "normal" algorithm + + // !NO break here! + } + default: + return insert_in_conflicting_cell(p, s, star_center); + } + + return Vertex_handle(); +} + +/* +[Undocumented function] + +Inserts the point `p` in the regular triangulation. `p` must be +in conflict with the second parameter `c`, which is used as a +starting point for `compute_conflict_zone`. +The function is faster than the standard `insert` function since +it does not need to call `locate`. + +If this insertion creates a vertex, this vertex is returned. + +If `p` coincides with an existing vertex and has a greater weight, +then the existing weighted point becomes hidden and `p` replaces it as vertex +of the triangulation. + +If `p` coincides with an already existing vertex (both point and +weights being equal), then this vertex is returned and the triangulation +remains unchanged. + +Otherwise if `p` does not appear as a vertex of the triangulation, +then it is stored as a hidden point and this method returns the default +constructed handle. + +\pre The point `p` must be in conflict with the full cell `c`. +*/ + +template< typename Traits, typename TDS > +typename Regular_triangulation<Traits, TDS>::Vertex_handle +Regular_triangulation<Traits, TDS> +::insert_in_conflicting_cell(const Weighted_point & p, + Full_cell_handle s, + Vertex_handle only_if_this_vertex_is_in_the_cz) +{ + typedef std::vector<Full_cell_handle> Full_cell_h_vector; + + bool in_conflict = is_in_conflict(p, s); + + // If p is not in conflict with s, then p is hidden + // => we don't insert it + if (!in_conflict) + { + m_hidden_points.push_back(p); + return Vertex_handle(); + } + else + { + Full_cell_h_vector cs; // for storing conflicting full_cells. + cs.reserve(64); + std::back_insert_iterator<Full_cell_h_vector> out(cs); + Facet ft = compute_conflict_zone(p, s, out); + + // Check if the CZ contains "only_if_this_vertex_is_in_the_cz" + if (only_if_this_vertex_is_in_the_cz != Vertex_handle() + && !does_cell_range_contain_vertex(cs.begin(), cs.end(), + only_if_this_vertex_is_in_the_cz)) + { + return Vertex_handle(); + } + + // Otherwise, proceed with the insertion + std::vector<Vertex_handle> cz_vertices; + cz_vertices.reserve(64); + process_conflict_zone(cs.begin(), cs.end(), + std::back_inserter(cz_vertices)); + + Vertex_handle ret = insert_in_hole(p, cs.begin(), cs.end(), ft); + + process_cz_vertices_after_insertion(cz_vertices.begin(), cz_vertices.end()); + + return ret; + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - GATHERING CONFLICTING SIMPLICES + +// NOT DOCUMENTED +template< typename Traits, typename TDS > +template< typename OrientationPred > +Oriented_side +Regular_triangulation<Traits, TDS> +::perturbed_power_side_of_power_sphere(const Weighted_point & p, Full_cell_const_handle s, + const OrientationPred & ori) const +{ + CGAL_precondition_msg( ! is_infinite(s), "full cell must be finite"); + CGAL_expensive_precondition( POSITIVE == orientation(s) ); + typedef std::vector<const Weighted_point *> Points; + Points points(current_dimension() + 2); + int i(0); + for( ; i <= current_dimension(); ++i ) + points[i] = &(s->vertex(i)->point()); + points[i] = &p; + std::sort(points.begin(), points.end(), + internal::Triangulation::Compare_points_for_perturbation<Self>(*this)); + typename Points::const_reverse_iterator cut_pt = points.rbegin(); + Points test_points; + while( cut_pt != points.rend() ) + { + if( &p == *cut_pt ) + // because the full_cell "s" is assumed to be positively oriented + return ON_NEGATIVE_SIDE; // we consider |p| to lie outside the sphere + test_points.clear(); + Point_const_iterator spit = points_begin(s); + int adjust_sign = -1; + for( i = 0; i < current_dimension(); ++i ) + { + if( &(*spit) == *cut_pt ) + { + ++spit; + adjust_sign = (((current_dimension() + i) % 2) == 0) ? -1 : +1; + } + test_points.push_back(&(*spit)); + ++spit; + } + test_points.push_back(&p); + + typedef typename CGAL::Iterator_project< + typename Points::iterator, + internal::Triangulation::Point_from_pointer<Self>, + const Weighted_point &, const Weighted_point * + > Point_pointer_iterator; + + Orientation ori_value = ori( + Point_pointer_iterator(test_points.begin()), + Point_pointer_iterator(test_points.end())); + + if( ZERO != ori_value ) + return Oriented_side( - adjust_sign * ori_value ); + + ++cut_pt; + } + CGAL_assertion(false); // we should never reach here + return ON_NEGATIVE_SIDE; +} + +template< typename Traits, typename TDS > +bool +Regular_triangulation<Traits, TDS> +::is_in_conflict(const Weighted_point & p, Full_cell_const_handle s) const +{ + CGAL_precondition( 1 <= current_dimension() ); + if( current_dimension() < maximal_dimension() ) + { + Conflict_pred_in_subspace c( + *this, p, + coaffine_orientation_predicate(), + power_side_of_power_sphere_for_non_maximal_dim_predicate()); + return c(s); + } + else + { + Orientation_d ori = geom_traits().orientation_d_object(); + Power_side_of_power_sphere_d side = geom_traits().power_side_of_power_sphere_d_object(); + Conflict_pred_in_fullspace c(*this, p, ori, side); + return c(s); + } +} + +template< typename Traits, typename TDS > +template< typename OutputIterator > +typename Regular_triangulation<Traits, TDS>::Facet +Regular_triangulation<Traits, TDS> +::compute_conflict_zone(const Weighted_point & p, Full_cell_handle s, OutputIterator out) const +{ + CGAL_precondition( 1 <= current_dimension() ); + if( current_dimension() < maximal_dimension() ) + { + Conflict_pred_in_subspace c( + *this, p, + coaffine_orientation_predicate(), + power_side_of_power_sphere_for_non_maximal_dim_predicate()); + Conflict_traversal_pred_in_subspace tp(*this, c); + return tds().gather_full_cells(s, tp, out); + } + else + { + Orientation_d ori = geom_traits().orientation_d_object(); + Power_side_of_power_sphere_d side = geom_traits().power_side_of_power_sphere_d_object(); + Conflict_pred_in_fullspace c(*this, p, ori, side); + Conflict_traversal_pred_in_fullspace tp(*this, c); + return tds().gather_full_cells(s, tp, out); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY + +template< typename Traits, typename TDS > +bool +Regular_triangulation<Traits, TDS> +::is_valid(bool verbose, int level) const +{ + if (!Base::is_valid(verbose, level)) + return false; + + int dim = current_dimension(); + if (dim == maximal_dimension()) + { + for (Finite_full_cell_const_iterator cit = finite_full_cells_begin() ; + cit != finite_full_cells_end() ; ++cit ) + { + Full_cell_const_handle ch = cit.base(); + for(int i = 0; i < dim+1 ; ++i ) + { + // If the i-th neighbor is not an infinite cell + Vertex_handle opposite_vh = + ch->neighbor(i)->vertex(ch->neighbor(i)->index(ch)); + if (!is_infinite(opposite_vh)) + { + Power_side_of_power_sphere_d side = + geom_traits().power_side_of_power_sphere_d_object(); + if (side(Point_const_iterator(ch->vertices_begin()), + Point_const_iterator(ch->vertices_end()), + opposite_vh->point()) == ON_POSITIVE_SIDE) + { + if (verbose) + CGAL_warning_msg(false, "Non-empty sphere"); + return false; + } + } + } + } + } + return true; +} + +} //namespace CGAL + +#endif //CGAL_REGULAR_TRIANGULATION_H diff --git a/src/common/include/gudhi_patches/CGAL/Regular_triangulation_traits_adapter.h b/src/common/include/gudhi_patches/CGAL/Regular_triangulation_traits_adapter.h new file mode 100644 index 00000000..78bb95a6 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/Regular_triangulation_traits_adapter.h @@ -0,0 +1,288 @@ +// Copyright (c) 2014 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Clement Jamin + +#ifndef CGAL_REGULAR_TRIANGULATION_TRAITS_ADAPTER_H +#define CGAL_REGULAR_TRIANGULATION_TRAITS_ADAPTER_H + +#include <CGAL/basic.h> + +#include <boost/iterator/transform_iterator.hpp> + +namespace CGAL { + +// Wrapper class to make a model of `RegularTriangulationTraits` easily usable +// by the `Regular_triangulation` class. By using this class: +// - Point_d (used by `Triangulation` and the TDS) becomes a weighted point +// - Predicates and functors such as Less_coordinate_d or Orientation_d +// can be called using weighted points instead of bare points (this is +// needed because `Weighted_point_d` is not convertible to `Point_d`) +// This way, `Triangulation` works perfectly well with weighted points. + +template <class K> +class Regular_triangulation_traits_adapter + : public K +{ +public: + typedef K Base; + + // Required by TriangulationTraits + typedef typename K::Dimension Dimension; + typedef typename K::FT FT; + typedef typename K::Flat_orientation_d Flat_orientation_d; + typedef typename K::Weighted_point_d Point_d; + + // Required by RegularTriangulationTraits + typedef typename K::Point_d Bare_point_d; + typedef typename K::Weighted_point_d Weighted_point_d; + typedef typename K::Construct_point_d Construct_point_d; + typedef typename K::Compute_weight_d Compute_weight_d; + typedef typename K::Power_side_of_power_sphere_d Power_side_of_power_sphere_d; + typedef typename K::In_flat_power_side_of_power_sphere_d + In_flat_power_side_of_power_sphere_d; + + //=========================================================================== + // Custom types + //=========================================================================== + + // Required by SpatialSortingTraits_d + class Less_coordinate_d + { + const K &m_kernel; + + public: + typedef bool result_type; + + Less_coordinate_d(const K &kernel) + : m_kernel(kernel) {} + + result_type operator()( + Weighted_point_d const& p, Weighted_point_d const& q, int i) const + { + Construct_point_d cp = m_kernel.construct_point_d_object(); + return m_kernel.less_coordinate_d_object() (cp(p), cp(q), i); + } + }; + + //=========================================================================== + + // Required by TriangulationTraits + class Orientation_d + { + const K &m_kernel; + + public: + typedef Orientation result_type; + + Orientation_d(const K &kernel) + : m_kernel(kernel) {} + + template <typename ForwardIterator> + result_type operator()(ForwardIterator start, ForwardIterator end) const + { + Construct_point_d cp = m_kernel.construct_point_d_object(); + return m_kernel.orientation_d_object() ( + boost::make_transform_iterator(start, cp), + boost::make_transform_iterator(end, cp) + ); + } + }; + + //=========================================================================== + + // Required by TriangulationTraits + class Construct_flat_orientation_d + { + const K &m_kernel; + + public: + typedef Flat_orientation_d result_type; + + Construct_flat_orientation_d(const K &kernel) + : m_kernel(kernel) {} + + template <typename ForwardIterator> + result_type operator()(ForwardIterator start, ForwardIterator end) const + { + Construct_point_d cp = m_kernel.construct_point_d_object(); + return m_kernel.construct_flat_orientation_d_object() ( + boost::make_transform_iterator(start, cp), + boost::make_transform_iterator(end, cp) + ); + } + }; + + + //=========================================================================== + + // Required by TriangulationTraits + class In_flat_orientation_d + { + const K &m_kernel; + + public: + typedef Orientation result_type; + + In_flat_orientation_d(const K &kernel) + : m_kernel(kernel) {} + + template <typename ForwardIterator> + result_type operator()(Flat_orientation_d orient, + ForwardIterator start, ForwardIterator end) const + { + Construct_point_d cp = m_kernel.construct_point_d_object(); + return m_kernel.in_flat_orientation_d_object() ( + orient, + boost::make_transform_iterator(start, cp), + boost::make_transform_iterator(end, cp) + ); + } + }; + + //=========================================================================== + + // Required by TriangulationTraits + class Contained_in_affine_hull_d + { + const K &m_kernel; + + public: + typedef bool result_type; + + Contained_in_affine_hull_d(const K &kernel) + : m_kernel(kernel) {} + + template <typename ForwardIterator> + result_type operator()(ForwardIterator start, ForwardIterator end, + const Weighted_point_d & p) const + { + Construct_point_d cp = m_kernel.construct_point_d_object(); + return m_kernel.contained_in_affine_hull_d_object() ( + boost::make_transform_iterator(start, cp), + boost::make_transform_iterator(end, cp), + cp(p) + ); + } + }; + + //=========================================================================== + + // Required by TriangulationTraits + class Compare_lexicographically_d + { + const K &m_kernel; + + public: + typedef Comparison_result result_type; + + Compare_lexicographically_d(const K &kernel) + : m_kernel(kernel) {} + + result_type operator()( + const Weighted_point_d & p, const Weighted_point_d & q) const + { + Construct_point_d cp = m_kernel.construct_point_d_object(); + return m_kernel.compare_lexicographically_d_object()(cp(p), cp(q)); + } + }; + + //=========================================================================== + + // Only for Triangulation_off_ostream.h (undocumented) + class Compute_coordinate_d + { + const K &m_kernel; + + public: + typedef FT result_type; + + Compute_coordinate_d(const K &kernel) + : m_kernel(kernel) {} + + result_type operator()( + const Weighted_point_d & p, const int i) const + { + Construct_point_d cp = m_kernel.construct_point_d_object(); + return m_kernel.compute_coordinate_d_object()(cp(p), i); + } + }; + + //=========================================================================== + + // To satisfy SpatialSortingTraits_d + // and also for Triangulation_off_ostream.h (undocumented) + class Point_dimension_d + { + const K &m_kernel; + + public: + typedef int result_type; + + Point_dimension_d(const K &kernel) + : m_kernel(kernel) {} + + result_type operator()( + const Weighted_point_d & p) const + { + Construct_point_d cp = m_kernel.construct_point_d_object(); + return m_kernel.point_dimension_d_object()(cp(p)); + } + }; + + //=========================================================================== + // Object creation + //=========================================================================== + + Less_coordinate_d less_coordinate_d_object() const + { + return Less_coordinate_d(*this); + } + Contained_in_affine_hull_d contained_in_affine_hull_d_object() const + { + return Contained_in_affine_hull_d(*this); + } + Orientation_d orientation_d_object() const + { + return Orientation_d(*this); + } + Construct_flat_orientation_d construct_flat_orientation_d_object() const + { + return Construct_flat_orientation_d(*this); + } + In_flat_orientation_d in_flat_orientation_d_object() const + { + return In_flat_orientation_d(*this); + } + Compare_lexicographically_d compare_lexicographically_d_object() const + { + return Compare_lexicographically_d(*this); + } + Compute_coordinate_d compute_coordinate_d_object() const + { + return Compute_coordinate_d(*this); + } + Point_dimension_d point_dimension_d_object() const + { + return Point_dimension_d(*this); + } +}; + + +} //namespace CGAL + +#endif // CGAL_REGULAR_TRIANGULATION_TRAITS_ADAPTER_H diff --git a/src/common/include/gudhi_patches/CGAL/TDS_full_cell_default_storage_policy.h b/src/common/include/gudhi_patches/CGAL/TDS_full_cell_default_storage_policy.h new file mode 100644 index 00000000..9a6030e5 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/TDS_full_cell_default_storage_policy.h @@ -0,0 +1,99 @@ +// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Samuel Hornus + +#ifndef CGAL_TDS_FULL_CELL_DEFAULT_STORAGE_POLICY_H +#define CGAL_TDS_FULL_CELL_DEFAULT_STORAGE_POLICY_H + +#include <CGAL/Dimension.h> +#include <CGAL/Compact_container.h> +#include <CGAL/internal/Static_or_dynamic_array.h> + +#include <boost/cstdint.hpp> + +namespace CGAL { + +// POLICY TAG + +struct TDS_full_cell_default_storage_policy {}; // stores no additional data. Uses XOR trick. + +template< typename V, typename S, typename D, typename StoragePolicy > +struct TFC_data; // TFC = Triangulation Full Cell + +template< typename Vertex_handle, typename Full_cell_handle, typename Dimen > +struct TFC_data< Vertex_handle, Full_cell_handle, Dimen, TDS_full_cell_default_storage_policy > +{ + typedef typename internal::Dimen_plus_one<Dimen>::type Dimen_plus; + typedef typename internal::S_or_D_array< Vertex_handle, Dimen_plus, true > Vertex_handle_array; + typedef typename internal::S_or_D_array< Full_cell_handle, Dimen_plus > Full_cell_handle_array; + + Vertex_handle_array vertices_; + Full_cell_handle_array neighbors_; + + TFC_data(const int dmax) + : vertices_(dmax+1), neighbors_(dmax+1) + {} + void* for_compact_container() const { return vertices_.for_compact_container(); } + void* & for_compact_container() { return vertices_.for_compact_container(); } + int dimension() const { return ( vertices_.size() - 1 ); } + void set_mirror_index(const int, const int) {} +#ifdef BOOST_NO_INT64_T + typedef std::ptrdiff_t Xor_type; +#else + typedef boost::int_least64_t Xor_type; +#endif + Xor_type xor_of_vertices(const int cur_dim) const + { + Xor_type result(0); + for( int i = 0; i <= cur_dim; ++i ) + result ^= reinterpret_cast<Xor_type>(&(*vertices_[i])); + return result; + } + // ASSUMES |*this| is indeed a neighbor of neighbor(i): + // NOT correct when the hole (in insert_in_hole) is doubly covered. + int mirror_index(const int i) const + { + int index = 0; + Full_cell_handle n = neighbors_[i]; + Full_cell_handle o = n->neighbor(index); + while( &(o->combinatorics_) != this ) + o = n->neighbor(++index); + return index; + } + Vertex_handle mirror_vertex(const int i, const int cur_dim) const + { + Xor_type opp_vertex = xor_of_vertices(cur_dim) + ^ neighbors_[i]->xor_of_vertices(cur_dim) + ^ reinterpret_cast<Xor_type>(&(*vertices_[i])); + Vertex_handle mirror; + typedef typename Vertex_handle::pointer pointer; + // mirror.set_pointer(reinterpret_cast<pointer>(opp_vertex)); + mirror = Compact_container<typename Vertex_handle::value_type> + ::s_iterator_to(*(reinterpret_cast<pointer>(opp_vertex))); + return mirror; + } + void swap_vertices(const int d1, const int d2) + { + std::swap(vertices_[d1], vertices_[d2]); + std::swap(neighbors_[d1], neighbors_[d2]); + } +}; + +} //namespace CGAL + +#endif // CGAL_TDS_FULL_CELL_DEFAULT_STORAGE_POLICY_H diff --git a/src/common/include/gudhi_patches/CGAL/TDS_full_cell_mirror_storage_policy.h b/src/common/include/gudhi_patches/CGAL/TDS_full_cell_mirror_storage_policy.h new file mode 100644 index 00000000..095dfe68 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/TDS_full_cell_mirror_storage_policy.h @@ -0,0 +1,71 @@ +// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Samuel Hornus + +#ifndef CGAL_TDS_FULL_CELL_MIRROR_STORAGE_POLICY_H +#define CGAL_TDS_FULL_CELL_MIRROR_STORAGE_POLICY_H + +#include <CGAL/TDS_full_cell_default_storage_policy.h> + +namespace CGAL { + +// POLICY TAGS + +struct TDS_full_cell_mirror_storage_policy {}; // Stores the mirror index of all vertices. + +template< typename Vertex_handle, typename Full_cell_handle, typename Maximal_dimension > +struct TFC_data< Vertex_handle, Full_cell_handle, Maximal_dimension, TDS_full_cell_mirror_storage_policy > +: public TFC_data< Vertex_handle, Full_cell_handle, Maximal_dimension, TDS_full_cell_default_storage_policy > +{ + typedef TFC_data< Vertex_handle, Full_cell_handle, Maximal_dimension, TDS_full_cell_default_storage_policy > Base; + typedef typename Base::Vertex_handle_array Vertex_handle_array; + typedef typename Base::Full_cell_handle_array Full_cell_handle_array; + typedef typename internal::S_or_D_array< int, typename Base::Dimen_plus > Int_array; + +private: + Int_array mirror_vertices_; + +public: + TFC_data(const int dmax) + : Base(dmax), mirror_vertices_(dmax+1) + {} + + void set_mirror_index(const int i, const int index) + { + mirror_vertices_[i] = index; + } + int mirror_index(const int i) const + { + return mirror_vertices_[i]; + } + Vertex_handle mirror_vertex(const int i, const int) const + { + return Base::neighbors_[i]->vertex(mirror_index(i)); + } + void swap_vertices(const int d1, const int d2) + { + Base::swap_vertices(d1, d2); + std::swap(mirror_vertices_[d1], mirror_vertices_[d2]); + Base::neighbors_[d1]->set_mirror_index(mirror_vertices_[d1], d1); + Base::neighbors_[d2]->set_mirror_index(mirror_vertices_[d2], d2); + } +}; + +} //namespace CGAL + +#endif // CGAL_TDS_FULL_CELL_MIRROR_STORAGE_POLICY_H diff --git a/src/common/include/gudhi_patches/CGAL/Triangulation.h b/src/common/include/gudhi_patches/CGAL/Triangulation.h new file mode 100644 index 00000000..906df92e --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/Triangulation.h @@ -0,0 +1,1424 @@ +// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Samuel Hornus + +#ifndef CGAL_TRIANGULATION_H +#define CGAL_TRIANGULATION_H + +#include <CGAL/internal/Triangulation/utilities.h> +#include <CGAL/Triangulation_data_structure.h> +#include <CGAL/Triangulation_full_cell.h> +#include <CGAL/Triangulation_vertex.h> +#include <CGAL/Iterator_project.h> +#include <CGAL/spatial_sort.h> +#include <CGAL/Dimension.h> +#include <CGAL/iterator.h> +#include <CGAL/Default.h> +#include <CGAL/Random.h> + +#include <boost/iterator/filter_iterator.hpp> +#include <boost/iterator/transform_iterator.hpp> + +namespace CGAL { + +// Iterator which iterates over vertex_handle's, but returns a point when +// dereferenced. If the current +// vertex_handle vh == vh_where_point_should_be_substituted, it returns +// "subtitute_point", otherwise, it returns vh->point() +template<class VertexHandleConstIter> +class Substitute_point_in_vertex_iterator +{ + typedef typename std::iterator_traits<VertexHandleConstIter>::value_type Vertex_handle; + typedef typename Vertex_handle::value_type Vertex; + typedef typename Vertex::Point Point; + +public: + typedef Point const& result_type; // For result_of + + Substitute_point_in_vertex_iterator( + Vertex_handle vh_where_point_should_be_substituted, + Point const *subtitute_point) + : vh_where_point_should_be_substituted_(vh_where_point_should_be_substituted) + , subtitute_point_(subtitute_point) + {} + + result_type operator()(Vertex_handle vh) const + { + if (vh == vh_where_point_should_be_substituted_) + return *subtitute_point_; + else + return vh->point(); + } + +private: + Vertex_handle vh_where_point_should_be_substituted_; + Point const *subtitute_point_; + +}; + + +template < class TriangulationTraits, class TDS_ = Default > +class Triangulation +{ + typedef typename TriangulationTraits::Dimension Maximal_dimension_; + typedef typename Default::Get<TDS_, Triangulation_data_structure + < Maximal_dimension_, + Triangulation_vertex<TriangulationTraits>, + Triangulation_full_cell<TriangulationTraits> > + >::type TDS; + typedef Triangulation<TriangulationTraits, TDS_> Self; + +protected: + typedef typename TriangulationTraits::Flat_orientation_d Flat_orientation_d; + typedef typename TriangulationTraits::Construct_flat_orientation_d Construct_flat_orientation_d; + typedef typename TriangulationTraits::In_flat_orientation_d In_flat_orientation_d; + + // Wrapper + struct Coaffine_orientation_d + { + boost::optional<Flat_orientation_d>* fop; + Construct_flat_orientation_d cfo; + In_flat_orientation_d ifo; + + Coaffine_orientation_d( + boost::optional<Flat_orientation_d>& x, + Construct_flat_orientation_d const&y, + In_flat_orientation_d const&z) + : fop(&x), cfo(y), ifo(z) {} + + template<class Iter> + CGAL::Orientation operator()(Iter a, Iter b) const + { + if (*fop) + return ifo(fop->get(),a,b); + *fop = cfo(a,b); + CGAL_assertion(ifo(fop->get(),a,b) == CGAL::POSITIVE); + return CGAL::POSITIVE; + } + }; + + void reset_flat_orientation() + { + if (current_dimension() == preset_flat_orientation_.first) + { + CGAL_assertion(preset_flat_orientation_.second != NULL); + flat_orientation_ = *preset_flat_orientation_.second; + } + else + flat_orientation_ = boost::none; + } + + typedef typename TriangulationTraits::Orientation_d + Orientation_d; + +public: + + typedef TriangulationTraits Geom_traits; + typedef TDS Triangulation_ds; + + typedef typename TDS::Vertex Vertex; + typedef typename TDS::Full_cell Full_cell; + typedef typename TDS::Facet Facet; + typedef typename TDS::Face Face; + + typedef Maximal_dimension_ Maximal_dimension; + typedef typename Geom_traits::Point_d Point; + + typedef typename TDS::Vertex_handle Vertex_handle; + typedef typename TDS::Vertex_iterator Vertex_iterator; + typedef typename TDS::Vertex_const_handle Vertex_const_handle; + typedef typename TDS::Vertex_const_iterator Vertex_const_iterator; + + typedef typename TDS::Full_cell_handle Full_cell_handle; + typedef typename TDS::Full_cell_iterator Full_cell_iterator; + typedef typename TDS::Full_cell_const_handle Full_cell_const_handle; + typedef typename TDS::Full_cell_const_iterator Full_cell_const_iterator; + + typedef typename TDS::Facet_iterator Facet_iterator; + + typedef typename TDS::size_type size_type; + typedef typename TDS::difference_type difference_type; + + /// The type of location a new point is found lying on + enum Locate_type + { + ON_VERTEX = 0 // simplex of dimension 0 + , IN_FACE = 1 // simplex of dimension in [ 1, |current_dimension()| - 2 ] + , IN_FACET = 2 // simplex of dimension |current_dimension()| - 1 + , IN_FULL_CELL = 3 /// simplex of dimension |current_dimension()| + , OUTSIDE_CONVEX_HULL = 4 + , OUTSIDE_AFFINE_HULL = 5 + }; + + // Finite elements iterators + + class Finiteness_predicate; + + typedef boost::filter_iterator<Finiteness_predicate, Vertex_iterator> + Finite_vertex_iterator; + typedef boost::filter_iterator<Finiteness_predicate, Vertex_const_iterator> + Finite_vertex_const_iterator; + typedef boost::filter_iterator<Finiteness_predicate, Full_cell_iterator> + Finite_full_cell_iterator; + typedef boost::filter_iterator<Finiteness_predicate, Full_cell_const_iterator> + Finite_full_cell_const_iterator; + typedef boost::filter_iterator<Finiteness_predicate, Facet_iterator> + Finite_facet_iterator; + +protected: // DATA MEMBERS + + Triangulation_ds tds_; + const Geom_traits kernel_; + Vertex_handle infinity_; + mutable std::vector<Oriented_side> orientations_; + mutable boost::optional<Flat_orientation_d> flat_orientation_; + // The user can specify a Flat_orientation_d object to be used for + // orienting simplices of a specific dimension + // (= preset_flat_orientation_.first) + // preset_flat_orientation_.first = numeric_limits<int>::max() otherwise) + std::pair<int, const Flat_orientation_d *> preset_flat_orientation_; + // for stochastic walk in the locate() function: + mutable Random rng_; +#ifdef CGAL_TRIANGULATION_STATISTICS + mutable unsigned long walk_size_; +#endif + +protected: // HELPER FUNCTIONS + + typedef CGAL::Iterator_project< + typename Full_cell::Vertex_handle_const_iterator, + internal::Triangulation::Point_from_vertex_handle<Vertex_handle, Point> + > Point_const_iterator; + + Point_const_iterator points_begin(Full_cell_const_handle c) const + { return Point_const_iterator(c->vertices_begin()); } + Point_const_iterator points_end(Full_cell_const_handle c) const + { return Point_const_iterator(c->vertices_end()); } + Point_const_iterator points_begin(Full_cell_handle c) const + { return Point_const_iterator(c->vertices_begin()); } + Point_const_iterator points_end(Full_cell_handle c) const + { return Point_const_iterator(c->vertices_end()); } + +public: + + // FACETS OPERATIONS + + Full_cell_handle full_cell(const Facet & f) const + { + return tds().full_cell(f); + } + + int index_of_covertex(const Facet & f) const + { + return tds().index_of_covertex(f); + } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - UTILITIES + + // A co-dimension 2 sub-simplex. called a Rotor because we can rotate + // the two "covertices" around the sub-simplex. Useful for traversing the + // boundary of a hole. NOT DOCUMENTED + typedef cpp11::tuple<Full_cell_handle, int, int> Rotor; + + // Commented out because it was causing "internal compiler error" in MSVC + /*Full_cell_handle full_cell(const Rotor & r) const // NOT DOCUMENTED + { + return cpp11::get<0>(r); + } + int index_of_covertex(const Rotor & r) const // NOT DOCUMENTED + { + return cpp11::get<1>(r); + } + int index_of_second_covertex(const Rotor & r) const // NOT DOCUMENTED + { + return cpp11::get<2>(r); + }*/ + Rotor rotate_rotor(Rotor & r) // NOT DOCUMENTED... + { + int opposite = cpp11::get<0>(r)->mirror_index(cpp11::get<1>(r)); + Full_cell_handle s = cpp11::get<0>(r)->neighbor(cpp11::get<1>(r)); + int new_second = s->index(cpp11::get<0>(r)->vertex(cpp11::get<2>(r))); + return Rotor(s, new_second, opposite); + } + + // - - - - - - - - - - - - - - - - - - - - - - - - CREATION / CONSTRUCTORS + + Triangulation(int dim, const Geom_traits &k = Geom_traits()) + : tds_(dim) + , kernel_(k) + , infinity_() + , preset_flat_orientation_((std::numeric_limits<int>::max)(), + (Flat_orientation_d*) NULL) + , rng_((long)0) +#ifdef CGAL_TRIANGULATION_STATISTICS + ,walk_size_(0) +#endif + { + clear(); + } + + // With this constructor, + // the user can specify a Flat_orientation_d object to be used for + // orienting simplices of a specific dimension + // (= preset_flat_orientation_.first) + // It it used for by dark triangulations created by DT::remove + Triangulation( + int dim, + const std::pair<int, const Flat_orientation_d *> &preset_flat_orientation, + const Geom_traits k = Geom_traits()) + : tds_(dim) + , kernel_(k) + , infinity_() + , preset_flat_orientation_(preset_flat_orientation) + , rng_((long)0) +#ifdef CGAL_TRIANGULATION_STATISTICS + ,walk_size_(0) +#endif + { + clear(); + } + + Triangulation(const Triangulation & t2) + : tds_(t2.tds_) + , kernel_(t2.kernel_) + , infinity_() + , preset_flat_orientation_((std::numeric_limits<int>::max)(), + (Flat_orientation_d*) NULL) + , rng_(t2.rng_) +#ifdef CGAL_TRIANGULATION_STATISTICS + ,walk_size_(t2.walk_size_) +#endif + { + // We find the vertex at infinity by scanning the vertices of both + // triangulations. This works because Compact_container garantees that + // the vertices in the copy (*this) are stored in the same order as in + // the original triangulation (t2) + infinity_ = vertices_begin(); + Vertex_const_iterator inf2 = t2.vertices_begin(); + while( inf2 != t2.infinite_vertex() ) + { + ++infinity_; + ++inf2; + } + // A full_cell has at most 1 + maximal_dimension() facets: + orientations_.resize(1 + maximal_dimension()); + // Our coaffine orientation predicates HAS state member variables + reset_flat_orientation(); + } + + ~Triangulation() {} + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ACCESS FUNCTIONS + + /* These three function are no longer needed since we do not use them anymore + in the Delaunay_triangulation::remove. *But*, they may reappear in the future + if we manage to passe the information that flags/TDS_data is available or not + for marking simplices in Delaunay_triangulation::remove. This would be useful + to make it a little faster, instead of binary searching if a simplex is marked + or not... + // NOT DOCUMENTED -- + bool get_visited(Full_cell_handle s) const + { + return tds().get_visited(s); + } + // NOT DOCUMENTED -- + bool get_visited(Full_cell_const_handle s) const + { + return tds().get_visited(s); + } + + // NOT DOCUMENTED -- + void set_visited(Full_cell_handle s, bool b) const + { + tds().set_visited(s, b); + } */ + + Coaffine_orientation_d coaffine_orientation_predicate() const + { + return Coaffine_orientation_d ( + flat_orientation_, + geom_traits().construct_flat_orientation_d_object(), + geom_traits().in_flat_orientation_d_object() + ); + } + + const Triangulation_ds & tds() const + { + return tds_; + } + + Triangulation_ds & tds() + { + return tds_; + } + + const Geom_traits & geom_traits() const + { + return kernel_; + } + + int maximal_dimension() const { return tds().maximal_dimension(); } + int current_dimension() const { return tds().current_dimension(); } + + bool empty() const + { + return current_dimension() == -1; + } + + size_type number_of_vertices() const + { + return tds().number_of_vertices() - 1; + } + + size_type number_of_full_cells() const + { + return tds().number_of_full_cells(); + } + + Vertex_handle infinite_vertex() const + { + return infinity_; + } + + Full_cell_handle infinite_full_cell() const + { + CGAL_assertion(infinite_vertex()->full_cell()->has_vertex(infinite_vertex())); + return infinite_vertex()->full_cell(); + } + +// - - - - - - - - - - - - - - - - - - - - - - - - - NON CONSTANT-TIME ACCESS FUNCTIONS + + size_type number_of_finite_full_cells() const + { + Full_cell_const_iterator s = full_cells_begin(); + size_type result = number_of_full_cells(); + for( ; s != full_cells_end(); ++s ) + { + if( is_infinite(s) ) + --result; + } + return result; + } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TRAVERSAL + + Vertex_iterator vertices_begin() { return tds().vertices_begin(); } + Vertex_iterator vertices_end() { return tds().vertices_end(); } + + Vertex_const_iterator vertices_begin() const { return tds().vertices_begin(); } + Vertex_const_iterator vertices_end() const { return tds().vertices_end(); } + + Finite_vertex_iterator finite_vertices_begin() + { return Finite_vertex_iterator(Finiteness_predicate(*this), vertices_begin(), vertices_end()); } + Finite_vertex_iterator finite_vertices_end() + { return Finite_vertex_iterator(Finiteness_predicate(*this), vertices_end(), vertices_end()); } + Finite_vertex_const_iterator finite_vertices_begin() const + { return Finite_vertex_const_iterator(Finiteness_predicate(*this), vertices_begin(), vertices_end()); } + Finite_vertex_const_iterator finite_vertices_end() const + { return Finite_vertex_const_iterator(Finiteness_predicate(*this), vertices_end(), vertices_end()); } + + Full_cell_iterator full_cells_begin() { return tds().full_cells_begin(); } + Full_cell_iterator full_cells_end() { return tds().full_cells_end(); } + + Full_cell_const_iterator full_cells_begin() const { return tds().full_cells_begin(); } + Full_cell_const_iterator full_cells_end() const { return tds().full_cells_end(); } + + Finite_full_cell_iterator finite_full_cells_begin() + { return Finite_full_cell_iterator(Finiteness_predicate(*this), full_cells_begin(), full_cells_end()); } + Finite_full_cell_iterator finite_full_cells_end() + { return Finite_full_cell_iterator(Finiteness_predicate(*this), full_cells_end(), full_cells_end()); } + Finite_full_cell_const_iterator finite_full_cells_begin() const + { return Finite_full_cell_const_iterator(Finiteness_predicate(*this), full_cells_begin(), full_cells_end()); } + Finite_full_cell_const_iterator finite_full_cells_end() const + { return Finite_full_cell_const_iterator(Finiteness_predicate(*this), full_cells_end(), full_cells_end()); } + + Facet_iterator facets_begin() { return tds().facets_begin(); } + Facet_iterator facets_end() { return tds().facets_end(); } + Facet_iterator finite_facets_begin() + { return Finite_facet_iterator(Finiteness_predicate(*this), facets_begin(), facets_end()); } + Facet_iterator finite_facets_end() + { return Finite_facet_iterator(Finiteness_predicate(*this), facets_end(), facets_end()); } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SOME PREDICATE FUNCTORS + + class Finiteness_predicate + { + const Self & t_; + public: + Finiteness_predicate(const Self & t) : t_(t) {} + template < class T > + bool operator()(const T & t) const + { + return ! t_.is_infinite(t); + } + }; + + class Point_equality_predicate + { + const Point & o_; + public: + Point_equality_predicate(const Point & o) : o_(o) {} + bool operator()(const Point & o) const { return (o == o_ );} + }; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SIMPLE QUERIES +/* + bool is_vertex(const Point & p, Vertex_handle & v, Full_cell_handle hint = Full_cell_handle()) const + { + Locate_type lt; + Face f(maximal_dimension()); + Facet ft; + Full_cell_handle s = locate(p, lt, f, ft, hint); + if( ON_VERTEX == lt ) + { + v = s->vertex(f.index(0)); + return true; + } + return false; + } + + bool is_vertex(Vertex_const_handle v) const + { + return tds().is_vertex(v); + } + + bool is_full_cell(Full_cell_const_handle s) const + { + return tds().is_full_cell(s); + } +*/ + + bool is_infinite(Vertex_const_handle v) const + { + CGAL_precondition(Vertex_const_handle() != v); + return (infinite_vertex() == v); + } + + bool is_infinite(const Vertex & v) const /* internal use, not documented */ + { + return (&(*infinite_vertex()) == &v); + } + + bool is_infinite(Full_cell_const_handle s) const + { + CGAL_precondition(Full_cell_const_handle() != s); + return is_infinite(*s); + } + bool is_infinite(const Full_cell & s) const /* internal use, not documented */ + { + for(int i = 0; i <= current_dimension(); ++i) + if( is_infinite(s.vertex(i)) ) + return true; + return false; + } + bool is_infinite(const Facet & ft) const + { + Full_cell_const_handle s = full_cell(ft); + CGAL_precondition(s != Full_cell_const_handle()); + if( is_infinite(s) ) + return (s->vertex(index_of_covertex(ft)) != infinite_vertex()); + return false; + } + + bool is_infinite(const Face & f) const + { + Full_cell_const_handle s = f.full_cell(); + CGAL_precondition(s != Full_cell_const_handle()); + if( is_infinite(s) ) + { + Vertex_handle v; + for( int i(0); i<= f.face_dimension(); ++i) + if ( is_infinite( f.vertex(i) )) return true; + } + return false; + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ELEMENT GATHERING + + + template< typename OutputIterator > + OutputIterator incident_full_cells(const Face & f, OutputIterator out) const + { + return tds().incident_full_cells(f, out); + } + template< typename OutputIterator > + OutputIterator incident_full_cells(Vertex_const_handle v, OutputIterator out) const + { + return tds().incident_full_cells(v, out); + } + template< typename OutputIterator > + OutputIterator star(const Face & f, OutputIterator out) const + { + return tds().star(f, out); + } + + template< typename OutputIterator > + OutputIterator incident_faces(Vertex_const_handle v, int d, OutputIterator out) const + { + return tds().incident_faces(v, d, out); + } + /* + template< typename OutputIterator, class Comparator > + OutputIterator incident_upper_faces( Vertex_const_handle v, int d, + OutputIterator out, Comparator cmp = Comparator()) + { + return tds().incident_upper_faces(v, d, out, cmp); + } + template< typename OutputIterator > + OutputIterator incident_upper_faces( Vertex_const_handle v, int d, + OutputIterator out) + { // FIXME: uncomment this function, since it uses a comparator specific to + // *geometric* triangulation (taking infinite vertex into account) + internal::Triangulation::Compare_vertices_for_upper_face<Self> cmp(*this); + return tds().incident_upper_faces(v, d, out, cmp); + } + */ + Orientation orientation(Full_cell_const_handle s, bool in_is_valid = false) const + { + if( ! in_is_valid ) + CGAL_assertion( ! is_infinite(s) ); + if( 0 == current_dimension() ) + return POSITIVE; + if( current_dimension() == maximal_dimension() ) + { + Orientation_d ori = geom_traits().orientation_d_object(); + return ori(points_begin(s), points_begin(s) + 1 + current_dimension()); + } + else + { + return coaffine_orientation_predicate()(points_begin(s), points_begin(s) + 1 + current_dimension()); + } + } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - UPDATE OPERATIONS + + void clear() + { + tds_.clear(); + infinity_ = tds().insert_increase_dimension(); + // A full_cell has at most 1 + maximal_dimension() facets: + orientations_.resize(1 + maximal_dimension()); + // Our coaffine orientation predicates HAS state member variables + reset_flat_orientation(); +#ifdef CGAL_TRIANGULATION_STATISTICS + walk_size_ = 0; +#endif + } + + void set_current_dimension(int d) + { + tds().set_current_dimension(d); + } + + Full_cell_handle new_full_cell() + { + return tds().new_full_cell(); + } + + Vertex_handle new_vertex() + { + return tds().new_vertex(); + } + + Vertex_handle new_vertex(const Point & p) + { + return tds().new_vertex(p); + } + + void set_neighbors(Full_cell_handle s, int i, Full_cell_handle s1, int j) + { + tds().set_neighbors(s, i, s1, j); + } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY + + bool is_valid(bool = false, int = 0) const; + bool are_incident_full_cells_valid(Vertex_const_handle, bool = false, int = 0) const; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - POINT LOCATION + +protected: + template< typename OrientationPredicate > + Full_cell_handle do_locate(const Point &, Locate_type &, Face &, Facet &, + Full_cell_handle start, + const OrientationPredicate & o) const; +public: + Full_cell_handle locate(const Point &, Locate_type &, Face &, Facet &, + Full_cell_handle start = Full_cell_handle()) const; + Full_cell_handle locate(const Point &, Locate_type &, Face &, Facet &, + Vertex_handle) const; + Full_cell_handle locate(const Point & p, Full_cell_handle s = Full_cell_handle()) const; + Full_cell_handle locate(const Point & p, Vertex_handle v) const; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS + + Vertex_handle contract_face(const Point &, const Face &); + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - POINT INSERTION + + template< typename ForwardIterator > + size_type insert(ForwardIterator start, ForwardIterator end) + { + size_type n = number_of_vertices(); + std::vector<Point> points(start, end); + spatial_sort(points.begin(), points.end(), geom_traits()); + Full_cell_handle hint = Full_cell_handle(); + typename std::vector<Point>::const_iterator s = points.begin(); + while( s != points.end() ) + { + hint = insert(*s++, hint)->full_cell(); + } + return number_of_vertices() - n; + } + Vertex_handle insert(const Point &, Locate_type, const Face &, const Facet &, Full_cell_handle); + Vertex_handle insert(const Point &, Full_cell_handle start = Full_cell_handle()); + Vertex_handle insert(const Point &, Vertex_handle); + template< typename ForwardIterator > + Vertex_handle insert_in_hole(const Point & p, ForwardIterator start, ForwardIterator end, const Facet & ft) + { + Emptyset_iterator out; + return insert_in_hole(p, start, end, ft, out); + } + template< typename ForwardIterator, typename OutputIterator > + Vertex_handle insert_in_hole(const Point & p, ForwardIterator start, ForwardIterator end, const Facet & ft, + OutputIterator out) + { + Vertex_handle v = tds().insert_in_hole(start, end, ft, out); + v->set_point(p); + return v; + } + Vertex_handle insert_in_face(const Point &, const Face &); + Vertex_handle insert_in_facet(const Point &, const Facet &); + Vertex_handle insert_in_full_cell(const Point &, Full_cell_handle); + Vertex_handle insert_outside_convex_hull_1(const Point &, Full_cell_handle); + Vertex_handle insert_outside_convex_hull(const Point &, Full_cell_handle); + Vertex_handle insert_outside_affine_hull(const Point &); + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - FACET-TRAVERSAL PREDICATES + + template< typename OrientationPredicate > + class Outside_convex_hull_traversal_predicate + { + Triangulation & t_; + const Point & p_; + OrientationPredicate const& ori_; + int cur_dim_; + public: + Outside_convex_hull_traversal_predicate(Triangulation & t, const Point & p, + OrientationPredicate const& ori) + : t_(t), p_(p), ori_(ori), cur_dim_(t.current_dimension()) {} + // FUTURE change parameter to const reference + bool operator()(Facet f) const + { + Full_cell_handle s = t_.full_cell(f); + const int i = t_.index_of_covertex(f); + Full_cell_handle n = s->neighbor(i); + if( ! t_.is_infinite(n) ) + return false; + int inf_v_index = n->index(t_.infinite_vertex()); + n->vertex(inf_v_index)->set_point(p_); + bool ok = (POSITIVE == ori_(t_.points_begin(n), t_.points_begin(n) + cur_dim_ + 1)); + return ok; + } + }; + + // make sure all full_cells have positive orientation + void reorient_full_cells(); + +protected: + // This is used in the |remove(v)| member function to manage sets of Full_cell_handles + template< typename FCH > + struct Full_cell_set : public std::vector<FCH> + { + typedef std::vector<FCH> Base_set; + using Base_set::begin; + using Base_set::end; + void make_searchable() + { // sort the full cell handles + std::sort(begin(), end()); + } + bool contains(const FCH & fch) const + { + return std::binary_search(begin(), end(), fch); + } + bool contains_1st_and_not_2nd(const FCH & fst, const FCH & snd) const + { + return ( ! contains(snd) ) && ( contains(fst) ); + } + }; + + void display_all_full_cells__debugging() const + { + std::cerr << "ALL FULL CELLS:" << std::endl; + for (Full_cell_const_iterator cit = full_cells_begin() ; + cit != full_cells_end() ; ++cit ) + { + std::cerr << std::hex << &*cit << ": "; + for (int jj = 0 ; jj <= current_dimension() ; ++jj) + std::cerr << (is_infinite(cit->vertex(jj)) ? 0xFFFFFFFF : (unsigned int)&*cit->vertex(jj)) << " - "; + std::cerr << std::dec << std::endl; + } + std::cerr << std::endl; + } + + +}; // Triangulation<...> + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// CLASS MEMBER FUNCTIONS + +template < class TT, class TDS > +void +Triangulation<TT, TDS> +::reorient_full_cells() +{ + if( current_dimension() < 1 ) + return; + + Full_cell_iterator sit = full_cells_begin(); + Full_cell_iterator send = full_cells_end(); + for ( ; sit != send ; ++sit) + { + if( ! (is_infinite(sit) && (1 == current_dimension())) ) + { + sit->swap_vertices(current_dimension() - 1, current_dimension()); + } + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// - - - - - - - - - - - - - - - - - - - - - - - - THE REMOVAL METHODS + +template < class TT, class TDS > +typename Triangulation<TT, TDS>::Vertex_handle +Triangulation<TT, TDS> +::contract_face(const Point & p, const Face & f) +{ + CGAL_precondition( ! is_infinite(f) ); + Vertex_handle v = tds().contract_face(f); + v->set_point(p); + CGAL_expensive_postcondition_msg(are_incident_full_cells_valid(v), "new point is not where it should be"); + return v; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// - - - - - - - - - - - - - - - - - - - - - - - - THE INSERTION METHODS + +template < class TT, class TDS > +typename Triangulation<TT, TDS>::Vertex_handle +Triangulation<TT, TDS> +::insert(const Point & p, Locate_type lt, const Face & f, const Facet & ft, Full_cell_handle s) +{ + switch( lt ) + { + case IN_FULL_CELL: + return insert_in_full_cell(p, s); + break; + case OUTSIDE_CONVEX_HULL: + return insert_outside_convex_hull(p, s); + break; + case OUTSIDE_AFFINE_HULL: + return insert_outside_affine_hull(p); + break; + case IN_FACET: + { + return insert_in_facet(p, ft); + break; + } + case IN_FACE: + return insert_in_face(p, f); + break; + case ON_VERTEX: + s->vertex(f.index(0))->set_point(p); + return s->vertex(f.index(0)); + break; + } + CGAL_assertion(false); + return Vertex_handle(); +} + +template < class TT, class TDS > +typename Triangulation<TT, TDS>::Vertex_handle +Triangulation<TT, TDS> +::insert(const Point & p, Full_cell_handle start) +{ + Locate_type lt; + Face f(maximal_dimension()); + Facet ft; + Full_cell_handle s = locate(p, lt, f, ft, start); + return insert(p, lt, f, ft, s); +} + +template < class TT, class TDS > +typename Triangulation<TT, TDS>::Vertex_handle +Triangulation<TT, TDS> +::insert(const Point & p, Vertex_handle v) +{ + if( Vertex_handle() == v ) + v = infinite_vertex(); + return insert(p, v->full_cell()); +} + +template < class TT, class TDS > +typename Triangulation<TT, TDS>::Vertex_handle +Triangulation<TT, TDS> +::insert_in_face(const Point & p, const Face & f) +{ + CGAL_precondition( ! is_infinite(f) ); + Vertex_handle v = tds().insert_in_face(f); + v->set_point(p); + return v; +} + +template < class TT, class TDS > +typename Triangulation<TT, TDS>::Vertex_handle +Triangulation<TT, TDS> +::insert_in_facet(const Point & p, const Facet & ft) +{ + CGAL_precondition( ! is_infinite(ft) ); + Vertex_handle v = tds().insert_in_facet(ft); + v->set_point(p); + return v; +} + +template < class TT, class TDS > +typename Triangulation<TT, TDS>::Vertex_handle +Triangulation<TT, TDS> +::insert_in_full_cell(const Point & p, Full_cell_handle s) +{ + CGAL_precondition( ! is_infinite(s) ); + Vertex_handle v = tds().insert_in_full_cell(s); + v->set_point(p); + return v; +} + +// NOT DOCUMENTED... +template < class TT, class TDS > +typename Triangulation<TT, TDS>::Vertex_handle +Triangulation<TT, TDS> +::insert_outside_convex_hull_1(const Point & p, Full_cell_handle s) +{ + // This is a special case for dimension 1, because in that case, the right + // infinite full_cell is not correctly oriented... (sice its first vertex is the + // infinite one... + CGAL_precondition( is_infinite(s) ); + CGAL_precondition( 1 == current_dimension() ); + Vertex_handle v = tds().insert_in_full_cell(s); + v->set_point(p); + return v; +} + +template < class TT, class TDS > +typename Triangulation<TT, TDS>::Vertex_handle +Triangulation<TT, TDS> +::insert_outside_convex_hull(const Point & p, Full_cell_handle s) +{ + if( 1 == current_dimension() ) + { + return insert_outside_convex_hull_1(p, s); + } + CGAL_precondition( is_infinite(s) ); + CGAL_assertion( current_dimension() >= 2 ); + std::vector<Full_cell_handle> simps; + simps.reserve(64); + std::back_insert_iterator<std::vector<Full_cell_handle> > out(simps); + if( current_dimension() < maximal_dimension() ) + { + Coaffine_orientation_d ori = coaffine_orientation_predicate(); + Outside_convex_hull_traversal_predicate<Coaffine_orientation_d> + ochtp(*this, p, ori); + tds().gather_full_cells(s, ochtp, out); + } + else + { + Orientation_d ori = geom_traits().orientation_d_object(); + Outside_convex_hull_traversal_predicate<Orientation_d> + ochtp(*this, p, ori); + tds().gather_full_cells(s, ochtp, out); + } + int inf_v_index = s->index(infinite_vertex()); + Vertex_handle v = insert_in_hole( + p, simps.begin(), simps.end(), Facet(s, inf_v_index)); + return v; +} + +template < class TT, class TDS > +typename Triangulation<TT, TDS>::Vertex_handle +Triangulation<TT, TDS> +::insert_outside_affine_hull(const Point & p) +{ + CGAL_precondition( current_dimension() < maximal_dimension() ); + Vertex_handle v = tds().insert_increase_dimension(infinite_vertex()); + // reset the orientation predicate: + reset_flat_orientation(); + v->set_point(p); + if( current_dimension() >= 1 ) + { + Full_cell_handle inf_v_cell = infinite_vertex()->full_cell(); + int inf_v_index = inf_v_cell->index(infinite_vertex()); + Full_cell_handle s = inf_v_cell->neighbor(inf_v_index); + Orientation o = orientation(s); + CGAL_assertion( COPLANAR != o ); + if( NEGATIVE == o ) + reorient_full_cells(); + + + // We just inserted the second finite point and the right infinite + // cell is like : (inf_v, v), but we want it to be (v, inf_v) to be + // consistent with the rest of the cells + if (current_dimension() == 1) + { + // Is "inf_v_cell" the right infinite cell? + // Then inf_v_index should be 1 + if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0 + && inf_v_index == 0) + { + inf_v_cell->swap_vertices( + current_dimension() - 1, current_dimension()); + } + // Otherwise, let's find the right infinite cell + else + { + inf_v_cell = inf_v_cell->neighbor((inf_v_index + 1) % 2); + inf_v_index = inf_v_cell->index(infinite_vertex()); + // Is "inf_v_cell" the right infinite cell? + // Then inf_v_index should be 1 + if (inf_v_cell->neighbor(inf_v_index)->index(inf_v_cell) == 0 + && inf_v_index == 0) + { + inf_v_cell->swap_vertices( + current_dimension() - 1, current_dimension()); + } + } + } + } + return v; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// - - - - - - - - - - - - - - - - - - - - THE MAIN LOCATE(...) FUNCTION + +template < class TT, class TDS > +template< typename OrientationPredicate > +typename Triangulation<TT, TDS>::Full_cell_handle +Triangulation<TT, TDS> +::do_locate(const Point & p, // query point + Locate_type & loc_type,// type of result (full_cell, face, vertex) + Face & face,// the face containing the query in its interior (when appropriate) + Facet & facet,// the facet containing the query in its interior (when appropriate) + Full_cell_handle start, // starting full_cell for the walk + OrientationPredicate const& orientation_pred + ) const +{ + const int cur_dim = current_dimension(); + + if( cur_dim == -1 ) + { + loc_type = OUTSIDE_AFFINE_HULL; + return Full_cell_handle(); + } + else if( cur_dim == 0 ) + { + Vertex_handle vit = infinite_full_cell()->neighbor(0)->vertex(0); + if( EQUAL != geom_traits().compare_lexicographically_d_object()(p, vit->point()) ) + { + loc_type = OUTSIDE_AFFINE_HULL; + return Full_cell_handle(); + } + else + { + loc_type = ON_VERTEX; + face.set_full_cell(vit->full_cell()); + face.set_index(0, 0); + return vit->full_cell(); + } + } + + Full_cell_handle s; + + // if we don't know where to start, we start from any bounded full_cell + if( Full_cell_handle() == start ) + { + // THE HACK THAT NOBODY SHOULD DO... BUT DIFFICULT TO WORK AROUND + // THIS... TODO: WORK AROUND IT + Full_cell_handle inf_c = const_cast<Self*>(this)->infinite_full_cell(); + int inf_v_index = inf_c->index(infinite_vertex()); + s = inf_c->neighbor(inf_v_index); + } + else + { + s = start; + if( is_infinite(s) ) + { + int inf_v_index = s->index(infinite_vertex()); + s = s->neighbor(inf_v_index); + } + } + + // Check if query |p| is outside the affine hull + if( cur_dim < maximal_dimension() ) + { + if( ! geom_traits().contained_in_affine_hull_d_object()( + points_begin(s), + points_begin(s) + current_dimension() + 1, + p) ) + { + loc_type = OUTSIDE_AFFINE_HULL; + return Full_cell_handle(); + } + } + + // we remember the |previous|ly visited full_cell to avoid the evaluation + // of one |orientation| predicate + Full_cell_handle previous = Full_cell_handle(); + bool full_cell_not_found = true; + while(full_cell_not_found) // we walk until we locate the query point |p| + { + #ifdef CGAL_TRIANGULATION_STATISTICS + ++walk_size_; + #endif + // For the remembering stochastic walk, we need to start trying + // with a random index: + int j, i = rng_.get_int(0, cur_dim); + // we check |p| against all the full_cell's hyperplanes in turn + + for(j = 0; j <= cur_dim; ++j, i = (i + 1) % (cur_dim + 1) ) + { + Full_cell_handle next = s->neighbor(i); + if( previous == next ) + { // no need to compute the orientation, we already know it + orientations_[i] = POSITIVE; + continue; // go to next full_cell's facet + } + + Substitute_point_in_vertex_iterator< + typename Full_cell::Vertex_handle_const_iterator> + spivi(s->vertex(i), &p); + + orientations_[i] = orientation_pred( + boost::make_transform_iterator(s->vertices_begin(), spivi), + boost::make_transform_iterator(s->vertices_begin() + cur_dim + 1, + spivi)); + + if( orientations_[i] != NEGATIVE ) + { + // from this facet's point of view, we are inside the + // full_cell or on its boundary, so we continue to next facet + continue; + } + + // At this point, we know that we have to jump to the |next| + // full_cell because orientation_[i] == NEGATIVE + previous = s; + s = next; + if( is_infinite(next) ) + { // we have arrived OUTSIDE the convex hull of the triangulation, + // so we stop the search + full_cell_not_found = false; + loc_type = OUTSIDE_CONVEX_HULL; + face.set_full_cell(s); + } + break; + } // end of the 'for' loop + if( ( cur_dim + 1 ) == j ) // we found the full_cell containing |p| + full_cell_not_found = false; + } + // Here, we know in which full_cell |p| is in. + // We now check more precisely where |p| landed: + // vertex, facet, face or full_cell. + if( ! is_infinite(s) ) + { + face.set_full_cell(s); + int num(0); + int verts(0); + for(int i = 0; i < cur_dim; ++i) + { + if( orientations_[i] == COPLANAR ) + { + ++num; + facet = Facet(s, i); + } + else + face.set_index(verts++, i); + } + //-- We could put the if{}else{} below in the loop above, but then we would + // need to test if (verts < cur_dim) many times... we do it only once + // here: + if( orientations_[cur_dim] == COPLANAR ) + { + ++num; + facet = Facet(s, cur_dim); + } + else if( verts < cur_dim ) + face.set_index(verts, cur_dim); + //-- end of remark above // + if( 0 == num ) + { + loc_type = IN_FULL_CELL; + face.clear(); + } + else if( cur_dim == num ) + loc_type = ON_VERTEX; + else if( 1 == num ) + loc_type = IN_FACET; + else + loc_type = IN_FACE; + } + return s; +} + +template < class TT, class TDS > +typename Triangulation<TT, TDS>::Full_cell_handle +Triangulation<TT, TDS> +::locate( const Point & p, // query point + Locate_type & loc_type,// type of result (full_cell, face, vertex) + Face & face,// the face containing the query in its interior (when appropriate) + Facet & facet,// the facet containing the query in its interior (when appropriate) + Full_cell_handle start// starting full_cell for the walk + ) const +{ + if( current_dimension() == maximal_dimension() ) + { + Orientation_d ori = geom_traits().orientation_d_object(); + return do_locate(p, loc_type, face, facet, start, ori); + } + else + return do_locate(p, loc_type, face, facet, start, coaffine_orientation_predicate()); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// - - - - - - - - - - - - - - - - - - - - the locate(...) variants + +template < class TT, class TDS > +typename Triangulation<TT, TDS>::Full_cell_handle +Triangulation<TT, TDS> +::locate( const Point & p, + Locate_type & loc_type, + Face & face, + Facet & facet, + Vertex_handle start) const +{ + if( Vertex_handle() == start ) + start = infinite_vertex(); + return locate(p, loc_type, face, facet, start->full_cell()); +} + +template < class TT, class TDS > +typename Triangulation<TT, TDS>::Full_cell_handle +Triangulation<TT, TDS> +::locate(const Point & p, Full_cell_handle s) const +{ + Locate_type lt; + Face face(maximal_dimension()); + Facet facet; + return locate(p, lt, face, facet, s); +} + +template < class TT, class TDS > +typename Triangulation<TT, TDS>::Full_cell_handle +Triangulation<TT, TDS> +::locate(const Point & p, Vertex_handle v) const +{ + if( Vertex_handle() != v ) + v = infinite_vertex(); + return this->locate(p, v->full_cell()); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY + +template < class TT, class TDS > +bool +Triangulation<TT, TDS> +::is_valid(bool verbose, int level) const +{ + if( ! tds().is_valid(verbose, level) ) + return false; + + Full_cell_const_iterator c; + if( current_dimension() < 0 ) + return true; + Orientation o; + for( c = full_cells_begin(); c != full_cells_end(); ++c ) + { + if( is_infinite(c) ) + { + if( current_dimension() > 1 ) + { + int i = c->index( infinite_vertex() ); + Full_cell_handle n = c->neighbor(i); + infinite_vertex()->set_point(n->vertex(c->mirror_index(i))->point()); + o = - orientation(c, true); + } + else + o = POSITIVE; + } + else + o = orientation(c, true); + if( NEGATIVE == o ) + { + if( verbose ) CGAL_warning_msg(false, "full_cell is not correctly oriented"); + return false; + } + if( COPLANAR == o ) + { + if( verbose ) CGAL_warning_msg(false, "full_cell is flat"); + return false; + } + } + return true; +} + +template < class TT, class TDS > +bool Triangulation<TT, TDS>::are_incident_full_cells_valid(Vertex_const_handle v, bool verbose, int) const +{ + if( current_dimension() <= 0 ) + return true; + typedef std::vector<Full_cell_const_handle> Simps; + Simps simps; + simps.reserve(64); + std::back_insert_iterator<Simps> out(simps); + incident_full_cells(v, out); + typename Simps::const_iterator sit = simps.begin(); + for( ; sit != simps.end(); ++sit ) + { + if( is_infinite(*sit) ) + continue; + Orientation o = orientation(*sit); + if( NEGATIVE == o ) + { + if( verbose ) CGAL_warning_msg(false, "full_cell is not correctly oriented"); + return false; + } + if( COPLANAR == o ) + { + if( verbose ) CGAL_warning_msg(false, "full_cell is flat"); + return false; + } + } + return true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +// FUNCTIONS THAT ARE NOT MEMBER FUNCTIONS: + +template < class TT, class TDS > +std::istream & +operator>>(std::istream & is, Triangulation<TT, TDS> & tr) + // reads : + // - the dimensions (maximal and current) + // - the number of finite vertices + // - the non combinatorial information on vertices (point, etc) + // - the number of full_cells + // - the full_cells by the indices of their vertices in the preceding list + // of vertices, plus the non combinatorial information on each full_cell + // - the neighbors of each full_cell by their index in the preceding list +{ + typedef Triangulation<TT, TDS> T; + typedef typename T::Vertex_handle Vertex_handle; + + // read current dimension and number of vertices + size_t n; + int cd; + if( is_ascii(is) ) + is >> cd >> n; + else + { + read(is, cd); + read(is, n, io_Read_write()); + } + + CGAL_assertion_msg( cd <= tr.maximal_dimension(), "input Triangulation has too high dimension"); + + tr.clear(); + tr.set_current_dimension(cd); + + if( n == 0 ) + return is; + + std::vector<Vertex_handle> vertices; + vertices.resize(n+1); + vertices[0] = tr.infinite_vertex(); + is >> (*vertices[0]); + + // read the vertices: + size_t i(1); + while( i <= n ) + { + vertices[i] = tr.new_vertex(); + is >> (*vertices[i]); // read a vertex + ++i; + } + + // now, read the combinatorial information + return tr.tds().read_full_cells(is, vertices); +} + +template < class TT, class TDS > +std::ostream & +operator<<(std::ostream & os, const Triangulation<TT, TDS> & tr) + // writes : + // - the dimensions (maximal and current) + // - the number of finite vertices + // - the non combinatorial information on vertices (point, etc) + // - the number of full_cells + // - the full_cells by the indices of their vertices in the preceding list + // of vertices, plus the non combinatorial information on each full_cell + // - the neighbors of each full_cell by their index in the preceding list +{ + typedef Triangulation<TT, TDS> T; + typedef typename T::Vertex_const_handle Vertex_handle; + typedef typename T::Vertex_const_iterator Vertex_iterator; + + // outputs dimensions and number of vertices + size_t n = tr.number_of_vertices(); + if( is_ascii(os) ) + os << tr.current_dimension() << std::endl << n << std::endl; + else + { + write(os, tr.current_dimension()); + write(os, n, io_Read_write()); + } + + if( n == 0 ) + return os; + + size_t i(0); + // write the vertices + std::map<Vertex_handle, int> index_of_vertex; + + // infinite vertex has index 0 (among all the vertices) + index_of_vertex[tr.infinite_vertex()] = i++; + os << *tr.infinite_vertex(); + for( Vertex_iterator it = tr.vertices_begin(); it != tr.vertices_end(); ++it ) + { + if( tr.is_infinite(it) ) + continue; + os << *it; // write the vertex + index_of_vertex[it] = i++; + } + CGAL_assertion( i == n+1 ); + + // output the combinatorial information + return tr.tds().write_full_cells(os, index_of_vertex); +} + +} //namespace CGAL + +#endif // CGAL_TRIANGULATION_H diff --git a/src/common/include/gudhi_patches/CGAL/Triangulation_data_structure.h b/src/common/include/gudhi_patches/CGAL/Triangulation_data_structure.h new file mode 100644 index 00000000..2493c712 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/Triangulation_data_structure.h @@ -0,0 +1,1603 @@ +// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Samuel Hornus + +#ifndef CGAL_TRIANGULATION_DATA_STRUCTURE_H +#define CGAL_TRIANGULATION_DATA_STRUCTURE_H + +#include <CGAL/basic.h> +#include <CGAL/Default.h> +#include <CGAL/iterator.h> +#include <CGAL/Compact_container.h> +#include <CGAL/Triangulation_face.h> +#include <CGAL/Triangulation_ds_vertex.h> +#include <CGAL/Triangulation_ds_full_cell.h> +#include <CGAL/internal/Combination_enumerator.h> +#include <CGAL/internal/Triangulation/utilities.h> +#include <CGAL/internal/Triangulation/Triangulation_ds_iterators.h> + +#include <algorithm> +#include <vector> +#include <queue> +#include <set> + +namespace CGAL { + +template< class Dimen, + class Vb = Default, + class Fcb = Default > +class Triangulation_data_structure +{ + typedef Triangulation_data_structure<Dimen, Vb, Fcb> Self; + typedef typename Default::Get<Vb, Triangulation_ds_vertex<> >::type V_base; + typedef typename Default::Get<Fcb, Triangulation_ds_full_cell<> >::type FC_base; + +public: + typedef typename V_base::template Rebind_TDS<Self>::Other Vertex; /* Concept */ + typedef typename FC_base::template Rebind_TDS<Self>::Other Full_cell; /* Concept */ + + // Tools to change the Vertex and Cell types of the TDS. + template < typename Vb2 > + struct Rebind_vertex { + typedef Triangulation_data_structure<Dimen, Vb2, Fcb> Other; + }; + + template < typename Fcb2 > + struct Rebind_full_cell { + typedef Triangulation_data_structure<Dimen, Vb, Fcb2> Other; + }; + + + + // we want to store an object of this class in every Full_cell: + class Full_cell_data + { + unsigned char bits_; + public: + Full_cell_data() : bits_(0) {} + Full_cell_data(const Full_cell_data & fcd) : bits_(fcd.bits_) {} + + void clear() { bits_ = 0; } + void mark_visited() { bits_ = 1; } + void clear_visited() { bits_ = 0; } + + bool is_clear() const { return bits_ == 0; } + bool is_visited() const { return bits_ == 1; } + // WARNING: if we use more bits and several bits can be set at once, + // then make sure to use bitwise operation above, instead of direct + // affectation. + }; + +protected: + typedef Compact_container<Vertex> Vertex_container; + typedef Compact_container<Full_cell> Full_cell_container; + +public: + typedef Dimen Maximal_dimension; + + typedef typename Vertex_container::size_type size_type; /* Concept */ + typedef typename Vertex_container::difference_type difference_type; /* Concept */ + + typedef typename Vertex_container::iterator Vertex_handle; /* Concept */ + typedef typename Vertex_container::iterator Vertex_iterator; /* Concept */ + typedef typename Vertex_container::const_iterator Vertex_const_handle; + typedef typename Vertex_container::const_iterator Vertex_const_iterator; + + typedef typename Full_cell_container::iterator Full_cell_handle; /* Concept */ + typedef typename Full_cell_container::iterator Full_cell_iterator; /* Concept */ + typedef typename Full_cell_container::const_iterator Full_cell_const_handle; + typedef typename Full_cell_container::const_iterator Full_cell_const_iterator; + + typedef internal::Triangulation:: + Triangulation_ds_facet_iterator<Self> Facet_iterator; /* Concept */ + + /* The 2 types defined below, |Facet| and |Rotor| are used when traversing + the boundary `B' of the union of a set of full cells. |Rotor| makes it + easy to rotate around itself, in the search of neighbors in `B' (see + |rotate_rotor| and |insert_in_tagged_hole|) */ + + // A co-dimension 1 sub-simplex. + class Facet /* Concept */ + { + Full_cell_handle full_cell_; + int index_of_covertex_; + public: + Facet() : full_cell_(), index_of_covertex_(0) {} + Facet(Full_cell_handle f, int i) : full_cell_(f), index_of_covertex_(i) {} + Full_cell_handle full_cell() const { return full_cell_; } + int index_of_covertex() const { return index_of_covertex_; } + }; + + // A co-dimension 2 sub-simplex. called a Rotor because we can rotate + // the two "covertices" around the sub-simplex. Useful for traversing the + // boundary of a hole. NOT DOCUMENTED + class Rotor : public Facet + { + int index_of_second_covertex_; + public: + Rotor() : Facet(), index_of_second_covertex_(0) {} + Rotor(Full_cell_handle f, int first, int second) : Facet(f, first), index_of_second_covertex_(second) {} + int index_of_second_covertex() const { return index_of_second_covertex_; } + }; + + typedef Triangulation_face<Self> Face; /* Concept */ + +protected: // DATA MEMBERS + + int dmax_, dcur_; // dimension of the current triangulation + Vertex_container vertices_; // list of all vertices + Full_cell_container full_cells_; // list of all full cells + +private: + + void clean_dynamic_memory() + { + vertices_.clear(); + full_cells_.clear(); + } + + template < class Dim_tag > + struct get_maximal_dimension + { + static int value(int D) { return D; } + }; + // specialization + template < int D > + struct get_maximal_dimension<Dimension_tag<D> > + { + static int value(int) { return D; } + }; + +public: + Triangulation_data_structure( int dim=0) /* Concept */ + : dmax_(get_maximal_dimension<Dimen>::value(dim)), dcur_(-2), + vertices_(), full_cells_() + { + CGAL_assertion_msg(dmax_ > 0, "maximal dimension must be positive."); + } + + ~Triangulation_data_structure() + { + clean_dynamic_memory(); + } + + Triangulation_data_structure(const Triangulation_data_structure & tds) + : dmax_(tds.dmax_), dcur_(tds.dcur_), + vertices_(tds.vertices_), full_cells_(tds.full_cells_) + { + typedef std::map<Vertex_const_handle, Vertex_handle> V_map; + typedef std::map<Full_cell_const_handle, Full_cell_handle> C_map; + V_map vmap; + C_map cmap; + Vertex_const_iterator vfrom = tds.vertices_begin(); + Vertex_iterator vto = vertices_begin(); + Full_cell_const_iterator cfrom = tds.full_cells_begin(); + Full_cell_iterator cto = full_cells_begin(); + while( vfrom != tds.vertices_end() ) + vmap[vfrom++] = vto++; + while( cfrom != tds.full_cells_end() ) + cmap[cfrom++] = cto++; + cto = full_cells_begin(); + while( cto != full_cells_end() ) + { + for( int i = 0; i <= (std::max)(0, current_dimension()); ++i ) + { + associate_vertex_with_full_cell(cto, i, vmap[cto->vertex(i)]); + cto->set_neighbor(i, cmap[cto->neighbor(i)]); + } + ++cto; + } + } + + // QUERIES + +protected: + + bool check_range(int i) const + { + if( current_dimension() < 0 ) + { + return (0 == i); + } + return ( (0 <= i) && (i <= current_dimension()) ); + } + +public: + + /* returns the current dimension of the full cells in the triangulation. */ + int maximal_dimension() const { return dmax_; } /* Concept */ + int current_dimension() const { return dcur_; } /* Concept */ + + size_type number_of_vertices() const /* Concept */ + { + return this->vertices_.size(); + } + size_type number_of_full_cells() const /* Concept */ + { + return this->full_cells_.size(); + } + + bool empty() const /* Concept */ + { + return current_dimension() == -2; + } + + Vertex_container & vertices() { return vertices_; } + const Vertex_container & vertices() const { return vertices_; } + Full_cell_container & full_cells() { return full_cells_; } + const Full_cell_container & full_cells() const { return full_cells_; } + + Vertex_handle vertex(Full_cell_handle s, int i) const /* Concept */ + { + CGAL_precondition(s != Full_cell_handle() && check_range(i)); + return s->vertex(i); + } + + Vertex_const_handle vertex(Full_cell_const_handle s, int i) const /* Concept */ + { + CGAL_precondition(s != Full_cell_handle() && check_range(i)); + return s->vertex(i); + } + + bool is_vertex(Vertex_const_handle v) const /* Concept */ + { + if( Vertex_const_handle() == v ) + return false; + Vertex_const_iterator vit = vertices_begin(); + while( vit != vertices_end() && ( v != vit ) ) + ++vit; + return v == vit; + } + + bool is_full_cell(Full_cell_const_handle s) const /* Concept */ + { + if( Full_cell_const_handle() == s ) + return false; + Full_cell_const_iterator sit = full_cells_begin(); + while( sit != full_cells_end() && ( s != sit ) ) + ++sit; + return s == sit; + } + + Full_cell_handle full_cell(Vertex_handle v) const /* Concept */ + { + CGAL_precondition(v != Vertex_handle()); + return v->full_cell(); + } + + Full_cell_const_handle full_cell(Vertex_const_handle v) const /* Concept */ + { + CGAL_precondition(Vertex_const_handle() != v); + return v->full_cell(); + } + + Full_cell_handle neighbor(Full_cell_handle s, int i) const /* Concept */ + { + CGAL_precondition(Full_cell_handle() != s && check_range(i)); + return s->neighbor(i); + } + + Full_cell_const_handle neighbor(Full_cell_const_handle s, int i) const/* Concept */ + { + CGAL_precondition(Full_cell_const_handle() != s && check_range(i)); + return s->neighbor(i); + } + + int mirror_index(Full_cell_handle s, int i) const /* Concept */ + { + CGAL_precondition(Full_cell_handle() != s && check_range(i)); + return s->mirror_index(i); + } + + int mirror_index(Full_cell_const_handle s, int i) const + { + CGAL_precondition(Full_cell_const_handle() != s && check_range(i)); /* Concept */ + return s->mirror_index(i); + } + + int mirror_vertex(Full_cell_handle s, int i) const /* Concept */ + { + CGAL_precondition(Full_cell_handle() != s && check_range(i)); + return s->mirror_vertex(i); + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FACETS OPERATIONS + + // works for Face_ = Facet and Face_ = Rotor. + // NOT DOCUMENTED for the Rotor case... + template< typename Face_ > + Full_cell_handle full_cell(const Face_ & f) const /* Concept */ + { + return f.full_cell(); + } + + // works for Face_ = Facet and Face_ = Rotor. + // NOT DOCUMENTED for the Rotor case... + template< class Face_ > + int index_of_covertex(const Face_ & f) const /* Concept */ + { + return f.index_of_covertex(); + } + + // NOT DOCUMENTED + // A Rotor has two covertices + int index_of_second_covertex(const Rotor & f) const + { + return f.index_of_second_covertex(); + } + + // works for Face_ = Facet and Face_ = Rotor. + // NOT DOCUMENTED... + template< class Face_ > + bool is_boundary_facet(const Face_ & f) const + { + if( get_visited(neighbor(full_cell(f), index_of_covertex(f))) ) + return false; + if( ! get_visited(full_cell(f)) ) + return false; + return true; + } + + // NOT DOCUMENTED... + Rotor rotate_rotor(Rotor & f) + { + int opposite = mirror_index(full_cell(f), index_of_covertex(f)); + Full_cell_handle s = neighbor(full_cell(f), index_of_covertex(f)); + int new_second = s->index(vertex(full_cell(f), index_of_second_covertex(f))); + return Rotor(s, new_second, opposite); + } + + // NICE UPDATE OPERATIONS + +protected: + void do_insert_increase_dimension(Vertex_handle, Vertex_handle); +public: +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REMOVALS + + Vertex_handle collapse_face(const Face &); /* Concept */ + void remove_decrease_dimension(Vertex_handle, Vertex_handle); /* Concept */ + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INSERTIONS + + Vertex_handle insert_in_full_cell(Full_cell_handle); /* Concept */ + Vertex_handle insert_in_face(const Face &); /* Concept */ + Vertex_handle insert_in_facet(const Facet &); /* Concept */ + template< typename Forward_iterator > + Vertex_handle insert_in_hole(Forward_iterator, Forward_iterator, Facet); /* Concept */ + template< typename Forward_iterator, typename OutputIterator > + Vertex_handle insert_in_hole(Forward_iterator, Forward_iterator, Facet, OutputIterator); /* Concept */ + + template< typename OutputIterator > + Full_cell_handle insert_in_tagged_hole(Vertex_handle, Facet, OutputIterator); + + Vertex_handle insert_increase_dimension(Vertex_handle=Vertex_handle()); /* Concept */ + +private: + + // Used by insert_in_tagged_hole + struct IITH_task + { + IITH_task( + Facet boundary_facet_, + int index_of_inside_cell_in_outside_cell_, + Full_cell_handle future_neighbor_ = Full_cell_handle(), + int new_cell_index_in_future_neighbor_ = -1, + int index_of_future_neighbor_in_new_cell_ = -1) + : boundary_facet(boundary_facet_), + index_of_inside_cell_in_outside_cell(index_of_inside_cell_in_outside_cell_), + future_neighbor(future_neighbor_), + new_cell_index_in_future_neighbor(new_cell_index_in_future_neighbor_), + index_of_future_neighbor_in_new_cell(index_of_future_neighbor_in_new_cell_) + {} + + // "new_cell" is the cell about to be created + Facet boundary_facet; + int index_of_inside_cell_in_outside_cell; + Full_cell_handle future_neighbor; + int new_cell_index_in_future_neighbor; + int index_of_future_neighbor_in_new_cell; + }; + + // NOT DOCUMENTED + void clear_visited_marks(Full_cell_handle) const; + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - DANGEROUS UPDATE OPERATIONS + +private: + + // NOT DOCUMENTED + template< typename FCH > // FCH = Full_cell_[const_]handle + bool get_visited(FCH c) const + { + return c->tds_data().is_visited(); + } + + // NOT DOCUMENTED + template< typename FCH > // FCH = Full_cell_[const_]handle + void set_visited(FCH c, bool m) const + { + if( m ) + c->tds_data().mark_visited(); + else + c->tds_data().clear_visited(); + } + +public: + + void clear() /* Concept */ + { + clean_dynamic_memory(); + dcur_ = -2; + } + + void set_current_dimension(int d) /* Concept */ + { + CGAL_precondition(-2<=d && d<=maximal_dimension()); + dcur_ = d; + } + + Full_cell_handle new_full_cell(Full_cell_handle s) + { + return full_cells_.emplace(*s); + } + + Full_cell_handle new_full_cell() /* Concept */ + { + return full_cells_.emplace(dmax_); + } + + void delete_full_cell(Full_cell_handle s) /* Concept */ + { + CGAL_precondition(Full_cell_handle() != s); + // CGAL_expensive_precondition(is_full_cell(s)); + full_cells_.erase(s); + } + + template< typename Forward_iterator > + void delete_full_cells(Forward_iterator start, Forward_iterator end) /* Concept */ + { + Forward_iterator s = start; + while( s != end ) + full_cells_.erase(*s++); + } + + template< class T > + Vertex_handle new_vertex( const T & t ) + { + return vertices_.emplace(t); + } + + Vertex_handle new_vertex() /* Concept */ + { + return vertices_.emplace(); + } + + void delete_vertex(Vertex_handle v) /* Concept */ + { + CGAL_precondition( Vertex_handle() != v ); + vertices_.erase(v); + } + + void associate_vertex_with_full_cell(Full_cell_handle s, int i, Vertex_handle v) /* Concept */ + { + CGAL_precondition(check_range(i)); + CGAL_precondition(s != Full_cell_handle()); + CGAL_precondition(v != Vertex_handle()); + s->set_vertex(i, v); + v->set_full_cell(s); + } + + void set_neighbors(Full_cell_handle s, int i, Full_cell_handle s1, int j) /* Concept */ + { + CGAL_precondition(check_range(i)); + CGAL_precondition(check_range(j)); + CGAL_precondition(s != Full_cell_handle()); + CGAL_precondition(s1 != Full_cell_handle()); + s->set_neighbor(i, s1); + s1->set_neighbor(j, s); + s->set_mirror_index(i, j); + s1->set_mirror_index(j, i); + } + + // SANITY CHECKS + + bool is_valid(bool = true, int = 0) const; /* Concept */ + + // NOT DOCUMENTED + template< class OutStream> void write_graph(OutStream &); + + Vertex_iterator vertices_begin() { return vertices_.begin(); } /* Concept */ + Vertex_iterator vertices_end() { return vertices_.end(); } /* Concept */ + Full_cell_iterator full_cells_begin() { return full_cells_.begin(); } /* Concept */ + Full_cell_iterator full_cells_end() { return full_cells_.end(); } /* Concept */ + + Vertex_const_iterator vertices_begin() const { return vertices_.begin(); } /* Concept */ + Vertex_const_iterator vertices_end() const { return vertices_.end(); } /* Concept */ + Full_cell_const_iterator full_cells_begin() const { return full_cells_.begin(); } /* Concept */ + Full_cell_const_iterator full_cells_end() const { return full_cells_.end(); } /* Concept */ + + Facet_iterator facets_begin() /* Concept */ + { + if( current_dimension() <= 0 ) + return facets_end(); + return Facet_iterator(*this); + } + Facet_iterator facets_end() /* Concept */ + { + return Facet_iterator(*this, 0); + } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - FULL CELL GATHERING + + // a traversal predicate for gathering full_cells incident to a given face + // ``incident'' means that the given face is a subface of the full_cell + class Incident_full_cell_traversal_predicate + { + const Face & f_; + int dim_; + const Triangulation_data_structure & tds_; + public: + Incident_full_cell_traversal_predicate(const Triangulation_data_structure & tds, + const Face & f) + : f_(f), tds_(tds) + { + dim_ = f.face_dimension(); + } + bool operator()(const Facet & facet) const + { + Vertex_handle v = tds_.full_cell(facet)->vertex(tds_.index_of_covertex(facet)); + for( int i = 0; i <= dim_; ++i ) + { + if( v == f_.vertex(i) ) + return false; + } + return true; + } + }; + + // a traversal predicate for gathering full_cells having a given face as subface + class Star_traversal_predicate + { + const Face & f_; + int dim_; + const Triangulation_data_structure & tds_; + public: + Star_traversal_predicate(const Triangulation_data_structure & tds, + const Face & f) + : f_(f), tds_(tds) + { + dim_ = f.face_dimension(); + } + bool operator()(const Facet & facet) const + { + Full_cell_handle s = tds_.full_cell(facet)->neighbor(tds_.index_of_covertex(facet)); + for( int j = 0; j <= tds_.current_dimension(); ++j ) + { + for( int i = 0; i <= dim_; ++i ) + if( s->vertex(j) == f_.vertex(i) ) + return true; + } + return false; + } + }; + + template< typename TraversalPredicate, typename OutputIterator > + Facet gather_full_cells(Full_cell_handle, TraversalPredicate &, OutputIterator &) const; /* Concept */ + template< typename OutputIterator > + OutputIterator incident_full_cells(const Face &, OutputIterator) const; /* Concept */ + template< typename OutputIterator > + OutputIterator incident_full_cells(Vertex_const_handle, OutputIterator) const; /* Concept */ + template< typename OutputIterator > + OutputIterator star(const Face &, OutputIterator) const; /* Concept */ +#ifndef CGAL_CFG_NO_CPP0X_DEFAULT_TEMPLATE_ARGUMENTS_FOR_FUNCTION_TEMPLATES + template< typename OutputIterator, typename Comparator = std::less<Vertex_const_handle> > + OutputIterator incident_upper_faces(Vertex_const_handle v, int dim, OutputIterator out, Comparator cmp = Comparator()) + { + return incident_faces(v, dim, out, cmp, true); + } + template< typename OutputIterator, typename Comparator = std::less<Vertex_const_handle> > + OutputIterator incident_faces(Vertex_const_handle, int, OutputIterator, Comparator = Comparator(), bool = false) const; +#else + template< typename OutputIterator, typename Comparator > + OutputIterator incident_upper_faces(Vertex_const_handle v, int dim, OutputIterator out, Comparator cmp = Comparator()) + { + return incident_faces(v, dim, out, cmp, true); + } + template< typename OutputIterator > + OutputIterator incident_upper_faces(Vertex_const_handle v, int dim, OutputIterator out) + { + return incident_faces(v, dim, out, std::less<Vertex_const_handle>(), true); + } + template< typename OutputIterator, typename Comparator > + OutputIterator incident_faces(Vertex_const_handle, int, OutputIterator, Comparator = Comparator(), bool = false) const; + template< typename OutputIterator > + OutputIterator incident_faces(Vertex_const_handle, int, OutputIterator, + std::less<Vertex_const_handle> = std::less<Vertex_const_handle>(), bool = false) const; +#endif + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INPUT / OUTPUT + + std::istream & read_full_cells(std::istream &, const std::vector<Vertex_handle> &); + std::ostream & write_full_cells(std::ostream &, std::map<Vertex_const_handle, int> &) const; + +}; // end of ``declaration/definition'' of Triangulation_data_structure<...> + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// FUNCTIONS THAT ARE MEMBER FUNCTIONS: + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// - - - - - - - - - - - - - - - - - - - - - - - - THE GATHERING METHODS + +template< class Dim, class Vb, class Fcb > +template< typename OutputIterator > +OutputIterator +Triangulation_data_structure<Dim, Vb, Fcb> +::incident_full_cells(const Face & f, OutputIterator out) const /* Concept */ +{ + // CGAL_expensive_precondition_msg(is_full_cell(f.full_cell()), "the facet does not belong to the Triangulation"); + Incident_full_cell_traversal_predicate tp(*this, f); + gather_full_cells(f.full_cell(), tp, out); + return out; +} + +template< class Dim, class Vb, class Fcb > +template< typename OutputIterator > +OutputIterator +Triangulation_data_structure<Dim, Vb, Fcb> +::incident_full_cells(Vertex_const_handle v, OutputIterator out) const /* Concept */ +{ +// CGAL_expensive_precondition(is_vertex(v)); + CGAL_precondition(Vertex_handle() != v); + Face f(v->full_cell()); + f.set_index(0, v->full_cell()->index(v)); + return incident_full_cells(f, out); +} + +template< class Dim, class Vb, class Fcb > +template< typename OutputIterator > +OutputIterator +Triangulation_data_structure<Dim, Vb, Fcb> +::star(const Face & f, OutputIterator out) const /* Concept */ +{ + // CGAL_precondition_msg(is_full_cell(f.full_cell()), "the facet does not belong to the Triangulation"); + Star_traversal_predicate tp(*this, f); + gather_full_cells(f.full_cell(), tp, out); + return out; +} + +template< class Dim, class Vb, class Fcb > +template< typename TraversalPredicate, typename OutputIterator > +typename Triangulation_data_structure<Dim, Vb, Fcb>::Facet +Triangulation_data_structure<Dim, Vb, Fcb> +::gather_full_cells(Full_cell_handle start, + TraversalPredicate & tp, + OutputIterator & out) const /* Concept */ +{ + std::queue<Full_cell_handle> queue; + set_visited(start, true); + queue.push(start); + const int cur_dim = current_dimension(); + Facet ft; + while( ! queue.empty() ) + { + Full_cell_handle s = queue.front(); + queue.pop(); + *out = s; + ++out; + for( int i = 0; i <= cur_dim; ++i ) + { + Full_cell_handle n = s->neighbor(i); + if( ! get_visited(n) ) + { + set_visited(n, true); + if( tp(Facet(s, i)) ) + queue.push(n); + else + ft = Facet(s, i); + } + } + } + clear_visited_marks(start); + return ft; +} + +#ifdef CGAL_CFG_NO_CPP0X_DEFAULT_TEMPLATE_ARGUMENTS_FOR_FUNCTION_TEMPLATES +template< class Dim, class Vb, class Fcb > +template< typename OutputIterator > +OutputIterator +Triangulation_data_structure<Dim, Vb, Fcb> +::incident_faces(Vertex_const_handle v, int dim, OutputIterator out, + std::less<Vertex_const_handle> cmp, bool upper_faces) const +{ + return incident_faces<OutputIterator, std::less<Vertex_const_handle> >(v, dim, out, cmp, upper_faces); +} +#endif + +template< class Dim, class Vb, class Fcb > +template< typename OutputIterator, typename Comparator > +OutputIterator +Triangulation_data_structure<Dim, Vb, Fcb> +::incident_faces(Vertex_const_handle v, int dim, OutputIterator out, Comparator cmp, bool upper_faces) const +{ + CGAL_precondition( 0 < dim ); + if( dim >= current_dimension() ) + return out; + typedef std::vector<Full_cell_handle> Simplices; + Simplices simps; + simps.reserve(64); + // gather incident full_cells + std::back_insert_iterator<Simplices> sout(simps); + incident_full_cells(v, sout); + // for storing the handles to the vertices of a full_cell + typedef std::vector<Vertex_const_handle> Vertices; + typedef std::vector<int> Indices; + Vertices vertices(1 + current_dimension()); + Indices sorted_idx(1 + current_dimension()); + // setup Face comparator and Face_set + typedef internal::Triangulation::Compare_faces_with_common_first_vertex<Self> + Upper_face_comparator; + Upper_face_comparator ufc(dim); + typedef std::set<Face, Upper_face_comparator> Face_set; + Face_set face_set(ufc); + for( typename Simplices::const_iterator s = simps.begin(); s != simps.end(); ++s ) + { + int v_idx(0); // the index of |v| in the sorted full_cell + // get the vertices of the full_cell and sort them + for( int i = 0; i <= current_dimension(); ++i ) + vertices[i] = (*s)->vertex(i); + if( upper_faces ) + { + std::sort(vertices.begin(), vertices.end(), cmp); + while( vertices[v_idx] != v ) + ++v_idx; + } + else + { + while( vertices[v_idx] != v ) + ++v_idx; + if( 0 != v_idx ) + std::swap(vertices[0], vertices[v_idx]); + v_idx = 0; + typename Vertices::iterator vbegin(vertices.begin()); + ++vbegin; + std::sort(vbegin, vertices.end(), cmp); + } + if( v_idx + dim > current_dimension() ) + continue; // |v| is too far to the right + // stores the index of the vertices of s in the same order + // as in |vertices|: + for( int i = 0; i <= current_dimension(); ++i ) + sorted_idx[i] = (*s)->index(vertices[i]); + // init state for enumerating all candidate faces: + internal::Combination_enumerator f_idx(dim, v_idx + 1, current_dimension()); + Face f(*s); + f.set_index(0, sorted_idx[v_idx]); + while( ! f_idx.end() ) + { + for( int i = 0; i < dim; ++i ) + f.set_index(1 + i, sorted_idx[f_idx[i]]); + face_set.insert(f); // checks if face has already been found + + // compute next sorted face (lexicographic enumeration) + ++f_idx; + } + } + typename Face_set::iterator fit = face_set.begin(); + while( fit != face_set.end() ) + *out++ = *fit++; + return out; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// - - - - - - - - - - - - - - - - - - - - - - - - THE REMOVAL METHODS + +template <class Dim, class Vb, class Fcb> +typename Triangulation_data_structure<Dim, Vb, Fcb>::Vertex_handle +Triangulation_data_structure<Dim, Vb, Fcb> +::collapse_face(const Face & f) /* Concept */ +{ + const int fd = f.face_dimension(); + CGAL_precondition( (1 <= fd ) && (fd < current_dimension())); + std::vector<Full_cell_handle> simps; + // save the Face's vertices: + Full_cell s; + for( int i = 0; i <= fd; ++i ) + s.set_vertex(i, f.vertex(i)); + // compute the star of f + simps.reserve(64); + std::back_insert_iterator<std::vector<Full_cell_handle> > out(simps); + star(f, out); + Vertex_handle v = insert_in_hole(simps.begin(), simps.end(), Facet(f.full_cell(), f.index(0))); + for( int i = 0; i <= fd; ++i ) + delete_vertex(s.vertex(i)); + return v; +} + +template <class Dim, class Vb, class Fcb> +void +Triangulation_data_structure<Dim, Vb, Fcb> +::remove_decrease_dimension(Vertex_handle v, Vertex_handle star) /* Concept */ +{ + CGAL_assertion( current_dimension() >= -1 ); + if( -1 == current_dimension() ) + { + clear(); + return; + } + else if( 0 == current_dimension() ) + { + delete_full_cell(v->full_cell()); + delete_vertex(v); + star->full_cell()->set_neighbor(0, Full_cell_handle()); + set_current_dimension(-1); + return; + } + else if( 1 == current_dimension() ) + { + Full_cell_handle s = v->full_cell(); + int star_index; + if( s->has_vertex(star, star_index) ) + s = s->neighbor(star_index); + // Here, |star| is not a vertex of |s|, so it's the only finite + // full_cell + Full_cell_handle inf1 = s->neighbor(0); + Full_cell_handle inf2 = s->neighbor(1); + Vertex_handle v2 = s->vertex(1 - s->index(v)); + delete_vertex(v); + delete_full_cell(s); + inf1->set_vertex(1, Vertex_handle()); + inf1->set_vertex(1, Vertex_handle()); + inf2->set_neighbor(1, Full_cell_handle()); + inf2->set_neighbor(1, Full_cell_handle()); + associate_vertex_with_full_cell(inf1, 0, star); + associate_vertex_with_full_cell(inf2, 0, v2); + set_neighbors(inf1, 0, inf2, 0); + set_current_dimension(0); + return; + } + typedef std::vector<Full_cell_handle> Simplices; + Simplices simps; + incident_full_cells(v, std::back_inserter(simps)); + for( typename Simplices::iterator it = simps.begin(); it != simps.end(); ++it ) + { + int v_idx = (*it)->index(v); + if( ! (*it)->has_vertex(star) ) + { + delete_full_cell((*it)->neighbor(v_idx)); + for( int i = 0; i <= current_dimension(); ++i ) + (*it)->vertex(i)->set_full_cell(*it); + } + else + star->set_full_cell(*it); + if( v_idx != current_dimension() ) + { + (*it)->swap_vertices(v_idx, current_dimension()); + (*it)->swap_vertices(current_dimension() - 2, current_dimension() - 1); + } + (*it)->set_vertex(current_dimension(), Vertex_handle()); + (*it)->set_neighbor(current_dimension(), Full_cell_handle()); + } + set_current_dimension(current_dimension()-1); + delete_vertex(v); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// - - - - - - - - - - - - - - - - - - - - - - - - THE INSERTION METHODS + +template <class Dim, class Vb, class Fcb> +typename Triangulation_data_structure<Dim, Vb, Fcb>::Vertex_handle +Triangulation_data_structure<Dim, Vb, Fcb> +::insert_in_full_cell(Full_cell_handle s) /* Concept */ +{ + CGAL_precondition(0 < current_dimension()); + CGAL_precondition(Full_cell_handle() != s); + // CGAL_expensive_precondition(is_full_cell(s)); + + const int cur_dim = current_dimension(); + Vertex_handle v = new_vertex(); + // the full_cell 'fc' is just used to store the handle to all the new full_cells. + Full_cell fc(maximal_dimension()); + for( int i = 1; i <= cur_dim; ++i ) + { + Full_cell_handle new_s = new_full_cell(s); + fc.set_neighbor(i, new_s); + associate_vertex_with_full_cell(new_s, i, v); + s->vertex(i-1)->set_full_cell(new_s); + set_neighbors(new_s, i, neighbor(s, i), mirror_index(s, i)); + } + fc.set_neighbor(0, s); + associate_vertex_with_full_cell(s, 0, v); + for( int i = 0; i <= cur_dim; ++i ) + for( int j = 0; j <= cur_dim; ++j ) + { + if( j == i ) continue; + set_neighbors(fc.neighbor(i), j, fc.neighbor(j), i); + } + return v; +} + +template <class Dim, class Vb, class Fcb > +typename Triangulation_data_structure<Dim, Vb, Fcb>::Vertex_handle +Triangulation_data_structure<Dim, Vb, Fcb> +::insert_in_face(const Face & f) /* Concept */ +{ + std::vector<Full_cell_handle> simps; + simps.reserve(64); + std::back_insert_iterator<std::vector<Full_cell_handle> > out(simps); + incident_full_cells(f, out); + return insert_in_hole(simps.begin(), simps.end(), Facet(f.full_cell(), f.index(0))); +} +template <class Dim, class Vb, class Fcb > +typename Triangulation_data_structure<Dim, Vb, Fcb>::Vertex_handle +Triangulation_data_structure<Dim, Vb, Fcb> +::insert_in_facet(const Facet & ft) /* Concept */ +{ + Full_cell_handle s[2]; + s[0] = full_cell(ft); + int i = index_of_covertex(ft); + s[1] = s[0]->neighbor(i); + i = ( i + 1 ) % current_dimension(); + return insert_in_hole(s, s+2, Facet(s[0], i)); +} + +template <class Dim, class Vb, class Fcb > +template < typename OutputIterator > +typename Triangulation_data_structure<Dim, Vb, Fcb>::Full_cell_handle +Triangulation_data_structure<Dim, Vb, Fcb> +::insert_in_tagged_hole(Vertex_handle v, Facet f, + OutputIterator new_full_cells) +{ + CGAL_assertion_msg(is_boundary_facet(f), "starting facet should be on the hole boundary"); + + const int cur_dim = current_dimension(); + Full_cell_handle new_s; + + std::queue<IITH_task> task_queue; + task_queue.push( + IITH_task(f, mirror_index(full_cell(f), index_of_covertex(f))) ); + + while (!task_queue.empty()) + { + IITH_task task = task_queue.front(); + task_queue.pop(); + + Full_cell_handle old_s = full_cell(task.boundary_facet); + const int facet_index = index_of_covertex(task.boundary_facet); + + Full_cell_handle outside_neighbor = neighbor(old_s, facet_index); + // Here, "new_s" might actually be a new cell, but it might also be "old_s" + // if it has not been treated already in the meantime + new_s = neighbor(outside_neighbor, task.index_of_inside_cell_in_outside_cell); + // If the cell has not been treated yet + if (old_s == new_s) + { + new_s = new_full_cell(); + + int i(0); + for ( ; i < facet_index ; ++i) + associate_vertex_with_full_cell(new_s, i, old_s->vertex(i)); + ++i; // skip facet_index + for ( ; i <= cur_dim ; ++i) + associate_vertex_with_full_cell(new_s, i, old_s->vertex(i)); + associate_vertex_with_full_cell(new_s, facet_index, v); + set_neighbors(new_s, + facet_index, + outside_neighbor, + mirror_index(old_s, facet_index)); + + // add the new full_cell to the list of new full_cells + *new_full_cells++ = new_s; + + // check all of |Facet f|'s neighbors + for (i = 0 ; i <= cur_dim ; ++i) + { + if (facet_index == i) + continue; + // we define a |Rotor| because it makes it easy to rotate around + // in a self contained fashion. The corresponding potential + // boundary facet is Facet(full_cell(rot), index_of_covertex(rot)) + Rotor rot(old_s, i, facet_index); + // |rot| on line above, stands for Candidate Facet + while (!is_boundary_facet(rot)) + rot = rotate_rotor(rot); + + // we did find the |i|-th neighbor of Facet(old_s, facet_index)... + // has it already been extruded to center point |v| ? + Full_cell_handle inside = full_cell(rot); + Full_cell_handle outside = neighbor(inside, index_of_covertex(rot)); + // "m" is the vertex of outside which is not on the boundary + Vertex_handle m = inside->mirror_vertex(index_of_covertex(rot), current_dimension()); // CJTODO: use mirror_index? + // "index" is the index of m in "outside" + int index = outside->index(m); + // new_neighbor is the inside cell which is registered as the neighbor + // of the outside cell => it's either a newly created inside cell or an + // old inside cell which we are about to delete + Full_cell_handle new_neighbor = outside->neighbor(index); + + // Is new_neighbor still the old neighbor? + if (new_neighbor == inside) + { + task_queue.push(IITH_task( + Facet(inside, index_of_covertex(rot)), // boundary facet + index, // index_of_inside_cell_in_outside_cell + new_s, // future_neighbor + i, // new_cell_index_in_future_neighbor + index_of_second_covertex(rot) // index_of_future_neighbor_in_new_cell + )); + } + } + } + + // If there is some neighbor stories to fix + if (task.future_neighbor != Full_cell_handle()) + { + // now the new neighboring full_cell exists, we link both + set_neighbors(new_s, + task.index_of_future_neighbor_in_new_cell, + task.future_neighbor, + task.new_cell_index_in_future_neighbor); + } + } + + return new_s; +} + +template< class Dim, class Vb, class Fcb > +template< typename Forward_iterator, typename OutputIterator > +typename Triangulation_data_structure<Dim, Vb, Fcb>::Vertex_handle +Triangulation_data_structure<Dim, Vb, Fcb> +::insert_in_hole(Forward_iterator start, Forward_iterator end, Facet f, + OutputIterator out) /* Concept */ +{ + CGAL_expensive_precondition( + ( std::distance(start, end) == 1 ) + || ( current_dimension() > 1 ) ); + Forward_iterator sit = start; + while( end != sit ) + set_visited(*sit++, true); + Vertex_handle v = new_vertex(); + insert_in_tagged_hole(v, f, out); + delete_full_cells(start, end); + return v; +} + +template< class Dim, class Vb, class Fcb > +template< typename Forward_iterator > +typename Triangulation_data_structure<Dim, Vb, Fcb>::Vertex_handle +Triangulation_data_structure<Dim, Vb, Fcb> +::insert_in_hole(Forward_iterator start, Forward_iterator end, Facet f) /* Concept */ +{ + Emptyset_iterator out; + return insert_in_hole(start, end, f, out); +} + +template <class Dim, class Vb, class Fcb> +void +Triangulation_data_structure<Dim, Vb, Fcb> +::clear_visited_marks(Full_cell_handle start) const // NOT DOCUMENTED +{ + CGAL_precondition(start != Full_cell_handle()); + + std::queue<Full_cell_handle> queue; + set_visited(start, false); + queue.push(start); + const int cur_dim = current_dimension(); + while( ! queue.empty() ) + { + Full_cell_handle s = queue.front(); + queue.pop(); + for( int i = 0; i <= cur_dim; ++i ) + { + if( get_visited(s->neighbor(i)) ) + { + set_visited(s->neighbor(i), false); + queue.push(s->neighbor(i)); + } + } + } +} + +template <class Dim, class Vb, class Fcb> +void Triangulation_data_structure<Dim, Vb, Fcb> +::do_insert_increase_dimension(Vertex_handle x, Vertex_handle star) +{ + Full_cell_handle start = full_cells_begin(); + Full_cell_handle swap_me; + const int cur_dim = current_dimension(); + for( Full_cell_iterator S = full_cells_begin(); S != full_cells_end(); ++S ) + { + if( Vertex_handle() != S->vertex(cur_dim) ) + continue; + set_visited(S, true); + // extends full_cell |S| to include the new vertex as the + // current_dimension()-th vertex + associate_vertex_with_full_cell(S, cur_dim, x); + if( ! S->has_vertex(star) ) + { // S is bounded, we create its unbounded "twin" full_cell + Full_cell_handle S_new = new_full_cell(); + set_neighbors(S, cur_dim, S_new, 0); + associate_vertex_with_full_cell(S_new, 0, star); + // here, we could be clever so as to get consistent orientation + for( int k = 1; k <= cur_dim; ++k ) + associate_vertex_with_full_cell(S_new, k, vertex(S, k - 1)); + } + } + // now we setup the neighbors + set_visited(start, false); + std::queue<Full_cell_handle> queue; + queue.push(start); + while( ! queue.empty() ) + { + Full_cell_handle S = queue.front(); + queue.pop(); + // here, the first visit above ensured that all neighbors exist now. + // Now we need to connect them with adjacency relation + int star_index; + if( S->has_vertex(star, star_index) ) + { + set_neighbors( S, cur_dim, neighbor(neighbor(S, star_index), cur_dim), + // this is tricky :-) : + mirror_index(S, star_index) + 1); + } + else + { + Full_cell_handle S_new = neighbor(S, cur_dim); + for( int k = 0 ; k < cur_dim ; ++k ) + { + Full_cell_handle S_opp = neighbor(S, k); + if( ! S_opp->has_vertex(star) ) + set_neighbors(S_new, k + 1, neighbor(S_opp, cur_dim), mirror_index(S, k) + 1); + // neighbor of S_new opposite to v is S_new' + // the vertex opposite to v remains the same but ... + // remember the shifting of the vertices one step to the right + } + } + for( int k = 0 ; k < cur_dim ; ++k ) + if( get_visited(neighbor(S, k)) ) + { + set_visited(neighbor(S, k), false); + queue.push(neighbor(S, k)); + } + } + if( ( ( cur_dim % 2 ) == 0 ) && ( cur_dim > 1 ) ) + { + for( Full_cell_iterator S = full_cells_begin(); S != full_cells_end(); ++S ) + { + if( x != S->vertex(cur_dim) ) + S->swap_vertices(cur_dim - 1, cur_dim); + } + } + if( Full_cell_handle() != swap_me ) + swap_me->swap_vertices(1, 2); +} + +template <class Dim, class Vb, class Fcb> +typename Triangulation_data_structure<Dim, Vb, Fcb>::Vertex_handle +Triangulation_data_structure<Dim, Vb, Fcb> +::insert_increase_dimension(Vertex_handle star) /* Concept */ +{ + const int prev_cur_dim = current_dimension(); + CGAL_precondition(prev_cur_dim < maximal_dimension()); + if( -2 != current_dimension() ) + { + CGAL_precondition( Vertex_handle() != star ); + CGAL_expensive_precondition(is_vertex(star)); + } + + set_current_dimension(prev_cur_dim + 1); + Vertex_handle v = new_vertex(); + switch( prev_cur_dim ) + { + case -2: + { // insertion of the first vertex + // ( geometrically : infinite vertex ) + Full_cell_handle s = new_full_cell(); + associate_vertex_with_full_cell(s, 0, v); + break; + } + case -1: + { // insertion of the second vertex + // ( geometrically : first finite vertex ) + //we create a triangulation of the 0-sphere, with + // vertices |star| and |v| + Full_cell_handle infinite_full_cell = star->full_cell(); + Full_cell_handle finite_full_cell = new_full_cell(); + associate_vertex_with_full_cell(finite_full_cell, 0, v); + set_neighbors(infinite_full_cell, 0, finite_full_cell, 0); + break; + } + default: + do_insert_increase_dimension(v, star); + break; + } + return v; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// - - - - - - - - - - - - - - - - - - - - - - - - VALIDITY CHECKS + +template <class Dimen, class Vb, class Fcb> +bool Triangulation_data_structure<Dimen, Vb, Fcb> +::is_valid(bool verbose, int /* level */) const /* Concept */ +{ + Full_cell_const_handle s, t; + Vertex_const_handle v; + int i, j, k; + + if( current_dimension() == -2 ) + { + if( ! vertices_.empty() || ! full_cells_.empty() ) + { + if( verbose ) CGAL_warning_msg(false, "current dimension is -2 but there are vertices or full_cells"); + return false; + } + } + + if( current_dimension() == -1 ) + { + if ( (number_of_vertices() != 1) || (number_of_full_cells() != 1) ) + { + if( verbose ) CGAL_warning_msg(false, "current dimension is -1 but there isn't one vertex and one full_cell"); + return false; + } + } + + for( v = vertices_begin(); v != vertices_end(); ++v ) + { + if( ! v->is_valid(verbose) ) + return false; + } + + // FUTURE: for each vertex v, gather incident full_cells. then, check that + // any full_cell containing v is among those gathered full_cells... + + if( current_dimension() < 0 ) + return true; + + for( s = full_cells_begin(); s != full_cells_end(); ++s ) + { + if( ! s->is_valid(verbose) ) + return false; + // check that the full cell has no duplicate vertices + for( i = 0; i <= current_dimension(); ++i ) + for( j = i + 1; j <= current_dimension(); ++j ) + if( vertex(s,i) == vertex(s,j) ) + { + CGAL_warning_msg(false, "a full_cell has two equal vertices"); + return false; + } + } + + for( s = full_cells_begin(); s != full_cells_end(); ++s ) + { + for( i = 0; i <= current_dimension(); ++i ) + if( (t = neighbor(s,i)) != Full_cell_const_handle() ) + { + int l = mirror_index(s,i); + if( s != neighbor(t,l) || i != mirror_index(t,l) ) + { + if( verbose ) CGAL_warning_msg(false, "neighbor relation is not symmetric"); + return false; + } + for( j = 0; j <= current_dimension(); ++j ) + if( j != i ) + { + // j must also occur as a vertex of t + for( k = 0; k <= current_dimension() && ( vertex(s,j) != vertex(t,k) || k == l); ++k ) + ; + if( k > current_dimension() ) + { + if( verbose ) CGAL_warning_msg(false, "too few shared vertices between neighbors full_cells."); + return false; + } + } + } + else + { + if( verbose ) CGAL_warning_msg(false, "full_cell has a NULL neighbor"); + return false; + } + } + return true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// - - - - - - - - - - - - - - - - - - - - - - - - INPUT / OUTPUT + +// NOT DOCUMENTED +template <class Dim, class Vb, class Fcb> +template <class OutStream> +void Triangulation_data_structure<Dim, Vb, Fcb> +::write_graph(OutStream & os) +{ + std::vector<std::set<int> > edges; + os << number_of_vertices() + 1; // add the vertex at infinity + int count(1); + for( Vertex_iterator vit = vertices_begin(); vit != vertices_end(); ++vit ) + vit->idx_ = count++; + edges.resize(number_of_vertices()+1); + for( Full_cell_iterator sit = full_cells_begin(); sit != full_cells_end(); ++sit ) + { + int v1 = 0; + while( v1 < current_dimension() ) + { + int v2 = v1 + 1; + while( v2 <= current_dimension() ) + { + int i1, i2; + if( Vertex_handle() != sit-> vertex(v1) ) + i1 = sit->vertex(v1)->idx_; + else + i1 = 0; + if( Vertex_handle() != sit-> vertex(v2) ) + i2 = sit->vertex(v2)->idx_; + else + i2 = 0; + edges[i1].insert(i2); + edges[i2].insert(i1); + ++v2; + } + ++v1; + } + } + for( std::size_t i = 0; i < edges.size(); ++i ) + { + os << std::endl << edges[i].size(); + for( std::set<int>::const_iterator nit = edges[i].begin(); + nit != edges[i].end(); ++nit ) + { + os << ' ' << (*nit); + } + } +} + +// NOT DOCUMENTED... +template<class Dimen, class Vb, class Fcb> +std::istream & +Triangulation_data_structure<Dimen, Vb, Fcb> +::read_full_cells(std::istream & is, const std::vector<Vertex_handle> & vertices) +{ + std::size_t m; // number of full_cells + int index; + const int cd = current_dimension(); + if( is_ascii(is) ) + is >> m; + else + read(is, m, io_Read_write()); + + std::vector<Full_cell_handle> full_cells; + full_cells.reserve(m); + // read the vertices of each full_cell + std::size_t i = 0; + while( i < m ) + { + Full_cell_handle s = new_full_cell(); + full_cells.push_back(s); + for( int j = 0; j <= cd; ++j ) + { + if( is_ascii(is) ) + is >> index; + else + read(is, index); + s->set_vertex(j, vertices[index]); + } + // read other non-combinatorial information for the full_cells + is >> (*s); + ++i; + } + + // read the neighbors of each full_cell + i = 0; + if( is_ascii(is) ) + while( i < m ) + { + for( int j = 0; j <= cd; ++j ) + { + is >> index; + full_cells[i]->set_neighbor(j, full_cells[index]); + } + ++i; + } + else + while( i < m ) + { + for( int j = 0; j <= cd; ++j ) + { + read(is, index); + full_cells[i]->set_neighbor(j, full_cells[index]); + } + ++i; + } + + // compute the mirror indices + for( i = 0; i < m; ++i ) + { + Full_cell_handle s = full_cells[i]; + for( int j = 0; j <= cd; ++j ) + { + if( -1 != s->mirror_index(j) ) + continue; + Full_cell_handle n = s->neighbor(j); + int k = 0; + Full_cell_handle nn = n->neighbor(k); + while( s != nn ) + nn = n->neighbor(++k); + s->set_mirror_index(j,k); + n->set_mirror_index(k,j); + } + } + return is; +} + +// NOT DOCUMENTED... +template<class Dimen, class Vb, class Fcb> +std::ostream & +Triangulation_data_structure<Dimen, Vb, Fcb> +::write_full_cells(std::ostream & os, std::map<Vertex_const_handle, int> & index_of_vertex) const +{ + std::map<Full_cell_const_handle, int> index_of_full_cell; + + std::size_t m = number_of_full_cells(); + + if( is_ascii(os) ) + os << std::endl << m; + else + write(os, m, io_Read_write()); + + const int cur_dim = current_dimension(); + // write the vertex indices of each full_cell + int i = 0; + for( Full_cell_const_iterator it = full_cells_begin(); it != full_cells_end(); ++it ) + { + index_of_full_cell[it] = i++; + if( is_ascii(os) ) + os << std::endl; + for( int j = 0; j <= cur_dim; ++j ) + { + if( is_ascii(os) ) + os << ' ' << index_of_vertex[it->vertex(j)]; + else + write(os, index_of_vertex[it->vertex(j)]); + } + // write other non-combinatorial information for the full_cells + os << (*it); + } + + CGAL_assertion( (std::size_t) i == m ); + + // write the neighbors of each full_cell + if( is_ascii(os) ) + for( Full_cell_const_iterator it = full_cells_begin(); it != full_cells_end(); ++it ) + { + os << std::endl; + for( int j = 0; j <= cur_dim; ++j ) + os << ' ' << index_of_full_cell[it->neighbor(j)]; + } + else + for( Full_cell_const_iterator it = full_cells_begin(); it != full_cells_end(); ++it ) + { + for( int j = 0; j <= cur_dim; ++j ) + write(os, index_of_full_cell[it->neighbor(j)]); + } + + return os; +} + +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +// FUNCTIONS THAT ARE NOT MEMBER FUNCTIONS: + +template<class Dimen, class Vb, class Fcb> +std::istream & +operator>>(std::istream & is, Triangulation_data_structure<Dimen, Vb, Fcb> & tr) + // reads : + // - the dimensions (maximal and current) + // - the number of finite vertices + // - the non combinatorial information on vertices (point, etc) + // - the number of full_cells + // - the full_cells by the indices of their vertices in the preceding list + // of vertices, plus the non combinatorial information on each full_cell + // - the neighbors of each full_cell by their index in the preceding list +{ + typedef Triangulation_data_structure<Dimen, Vb, Fcb> TDS; + typedef typename TDS::Vertex_handle Vertex_handle; + + // read current dimension and number of vertices + std::size_t n; + int cd; + if( is_ascii(is) ) + is >> cd >> n; + else + { + read(is, cd); + read(is, n, io_Read_write()); + } + + CGAL_assertion_msg( cd <= tr.maximal_dimension(), "input Triangulation_data_structure has too high dimension"); + + tr.clear(); + tr.set_current_dimension(cd); + + if( n == 0 ) + return is; + + std::vector<Vertex_handle> vertices; + vertices.resize(n); + + // read the vertices: + std::size_t i(0); + while( i < n ) + { + vertices[i] = tr.new_vertex(); + is >> (*vertices[i]); // read a vertex + ++i; + } + + // now, read the combinatorial information + return tr.read_full_cells(is, vertices); +} + +template<class Dimen, class Vb, class Fcb> +std::ostream & +operator<<(std::ostream & os, const Triangulation_data_structure<Dimen, Vb, Fcb> & tr) + // writes : + // - the dimensions (maximal and current) + // - the number of finite vertices + // - the non combinatorial information on vertices (point, etc) + // - the number of full cells + // - the full cells by the indices of their vertices in the preceding list + // of vertices, plus the non combinatorial information on each full_cell + // - the neighbors of each full_cell by their index in the preceding list +{ + typedef Triangulation_data_structure<Dimen, Vb, Fcb> TDS; + typedef typename TDS::Vertex_const_handle Vertex_handle; + typedef typename TDS::Vertex_const_iterator Vertex_iterator; + + // outputs dimension and number of vertices + std::size_t n = tr.number_of_vertices(); + if( is_ascii(os) ) + os << tr.current_dimension() << std::endl << n; + else + { + write(os, tr.current_dimension()); + write(os, n, io_Read_write()); + } + + if( n == 0 ) + return os; + + // write the vertices + std::map<Vertex_handle, int> index_of_vertex; + int i = 0; + for( Vertex_iterator it = tr.vertices_begin(); it != tr.vertices_end(); ++it, ++i ) + { + os << *it; // write the vertex + if (is_ascii(os)) + os << std::endl; + index_of_vertex[it] = i; + } + CGAL_assertion( (std::size_t) i == n ); + + // output the combinatorial information + return tr.write_full_cells(os, index_of_vertex); +} + +} //namespace CGAL + +#endif // CGAL_TRIANGULATION_DATA_STRUCTURE_H diff --git a/src/common/include/gudhi_patches/CGAL/Triangulation_ds_full_cell.h b/src/common/include/gudhi_patches/CGAL/Triangulation_ds_full_cell.h new file mode 100644 index 00000000..541a6a85 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/Triangulation_ds_full_cell.h @@ -0,0 +1,311 @@ +// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Samuel Hornus + +#ifndef CGAL_TRIANGULATION_DS_FULL_CELL_H +#define CGAL_TRIANGULATION_DS_FULL_CELL_H + +#include <CGAL/TDS_full_cell_default_storage_policy.h> +#include <CGAL/TDS_full_cell_mirror_storage_policy.h> +#include <CGAL/internal/Triangulation/Dummy_TDS.h> +#include <CGAL/Dimension.h> +#include <CGAL/Default.h> +#include <CGAL/array.h> + +namespace CGAL { + +template< class TDS = void, typename FullCellStoragePolicy = Default > +class Triangulation_ds_full_cell +{ + typedef typename Default::Get<FullCellStoragePolicy, TDS_full_cell_default_storage_policy>::type + Storage_policy; + typedef Triangulation_ds_full_cell<TDS> Self; + typedef typename TDS::Maximal_dimension Maximal_dimension; + +public: + typedef TDS Triangulation_data_structure; + typedef typename TDS::Face Face; + typedef typename TDS::Vertex_handle Vertex_handle; /* Concept */ + typedef typename TDS::Vertex_const_handle Vertex_const_handle; + typedef typename TDS::Full_cell_handle Full_cell_handle; /* Concept */ + typedef typename TDS::Full_cell_const_handle Full_cell_const_handle; + typedef typename TDS::Full_cell_data TDS_data; /* data that the TDS wants to be stored here */ + template< typename TDS2 > + struct Rebind_TDS /* Concept */ + { + typedef Triangulation_ds_full_cell<TDS2, FullCellStoragePolicy> Other; + }; + +private: // STORAGE + typedef TFC_data< Vertex_handle, Full_cell_handle, + Maximal_dimension, Storage_policy > Combinatorics; + friend struct TFC_data< Vertex_handle, Full_cell_handle, + Maximal_dimension, Storage_policy >; + // array of vertices + typedef typename Combinatorics::Vertex_handle_array Vertex_handle_array; + // neighbor simplices + typedef typename Combinatorics::Full_cell_handle_array Full_cell_handle_array; + + // NOT DOCUMENTED... + typename Combinatorics::Xor_type xor_of_vertices(const int cur_dim) const + { + return combinatorics_.xor_of_vertices(cur_dim); + } + +public: + typedef typename Vertex_handle_array::const_iterator Vertex_handle_const_iterator; + typedef Vertex_handle_const_iterator Vertex_handle_iterator; /* Concept */ + + Triangulation_ds_full_cell(const int dmax) /* Concept */ + : combinatorics_(dmax), tds_data_() + { + CGAL_assertion( dmax > 0 ); + for( int i = 0; i <= dmax; ++i ) + { + set_neighbor(i, Full_cell_handle()); + set_vertex(i, Vertex_handle()); + set_mirror_index(i, -1); + } + } + + Triangulation_ds_full_cell(const Triangulation_ds_full_cell & s) /* Concept */ + : combinatorics_(s.combinatorics_), tds_data_(s.tds_data_) + {} + + ~Triangulation_ds_full_cell() {} + + int maximal_dimension() const /* Concept */ + { + return static_cast<int>(vertices().size() - 1); + } + + Vertex_handle_const_iterator vertices_begin() const /* Concept */ + { + return vertices().begin(); + } + + Vertex_handle_const_iterator vertices_end() const /* Concept */ + { + return vertices().end(); + } + + Vertex_handle vertex(const int i) const /* Concept */ + { + CGAL_precondition(0<=i && i<=maximal_dimension()); + return vertices()[i]; + } + + Full_cell_handle neighbor(const int i) const /* Concept */ + { + CGAL_precondition(0<=i && i<=maximal_dimension()); + return neighbors()[i]; + } + + int mirror_index(const int i) const /* Concept */ + { + CGAL_precondition(0<=i && i<=maximal_dimension()); + return combinatorics_.mirror_index(i); + } + + // Advanced... + Vertex_handle mirror_vertex(const int i, const int cur_dim) const /* Concept */ + { + CGAL_precondition(0<=i && i<=maximal_dimension()); + return combinatorics_.mirror_vertex(i, cur_dim); + } + + int index(Full_cell_const_handle s) const /* Concept */ + { + // WE ASSUME THE FULL CELL WE ARE LOOKING FOR INDEED EXISTS ! + CGAL_precondition(has_neighbor(s)); + int index(0); + while( neighbor(index) != s ) + ++index; + return index; + } + + int index(Vertex_const_handle v) const /* Concept */ + { + // WE ASSUME THE VERTEX WE ARE LOOKING FOR INDEED EXISTS ! + CGAL_precondition(has_vertex(v)); + int index(0); + while( vertex(index) != v ) + ++index; + return index; + } + + void set_vertex(const int i, Vertex_handle v) /* Concept */ + { + CGAL_precondition(0<=i && i<=maximal_dimension()); + vertices()[i] = v; + } + + void set_neighbor(const int i, Full_cell_handle s) /* Concept */ + { + CGAL_precondition(0<=i && i<=maximal_dimension()); + neighbors()[i] = s; + } + + void set_mirror_index(const int i, const int index) /* Concept */ + { + CGAL_precondition(0<=i && i<=maximal_dimension()); + combinatorics_.set_mirror_index(i, index); + } + + bool has_vertex(Vertex_const_handle v) const /* Concept */ + { + int index; + return has_vertex(v, index); + } + + bool has_vertex(Vertex_const_handle v, int & index) const /* Concept */ + { + const int d = maximal_dimension(); + index = 0; + while( (index <= d) && (vertex(index) != v) ) + ++index; + return (index <= d); + } + + bool has_neighbor(Full_cell_const_handle s) const /* Concept */ + { + int index; + return has_neighbor(s, index); + } + + bool has_neighbor(Full_cell_const_handle s, int & index) const /* Concept */ + { + const int d = maximal_dimension(); + index = 0; + while( (index <= d) && (neighbor(index) != s) ) + ++index; + return (index <= d); + } + + void swap_vertices(const int d1, const int d2) /* Concept */ + { + CGAL_precondition(0 <= d1 && d1<=maximal_dimension()); + CGAL_precondition(0 <= d2 && d2<=maximal_dimension()); + combinatorics_.swap_vertices(d1, d2); + } + + const TDS_data & tds_data() const { return tds_data_; } /* Concept */ + TDS_data & tds_data() { return tds_data_; } /* Concept */ + + void* for_compact_container() const { return combinatorics_.for_compact_container(); } + void* & for_compact_container() { return combinatorics_.for_compact_container(); } + + bool is_valid(bool verbose = false, int = 0) const /* Concept */ + { + const int d = maximal_dimension(); + int i(0); + // test that the non-null Vertex_handles come first, before all null ones + while( i <= d && vertex(i) != Vertex_handle() ) ++i; + while( i <= d && vertex(i) == Vertex_handle() ) ++i; + if( i <= d ) + { + if( verbose ) CGAL_warning_msg(false, "full cell has garbage handles to vertices."); + return false; + } + for( i = 0; i <= d; ++i ) + { + if( Vertex_handle() == vertex(i) ) + break; // there are no more vertices + Full_cell_handle n(neighbor(i)); + if( Full_cell_handle() != n ) + { + int mirror_idx(mirror_index(i)); + if( n->neighbor(mirror_idx) == Full_cell_handle() ) + { + if( verbose ) CGAL_warning_msg(false, "neighbor has no back-neighbor."); + return false; + } + if( &(*(n->neighbor(mirror_idx))) != this ) + { + if( verbose ) CGAL_warning_msg(false, "neighbor does not point back to correct full cell."); + return false; + } + } + } + return true; + } + +private: + // access to data members: + Full_cell_handle_array & neighbors() {return combinatorics_.neighbors_; } + const Full_cell_handle_array & neighbors() const {return combinatorics_.neighbors_; } + Vertex_handle_array & vertices() {return combinatorics_.vertices_; } + const Vertex_handle_array & vertices() const {return combinatorics_.vertices_; } + + // DATA MEMBERS + Combinatorics combinatorics_; + mutable TDS_data tds_data_; +}; + +// FUNCTIONS THAT ARE NOT MEMBER FUNCTIONS: + +template < typename TDS, typename SSP > +std::ostream & +operator<<(std::ostream & O, const Triangulation_ds_full_cell<TDS,SSP> &) /* Concept */ +{ + /*if( is_ascii(O) ) + { + // os << '\n'; + } + else {}*/ + return O; +} + +template < typename TDS, typename SSP > +std::istream & +operator>>(std::istream & I, Triangulation_ds_full_cell<TDS,SSP> &) /* Concept */ +{ + /*if( is_ascii(I) ) + {} + else {}*/ + return I; +} + +// Special case: specialization when template parameter is void. + +// we must declare it for each possible full_cell storage policy because : +// (GCC error:) default template arguments may not be used in partial specializations +template< typename StoragePolicy > +class Triangulation_ds_full_cell<void, StoragePolicy> +{ +public: + typedef internal::Triangulation::Dummy_TDS TDS; + typedef TDS Triangulation_data_structure; + typedef TDS::Vertex_handle Vertex_handle; + typedef TDS::Vertex_const_handle Vertex_const_handle; + typedef TDS::Full_cell_handle Full_cell_handle; + typedef TDS::Full_cell_const_handle Full_cell_const_handle; + typedef TDS::Vertex_handle_const_iterator Vertex_handle_const_iterator; + typedef TDS::Full_cell_data TDS_data; + template <typename TDS2> + struct Rebind_TDS + { + typedef Triangulation_ds_full_cell<TDS2, StoragePolicy> Other; + }; + Vertex_handle_const_iterator vertices_begin(); + Vertex_handle_const_iterator vertices_end(); +}; + +} //namespace CGAL + +#endif // CGAL_TRIANGULATION_DS_FULL_CELL_H diff --git a/src/common/include/gudhi_patches/CGAL/Triangulation_ds_vertex.h b/src/common/include/gudhi_patches/CGAL/Triangulation_ds_vertex.h new file mode 100644 index 00000000..381b97e1 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/Triangulation_ds_vertex.h @@ -0,0 +1,154 @@ +// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Samuel Hornus + +#ifndef CGAL_TRIANGULATION_DS_VERTEX_H +#define CGAL_TRIANGULATION_DS_VERTEX_H + +#include <CGAL/Compact_container.h> +#include <CGAL/internal/Triangulation/Dummy_TDS.h> + +namespace CGAL { + +/* The template parameter TDS must be a model of the concept + * 'TriangulationDataStructure' that stores vertices of type + * 'Triangulation_ds_vertex<TDS>' + */ +template< class TDS = void > +class Triangulation_ds_vertex +{ + typedef Triangulation_ds_vertex<TDS> Self; + +public: + typedef TDS Triangulation_data_structure; + typedef typename TDS::Full_cell_handle Full_cell_handle; /* Concept */ + + template <typename TDS2> + struct Rebind_TDS /* Concept */ + { + typedef Triangulation_ds_vertex<TDS2> Other; + }; + +protected: // DATA MEMBERS + Full_cell_handle full_cell_; // A handle to an incident full_cell + +public: + // Constructs a vertex with incident full_cell 's' + Triangulation_ds_vertex(Full_cell_handle s) : full_cell_(s) /* Concept */ + { + CGAL_assertion( Full_cell_handle() != s ); + } + // Constructs a vertex with no incident full_cell + Triangulation_ds_vertex() : full_cell_() {} /* Concept */ + + ~Triangulation_ds_vertex() {} + + /// Set 's' as an incident full_cell + void set_full_cell(Full_cell_handle s) /* Concept */ + { + full_cell_ = s; + } + + /// Returns a full_cell incident to the vertex + Full_cell_handle full_cell() const /* Concept */ + { + return full_cell_; + } + + bool is_valid(bool verbose = false, int /* level */ = 0) const /* Concept */ + { + if( Full_cell_handle() == full_cell() ) + { + if( verbose ) + CGAL_warning_msg(false, "vertex has no incident full cell."); + return false; + } + bool found(false); + // These two typename below are OK because TDS fullfils the + // TriangulationDataStructure concept. + typename TDS::Full_cell::Vertex_handle_iterator vit(full_cell()->vertices_begin()); + typedef typename TDS::Vertex_handle Vertex_handle; + while( vit != full_cell()->vertices_end() ) + { + if( Vertex_handle() == *vit ) + break; // The full cell has no more vertices + if( this == &(**vit) ) + { + found = true; + break; + } + ++vit; + } + if( ! found ) + { + if( verbose ) + CGAL_warning_msg(false, "vertex's adjacent full cell does not contain that vertex."); + return false; + } + return true; + } + +public: // FOR MEMORY MANAGEMENT + + void* for_compact_container() const { return full_cell_.for_compact_container(); } + void* & for_compact_container() { return full_cell_.for_compact_container(); } + +}; // end of Triangulation_ds_vertex + +// FUNCTIONS THAT ARE NOT MEMBER FUNCTIONS: + +template < class TDS > +std::istream & +operator>>(std::istream & is, Triangulation_ds_vertex<TDS> &) /* Concept */ +{ + /*if( is_ascii(is) ) + {} + else {}*/ + return is; +} + +template< class TDS > +std::ostream & +operator<<(std::ostream & os, const Triangulation_ds_vertex<TDS> &) /* Concept */ +{ + /*if( is_ascii(os) ) + { + os << '\n'; + } + else {}*/ + return os; +} + +// Special case: specialization when template parameter is void. + +template<> +class Triangulation_ds_vertex<void> +{ +public: + typedef internal::Triangulation::Dummy_TDS Triangulation_data_structure; + typedef Triangulation_data_structure::Full_cell_handle Full_cell_handle; /* Concept */ + template <typename TDS2> + struct Rebind_TDS /* Concept */ + { + typedef Triangulation_ds_vertex<TDS2> Other; + }; +}; + +} //namespace CGAL + +#endif // CGAL_TRIANGULATION_DS_VERTEX_H diff --git a/src/common/include/gudhi_patches/CGAL/Triangulation_face.h b/src/common/include/gudhi_patches/CGAL/Triangulation_face.h new file mode 100644 index 00000000..bc9c1781 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/Triangulation_face.h @@ -0,0 +1,111 @@ +// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Samuel Hornus + +#ifndef CGAL_TRIANGULATION_FACE_H +#define CGAL_TRIANGULATION_FACE_H + +#include <CGAL/basic.h> +#include <CGAL/internal/Static_or_dynamic_array.h> + +namespace CGAL { + +template< typename TDS > +class Triangulation_face +{ + typedef typename internal::Dimen_plus_one<typename TDS::Maximal_dimension>::type Dimen_plus; +public: + typedef TDS Triangulation_data_structure; + typedef typename TDS::Full_cell_handle Full_cell_handle; /* Concept */ + typedef typename TDS::Vertex_handle Vertex_handle; /* Concept */ + typedef internal::S_or_D_array<int, Dimen_plus> Indices; + +protected: + Full_cell_handle full_cell_; + Indices indices_; + +public: + explicit Triangulation_face(Full_cell_handle s) /* Concept */ + : full_cell_(s), indices_(s->maximal_dimension()+2) + { + CGAL_assertion( Full_cell_handle() != s ); + clear(); + } + + explicit Triangulation_face(const int maximal_dim) /* Concept */ + : full_cell_(), indices_(maximal_dim+2) + { + clear(); + } + + Triangulation_face(const Triangulation_face & f) /* Concept */ + : full_cell_(f.full_cell_), indices_(f.indices_) + {} + + int face_dimension() const /* Concept */ + { + int i(0); + while( -1 != indices_[i] ) ++i; + return (i-1); + } + + Full_cell_handle full_cell() const /* Concept */ + { + return full_cell_; + } + + int index(const int i) const /* Concept */ + { + CGAL_precondition( (0 <= i) && (i <= face_dimension()) ); + return indices_[i]; + } + + Vertex_handle vertex(const int i) const /* Concept */ + { + int j = index(i); + if( j == -1 ) + return Vertex_handle(); + return full_cell()->vertex(j); + } + +// - - - - - - - - - - - - - - - - - - UPDATE FUNCTIONS + + void clear() /* Concept */ + { + const std::size_t d = indices_.size(); + for(std::size_t i = 0; i < d; ++i ) + indices_[i] = -1; + } + + void set_full_cell(Full_cell_handle s) /* Concept */ + { + CGAL_precondition( Full_cell_handle() != s ); + full_cell_ = s; + } + + void set_index(const int i, const int idx) /* Concept */ + { + CGAL_precondition( (0 <= i) && ((size_t)i+1 < indices_.size()) ); + CGAL_precondition( (0 <= idx) && ((size_t)idx < indices_.size()) ); + indices_[i] = idx; + } +}; + +} //namespace CGAL + +#endif // CGAL_TRIANGULATION_FACE_H diff --git a/src/common/include/gudhi_patches/CGAL/Triangulation_full_cell.h b/src/common/include/gudhi_patches/CGAL/Triangulation_full_cell.h new file mode 100644 index 00000000..a0c5246f --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/Triangulation_full_cell.h @@ -0,0 +1,148 @@ +// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Samuel Hornus + +#ifndef CGAL_TRIANGULATION_SIMPLEX_H +#define CGAL_TRIANGULATION_SIMPLEX_H + +#include <CGAL/Triangulation_ds_full_cell.h> +#include <CGAL/internal/Triangulation/utilities.h> +#include <CGAL/Iterator_project.h> +#include <CGAL/Default.h> + +namespace CGAL { + +struct No_full_cell_data {}; + +template< class TriangulationTraits, typename Data_ = No_full_cell_data, class TDSFullCell = Default > +class Triangulation_full_cell : public Default::Get<TDSFullCell, Triangulation_ds_full_cell<> >::type +{ + // The default type for TDSFullCell is Triangulation_ds_full_cell<> : + typedef typename Default::Get<TDSFullCell, Triangulation_ds_full_cell<> >::type + Base; + typedef Triangulation_full_cell<TriangulationTraits, Data_, TDSFullCell> Self; +public: + typedef Data_ Data; + typedef typename Base::Vertex_handle Vertex_handle; + typedef typename Base::Vertex_const_handle Vertex_const_handle; + typedef typename Base::Vertex_handle_const_iterator Vertex_handle_const_iterator; + typedef typename Base::Full_cell_const_handle Full_cell_const_handle; + typedef typename TriangulationTraits::Point_d Point; + typedef typename TriangulationTraits::Point_d Point_d; + +private: // DATA MEMBERS + Data data_; + +public: + + using Base::vertices_begin; + using Base::vertices_end; + + template< class TDS2 > + struct Rebind_TDS + { + typedef typename Base::template Rebind_TDS<TDS2>::Other TDSFullCell2; + typedef Triangulation_full_cell<TriangulationTraits, Data_, TDSFullCell2> Other; + }; + + Triangulation_full_cell(const int d) + : Base(d), data_() {} + + Triangulation_full_cell(const Self & s) + : Base(s), data_(s.data_) {} + + const Data & data() const + { + return data_; + } + + Data & data() + { + return data_; + } + + struct Point_from_vertex_handle + { + typedef Vertex_handle argument_type; + typedef Point result_type; + result_type & operator()(argument_type & x) const + { + return x->point(); + } + const result_type & operator()(const argument_type & x) const + { + return x->point(); + } + }; + +protected: + + typedef CGAL::Iterator_project< + Vertex_handle_const_iterator, + internal::Triangulation::Point_from_vertex_handle<Vertex_handle, Point> + > Point_const_iterator; + + Point_const_iterator points_begin() const + { return Point_const_iterator(Base::vertices_begin()); } + Point_const_iterator points_end() const + { return Point_const_iterator(Base::vertices_end()); } +}; + +// FUNCTIONS THAT ARE NOT MEMBER FUNCTIONS: + +inline +std::istream & +operator>>(std::istream & is, No_full_cell_data &) +{ + return is; +} + +inline +std::ostream & +operator<<(std::ostream & os, const No_full_cell_data &) +{ + return os; +} + +template < typename TDS, typename Data, typename SSP > +std::ostream & +operator<<(std::ostream & O, const Triangulation_full_cell<TDS, Data, SSP> & s) +{ + /*if( is_ascii(O) ) + { + // os << '\n'; + } + else {}*/ + O << s.data(); + return O; +} + +template < typename TDS, typename Data, typename SSP > +std::istream & +operator>>(std::istream & I, Triangulation_full_cell<TDS, Data, SSP> & s) +{ + /*if( is_ascii(I) ) + {} + else {}*/ + I >> s.data(); + return I; +} + +} //namespace CGAL + +#endif // CGAL_TRIANGULATION_SIMPLEX_H diff --git a/src/common/include/gudhi_patches/CGAL/Triangulation_vertex.h b/src/common/include/gudhi_patches/CGAL/Triangulation_vertex.h new file mode 100644 index 00000000..f364717f --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/Triangulation_vertex.h @@ -0,0 +1,128 @@ +// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Samuel Hornus + +#ifndef CGAL_TRIANGULATION_VERTEX_H +#define CGAL_TRIANGULATION_VERTEX_H + +#include <CGAL/Triangulation_ds_vertex.h> +#include <CGAL/Default.h> + +namespace CGAL { + +struct No_vertex_data {}; + +template< class TriangulationTraits, typename Data_ = No_vertex_data, class TDSVertex = Default > +class Triangulation_vertex : public Default::Get<TDSVertex, Triangulation_ds_vertex<> >::type +{ + // The default type for TDSVertex is Triangulation_ds_vertex<> : + typedef typename Default::Get<TDSVertex, Triangulation_ds_vertex<> >::type + Base; + typedef Triangulation_vertex<TriangulationTraits, Data_, TDSVertex> Self; +public: + typedef Data_ Data; + typedef typename TriangulationTraits::Point_d Point; + typedef typename TriangulationTraits::Point_d Point_d; + typedef typename Base::Full_cell_handle Full_cell_handle; + + template <typename TDS2> + struct Rebind_TDS + { + typedef typename Base::template Rebind_TDS<TDS2>::Other TDSVertex2; + typedef Triangulation_vertex<TriangulationTraits, Data_, TDSVertex2> Other; + }; + +private: // DATA MEMBERS + Point point_; + Data data_; + +public: + template< typename T > + Triangulation_vertex(Full_cell_handle s, const Point & p, const T & t) + : Base(s), point_(p), data_(t) {} + Triangulation_vertex(Full_cell_handle s, const Point & p) + : Base(s), point_(p), data_() {} + template< typename T > + Triangulation_vertex(const Point & p, const T & t) + : Base(), point_(p), data_(t) {} + Triangulation_vertex(const Point & p) + : Base(), point_(p), data_() {} + Triangulation_vertex() : Base(), point_(), data_() {} + + ~Triangulation_vertex() {} + + /// Set the position in space of the vertex to 'p' + void set_point(const Point & p) + { + point_ = p; + } + + /// Returns the position in space of the vertex + const Point & point() const + { + return point_; + } + + const Data & data() const + { + return data_; + } + + Data & data() + { + return data_; + } + +}; // end of Triangulation_vertex + +// NON CLASS-MEMBER FUNCTIONS + +inline +std::istream & +operator>>(std::istream & is, No_vertex_data &) +{ + return is; +} + +inline +std::ostream & +operator<<(std::ostream & os, const No_vertex_data &) +{ + return os; +} + +template < class A, typename Data, class B > +std::istream & +operator>>(std::istream & is, Triangulation_vertex<A, Data, B> & v) +{ + is >> v.point(); + return (is >> v.data()); +} + +template< class A, typename Data, class B > +std::ostream & +operator<<(std::ostream & os, const Triangulation_vertex<A, Data, B> & v) +{ + os << v.point(); + os << v.data(); + return os; +} + +} //namespace CGAL + +#endif // CGAL_TRIANGULATION_VERTEX_H diff --git a/src/common/include/gudhi_patches/CGAL/argument_swaps.h b/src/common/include/gudhi_patches/CGAL/argument_swaps.h new file mode 100644 index 00000000..aa16f29b --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/argument_swaps.h @@ -0,0 +1,88 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_ARGUMENT_SWAPS_H +#define CGAL_ARGUMENT_SWAPS_H + +#include <CGAL/config.h> +#include <utility> + +#ifndef CGAL_CXX11 +#include <boost/preprocessor/repetition.hpp> +#include <boost/utility/result_of.hpp> +#endif + +namespace CGAL { + +#ifdef CGAL_CXX11 + +namespace internal { + +template<int,class...> struct Apply_to_last_then_rest_; + +template<int d,class F,class T,class... U> +struct Apply_to_last_then_rest_<d,F,T,U...> { + typedef typename Apply_to_last_then_rest_<d-1,F,U...,T>::result_type result_type; + inline result_type operator()(F&&f,T&&t,U&&...u)const{ + return Apply_to_last_then_rest_<d-1,F,U...,T>()( + std::forward<F>(f), + std::forward<U>(u)..., + std::forward<T>(t)); + } +}; + +template<class F,class T,class... U> +struct Apply_to_last_then_rest_<0,F,T,U...> { + typedef decltype(std::declval<F>()(std::declval<T>(), std::declval<U>()...)) result_type; + inline result_type operator()(F&&f,T&&t,U&&...u)const{ + return std::forward<F>(f)(std::forward<T>(t), std::forward<U>(u)...); + } +}; + +} // namespace internal + + +struct Apply_to_last_then_rest { + template<class F,class T,class...U> inline + typename internal::Apply_to_last_then_rest_<sizeof...(U),F,T,U...>::result_type + operator()(F&&f,T&&t,U&&...u)const{ + return internal::Apply_to_last_then_rest_<sizeof...(U),F,T,U...>()( + std::forward<F>(f), + std::forward<T>(t), + std::forward<U>(u)...); + } +}; + +#else // CGAL_CXX11 + +struct Apply_to_last_then_rest { +#define CGAL_CODE(Z,N,_) template<class F,class T,BOOST_PP_ENUM_PARAMS(N,class T)> \ + typename boost::result_of<F(T,BOOST_PP_ENUM_PARAMS(N,T))>::type \ + operator()(F const&f, BOOST_PP_ENUM_BINARY_PARAMS(N,T,const&t), T const&t) const { \ + return f(t,BOOST_PP_ENUM_PARAMS(N,t)); \ + } + BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_) +#undef CGAL_CODE +}; + +#endif // CGAL_CXX11 + +} // namespace CGAL + +#endif // CGAL_ARGUMENT_SWAPS_H diff --git a/src/common/include/gudhi_patches/CGAL/determinant_of_vectors.h b/src/common/include/gudhi_patches/CGAL/determinant_of_vectors.h new file mode 100644 index 00000000..e1bad64e --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/determinant_of_vectors.h @@ -0,0 +1,117 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_DETVEC_H +#define CGAL_DETVEC_H +#include <CGAL/determinant.h> +#include <CGAL/predicates/sign_of_determinant.h> + +namespace CGAL { + // TODO: determine whether it is better to pass them by lines or columns. + + template <class NT, class Vector> inline + NT determinant_of_vectors(Vector const&a, Vector const&b){ + return determinant<NT>(a[0],a[1],b[0],b[1]); + } + template <class NT, class Vector> inline + typename Sgn<NT>::result_type + sign_of_determinant_of_vectors(Vector const&a, Vector const&b){ + return sign_of_determinant<NT>(a[0],a[1],b[0],b[1]); + } + + template <class NT, class Vector> + NT determinant_of_vectors(Vector const&a, Vector const&b, + Vector const&c){ + return determinant<NT>(a[0],a[1],a[2],b[0],b[1],b[2],c[0],c[1],c[2]); + } + template <class NT, class Vector> + typename Sgn<NT>::result_type + sign_of_determinant_of_vectors(Vector const&a, Vector const&b, + Vector const&c){ + return sign_of_determinant<NT>(a[0],a[1],a[2],b[0],b[1],b[2],c[0],c[1],c[2]); + } + + template <class NT, class Vector> + NT determinant_of_vectors(Vector const&a, Vector const&b, + Vector const&c, Vector const&d){ + return determinant<NT>( + a[0],a[1],a[2],a[3], + b[0],b[1],b[2],b[3], + c[0],c[1],c[2],c[3], + d[0],d[1],d[2],d[3]); + } + template <class NT, class Vector> + typename Sgn<NT>::result_type + sign_of_determinant_of_vectors(Vector const&a, Vector const&b, + Vector const&c, Vector const&d){ + return sign_of_determinant<NT>( + a[0],a[1],a[2],a[3], + b[0],b[1],b[2],b[3], + c[0],c[1],c[2],c[3], + d[0],d[1],d[2],d[3]); + } + + template <class NT, class Vector> + NT determinant_of_vectors(Vector const&a, Vector const&b, + Vector const&c, Vector const&d, Vector const&e){ + return determinant<NT>( + a[0],a[1],a[2],a[3],a[4], + b[0],b[1],b[2],b[3],b[4], + c[0],c[1],c[2],c[3],c[4], + d[0],d[1],d[2],d[3],d[4], + e[0],e[1],e[2],e[3],e[4]); + } + template <class NT, class Vector> + typename Sgn<NT>::result_type + sign_of_determinant_of_vectors(Vector const&a, Vector const&b, + Vector const&c, Vector const&d, Vector const&e){ + return sign_of_determinant<NT>( + a[0],a[1],a[2],a[3],a[4], + b[0],b[1],b[2],b[3],b[4], + c[0],c[1],c[2],c[3],c[4], + d[0],d[1],d[2],d[3],d[4], + e[0],e[1],e[2],e[3],e[4]); + } + + template <class NT, class Vector> + NT determinant_of_vectors(Vector const&a, Vector const&b, + Vector const&c, Vector const&d, Vector const&e, Vector const&f){ + return determinant<NT>( + a[0],a[1],a[2],a[3],a[4],a[5], + b[0],b[1],b[2],b[3],b[4],b[5], + c[0],c[1],c[2],c[3],c[4],c[5], + d[0],d[1],d[2],d[3],d[4],d[5], + e[0],e[1],e[2],e[3],e[4],e[5], + f[0],f[1],f[2],f[3],f[4],f[5]); + } + template <class NT, class Vector> + typename Sgn<NT>::result_type + sign_of_determinant_of_vectors(Vector const&a, Vector const&b, + Vector const&c, Vector const&d, Vector const&e, Vector const&f){ + return sign_of_determinant<NT>( + a[0],a[1],a[2],a[3],a[4],a[5], + b[0],b[1],b[2],b[3],b[4],b[5], + c[0],c[1],c[2],c[3],c[4],c[5], + d[0],d[1],d[2],d[3],d[4],d[5], + e[0],e[1],e[2],e[3],e[4],e[5], + f[0],f[1],f[2],f[3],f[4],f[5]); + } + +} +#endif diff --git a/src/common/include/gudhi_patches/CGAL/internal/Combination_enumerator.h b/src/common/include/gudhi_patches/CGAL/internal/Combination_enumerator.h new file mode 100644 index 00000000..f411e827 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/internal/Combination_enumerator.h @@ -0,0 +1,148 @@ +// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Samuel Hornus + +#ifndef CGAL_INTERNAL_COMBINATION_ENUMERATOR_H +#define CGAL_INTERNAL_COMBINATION_ENUMERATOR_H + +#include <CGAL/basic.h> +#include <vector> + +namespace CGAL { + +namespace internal { + +class Combination_enumerator +{ + // types and member data + typedef std::vector<int> Combination; + Combination combi_; + const int k_; + const int min_; + const int max_; + const int max_at_pos_0_; + +public: + + // For generating all the combinations of |k| distinct elements in the + // interval [min, max] (both included) + Combination_enumerator(const int k, const int min, const int max) + : combi_(k), k_(k), min_(min), max_(max), max_at_pos_0_(max + 1 - k) + { + CGAL_assertion_msg( min <= max, "min is larger than max"); + CGAL_assertion_msg( 1 <= k && k <= ( max - min + 1 ), "wrong value of k"); + init(); + } + + Combination_enumerator(const Combination_enumerator & c) + : combi_(c.combi_), k_(c.k_), min_(c.min_), max_(c.max_), max_at_pos_0_(c.max_at_pos_0_) + {} + + int number_of_elements() + { + return k_; + } + + void init() + { + combi_.resize(k_); + for( int i = 0; i < k_; ++i ) + element(i) = min_ + i; + } + + bool end() const + { + return ( element(0) > max_at_pos_0_ ); + } + + int element(const int i) const + { + CGAL_assertion( 0 <= i && i < k_ ); + return combi_[i]; + } + + int & element(const int i) + { + CGAL_assertion( 0 <= i && i < k_ ); + return combi_[i]; + } + + int operator[](const int i) const + { + return element(i); + } + + int & operator[](const int i) + { + return element(i); + } + + void operator++() + { + int i = k_ - 1; + int max_at_pos_i(max_); + while( ( i >= 0 ) && ( element(i) >= max_at_pos_i ) ) + { + --i; + --max_at_pos_i; + } + if( -1 == i ) + { + if( element(0) == max_at_pos_0_ ) + ++element(0); // mark then end of the enumeration with an impossible value + // Note than when we have arrived at the end of the enumeration, applying + // operator++() again does not change anything, so it is safe to + // apply it too many times. + } + else + { + ++element(i); + for( int j = i + 1; j < k_; ++j ) + element(j) = element(i) + j - i; + } + } + + Combination_enumerator operator++(int) + { + Combination_enumerator tmp(*this); + ++(*this); + return tmp; + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - TESTING +#if 0 + void test() + { + std::cerr << '\n'; + while( ! end() ) + { + std::cerr << '\n'; + for( int i = 0; i < k_; ++i ) + std::cerr << element(i) << ' '; + ++(*this); + } + init(); + } +#endif +}; + +} // end of namespace internal + +} // end of namespace CGAL + +#endif // CGAL_INTERNAL_COMBINATION_ENUMERATOR_H diff --git a/src/common/include/gudhi_patches/CGAL/internal/Static_or_dynamic_array.h b/src/common/include/gudhi_patches/CGAL/internal/Static_or_dynamic_array.h new file mode 100644 index 00000000..ee6195d9 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/internal/Static_or_dynamic_array.h @@ -0,0 +1,116 @@ +// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Samuel Hornus + +#ifndef CGAL_INTERNAL_STATIC_OR_DYNAMIC_ARRAY_H +#define CGAL_INTERNAL_STATIC_OR_DYNAMIC_ARRAY_H + +#include <CGAL/Compact_container.h> +#include <CGAL/Dimension.h> +#include <CGAL/array.h> +#include <vector> + +namespace CGAL { + +namespace internal { + +// Utility for adding one to an Dimension_tag: + +template<typename D> +struct Dimen_plus_one; + +template<> +struct Dimen_plus_one<Dynamic_dimension_tag> +{ + typedef Dynamic_dimension_tag type; +}; + +template<int D> +struct Dimen_plus_one<Dimension_tag<D> > +{ + typedef Dimension_tag<D+1> type; +}; + +// A SMALL CONTAINER UTILITY FOR DYNAMIC/STATIC MEMORY MANAGEMENT + +// stores an array of static or dynamic size, depending on template parameter <B>. + +template< typename Containee, typename D, bool WithCompactContainerHelper = false> + struct S_or_D_array; // S = static, D = dynamic + +// The case of static size: +template< typename Containee, int D, bool WithCompactContainerHelper > +struct S_or_D_array< Containee, Dimension_tag< D >, WithCompactContainerHelper > +: public array<Containee, D> +{ + typedef array<Containee, D> Base; + S_or_D_array(const int) + : Base() + {} + S_or_D_array(const int, const Containee & c) + : Base() + { + assign(c); + } + void* for_compact_container() const + { + return (*this)[0].for_compact_container(); + } + void* & for_compact_container() + { + return (*this)[0].for_compact_container(); + } +}; + +// The case of dynamic size +template< typename Containee > +struct S_or_D_array< Containee, Dynamic_dimension_tag, false > +: public std::vector<Containee> +{ + typedef std::vector<Containee> Base; + // TODO: maybe we should use some "small-vector-optimized" class. + S_or_D_array(const int d) + : Base(d) + {} + S_or_D_array(const int d, const Containee & c) + : Base(d, c) + {} +}; + +// The case of dynamic size with for_compact_container +template< typename Containee > +struct S_or_D_array< Containee, Dynamic_dimension_tag, true > +: public std::vector<Containee> +{ + typedef std::vector<Containee> Base; + S_or_D_array(const int d) + : Base(d), fcc_(NULL) + {} + S_or_D_array(const int d, const Containee & c) + : Base(d, c), fcc_(NULL) + {} + void* fcc_; + void* for_compact_container() const { return fcc_; } + void* & for_compact_container() { return fcc_; } +}; + +} // end of namespace internal + +} // end of namespace CGAL + +#endif // CGAL_INTERNAL_STATIC_OR_DYNAMIC_ARRAY_H diff --git a/src/common/include/gudhi_patches/CGAL/internal/Triangulation/Dummy_TDS.h b/src/common/include/gudhi_patches/CGAL/internal/Triangulation/Dummy_TDS.h new file mode 100644 index 00000000..b3a0ec98 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/internal/Triangulation/Dummy_TDS.h @@ -0,0 +1,49 @@ +// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Samuel Hornus + +#ifndef CGAL_INTERNAL_TRIANGULATION_DUMMY_TDS_H +#define CGAL_INTERNAL_TRIANGULATION_DUMMY_TDS_H + +namespace CGAL { + +namespace internal { +namespace Triangulation { + +struct Dummy_TDS +{ + struct Vertex {}; + struct Vertex_handle {}; + struct Vertex_iterator {}; + struct Vertex_const_handle {}; + struct Vertex_const_iterator {}; + struct Full_cell {}; + struct Full_cell_handle {}; + struct Full_cell_iterator {}; + struct Full_cell_const_handle {}; + struct Full_cell_const_iterator {}; + struct Vertex_handle_const_iterator {}; + struct Full_cell_data {}; +}; + +} // namespace Triangulation +} // namespace internal + +} //namespace CGAL + +#endif // CGAL_INTERNAL_TRIANGULATION_DUMMY_TDS_H diff --git a/src/common/include/gudhi_patches/CGAL/internal/Triangulation/Triangulation_ds_iterators.h b/src/common/include/gudhi_patches/CGAL/internal/Triangulation/Triangulation_ds_iterators.h new file mode 100644 index 00000000..7e360026 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/internal/Triangulation/Triangulation_ds_iterators.h @@ -0,0 +1,154 @@ +// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Samuel Hornus (Well... `copy, paste and hack' of Monique Teillaud's work) + +#ifndef CGAL_INTERNAL_TRIANGULATION_TRIANGULATION_DS_ITERATORS_H +#define CGAL_INTERNAL_TRIANGULATION_TRIANGULATION_DS_ITERATORS_H + +namespace CGAL { + +namespace internal { +namespace Triangulation { + +template< typename TDS > +class Triangulation_ds_facet_iterator +{ + typedef typename TDS::Full_cell_handle Full_cell_handle; + typedef typename TDS::Facet Facet; + + typedef Facet value_type; + typedef const Facet * pointer; + typedef const Facet & reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + + typedef Triangulation_ds_facet_iterator<TDS> Facet_iterator; + + TDS & tds_; + Facet ft_; + const int cur_dim_; + +public: + Triangulation_ds_facet_iterator(TDS & tds) + : tds_(tds), ft_(tds.full_cells_begin(), 0), cur_dim_(tds.current_dimension()) + { + CGAL_assertion( cur_dim_ > 0 ); + while( ! canonical() ) + raw_increment(); + } + + Triangulation_ds_facet_iterator(TDS & tds, int) + : tds_(tds), ft_(tds.full_cells_end(), 0), cur_dim_(tds.current_dimension()) + { + CGAL_assertion( cur_dim_ > 0 ); + CGAL_assertion( canonical() ); + } + + Facet_iterator & operator++() + { + increment(); + return (*this); + } + + Facet_iterator operator++(int) + { + Facet_iterator tmp(*this); + increment(); + return tmp; + } + + Facet_iterator & operator--() + { + decrement(); + return (*this); + } + + Facet_iterator operator--(int) + { + Facet_iterator tmp(*this); + decrement(); + return tmp; + } + + bool operator==(const Facet_iterator & fi) const + { + return (&tds_ == &fi.tds_) && + (tds_.index_of_covertex(ft_) == fi.tds_.index_of_covertex(fi.ft_)) && + (tds_.full_cell(ft_) == fi.tds_.full_cell(fi.ft_)); + } + + bool operator!=(const Facet_iterator & fi) const + { + return !(*this == fi); + } + + reference operator*() const + { + return ft_; + } + + pointer operator->() const + { + return &ft_; + } + +private: + bool canonical() + { + if( tds_.full_cells_end() == tds_.full_cell(ft_) ) + return ( 0 == tds_.index_of_covertex(ft_) ); + return ( tds_.full_cell(ft_) < + tds_.full_cell(ft_)->neighbor(tds_.index_of_covertex(ft_)) ); + } + + void raw_decrement() + { + int i = tds_.index_of_covertex(ft_); + if( i == 0 ) + ft_ = Facet(--tds_.full_cell(ft_), cur_dim_); + else + ft_ = Facet(tds_.full_cell(ft_), i - 1); + } + + void raw_increment() + { + int i = tds_.index_of_covertex(ft_); + if( i == cur_dim_ ) + ft_ = Facet(++tds_.full_cell(ft_), 0); + else + ft_ = Facet(tds_.full_cell(ft_), i + 1); + } + + void decrement() + { + do { raw_decrement(); } while( ! canonical() ); + } + + void increment() + { + do { raw_increment(); } while( ! canonical() ); + } +}; + +} // namespace Triangulation +} // namespace internal + +} //namespace CGAL + +#endif // CGAL_INTERNAL_TRIANGULATION_TRIANGULATION_DS_ITERATORS_H diff --git a/src/common/include/gudhi_patches/CGAL/internal/Triangulation/utilities.h b/src/common/include/gudhi_patches/CGAL/internal/Triangulation/utilities.h new file mode 100644 index 00000000..a1ffc775 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/internal/Triangulation/utilities.h @@ -0,0 +1,154 @@ +// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Samuel Hornus + +#ifndef CGAL_INTERNAL_TRIANGULATION_UTILITIES_H +#define CGAL_INTERNAL_TRIANGULATION_UTILITIES_H + +#include <CGAL/basic.h> + +namespace CGAL { + +namespace internal { +namespace Triangulation { + +template< class TDS > +struct Dark_full_cell_data +{ + typedef typename TDS::Full_cell_handle Full_cell_handle; + Full_cell_handle light_copy_; + int count_; + Dark_full_cell_data() : light_copy_(), count_(0) {} +}; + +template< class TDS > +struct Compare_faces_with_common_first_vertex +{ + typedef typename TDS::Face Face; + + const int d_; + +public: + + Compare_faces_with_common_first_vertex(const int d) + : d_(d) + { + CGAL_assertion( 0 < d ); + } + + explicit Compare_faces_with_common_first_vertex(); + + bool operator()(const Face & left, const Face & right) const + { + CGAL_assertion( d_ == left.face_dimension() ); + CGAL_assertion( d_ == right.face_dimension() ); + for( int i = 1; i <= d_; ++i ) + { + if( left.vertex(i) < right.vertex(i) ) + return true; + if( right.vertex(i) < left.vertex(i) ) + return false; + } + return false; + } +}; + +template< class T > +struct Compare_vertices_for_upper_face +{ + typedef typename T::Vertex_const_handle VCH; + + const T & t_; + +public: + + Compare_vertices_for_upper_face(const T & t) + : t_(t) + {} + + explicit Compare_vertices_for_upper_face(); + + bool operator()(const VCH & left, const VCH & right) const + { + if( left == right ) + return false; + if( t_.is_infinite(left) ) + return true; + if( t_.is_infinite(right) ) + return false; + return left < right; + } +}; + +template< class T > +struct Compare_points_for_perturbation +{ + typedef typename T::Geom_traits::Point_d Point; + + const T & t_; + +public: + + Compare_points_for_perturbation(const T & t) + : t_(t) + {} + + explicit Compare_points_for_perturbation(); + + bool operator()(const Point * left, const Point * right) const + { + return (SMALLER == t_.geom_traits().compare_lexicographically_d_object()(*left, *right)); + } +}; + +template< class T > +struct Point_from_pointer +{ + typedef const typename T::Geom_traits::Point_d * argument_type; + typedef const typename T::Geom_traits::Point_d result_type; + result_type & operator()(argument_type & x) const + { + return (*x); + } + const result_type & operator()(const argument_type & x) const + { + return (*x); + } +}; + +template< typename Vertex_handle, typename Point > +struct Point_from_vertex_handle +{ + typedef Vertex_handle argument_type; + typedef Point result_type; + result_type & operator()(argument_type & x) const + { + return x->point(); + } + const result_type & operator()(const argument_type & x) const + { + return x->point(); + } +}; + +} // namespace Triangulation +} // namespace internal + +} //namespace CGAL + +#endif // CGAL_INTERNAL_TRIANGULATION_UTILITIES_H diff --git a/src/common/include/gudhi_patches/CGAL/iterator_from_indices.h b/src/common/include/gudhi_patches/CGAL/iterator_from_indices.h new file mode 100644 index 00000000..110bb4be --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/iterator_from_indices.h @@ -0,0 +1,75 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_ITERATOR_FROM_INDICES_H +#define CGAL_ITERATOR_FROM_INDICES_H +#include <CGAL/config.h> +#include <boost/iterator/iterator_facade.hpp> +namespace CGAL { +template <class Ref_> +struct Default_coordinate_access { + typedef Ref_ result_type; + template<class T> Ref_ operator()(T const& t, std::ptrdiff_t i)const{ + return t[i]; + } +}; + +//TODO: default type for Value_: typename same_cv<Container_,typename remove_cv<Container_>::type::value_type>::type +template <class Container_, class Value_, class Ref_= +#ifdef CGAL_CXX11 + decltype(std::declval<Container_>()[0]) +#else + Value_& +#endif + , class Coord_access = Default_coordinate_access<Ref_> + > +class Iterator_from_indices +: public boost::iterator_facade<Iterator_from_indices<Container_,Value_,Ref_,Coord_access>, + Value_, std::bidirectional_iterator_tag, Ref_> +{ + friend class boost::iterator_core_access; + //FIXME: use int to save space + //TODO: use a tuple to save space when Coord_access is empty + typedef std::ptrdiff_t index_t; + Container_* cont; + index_t index; + Coord_access ca; + void increment(){ ++index; } + void decrement(){ --index; } + void advance(std::ptrdiff_t n){ index+=n; } + ptrdiff_t distance_to(Iterator_from_indices const& other)const{ + return other.index-index; + } + bool equal(Iterator_from_indices const& other)const{ + return index==other.index; + } + Ref_ dereference()const{ + //FIXME: use the functor properly + //Uh, and what did I mean by that? + return ca(*cont,index); + } + public: + Iterator_from_indices(Container_& cont_,std::size_t n) + : cont(&cont_), index(n) {} + template<class T> + Iterator_from_indices(Container_& cont_,std::size_t n,T const&t) + : cont(&cont_), index(n), ca(t) {} +}; +} +#endif // CGAL_ITERATOR_FROM_INDICES_H diff --git a/src/common/include/gudhi_patches/CGAL/transforming_iterator.h b/src/common/include/gudhi_patches/CGAL/transforming_iterator.h new file mode 100644 index 00000000..15ea19a5 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/transforming_iterator.h @@ -0,0 +1,123 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_TRANSFORMING_ITERATOR_H +#define CGAL_TRANSFORMING_ITERATOR_H +#include <boost/iterator/iterator_adaptor.hpp> +#include <boost/utility/result_of.hpp> +#include <boost/type_traits/is_empty.hpp> +#include <boost/type_traits/is_reference.hpp> +#include <boost/type_traits/is_integral.hpp> +#include <boost/mpl/if.hpp> +#include <boost/mpl/or.hpp> +#include <CGAL/Default.h> +#include <utility> + +// Inspired by the boost version, but more compact and +// without any iterator_category games. + +namespace CGAL { +namespace internal { + +// non-empty case +template<class T,bool=boost::is_empty<T>::value> struct Functor_as_base { + Functor_as_base(){} + Functor_as_base(T const& t):f(t){} + //template<class T2> Functor_as_base(Functor_as_base<T2> const&g):f(g.functor()){} + T const& functor()const{return f;} + T & functor() {return f;} + private: + T f; +}; + +// empty case +template<class T> struct Functor_as_base<T,true> : public T { + Functor_as_base(){} + Functor_as_base(T const& t):T(t){} + //template<class T2> Functor_as_base(Functor_as_base<T2> const&g):T(g.functor()){} + T const& functor()const{return *this;} + T & functor() {return *this;} +}; + +template <typename Derived, typename F, typename Iter, typename Ref, typename Val> +class transforming_iterator_helper +{ + typedef std::iterator_traits<Iter> Iter_traits; + typedef typename Iter_traits::reference Iter_ref; + typedef typename Default::Get<Ref, +#ifdef CGAL_CXX11 + decltype(std::declval<F>()(std::declval<Iter_ref>())) +#else + typename boost::result_of<F(typename Iter_traits::value_type)>::type + // should be reference instead of value_type +#endif + >::type reference_; + + typedef typename Default::Get<Val,typename boost::remove_cv<typename boost::remove_reference<reference_>::type>::type>::type value_type; + + // Crappy heuristic. If we have *it that returns a Weighted_point and F that returns a reference to the Point contained in the Weighted_point it takes as argument, we do NOT want the transformed iterator to return a reference to the temporary *it. On the other hand, if *it returns an int n, and F returns a reference to array[n] it is not so good to lose the reference. This probably should be done elsewhere and should at least be made optional... + typedef typename boost::mpl::if_< + boost::mpl::or_<boost::is_reference<Iter_ref>, + boost::is_integral<Iter_ref> >, + reference_, value_type>::type reference; + + public: + typedef boost::iterator_adaptor< + Derived, + Iter, + value_type, + typename Iter_traits::iterator_category, + reference + > type; +}; +} + +template <typename F, typename Iter, typename Ref=Default, typename Val=Default> +class transforming_iterator +: public internal::transforming_iterator_helper<transforming_iterator<F,Iter,Ref,Val>,F,Iter,Ref,Val>::type, +private internal::Functor_as_base<F> +{ + friend class boost::iterator_core_access; + typedef typename internal::transforming_iterator_helper<transforming_iterator,F,Iter,Ref,Val>::type Base; + typedef internal::Functor_as_base<F> Functor_base; + typename Base::reference dereference()const{ + return functor()(*this->base_reference()); + } + public: + using Functor_base::functor; + transforming_iterator(){} + explicit transforming_iterator(Iter i,F const& f=F()) + :Base(i),Functor_base(f){} + template<class F2,class I2,class R2,class V2> + transforming_iterator( + transforming_iterator<F2,I2,R2,V2> const&i, + typename boost::enable_if_convertible<I2, Iter>::type* = 0, + typename boost::enable_if_convertible<F2, F>::type* = 0) + : Base(i.base()),Functor_base(i.functor()) {} + +}; + +template <typename F, typename Iter> inline +transforming_iterator<F,Iter> make_transforming_iterator(Iter i, F const&f=F()) { + return transforming_iterator<F,Iter>(i,f); +} + +} + +#endif // CGAL_TRANSFORMING_ITERATOR_H diff --git a/src/common/include/gudhi_patches/CGAL/transforming_pair_iterator.h b/src/common/include/gudhi_patches/CGAL/transforming_pair_iterator.h new file mode 100644 index 00000000..48dac132 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/transforming_pair_iterator.h @@ -0,0 +1,127 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_TRANSFORMING_PAIR_ITERATOR_H +#define CGAL_TRANSFORMING_PAIR_ITERATOR_H +// Should be a combination of transform_iterator and zip_iterator, +// but boost's iterator_category games are a pain. + +#include <CGAL/transforming_iterator.h> +#include <CGAL/assertions.h> +#include <boost/type_traits/is_convertible.hpp> + + + + +namespace CGAL { +namespace internal { +template <class Cat1, class Cat2, bool=boost::is_convertible<Cat1,Cat2>::value> +struct Min_category { + CGAL_static_assertion((boost::is_convertible<Cat2,Cat1>::value)); + typedef Cat1 type; +}; + +template <class Cat1, class Cat2> +struct Min_category<Cat1,Cat2,true> { + typedef Cat2 type; +}; + + +template <typename Derived, typename F, typename It1, typename It2, typename Ref, typename Val> +class transforming_pair_iterator_helper +{ + typedef typename Min_category< + typename std::iterator_traits<It1>::iterator_category, + typename std::iterator_traits<It1>::iterator_category> + ::type iterator_category; + + typedef typename Default::Get<Ref, +#ifdef CGAL_CXX11 + decltype(std::declval<F>()(std::declval<typename std::iterator_traits<It1>::reference>(),std::declval<typename std::iterator_traits<It2>::reference>())) +#else + typename boost::result_of<F(typename std::iterator_traits<It1>::value_type,typename std::iterator_traits<It2>::value_type)>::type + // should be reference instead of value_type +#endif + >::type reference; + + typedef typename Default::Get<Val,typename boost::remove_cv<typename boost::remove_reference<reference>::type>::type>::type value_type; + + public: + typedef boost::iterator_facade< + Derived, + value_type, + iterator_category, + reference + // expect ptrdiff_t is good enough for difference + > type; +}; +} + +template <typename F, typename It1, typename It2, typename Ref=Default, typename Val=Default> +class transforming_pair_iterator +: public internal::transforming_pair_iterator_helper<transforming_pair_iterator<F,It1,It2,Ref,Val>,F,It1,It2,Ref,Val>::type, +private internal::Functor_as_base<F> +{ + It1 iter1; It2 iter2; + friend class boost::iterator_core_access; + typedef typename internal::transforming_pair_iterator_helper<transforming_pair_iterator,F,It1,It2,Ref,Val>::type Base; + typedef internal::Functor_as_base<F> Functor_base; + typename Base::reference dereference()const{ + return functor()(*iter1,*iter2); + } + bool equal(transforming_pair_iterator const&i)const{ + bool b=(iter1==i.iter1); + CGAL_assertion(b==(iter2==i.iter2)); + //FIXME: or do we want only one driving iterator + return b; + } + void increment(){ ++iter1; ++iter2; } + void decrement(){ --iter1; --iter2; } + void advance(std::ptrdiff_t n){ + std::advance(iter1,n); + std::advance(iter2,n); + } + std::ptrdiff_t distance_to(transforming_pair_iterator const&i)const{ + std::ptrdiff_t dist=std::distance(iter1,i.iter1); + CGAL_assertion(dist==std::distance(iter2,i.iter2)); + return dist; + } + public: + using Functor_base::functor; + transforming_pair_iterator(){} + explicit transforming_pair_iterator(It1 i1,It2 i2,F const& f=F()) + :Functor_base(f),iter1(i1),iter2(i2){} + template<class F2,class J1,class J2,class R2,class V2> + transforming_pair_iterator( + transforming_pair_iterator<F2,J1,J2,R2,V2> const&i, + typename boost::enable_if_convertible<J1, It1>::type* = 0, + typename boost::enable_if_convertible<J2, It2>::type* = 0, + typename boost::enable_if_convertible<F2, F>::type* = 0) + : Functor_base(i.functor()),iter1(i.iter1),iter2(i.iter2) {} + +}; + +template <typename F, typename It1, typename It2> inline +transforming_pair_iterator<F,It1,It2> make_transforming_pair_iterator(It1 i1, It2 i2, F const&f=F()) { + return transforming_pair_iterator<F,It1,It2>(i1,i2,f); +} + +} + +#endif // CGAL_TRANSFORMING_PAIR_ITERATOR_H diff --git a/src/common/include/gudhi_patches/CGAL/typeset.h b/src/common/include/gudhi_patches/CGAL/typeset.h new file mode 100644 index 00000000..d4e24281 --- /dev/null +++ b/src/common/include/gudhi_patches/CGAL/typeset.h @@ -0,0 +1,117 @@ +// Copyright (c) 2014 +// INRIA Saclay-Ile de France (France) +// +// This file is part of CGAL (www.cgal.org); 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. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Marc Glisse + +#ifndef CGAL_TYPESET_H +#define CGAL_TYPESET_H +#include <CGAL/config.h> +#ifdef CGAL_CXX11 +#include <type_traits> +#else +#include <boost/type_traits.hpp> +#endif + +// Sometimes using tuple just to list types is overkill (takes forever to +// instantiate). + +namespace CGAL { +#ifdef CGAL_CXX11 + template<class...> struct typeset; + template<class H,class...U> struct typeset<H,U...> { + typedef H head; + typedef typeset<U...> tail; + typedef typeset type; + template<class X> using contains = typename + std::conditional< + std::is_same<H,X>::value, + std::true_type, + typename tail::template contains<X> + >::type; + template<class X> using add = typename + std::conditional< + contains<X>::value, + typeset<H,U...>, + typeset<H,U...,X> + >::type; + }; + template<> struct typeset<> { + typedef typeset type; + template<class X> using contains = std::false_type; + template<class X> using add = typeset<X>; + }; +#else + template<class,class> struct typeset; + template<class H=void, class T=typename + boost::mpl::if_<boost::is_same<H,void>, void, typeset<void, void> >::type > + struct typeset { + typedef typeset type; + typedef H head; + typedef T tail; + template<class X> struct contains : + boost::mpl::if_<boost::is_same<H,X>,boost::true_type,typename tail::template contains<X> >::type + {}; + template<class X,class=void> struct add; + //boost::mpl::if_<boost::is_same<H,X>,typeset,typeset<X,typeset> >::type + }; + template<> struct typeset<> { + typedef typeset type; + template<class X> struct contains : boost::false_type {}; + template<class X> struct add : CGAL::typeset<X> {}; + }; + + template<class H,class T> + template<class X,class> + struct typeset<H,T>::add : typeset<H,typename T::template add<X>::type> {}; + template<class H,class T> + template<class V> + struct typeset<H,T>::add<H,V> : typeset<H,T> {}; +#endif + + template<class T1, class T2> struct typeset_union_ : + typeset_union_<typename T1::template add<typename T2::head>::type, typename T2::tail> + {}; + template<class T> struct typeset_union_ <T, typeset<> > : T {}; + + template<class T1, class T2> + struct typeset_intersection_ { + typedef typename T1::head H; + typedef typename typeset_intersection_<typename T1::tail,T2>::type U; + typedef typename +#ifdef CGAL_CXX11 + std::conditional<T2::template contains<H>::value, +#else + boost::mpl::if_<typename T2::template contains<H>, +#endif + typename U::template add<H>::type, U>::type type; + }; + template<class T> + struct typeset_intersection_<typeset<>,T> : typeset<> {}; + +#ifdef CGAL_CXX11 + template<class T1, class T2> + using typeset_union = typename typeset_union_<T1,T2>::type; + template<class T1, class T2> + using typeset_intersection = typename typeset_intersection_<T1,T2>::type; +#else + template<class T1, class T2> + struct typeset_union : typeset_union_<T1,T2>::type {}; + template<class T1, class T2> + struct typeset_intersection : typeset_intersection_<T1,T2>::type {}; +#endif +} +#endif |