// Copyright (c) 2003 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$ // SPDX-License-Identifier: GPL-3.0+ // // Author(s) : Julia Floetotto #ifndef CGAL_INTERPOLATION_FUNCTIONS_H #define CGAL_INTERPOLATION_FUNCTIONS_H #include #include #include #include #include #include #include #include namespace CGAL { // Functor class for accessing the function values/gradients template< class Map > struct Data_access : public CGAL::cpp98::unary_function > { typedef typename Map::mapped_type Data_type; typedef typename Map::key_type Key_type; Data_access(const Map& m): map(m){} std::pair< Data_type, bool> operator()(const Key_type& p) const { typename Map::const_iterator mit = map.find(p); if(mit!= map.end()) return std::make_pair(mit->second, true); return std::make_pair(Data_type(), false); } const Map& map; }; //the interpolation functions: template < class ForwardIterator, class ValueFunctor > 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 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); result_type val; for(; first!=beyond; ++first) { val = value_function(first->first); CGAL_assertion(val.second); result += (first->second / norm) * val.first; } return result; } template < class ForwardIterator, class ValueFunctor, class GradFunctor, class Traits, class Point > 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, ValueFunctor value_function, GradFunctor gradient_function, const Traits& traits) { CGAL_precondition(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 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); value_functor_result_type f; gradient_functor_result_type grad; for(; first!=beyond; ++first) { f = value_function(first->first); grad = gradient_function(first->first); //test if value and gradient are correctly retrieved: CGAL_assertion(f.second); if(!grad.second) return std::make_pair(Value_type(0), false); result += (first->second/norm) * (f.first + grad.first * traits.construct_scaled_vector_d_object() (traits.construct_vector_d_object()(cp(first->first), bp), 0.5)); } return std::make_pair(result, true); } template < class ForwardIterator, class ValueFunctor, class GradFunctor, class Traits, class Point > 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, ValueFunctor value_function, GradFunctor gradient_function, const Traits& traits) { CGAL_precondition(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 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); value_functor_result_type f; gradient_functor_result_type grad; for(; first!=beyond; ++first) { f = value_function(first->first); grad = gradient_function(first->first); CGAL_assertion(f.second); if(!grad.second) return std::make_pair(Value_type(0), false); //the values are not correct Coord_type coeff = first->second/norm; Coord_type squared_dist = traits.compute_squared_distance_d_object()(cp(first->first), bp); Coord_type dist = CGAL_NTS sqrt(squared_dist); if(squared_dist == 0) { ForwardIterator it = first; CGAL_USE(it); CGAL_assertion(++it == beyond); return std::make_pair(f.first, true); } //three different terms to mix linear and gradient //interpolation term1 += coeff / dist; term2 += coeff * squared_dist; term3 += coeff * dist; linear_int += coeff * f.first; gradient_int += (coeff/dist) * (f.first + grad.first * traits.construct_vector_d_object()(cp(first->first), bp)); } term4 = term3 / term1; gradient_int = gradient_int / term1; return std::make_pair((term4 * linear_int + term2 * gradient_int) / (term4 + term2), true); } // This method works with rational number types: // modification of Sibson's interpolant without sqrt // following a proposition by Gunther Rote: // // The general scheme: // Coord_type inv_weight = f(dist); //i.e. dist^2 // term1 += coeff/inv_weight; // term2 += coeff * squared_dist; // term3 += coeff*(squared_dist/inv_weight); // 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 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, ValueFunctor value_function, GradFunctor gradient_function, const Traits& traits) { CGAL_precondition(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 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); value_functor_result_type f; gradient_functor_result_type grad; for(; first!=beyond; ++first) { f = value_function(first->first); grad = gradient_function(first->first); CGAL_assertion(f.second); if(!grad.second) return std::make_pair(Value_type(0), false); // the gradient is not known Coord_type coeff = first->second/norm; Coord_type squared_dist = traits.compute_squared_distance_d_object()(cp(first->first), bp); if(squared_dist ==0) { ForwardIterator it = first; CGAL_USE(it); CGAL_assertion(++it == beyond); return std::make_pair(f.first, true); } //three different terms to mix linear and gradient //interpolation term1 += coeff / squared_dist; term2 += coeff * squared_dist; term3 += coeff; linear_int += coeff * f.first; gradient_int += (coeff/squared_dist) * (f.first + grad.first * traits.construct_vector_d_object()(cp(first->first), bp)); } term4 = term3/ term1; gradient_int = gradient_int / term1; return std::make_pair((term4 * linear_int + term2 * gradient_int)/ (term4 + term2), true); } template < class RandomAccessIterator, class ValueFunctor, class GradFunctor, class Traits, class Point_> 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, const Point_& /*p*/, ValueFunctor value_function, GradFunctor gradient_function, const Traits& traits) { CGAL_precondition(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 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); value_functor_result_type f; gradient_functor_result_type grad; int n = static_cast(beyond - first); if(n == 1) { f = value_function(first->first); CGAL_assertion(f.second); return std::make_pair(f.first, true); } //there must be one or at least three NN-neighbors: CGAL_assertion(n > 2); RandomAccessIterator it2, it; Value_type result(0); const Coord_type fac3(3); std::vector< std::vector > ordinates(n, std::vector(n, Value_type(0))); for(int i=0; isecond); // for later: the function value of it->first: f = value_function(it->first); CGAL_assertion(f.second); ordinates[i][i] = f.first; // control point = data point result += coord_i_square * it->second* ordinates[i][i]; // compute tangent plane control point (one 2, one 1 entry) Value_type res_i(0); for(int j=0; jfirst); if(!grad.second) return std::make_pair(Value_type(0), false); // the gradient is not known //ordinates[i][j] = (p_j - p_i) * g_i ordinates[i][j] = grad.first * traits.construct_vector_d_object()(cp(it->first),cp(it2->first)); // a point in the tangent plane: // 3( f(p_i) + (1/3)(p_j - p_i) * g_i) // => 3*f(p_i) + (p_j - p_i) * g_i res_i += (fac3 * ordinates[i][i] + ordinates[i][j])* it2->second; } } // res_i already multiplied by three result += coord_i_square *res_i; } // the third type of control points: three 1 entries i,j,k for(int i=0; i< n; ++i) { for(int j=i+1; j< n; ++j) { for(int k=j+1; k 6 * b_ijk = 3*(f_i + f_j + f_k) + 0.5*a result += (Coord_type(2.0)*(ordinates[i][i]+ ordinates[j][j]+ ordinates[k][k]) + Coord_type(0.5)*(ordinates[i][j] + ordinates[i][k] + ordinates[j][i] + ordinates[j][k] + ordinates[k][i]+ ordinates[k][j])) * (first+i)->second *(first+j)->second *(first+k)->second ; } } } return std::make_pair(result/(CGAL_NTS square(norm)*norm), true); } } // namespace CGAL #endif // CGAL_INTERPOLATION_FUNCTIONS_H