diff --git a/Interpolation/doc/Interpolation/CGAL/sibson_gradient_fitting.h b/Interpolation/doc/Interpolation/CGAL/sibson_gradient_fitting.h index bd616271d4e..b3e70f96ca1 100644 --- a/Interpolation/doc/Interpolation/CGAL/sibson_gradient_fitting.h +++ b/Interpolation/doc/Interpolation/CGAL/sibson_gradient_fitting.h @@ -86,8 +86,7 @@ function \ref PkgInterpolationNaturalNeighborCoordinates2. \tparam OutputFunctor must be a functor with argument type `std::pair`. Note that the result type of the functor is not specified and is chosen by users to fit their needs. \tparam ValueFunctor must be a functor where: -- `ValueFunctor::argument_type` must be either `std::pair` -or `std::pair`. +- `ValueFunctor::argument_type` must be either `Dt::Vertex_handle` or `Dt::Point`. - `ValueFunctor::result_type` is a pair of the function value type and a Boolean. The function value type must provide a multiplication and addition operation with the type `Traits::FT` as well as a constructor with argument `0`. @@ -124,8 +123,7 @@ functions \ref PkgInterpolationRegularNeighborCoordinates2. \tparam OutputFunctor must be a functor with argument type `std::pair`. Note that the result type of the functor is not specified and is chosen by users to fit their needs. \tparam ValueFunctor must be a functor where: -- `ValueFunctor::argument_type` must be either `std::pair` -or `std::pair`. +- `ValueFunctor::argument_type` must be either `Rt::Vertex_handle` or `Rt::Weighted_point`. - `ValueFunctor::result_type` is a pair of the function value type and a Boolean. The function value type must provide a multiplication and addition operation with the type `Traits::FT` as well as a constructor with argument `0`. diff --git a/Interpolation/examples/Interpolation/interpolation_vertex_with_info_2.cpp b/Interpolation/examples/Interpolation/interpolation_vertex_with_info_2.cpp index 99a58929525..b43a2b1535e 100644 --- a/Interpolation/examples/Interpolation/interpolation_vertex_with_info_2.cpp +++ b/Interpolation/examples/Interpolation/interpolation_vertex_with_info_2.cpp @@ -94,6 +94,7 @@ int main() Delaunay_triangulation T; + // Note that a supported alternative to creating the functors below is to use lambdas Value_function value_function; Gradient_function gradient_function; diff --git a/Interpolation/examples/Interpolation/sibson_interpolation_rn_vertex_with_info_2.cpp b/Interpolation/examples/Interpolation/sibson_interpolation_rn_vertex_with_info_2.cpp index 434b911d9fd..d86378ebf04 100644 --- a/Interpolation/examples/Interpolation/sibson_interpolation_rn_vertex_with_info_2.cpp +++ b/Interpolation/examples/Interpolation/sibson_interpolation_rn_vertex_with_info_2.cpp @@ -73,6 +73,7 @@ int main() { Regular_triangulation rt; + // Note that a supported alternative to creating the functors below is to use lambdas Value_function value_function; Gradient_function gradient_function; diff --git a/Interpolation/examples/Interpolation/sibson_interpolation_vertex_with_info_2.cpp b/Interpolation/examples/Interpolation/sibson_interpolation_vertex_with_info_2.cpp index d5373c62e1b..8e74eab6aa1 100644 --- a/Interpolation/examples/Interpolation/sibson_interpolation_vertex_with_info_2.cpp +++ b/Interpolation/examples/Interpolation/sibson_interpolation_vertex_with_info_2.cpp @@ -74,6 +74,7 @@ int main() { Delaunay_triangulation dt; + // Note that a supported alternative to creating the functors below is to use lambdas Value_function value_function; Gradient_function gradient_function; diff --git a/Interpolation/include/CGAL/interpolation_functions.h b/Interpolation/include/CGAL/interpolation_functions.h index 3efe93387d3..cac67d5aa40 100644 --- a/Interpolation/include/CGAL/interpolation_functions.h +++ b/Interpolation/include/CGAL/interpolation_functions.h @@ -27,6 +27,8 @@ #include #include +#include + #include #include #include @@ -58,17 +60,21 @@ struct Data_access //the interpolation functions: template < class ForwardIterator, class ValueFunctor > -typename ValueFunctor::result_type::first_type +typename boost::result_of< + ValueFunctor(typename std::iterator_traits::value_type::first_type)> + ::type::first_type linear_interpolation(ForwardIterator first, ForwardIterator beyond, const typename std::iterator_traits::value_type::second_type& norm, ValueFunctor value_function) { CGAL_precondition(norm > 0); - typedef typename ValueFunctor::result_type::first_type Value_type; + typedef typename std::iterator_traits::value_type::first_type arg_type; + typedef typename boost::result_of::type result_type; + typedef typename result_type::first_type Value_type; Value_type result(0); - typename ValueFunctor::result_type val; + result_type val; for(; first!=beyond; ++first) { val = value_function(first->first); @@ -78,9 +84,12 @@ linear_interpolation(ForwardIterator first, ForwardIterator beyond, return result; } - template < class ForwardIterator, class ValueFunctor, class GradFunctor, class Traits, class Point > -std::pair< typename ValueFunctor::result_type::first_type, bool> +std::pair< + typename boost::result_of< + ValueFunctor(typename std::iterator_traits::value_type::first_type)> + ::type::first_type, + bool> quadratic_interpolation(ForwardIterator first, ForwardIterator beyond, const typename std::iterator_traits::value_type::second_type& norm, const Point& p, @@ -89,15 +98,20 @@ quadratic_interpolation(ForwardIterator first, ForwardIterator beyond, const Traits& traits) { CGAL_precondition(norm > 0); - typedef typename ValueFunctor::result_type::first_type Value_type; - typedef typename Traits::Point_d Bare_point; + + typedef typename std::iterator_traits::value_type::first_type arg_type; + typedef typename boost::result_of::type value_functor_result_type; + typedef typename boost::result_of::type gradient_functor_result_type; + typedef typename value_functor_result_type::first_type Value_type; + + typedef typename Traits::Point_d Bare_point; Interpolation::internal::Extract_bare_point cp(traits); const Bare_point& bp = cp(p); Value_type result(0); - typename ValueFunctor::result_type f; - typename GradFunctor::result_type grad; + value_functor_result_type f; + gradient_functor_result_type grad; for(; first!=beyond; ++first) { @@ -119,7 +133,11 @@ quadratic_interpolation(ForwardIterator first, ForwardIterator beyond, template < class ForwardIterator, class ValueFunctor, class GradFunctor, class Traits, class Point > -std::pair< typename ValueFunctor::result_type::first_type, bool > +std::pair< + typename boost::result_of< + ValueFunctor(typename std::iterator_traits::value_type::first_type)> + ::type::first_type, + bool> sibson_c1_interpolation(ForwardIterator first, ForwardIterator beyond, const typename std::iterator_traits::value_type::second_type& norm, const Point& p, @@ -129,17 +147,21 @@ sibson_c1_interpolation(ForwardIterator first, ForwardIterator beyond, { CGAL_precondition(norm >0); - typedef typename ValueFunctor::result_type::first_type Value_type; - typedef typename Traits::FT Coord_type; - typedef typename Traits::Point_d Bare_point; + typedef typename std::iterator_traits::value_type::first_type arg_type; + typedef typename boost::result_of::type value_functor_result_type; + typedef typename boost::result_of::type gradient_functor_result_type; + typedef typename value_functor_result_type::first_type Value_type; + + typedef typename Traits::FT Coord_type; + typedef typename Traits::Point_d Bare_point; Interpolation::internal::Extract_bare_point cp(traits); const Bare_point& bp = cp(p); Coord_type term1(0), term2(term1), term3(term1), term4(term1); Value_type linear_int(0), gradient_int(0); - typename ValueFunctor::result_type f; - typename GradFunctor::result_type grad; + value_functor_result_type f; + gradient_functor_result_type grad; for(; first!=beyond; ++first) { @@ -193,7 +215,11 @@ sibson_c1_interpolation(ForwardIterator first, ForwardIterator beyond, // gradient_int += (coeff/inv_weight) * (vh->get_value()+ vh->get_gradient() * (p - vh->point())); template < class ForwardIterator, class ValueFunctor, class GradFunctor, class Traits, class Point > -std::pair< typename ValueFunctor::result_type::first_type, bool > +std::pair< + typename boost::result_of< + ValueFunctor(typename std::iterator_traits::value_type::first_type)> + ::type::first_type, + bool> sibson_c1_interpolation_square(ForwardIterator first, ForwardIterator beyond, const typename std::iterator_traits::value_type::second_type& norm, const Point& p, @@ -203,17 +229,21 @@ sibson_c1_interpolation_square(ForwardIterator first, ForwardIterator beyond, { CGAL_precondition(norm > 0); - typedef typename ValueFunctor::result_type::first_type Value_type; - typedef typename Traits::FT Coord_type; - typedef typename Traits::Point_d Bare_point; + typedef typename std::iterator_traits::value_type::first_type arg_type; + typedef typename boost::result_of::type value_functor_result_type; + typedef typename boost::result_of::type gradient_functor_result_type; + typedef typename value_functor_result_type::first_type Value_type; + + typedef typename Traits::FT Coord_type; + typedef typename Traits::Point_d Bare_point; Interpolation::internal::Extract_bare_point cp(traits); const Bare_point& bp = cp(p); Coord_type term1(0), term2(term1), term3(term1), term4(term1); Value_type linear_int(0), gradient_int(0); - typename ValueFunctor::result_type f; - typename GradFunctor::result_type grad; + value_functor_result_type f; + gradient_functor_result_type grad; for(; first!=beyond; ++first) { @@ -257,7 +287,11 @@ sibson_c1_interpolation_square(ForwardIterator first, ForwardIterator beyond, template < class RandomAccessIterator, class ValueFunctor, class GradFunctor, class Traits, class Point_> -std::pair< typename ValueFunctor::result_type::first_type, bool> +std::pair< + typename boost::result_of< + ValueFunctor(typename std::iterator_traits::value_type::first_type)> + ::type::first_type, + bool> farin_c1_interpolation(RandomAccessIterator first, RandomAccessIterator beyond, const typename std::iterator_traits::value_type::second_type& norm, @@ -268,14 +302,16 @@ farin_c1_interpolation(RandomAccessIterator first, { CGAL_precondition(norm >0); - // the function value is available for all points - // if a gradient value is not availble: function returns false - typedef typename ValueFunctor::result_type::first_type Value_type; - typedef typename Traits::FT Coord_type; + typedef typename std::iterator_traits::value_type::first_type arg_type; + typedef typename boost::result_of::type value_functor_result_type; + typedef typename boost::result_of::type gradient_functor_result_type; + typedef typename value_functor_result_type::first_type Value_type; + + typedef typename Traits::FT Coord_type; Interpolation::internal::Extract_bare_point cp(traits); - typename ValueFunctor::result_type f; - typename GradFunctor::result_type grad; + value_functor_result_type f; + gradient_functor_result_type grad; int n = static_cast(beyond - first); if(n == 1) diff --git a/Interpolation/include/CGAL/sibson_gradient_fitting.h b/Interpolation/include/CGAL/sibson_gradient_fitting.h index 04830e4845c..3087a72de23 100644 --- a/Interpolation/include/CGAL/sibson_gradient_fitting.h +++ b/Interpolation/include/CGAL/sibson_gradient_fitting.h @@ -29,14 +29,22 @@ #include #include +#include +#include #include -#include +#include +#include #include #include #include +#ifdef CGAL_CXX11 + #include + #include +#endif + namespace CGAL { template < class ForwardIterator, class ValueFunctor, class Traits, class Point > @@ -45,12 +53,17 @@ sibson_gradient_fitting(ForwardIterator first, ForwardIterator beyond, const typename std::iterator_traits::value_type::second_type& norm, const Point& p, - const typename ValueFunctor::result_type::first_type fn, + const typename boost::result_of< + ValueFunctor(typename std::iterator_traits::value_type::first_type)> + ::type::first_type fn, ValueFunctor value_function, const Traits& traits) { CGAL_precondition( first != beyond && norm != 0); + typedef typename std::iterator_traits::value_type::first_type arg_type; + typedef typename boost::result_of::type value_functor_result_type; + typedef typename Traits::Aff_transformation_d Aff_transformation; typedef typename Traits::FT Coord_type; typedef typename Traits::Point_d Bare_point; @@ -69,7 +82,7 @@ sibson_gradient_fitting(ForwardIterator first, typename Traits::Vector_d d = traits.construct_vector_d_object()(bp, bare_f); // compute the vector pn: - typename ValueFunctor::result_type f = value_function(first->first); + value_functor_result_type f = value_function(first->first); CGAL_assertion(f.second); // function value of first->first is valid pn = pn + traits.construct_scaled_vector_d_object()(d, scale * (f.first - fn)); @@ -91,7 +104,10 @@ sibson_gradient_fitting(ForwardIterator first, ValueFunctor value_function, const Traits& traits) { - typename ValueFunctor::result_type fn = value_function(p); + typedef typename std::iterator_traits::value_type::first_type arg_type; + typedef typename boost::result_of::type value_functor_result_type; + + value_functor_result_type fn = value_function(p); CGAL_assertion(fn.second); return sibson_gradient_fitting(first, beyond, norm, p, fn.first, value_function, traits); @@ -110,8 +126,11 @@ sibson_gradient_fitting_internal(ForwardIterator first, const Traits& traits, const typename Traits::Point_d& /*dummy*/) { + typedef typename std::iterator_traits::value_type::first_type arg_type; + typedef typename boost::result_of::type value_functor_result_type; + const typename Traits::Point_d& bare_p = traits.construct_point_d_object()(vh->point()); - typename ValueFunctor::result_type fn = value_function(bare_p); + value_functor_result_type fn = value_function(bare_p); CGAL_assertion(fn.second); return sibson_gradient_fitting(first, beyond, norm, bare_p, fn.first, value_function, traits); @@ -129,7 +148,10 @@ sibson_gradient_fitting_internal(ForwardIterator first, const Traits& traits, const typename Traits::Weighted_point_d& /*dummy*/) { - typename ValueFunctor::result_type fn = value_function(vh->point()); + typedef typename std::iterator_traits::value_type::first_type arg_type; + typedef typename boost::result_of::type value_functor_result_type; + + value_functor_result_type fn = value_function(vh->point()); CGAL_assertion(fn.second); return sibson_gradient_fitting(first, beyond, norm, vh->point(), fn.first, value_function, traits); @@ -147,15 +169,19 @@ sibson_gradient_fitting_internal(ForwardIterator first, const Traits& traits, VH /*dummy*/) { + typedef typename std::iterator_traits::value_type::first_type arg_type; + typedef typename boost::result_of::type value_functor_result_type; + const typename Traits::Point_d& bare_p = traits.construct_point_d_object()(vh->point()); - typename ValueFunctor::result_type fn = value_function(vh); + value_functor_result_type fn = value_function(vh); CGAL_assertion(fn.second); return sibson_gradient_fitting(first, beyond, norm, bare_p, fn.first, value_function, traits); } -template < class Tr, class OutputIterator, class OutputFunctor, +template < class ValueFunctorArgType, + class Tr, class OutputIterator, class OutputFunctor, class ValueFunctor, class CoordFunctor, class Traits > OutputIterator sibson_gradient_fitting_internal(const Tr& tr, @@ -170,7 +196,7 @@ sibson_gradient_fitting_internal(const Tr& tr, typedef typename Tr::Vertex_handle Vertex_handle; Coord_type norm; - std::vector > coords; + std::vector > coords; typename Tr::Finite_vertices_iterator vit = tr.finite_vertices_begin(); for(; vit != tr.finite_vertices_end(); ++vit) @@ -187,7 +213,7 @@ sibson_gradient_fitting_internal(const Tr& tr, Vertex_handle(vit), value_function, traits, - typename ValueFunctor::argument_type()))); + ValueFunctorArgType()))); coords.clear(); } @@ -196,12 +222,73 @@ sibson_gradient_fitting_internal(const Tr& tr, return out; } - // The following functions allow to fit the gradients for all points in // a triangulation except the convex hull points. // -> _nn2: natural_neighbor_coordinates_2 // -> _rn2: regular_neighbor_coordinates_2 // -> _sn2_3: surface_neighbor_coordinates_2_3 + +// The ugly distinction below is needed to make it work with lambdas for C++11 because std::is_constructible +// is used, which is C++11 (there is a boost equivalent, but it is said (by boost) to be relying on C++11 features +// to properly work...) +#ifdef CGAL_CXX11 + +template < class Dt, class OutputIterator, class OutputFunctor, class ValueFunctor, class Traits > +OutputIterator +sibson_gradient_fitting_nn_2(const Dt& dt, + OutputIterator out, + OutputFunctor fct, + ValueFunctor value_function, + const Traits& traits, + // Some SFINAE to distinguish whether the argument type + // of the value functor is 'DT::Point' or 'DT::Vertex_handle' + typename boost::enable_if_c< + std::is_constructible< + std::function, + ValueFunctor + >::value>::type* = NULL) +{ + typedef typename Traits::FT FT; + typedef typename Dt::Point VF_arg_type; + typedef typename std::back_insert_iterator > > CoordInserter; + typedef Interpolation::internal::Extract_point_in_pair Coord_OutputFunctor; + + return sibson_gradient_fitting_internal(dt, out, fct, value_function, + natural_neighbor_coordinates_2_object(), + traits); +} + +template < class Dt, class OutputIterator, class OutputFunctor, class ValueFunctor, class Traits > +OutputIterator +sibson_gradient_fitting_nn_2(const Dt& dt, + OutputIterator out, + OutputFunctor fct, + ValueFunctor value_function, + const Traits& traits, + typename boost::enable_if_c< + std::is_constructible< + std::function, + ValueFunctor + >::value>::type* = NULL) +{ + typedef typename Traits::FT FT; + typedef typename Dt::Vertex_handle VF_arg_type; + typedef typename std::back_insert_iterator > > CoordInserter; + typedef CGAL::Identity > Coord_OutputFunctor; + + return sibson_gradient_fitting_internal(dt, out, fct, value_function, + natural_neighbor_coordinates_2_object(), + traits); +} + +#else // not CGAL_CXX11 + template < class Dt, class OutputIterator, class OutputFunctor, class ValueFunctor, class Traits > OutputIterator sibson_gradient_fitting_nn_2(const Dt& dt, @@ -224,15 +311,16 @@ sibson_gradient_fitting_nn_2(const Dt& dt, CGAL::Identity > >::type Coord_OutputFunctor; - return sibson_gradient_fitting_internal(dt, out, fct, value_function, - natural_neighbor_coordinates_2_object(), - traits); + return sibson_gradient_fitting_internal(dt, out, fct, value_function, + natural_neighbor_coordinates_2_object(), + traits); } +#endif // CGAL_CXX11 - -// Same as above but without OutputFunctor. Default to extracting the point, for backward compatibility. +// Same as above but without OutputFunctor. +// Defaults to extracting the point, for backward compatibility. template < class Dt, class OutputIterator, class ValueFunctor, class Traits > OutputIterator sibson_gradient_fitting_nn_2(const Dt& dt, @@ -246,6 +334,64 @@ sibson_gradient_fitting_nn_2(const Dt& dt, return sibson_gradient_fitting_nn_2(dt, out, OutputFunctor(), value_function, traits); } +// See above for the explanation. +#ifdef CGAL_CXX11 + +template < class Rt, class OutputIterator, class OutputFunctor, class ValueFunctor, class Traits > +OutputIterator +sibson_gradient_fitting_rn_2(const Rt& rt, + OutputIterator out, + OutputFunctor fct, + ValueFunctor value_function, + const Traits& traits, + // Some SFINAE to distinguish whether the argument type + // of the value functor is 'Rt::Point' (weighted point) or 'Rt::Vertex_handle' + typename boost::enable_if_c< + std::is_constructible< + std::function, + ValueFunctor + >::value>::type* = NULL) +{ + typedef typename Traits::FT FT; + typedef typename Rt::Point VF_arg_type; + typedef typename std::back_insert_iterator > > CoordInserter; + typedef Interpolation::internal::Extract_point_in_pair Coord_OutputFunctor; + + return sibson_gradient_fitting_internal(rt, out, fct, value_function, + regular_neighbor_coordinates_2_object(), + traits); +} + +template < class Rt, class OutputIterator, class OutputFunctor, class ValueFunctor, class Traits > +OutputIterator +sibson_gradient_fitting_rn_2(const Rt& rt, + OutputIterator out, + OutputFunctor fct, + ValueFunctor value_function, + const Traits& traits, + typename boost::enable_if_c< + std::is_constructible< + std::function, + ValueFunctor + >::value>::type* = NULL) +{ + typedef typename Traits::FT FT; + typedef typename Rt::Vertex_handle VF_arg_type; + typedef typename std::back_insert_iterator > > CoordInserter; + typedef CGAL::Identity > Coord_OutputFunctor; + + return sibson_gradient_fitting_internal(rt, out, fct, value_function, + regular_neighbor_coordinates_2_object(), + traits); +} + +#else // CGAL_CXX11 template < class Rt, class OutputIterator, class OutputFunctor, class ValueFunctor, class Traits > OutputIterator @@ -269,13 +415,14 @@ sibson_gradient_fitting_rn_2(const Rt& rt, CGAL::Identity > >::type Coord_OutputFunctor; - return sibson_gradient_fitting_internal(rt, out, fct, value_function, - regular_neighbor_coordinates_2_object(), - traits); + return sibson_gradient_fitting_internal(rt, out, fct, value_function, + regular_neighbor_coordinates_2_object(), + traits); } +#endif // Same as above but without OutputFunctor. Default to extracting the point, for backward compatibility. template < class Rt, class OutputIterator, class ValueFunctor, class Traits > diff --git a/Interpolation/test/Interpolation/include/CGAL/_test_interpolation_functions_2.cpp b/Interpolation/test/Interpolation/include/CGAL/_test_interpolation_functions_2.cpp index 88818490ccd..1d245501276 100644 --- a/Interpolation/test/Interpolation/include/CGAL/_test_interpolation_functions_2.cpp +++ b/Interpolation/test/Interpolation/include/CGAL/_test_interpolation_functions_2.cpp @@ -31,11 +31,14 @@ #include #include #include +#include #include #include #include #include +#include + #include #include #include @@ -47,6 +50,8 @@ struct Extract_point typedef typename Traits::Point_2 Point_2; typedef typename Traits::Weighted_point_2 Weighted_point_2; + typedef typename Traits::Construct_point_2 Construct_point_2; + Extract_point(const Traits& traits = Traits()) : traits(traits) {} const Point_2& operator()(const Point_2& p) const { return p; } @@ -56,7 +61,8 @@ struct Extract_point } template - const Point_2& operator()(const VH& vh) const { + typename boost::result_of::type + operator()(const VH& vh) const { return traits.construct_point_2_object()(vh->point()); } @@ -64,6 +70,42 @@ private: Traits traits; }; +template +struct Value_function +{ + typedef V argument_type; + typedef std::pair result_type; + + Value_function(std::size_t i) : index(i) { } + + result_type operator()(const argument_type& a) const { + return result_type(a->info()[index].value, true); + } + +private: + std::size_t index; +}; + +template +struct Gradient_function + : public CGAL::iterator +{ + + typedef V argument_type; + typedef std::pair result_type; + + Gradient_function(std::size_t i) : index(i) { } + + result_type operator()(const argument_type& a) const { + return std::make_pair(a->info()[index].gradient, + a->info()[index].gradient != CGAL::NULL_VECTOR); + } + +private: + std::size_t index; +}; + + template < class ForwardIterator > bool test_norm(ForwardIterator first, ForwardIterator beyond, typename std::iterator_traits::value_type::second_type norm) @@ -83,10 +125,10 @@ bool test_norm(ForwardIterator first, ForwardIterator beyond, } } -template < class Tr, class ForwardIterator > +template < class Tr, class ForwardIterator, class Point > bool test_barycenter(ForwardIterator first, ForwardIterator beyond, typename std::iterator_traits::value_type::second_type norm, - const typename std::iterator_traits::value_type::first_type& p, + const Point& p, const typename std::iterator_traits::value_type::second_type& tolerance) { typedef typename Tr::Geom_traits Gt; @@ -133,9 +175,13 @@ bool _test_sibson_c1_interpolation_sqrt(ForwardIterator first, ForwardIterator b const typename std::iterator_traits::value_type::second_type& exact_value, CGAL::Field_with_sqrt_tag) { - typename ValueFunctor::result_type res = CGAL::sibson_c1_interpolation(first, beyond, - norm, p, f, - grad_f, geom_traits); + typedef typename std::iterator_traits::value_type::first_type arg_type; + typedef typename boost::result_of::type value_functor_result_type; + + value_functor_result_type res = CGAL::sibson_c1_interpolation(first, beyond, + norm, p, f, + grad_f, geom_traits); + return res.second && (CGAL_NTS abs(res.first-exact_value) <= tolerance); } @@ -143,14 +189,18 @@ template < class ForwardIterator, class ValueFunctor, class GradFunctor, class G bool test_interpolation_with_value(ForwardIterator first, ForwardIterator beyond, const typename std::iterator_traits::value_type::second_type& norm, const Point& p, - const typename ValueFunctor::result_type::first_type exact_value, + const typename boost::result_of< + ValueFunctor(typename std::iterator_traits::value_type::first_type)> + ::type::first_type exact_value, ValueFunctor f, GradFunctor grad_f, const Gt& geom_traits, const int& i, const typename std::iterator_traits::value_type::second_type& tolerance) { - typedef typename ValueFunctor::result_type::first_type Value_type; + typedef typename std::iterator_traits::value_type::first_type arg_type; + typedef typename boost::result_of::type value_functor_result_type; + typedef typename value_functor_result_type::first_type Value_type; if(i == 0) { @@ -158,8 +208,8 @@ bool test_interpolation_with_value(ForwardIterator first, ForwardIterator beyond assert(CGAL_NTS abs(val - exact_value) <= tolerance); } - typename ValueFunctor::result_type res = CGAL::quadratic_interpolation(first, beyond, norm, p, f, - grad_f, geom_traits); + value_functor_result_type res = CGAL::quadratic_interpolation(first, beyond, norm, p, f, + grad_f, geom_traits); assert(res.second && (CGAL_NTS abs(res.first - exact_value) <= tolerance)); if(i<2) @@ -185,20 +235,17 @@ bool test_interpolation_with_value(ForwardIterator first, ForwardIterator beyond return true; } -template < class ForwardIterator, class ValueFunctor, class GradFunctor, class Gt, class Point> +template < class ForwardIterator, class ValueFunctor, class GradFunctor, class Gt, class Point, class Value_type> bool test_interpolation(ForwardIterator first, ForwardIterator beyond, const typename std::iterator_traits::value_type::second_type& norm, const Point& p, + const Value_type exact_value, ValueFunctor f, GradFunctor grad_f, const Gt& geom_traits, const int& i, const typename std::iterator_traits::value_type::second_type& tolerance) { - typedef typename ValueFunctor::result_type::first_type Value_type; - assert(f(p).second); - Value_type exact_value = f(p).first; - return test_interpolation_with_value(first, beyond, norm, p, exact_value, f, grad_f, geom_traits, i, tolerance); } @@ -222,7 +269,7 @@ void _test_interpolation_functions_2_Delaunay_without_OutputFunctor(const Dt&, c typedef typename Gt::FT Coord_type; typedef typename Gt::Vector_2 Vector; - typedef std::map Point_value_map ; + typedef std::map Point_value_map; typedef std::map Point_vector_map; typedef std::vector > Point_coordinate_vector; @@ -308,7 +355,8 @@ void _test_interpolation_functions_2_Delaunay_without_OutputFunctor(const Dt&, c for(int i=0; i<3; ++i) { - assert(test_interpolation(coords.begin(), coords.end(), norm, points[j], + assert(test_interpolation(coords.begin(), coords.end(), norm, + points[j], values[i][points[j]], CGAL::Data_access< Point_value_map >(values[i]), CGAL::Data_access< Point_vector_map >(gradients[i]), Traits(), i, tolerance)); @@ -368,7 +416,8 @@ void _test_interpolation_functions_2_Delaunay_without_OutputFunctor(const Dt&, c for(int j=0; j<3; ++j) { - assert(test_interpolation(coords.begin(), coords.end(), norm, points[n/2], + assert(test_interpolation(coords.begin(), coords.end(), norm, + points[n/2], values[j][points[n/2]], CGAL::Data_access(values[j]), CGAL::Data_access(gradients[j]), Traits(), j, tolerance)); @@ -391,16 +440,18 @@ void _test_interpolation_functions_2_Delaunay_with_OutputFunctor(const Dt&, cons typedef typename Dt::Geom_traits Gt; typedef CGAL::Interpolation_traits_2 Traits; + typedef typename Dt::Vertex_handle Vertex_handle; + typedef typename Gt::FT Coord_type; typedef typename Dt::Point Point; typedef typename Gt::Vector_2 Vector; - typedef std::map Point_value_map ; - typedef std::map Point_vector_map; + typedef std::vector > Coordinate_vector; + typedef typename Coordinate_vector::const_iterator CV_cit; + typedef CGAL::Identity > Output_functor; - typedef std::vector > Point_coordinate_vector; - typedef typename Point_coordinate_vector::const_iterator PCV_cit; - typedef CGAL::Interpolation::internal::Extract_point_in_pair Point_output_functor; + typedef std::map Point_value_map; + typedef std::map Point_vector_map; std::cout << "NN2: Testing random points." << std::endl; @@ -420,9 +471,6 @@ void _test_interpolation_functions_2_Delaunay_with_OutputFunctor(const Dt&, cons CGAL::Random random; - Point_value_map values[3]; - Point_vector_map gradients[3]; - Coord_type alpha = Coord_type(random.get_double(-max_value, max_value)), beta1 = Coord_type(random.get_double(-max_value, max_value)), beta2 = Coord_type(random.get_double(-max_value, max_value)), @@ -431,67 +479,110 @@ void _test_interpolation_functions_2_Delaunay_with_OutputFunctor(const Dt&, cons gamma3 = Coord_type(random.get_double(-max_value, max_value)); //INSERTION + DET. of GRADIENT for n DATA POINTS : - for(int j=0; j p_to_vh; + + for(int j=0; jinfo()[0].gradient = gradient0; + vh->info()[1].gradient = gradient1; + vh->info()[2].gradient = gradient2; + + + vh->info()[0].value = value0; + vh->info()[1].value = value1; + vh->info()[2].value = value2; + } + else + { + exact_values[0][points[j]] = value0; + exact_values[1][points[j]] = value1; + exact_values[2][points[j]] = value2; + } } //INTERPOLATION OF RANDOM POINTS: Coord_type norm; - Point_coordinate_vector pt_coords; - Point_output_functor pt_fct; + Coordinate_vector coords; + Output_functor out_fct; for(int j=n; j, Coord_type, bool> coordinate_result = - CGAL::natural_neighbor_coordinates_2(T, points[j], std::back_inserter(pt_coords), pt_fct); + CGAL::Triple, Coord_type, bool> coordinate_result = + CGAL::natural_neighbor_coordinates_2(T, points[j], std::back_inserter(coords), out_fct); assert(coordinate_result.third); norm = coordinate_result.second; - bool is_equal = test_norm(pt_coords.begin(), pt_coords.end(), norm); + bool is_equal = test_norm(coords.begin(), coords.end(), norm); assert(norm > 0); assert(is_equal); - is_equal = test_barycenter
(pt_coords.begin(), pt_coords.end(), norm, points[j], tolerance); + is_equal = test_barycenter
(coords.begin(), coords.end(), norm, points[j], tolerance); assert(is_equal); +#ifndef CGAL_CFG_NO_CPP0X_LAMBDAS + assert(test_interpolation(coords.begin(), coords.end(), norm, + points[j], exact_values[0][points[j]], + [](const Vertex_handle vh) -> std::pair { return std::make_pair(vh->info()[0].value, true); }, + [](const Vertex_handle vh) -> std::pair { return std::make_pair(vh->info()[0].gradient, true); }, + Traits(), 0, tolerance)); + + + // wrapping the lambda in a std function + CGAL::cpp11::function(const Vertex_handle)> value_function_1 = + [](const Vertex_handle vh) -> std::pair { return std::make_pair(vh->info()[1].value, true); }; + + std::function(const Vertex_handle)> gradient_function_1 = + [](const Vertex_handle vh) -> std::pair { return std::make_pair(vh->info()[1].gradient, true); }; + + assert(test_interpolation(coords.begin(), coords.end(), norm, + points[j], exact_values[1][points[j]], + value_function_1, gradient_function_1, + Traits(), 1, tolerance)); + + assert(test_interpolation(coords.begin(), coords.end(), norm, + points[j], exact_values[2][points[j]], + [](const Vertex_handle vh) -> std::pair { return std::make_pair(vh->info()[2].value, true); }, + [](const Vertex_handle vh) -> std::pair { return std::make_pair(vh->info()[2].gradient, true); }, + Traits(), 2, tolerance)); +#else for(int i=0; i<3; ++i) { - assert(test_interpolation(pt_coords.begin(), pt_coords.end(), norm, points[j], - CGAL::Data_access< Point_value_map >(values[i]), - CGAL::Data_access< Point_vector_map >(gradients[i]), + Value_function value_function(i); + Gradient_function gradient_function(i); + + assert(test_interpolation(coords.begin(), coords.end(), norm, + points[j], exact_values[i][points[j]], + value_function, gradient_function, Traits(), i, tolerance)); } - pt_coords.clear(); +#endif + + coords.clear(); } //TESTING THE GRADIENT APPRXIMATION METHOD: @@ -499,18 +590,44 @@ void _test_interpolation_functions_2_Delaunay_with_OutputFunctor(const Dt&, cons std::cout << "Testing gradient estimation method on random points." << std::endl; typedef CGAL::Interpolation_gradient_fitting_traits_2 GradTraits; + Point_vector_map approx_gradients[2]; + +#ifndef CGAL_CFG_NO_CPP0X_LAMBDAS + { + CGAL::sibson_gradient_fitting_nn_2(T, + std::inserter(approx_gradients[0], approx_gradients[0].begin()), // OutputIterator + CGAL::Interpolation::internal::Extract_point_in_pair(), // OutputFunctor + [](const Vertex_handle vh) + -> std::pair + { return std::make_pair(vh->info()[0].value, true); }, + GradTraits()); + + std::function(const Vertex_handle)> value_function_1 = + [](const Vertex_handle vh) -> std::pair { return std::make_pair(vh->info()[1].value, true); }; + + CGAL::sibson_gradient_fitting_nn_2(T, + std::inserter(approx_gradients[1], approx_gradients[1].begin()), + CGAL::Interpolation::internal::Extract_point_in_pair(), + value_function_1, + GradTraits()); + } +#else + Value_function value_function_0(0); + Value_function value_function_1(1); + CGAL::sibson_gradient_fitting_nn_2(T, std::inserter(approx_gradients[0], approx_gradients[0].begin()), // OutputIterator CGAL::Interpolation::internal::Extract_point_in_pair(), // OutputFunctor - CGAL::Data_access(values[0]), // ValueFunctor + value_function_0, GradTraits()); CGAL::sibson_gradient_fitting_nn_2(T, std::inserter(approx_gradients[1], approx_gradients[1].begin()), CGAL::Interpolation::internal::Extract_point_in_pair(), - CGAL::Data_access(values[1]), + value_function_1, GradTraits()); +#endif for(int j=0; j gradient_function_0(0); + Gradient_function gradient_function_1(1); + // if it is the exact computation kernel: test the equality: assert(tolerance > Coord_type(0) || - res.first == CGAL::Data_access(gradients[0])(points[j]).first); + res.first == (gradient_function_0(p_to_vh[points[j]])).first); res = CGAL::Data_access(approx_gradients[1])(points[j]); // if one exists->the other must also exist assert(res.second); assert(tolerance > Coord_type(0) || - res.first == CGAL::Data_access(gradients[1])(points[j]).first); + res.first == gradient_function_1(p_to_vh[points[j]]).first); } else { @@ -536,31 +656,66 @@ void _test_interpolation_functions_2_Delaunay_with_OutputFunctor(const Dt&, cons } //TESTING A POINT == A DATA POINT: - CGAL::Triple, Coord_type, bool> coordinate_result = - CGAL::natural_neighbor_coordinates_2(T, points[n/2], std::back_inserter(pt_coords), pt_fct); + CGAL::Triple, Coord_type, bool> coordinate_result = + CGAL::natural_neighbor_coordinates_2(T, points[n/2], std::back_inserter(coords), out_fct); assert(coordinate_result.third); norm = coordinate_result.second; assert(norm == Coord_type(1)); - PCV_cit ci = pt_coords.begin(); - assert(ci->first == points[n/2]); + CV_cit ci = coords.begin(); + assert(ci->first == p_to_vh[points[n/2]]); assert(ci->second == Coord_type(1)); ci++; - assert(ci == pt_coords.end()); + assert(ci == coords.end()); +#ifndef CGAL_CFG_NO_CPP0X_LAMBDAS + Value_function value_function_0(0); + Value_function value_function_2(2); + + assert(test_interpolation(coords.begin(), coords.end(), norm, + points[n/2], value_function_0(p_to_vh[points[n/2]]).first, + [](const Vertex_handle vh) -> std::pair { return std::make_pair(vh->info()[0].value, true); }, + [](const Vertex_handle vh) -> std::pair { return std::make_pair(vh->info()[0].gradient, true); }, + Traits(), 0, tolerance)); + + // wrapping the lambda in a std function + CGAL::cpp11::function(const Vertex_handle)> value_function_1 = + [](const Vertex_handle vh) -> std::pair { return std::make_pair(vh->info()[1].value, true); }; + + std::function(const Vertex_handle)> gradient_function_1 = + [](const Vertex_handle vh) -> std::pair { return std::make_pair(vh->info()[1].gradient, true); }; + + assert(test_interpolation(coords.begin(), coords.end(), norm, + points[n/2], value_function_1(p_to_vh[points[n/2]]).first, + value_function_1, gradient_function_1, + Traits(), 1, tolerance)); + + assert(test_interpolation(coords.begin(), coords.end(), norm, + points[n/2], value_function_2(p_to_vh[points[n/2]]).first, + [](const Vertex_handle vh) -> std::pair { return std::make_pair(vh->info()[2].value, true); }, + [](const Vertex_handle vh) -> std::pair { return std::make_pair(vh->info()[2].gradient, true); }, + Traits(), 2, tolerance)); +#else for(int j=0; j<3; ++j) { - assert(test_interpolation(pt_coords.begin(), pt_coords.end(), norm, points[n/2], - CGAL::Data_access(values[j]), - CGAL::Data_access(gradients[j]), + Value_function value_function(j); + Gradient_function gradient_function(j); + + assert(test_interpolation(coords.begin(), coords.end(), norm, + points[n/2], value_function(p_to_vh[points[n/2]]).first, + value_function, gradient_function, Traits(), j, tolerance)); } - pt_coords.clear(); +#endif + + coords.clear(); } template void _test_interpolation_functions_2_regular_without_OutputFunctor(const Rt&, const typename Rt::Geom_traits::FT& tolerance) { + std::cout << "Testing backward compatibility..." << std::endl; + CGAL::Set_ieee_double_precision pfr; Rt T; @@ -577,12 +732,12 @@ void _test_interpolation_functions_2_regular_without_OutputFunctor(const Rt&, co typedef typename Gt::FT Coord_type; typedef typename Gt::Vector_2 Vector; - typedef std::map Point_value_map ; + typedef std::map Point_value_map; typedef std::map Point_vector_map; typedef std::vector > Point_coordinate_vector; - std::cout << "NN2: Testing random points." << std::endl; + std::cout << "RN2: Testing random points." << std::endl; // test random points in a square of length r: std::vector points; @@ -674,7 +829,8 @@ void _test_interpolation_functions_2_regular_without_OutputFunctor(const Rt&, co for(int i=0; i<3; ++i) { - assert(test_interpolation(coords.begin(), coords.end(), norm, points[j], + assert(test_interpolation(coords.begin(), coords.end(), norm, + points[j], values[i][points[j]], CGAL::Data_access< Point_value_map >(values[i]), CGAL::Data_access< Point_vector_map >(gradients[i]), Traits(), i, tolerance)); @@ -735,7 +891,8 @@ void _test_interpolation_functions_2_regular_without_OutputFunctor(const Rt&, co for(int j=0; j<3; ++j) { - assert(test_interpolation(coords.begin(), coords.end(), norm, points[n/2], + assert(test_interpolation(coords.begin(), coords.end(), norm, + points[n/2], values[j][points[n/2]], CGAL::Data_access(values[j]), CGAL::Data_access(gradients[j]), Traits(), j, tolerance)); @@ -771,7 +928,7 @@ void _test_interpolation_functions_2_regular_with_OutputFunctor(const Rt&, const typedef typename Rt::Vertex_handle Vertex_handle; // These are the values at points which won't be inserted in the triangulation - typedef std::map Point_value_map ; + typedef std::map Point_value_map; typedef std::map Vertex_value_map; typedef std::map Vertex_vector_map; @@ -782,7 +939,7 @@ void _test_interpolation_functions_2_regular_with_OutputFunctor(const Rt&, const Identity_output_functor vh_fct; - std::cout << "NN2: Testing random points." << std::endl; + std::cout << "RN2: Testing random points." << std::endl; // test random points in a square of length r: std::vector points; @@ -979,8 +1136,8 @@ void _test_interpolation_functions_2_regular_with_OutputFunctor(const Rt&, const std::pair ev = CGAL::Data_access(values[j])(vh); assert(ev.second); - assert(test_interpolation_with_value(vh_coords.begin(), vh_coords.end(), norm, vh->point(), - ev.first /*exact value*/, + assert(test_interpolation_with_value(vh_coords.begin(), vh_coords.end(), norm, + vh->point(), ev.first /*exact value*/, CGAL::Data_access(values[j]), CGAL::Data_access(gradients[j]), Traits(), j, tolerance)); diff --git a/Interpolation/test/Interpolation/test_interpolation_functions_2.cpp b/Interpolation/test/Interpolation/test_interpolation_functions_2.cpp index ca18ef2faf2..c43b255d071 100644 --- a/Interpolation/test/Interpolation/test_interpolation_functions_2.cpp +++ b/Interpolation/test/Interpolation/test_interpolation_functions_2.cpp @@ -21,44 +21,59 @@ #include #include +#include +#include #include #include +#include #include -typedef CGAL::Exact_predicates_exact_constructions_kernel K; -typedef CGAL::Delaunay_triangulation_2 Dt; -typedef CGAL::Regular_triangulation_2 Rt; +typedef CGAL::Exact_predicates_exact_constructions_kernel EPECK; +typedef CGAL::Exact_predicates_inexact_constructions_kernel EPICK; -typedef CGAL::Exact_predicates_inexact_constructions_kernel K2; -typedef CGAL::Delaunay_triangulation_2 Dt2; -typedef CGAL::Regular_triangulation_2 Rt2; +template +struct Value_and_gradient +{ + Value_and_gradient() : value(), gradient(CGAL::NULL_VECTOR) {} + + V value; + G gradient; +}; + +template +void test_interpolation_functions() +{ + // For the Delaunay triangulation, values and gradients (three different data sets) + // are stored directly in the vertices + typedef typename Kernel::FT Coord_type; + typedef typename Kernel::Vector_2 Vector; + + typedef CGAL::Triangulation_vertex_base_with_info_2< + CGAL::cpp11::array< + Value_and_gradient, 3>, + Kernel> Vb; + typedef CGAL::Triangulation_data_structure_2 Tds; + typedef CGAL::Delaunay_triangulation_2 Delaunay_triangulation; + + typedef CGAL::Regular_triangulation_2 Regular_triangulation; + + std::cout << "Testing interpolation functions with 2D NN neighbors " << std::endl; + _test_interpolation_functions_2_Delaunay(Delaunay_triangulation(), Coord_type(1e-10)); + + std::cout << "Testing interpolation functions with 2D RN neighbors " << std::endl; + _test_interpolation_functions_2_regular(Regular_triangulation(), Coord_type(1e-10)); +} int main() { - std::cout << "Testing interpolation functions with 2D NN neighbors " - << std::endl; - std::cout << " using Exact_predicates_exact_constructions_kernel: " - << std::endl ; - _test_interpolation_functions_2_Delaunay(Dt(), K::FT(1e-10)); + std::cout << "--------------------------------------------" << std::endl; + std::cout << "Testing with EPECK" << std::endl; + test_interpolation_functions(); - std::cout << "Testing interpolation functions with 2D NN neighbors " - << std::endl; - std::cout << " using Exact_predicates_inexact_constructions_kernel: " - << std::endl ; - _test_interpolation_functions_2_Delaunay(Dt2(), K2::FT(1e-10)); - - std::cout << "Testing interpolation functions with 2D RN neighbors " - << std::endl; - std::cout << " using Exact_predicates_exact_constructions_kernel: " - << std::endl ; - _test_interpolation_functions_2_regular(Rt(), K::FT(1e-10)); - - std::cout << "Testing interpolation functions with 2D RN neighbors " - << std::endl; - std::cout << " using Exact_predicates_inexact_constructions_kernel: " - << std::endl ; - _test_interpolation_functions_2_regular(Rt2(), K2::FT(1e-10)); + std::cout << "--------------------------------------------" << std::endl; + std::cout << "Testing with EPICK" << std::endl; + test_interpolation_functions(); std::cout << "test_interpolation_functions_2 is finished" << std::endl;