File: interpolation_functions.h

package info (click to toggle)
cgal 6.1.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 144,952 kB
  • sloc: cpp: 811,597; ansic: 208,576; sh: 493; python: 411; makefile: 286; javascript: 174
file content (399 lines) | stat: -rw-r--r-- 14,565 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
// Copyright (c) 2003  INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL: https://github.com/CGAL/cgal/blob/v6.1.1/Interpolation/include/CGAL/interpolation_functions.h $
// $Id: include/CGAL/interpolation_functions.h 08b27d3db14 $
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s)     : Julia Floetotto

#ifndef CGAL_INTERPOLATION_FUNCTIONS_H
#define CGAL_INTERPOLATION_FUNCTIONS_H

#include <CGAL/license/Interpolation.h>

#include <CGAL/Interpolation/internal/helpers.h>
#include <CGAL/double.h>
#include <CGAL/use.h>

#include <boost/utility/result_of.hpp>
#include <iterator>
#include <utility>
#include <vector>

namespace CGAL {

// Functor class for accessing the function values/gradients
template< class Map >
struct Data_access
  : public CGAL::cpp98::unary_function<typename Map::key_type,
                                       std::pair<typename Map::mapped_type, bool> >
{
  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<ForwardIterator>::value_type::first_type)>
             ::type::first_type
linear_interpolation(ForwardIterator first, ForwardIterator beyond,
                     const typename std::iterator_traits<ForwardIterator>::value_type::second_type& norm,
                     ValueFunctor value_function)
{
  CGAL_precondition(first != beyond);
  CGAL_precondition(norm > 0);

  typedef typename std::iterator_traits<ForwardIterator>::value_type::first_type  arg_type;
  typedef typename boost::result_of<ValueFunctor(arg_type)>::type                 result_type;
  typedef typename result_type::first_type                                        Value_type;

  result_type val = value_function(first->first);
  CGAL_assertion(val.second);
  Value_type result = (first->second / norm) * val.first;
  ++first;
  for(; first!=beyond; ++first)
  {
    val = value_function(first->first);
    result = 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<ForwardIterator>::value_type::first_type)>
               ::type::first_type,
  bool>
quadratic_interpolation(ForwardIterator first, ForwardIterator beyond,
                        const typename std::iterator_traits<ForwardIterator>::value_type::second_type& norm,
                        const Point& p,
                        ValueFunctor value_function,
                        GradFunctor gradient_function,
                        const Traits& traits)
{
  CGAL_precondition(first != beyond);
  CGAL_precondition(norm > 0);

  typedef typename std::iterator_traits<ForwardIterator>::value_type::first_type  arg_type;
  typedef typename boost::result_of<ValueFunctor(arg_type)>::type                 value_functor_result_type;
  typedef typename boost::result_of<GradFunctor(arg_type)>::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<Traits> 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<ForwardIterator>::value_type::first_type)>
               ::type::first_type,
  bool>
sibson_c1_interpolation(ForwardIterator first, ForwardIterator beyond,
                        const typename std::iterator_traits<ForwardIterator>::value_type::second_type& norm,
                        const Point& p,
                        ValueFunctor value_function,
                        GradFunctor gradient_function,
                        const Traits& traits)
{
  CGAL_precondition(first != beyond);
  CGAL_precondition(norm >0);

  typedef typename std::iterator_traits<ForwardIterator>::value_type::first_type  arg_type;
  typedef typename boost::result_of<ValueFunctor(arg_type)>::type                 value_functor_result_type;
  typedef typename boost::result_of<GradFunctor(arg_type)>::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<Traits> 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<ForwardIterator>::value_type::first_type)>
               ::type::first_type,
  bool>
sibson_c1_interpolation_square(ForwardIterator first, ForwardIterator beyond,
                               const typename std::iterator_traits<ForwardIterator>::value_type::second_type& norm,
                               const Point& p,
                               ValueFunctor value_function,
                               GradFunctor gradient_function,
                               const Traits& traits)
{
  CGAL_precondition(first != beyond);
  CGAL_precondition(norm > 0);

  typedef typename std::iterator_traits<ForwardIterator>::value_type::first_type  arg_type;
  typedef typename boost::result_of<ValueFunctor(arg_type)>::type                 value_functor_result_type;
  typedef typename boost::result_of<GradFunctor(arg_type)>::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<Traits> 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<RandomAccessIterator>::value_type::first_type)>
               ::type::first_type,
  bool>
farin_c1_interpolation(RandomAccessIterator first,
                       RandomAccessIterator beyond,
                       const typename std::iterator_traits<RandomAccessIterator>::value_type::second_type& norm,
                       const Point_& /*p*/,
                       ValueFunctor value_function,
                       GradFunctor gradient_function,
                       const Traits& traits)
{
  CGAL_precondition(first != beyond);
  CGAL_precondition(norm >0);

  typedef typename std::iterator_traits<RandomAccessIterator>::value_type::first_type  arg_type;
  typedef typename boost::result_of<ValueFunctor(arg_type)>::type                 value_functor_result_type;
  typedef typename boost::result_of<GradFunctor(arg_type)>::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<Traits> cp(traits);
  value_functor_result_type f;
  gradient_functor_result_type grad;

  int n = static_cast<int>(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<Value_type> > ordinates(n, std::vector<Value_type>(n, Value_type(0)));

  for(int i=0; i<n; ++i)
  {
    it = first + i;
    Coord_type coord_i_square = CGAL_NTS square(it->second);

    // 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; j<n; ++j)
    {
      if(i!=j)
      {
        it2 = first + j;

        grad = gradient_function(it->first);
        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<n; ++k)
      {
        // add 6* (u_i*u_j*u_k) * b_ijk
        //  b_ijk = 1.5 * a - 0.5*c
        // where
        // c : average of the three data control points
        // a : 1.5*a = 1/12 * (ord[i][j] + ord[i][k] + ord[j][i] +
        //             ord[j][k] + ord[k][i]+ ord[k][j])
        // =>  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