OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
HermiteInterpolator.cpp
Go to the documentation of this file.
1 //----------------------------------------------------------------------------
2 //
3 // "Copyright Centre National d'Etudes Spatiales"
4 //
5 // License: LGPL
6 //
7 // See LICENSE.txt file in the top level directory for more details.
8 //
9 //----------------------------------------------------------------------------
10 // $Id$
11 
13 
14 #include <string>
15 #include <cassert>
16 #include <cmath>
17 
18 namespace ossimplugins
19 {
20 
21 
23  theNPointsAvailable(0),
24  theXValues(NULL),
25  theYValues(NULL),
26  thedYValues(NULL),
27  prodC(NULL),
28  sumC(NULL),
29  isComputed(false)
30 {
31 }
32 
33 HermiteInterpolator::HermiteInterpolator(int nbrPoints, double* x, double* y, double* dy):
34  theNPointsAvailable(nbrPoints),
35  prodC(NULL),
36  sumC(NULL),
37  isComputed(false)
38 {
39  if(x != NULL)
40  {
41  theXValues = new double[theNPointsAvailable];
42  for (int i=0;i<theNPointsAvailable;i++)
43  {
44  theXValues[i] = x[i];
45  }
46  }
47  else
48  {
49  theXValues = NULL;
50  }
51 
52  if(y != NULL)
53  {
54  theYValues = new double[theNPointsAvailable];
55  for (int i=0;i<theNPointsAvailable;i++)
56  {
57  theYValues[i] = y[i];
58  }
59  }
60  else
61  {
62  theYValues = NULL;
63  }
64 
65  if(dy != NULL)
66  {
67  thedYValues = new double[theNPointsAvailable];
68  for (int i=0;i<theNPointsAvailable;i++)
69  {
70  thedYValues[i] = dy[i];
71  }
72  }
73  else
74  {
75  thedYValues = NULL;
76  }
77 
78  for (int i = 1 ; i < theNPointsAvailable ; i++)
79  {
84  /*
85  * Les abscisses ne sont pas croissantes
86  */
87 // if (theXValues[i] <= theXValues[i-1])
88 // std::cerr << "WARNING: Hermite interpolation assumes increasing x values" << std::endl;
89  assert(theXValues[i] > theXValues[i-1]);
90  }
91 }
92 
94 {
95  Clear();
96 }
97 
99  theNPointsAvailable(rhs.theNPointsAvailable),
100  prodC(NULL),
101  sumC(NULL),
102  isComputed(false)
103 {
104  if(rhs.theXValues != NULL)
105  {
106  theXValues = new double[theNPointsAvailable];
107  for (int i=0;i<theNPointsAvailable;i++)
108  {
109  theXValues[i] = rhs.theXValues[i];
110  }
111  }
112  else
113  {
114  theXValues = NULL;
115  }
116 
117  if(rhs.theYValues != NULL)
118  {
119  theYValues = new double[theNPointsAvailable];
120  for (int i=0;i<theNPointsAvailable;i++)
121  {
122  theYValues[i] = rhs.theYValues[i];
123  }
124  }
125  else
126  {
127  theYValues = NULL;
128  }
129 
130  if(rhs.thedYValues != NULL)
131  {
132  thedYValues = new double[theNPointsAvailable];
133  for (int i=0;i<theNPointsAvailable;i++)
134  {
135  thedYValues[i] = rhs.thedYValues[i];
136  }
137  }
138  else
139  {
140  thedYValues = NULL;
141  }
142 }
143 
145 {
146  Clear();
148  isComputed = false;
149  if(rhs.theXValues != NULL)
150  {
151  theXValues = new double[theNPointsAvailable];
152  for (int i=0;i<theNPointsAvailable;i++)
153  {
154  theXValues[i] = rhs.theXValues[i];
155  }
156  }
157  else
158  {
159  theXValues = NULL;
160  }
161 
162  if(rhs.theYValues != NULL)
163  {
164  theYValues = new double[theNPointsAvailable];
165  for (int i=0;i<theNPointsAvailable;i++)
166  {
167  theYValues[i] = rhs.theYValues[i];
168  }
169  }
170  else
171  {
172  theYValues = NULL;
173  }
174 
175  if(rhs.thedYValues != NULL)
176  {
177  thedYValues = new double[theNPointsAvailable];
178  for (int i=0;i<theNPointsAvailable;i++)
179  {
180  thedYValues[i] = rhs.thedYValues[i];
181  }
182  }
183  else
184  {
185  thedYValues = NULL;
186  }
187  prodC = NULL;
188  sumC = NULL;
189 
190  return *this;
191 }
192 
193 // Interpolation method for the value and the derivative
194 int HermiteInterpolator::Interpolate(double x, double& y, double& dy) const
195 {
196  //NOTE assume that x is increasing
197 
198  // Not enough points to interpolate
199  if (theNPointsAvailable < 2) return -1;
200 
201  y = 0.0;
202  dy = 0.0;
203 
204  double epsilon = 0.0000000000001;
205 
206  //Precompute useful value if they are not available
207  if (!isComputed)
208  {
209  Precompute();
210  }
211 
212  for (int i = 0; i < theNPointsAvailable; i++)
213  {
214  double si = 0.0;
215  double hi = 1.0;
216  double ui = 0; //derivative computation
217  double r = x - theXValues[i];
218 
219  // check if the point is on the list
220  if ( std::abs(r) < epsilon )
221  {
222  y = theYValues[i];
223  dy = thedYValues[i];
224  return 0;
225  }
226 
227  for (int j = 0; j < theNPointsAvailable; j++)
228  {
229  if (j != i)
230  {
231  hi = hi * (x - theXValues[j]);
232  ui = ui + 1 / (x - theXValues[j]);//derivative computation
233  }
234  }
235  hi *= prodC[i];
236  si = sumC[i];
237 
238  double f = 1.0 - 2.0 * r * si;
239 
240  y += (theYValues[i] * f + thedYValues[i] * r) * hi * hi;
241 
242  ui *= hi;//derivative computation
243 
244  double fp = 2.0 * hi * (ui * (1.0 - 2.0 * si * r) - hi * si);//derivative computation
245  double d = hi * (hi + 2.0 * r * ui);//derivative computation
246 
247  dy += fp * theYValues[i] + d * thedYValues[i];//derivative computation
248 
249  }
250 
251  return 0;
252 }
253 
254 // Interpolation method for the value only
255 // this is about 5 times faster and should be used when time
256 // is a constraint.
257 int HermiteInterpolator::Interpolate(double x, double& y) const
258 {
259  //NOTE assume that x is increasing
260 
261  // Not enough points to interpolate
262  if (theNPointsAvailable < 2) return -1;
263 
264  y = 0.0;
265 
266  //Precompute useful value if they are not available
267  if (!isComputed)
268  {
269  Precompute();
270  }
271 
272  for (int i = 0; i < theNPointsAvailable; i++)
273  {
274  double si = 0.0;
275  double hi = 1.0;
276  double r = x - theXValues[i];
277 
278  for (int j = 0; j < theNPointsAvailable; j++)
279  {
280  if (j != i)
281  {
282  hi = hi * (x - theXValues[j]);
283  }
284  }
285  hi *= prodC[i];
286  si = sumC[i];
287 
288  double f = 1.0 - 2.0 * r * si;
289 
290  y += (theYValues[i] * f + thedYValues[i] * r) * hi * hi;
291 
292  }
293 
294  return 0;
295 }
296 
298 {
299  prodC = new double[theNPointsAvailable];
300  sumC= new double[theNPointsAvailable];
301 
302  for (int i = 0; i < theNPointsAvailable; i++)
303  {
304  prodC[i] = 1;
305  sumC[i] = 0;
306  for (int j = 0; j < theNPointsAvailable; j++)
307  {
308  if (j != i)
309  {
310  double v = 1.0 / (theXValues[i] - theXValues[j]);
311  prodC[i] *= v;
312  sumC[i] += v;
313  }
314  }
315  }
316  isComputed = true;
317  return 0;
318 }
319 
321 {
322  if (theXValues != NULL)
323  {
324  delete[] theXValues;
325  theXValues = NULL;
326  }
327 
328  if (theYValues != NULL)
329  {
330  delete[] theYValues;
331  theYValues = NULL;
332  }
333 
334  if (thedYValues != NULL)
335  {
336  delete[] thedYValues;
337  thedYValues = NULL;
338  }
339 
340  if (prodC != NULL)
341  {
342  delete[] prodC;
343  prodC = NULL;
344  }
345 
346  if (sumC != NULL)
347  {
348  delete[] sumC;
349  prodC = NULL;
350  }
351  isComputed = false;
353 }
354 }
ossim_uint32 x
ossim_uint32 y
#define abs(a)
Definition: auxiliary.h:74
HermiteInterpolator & operator=(const HermiteInterpolator &rhs)
Affectation operator.
int Interpolate(double x, double &y, double &dy) const
This function performs the interpolation for the abscissa x.