CubicSpline.hpp
Go to the documentation of this file.
1 //==============================================================================
2 //
3 // This file is part of GNSSTk, the ARL:UT GNSS Toolkit.
4 //
5 // The GNSSTk is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published
7 // by the Free Software Foundation; either version 3.0 of the License, or
8 // any later version.
9 //
10 // The GNSSTk is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with GNSSTk; if not, write to the Free Software Foundation,
17 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
18 //
19 // This software was developed by Applied Research Laboratories at the
20 // University of Texas at Austin.
21 // Copyright 2004-2022, The Board of Regents of The University of Texas System
22 //
23 //==============================================================================
24 
25 //==============================================================================
26 //
27 // This software was developed by Applied Research Laboratories at the
28 // University of Texas at Austin, under contract to an agency or agencies
29 // within the U.S. Department of Defense. The U.S. Government retains all
30 // rights to use, duplicate, distribute, disclose, or release this software.
31 //
32 // Pursuant to DoD Directive 523024
33 //
34 // DISTRIBUTION STATEMENT A: This software has been approved for public
35 // release, distribution is unlimited.
36 //
37 //==============================================================================
38 
43 #ifndef INCLUDE_CUBIC_SPLINE_HPP
44 #define INCLUDE_CUBIC_SPLINE_HPP
45 
46 #include "Exception.hpp"
47 #include "StringUtils.hpp"
48 #include <vector>
49 
50 namespace gnsstk
51 {
53 
54 
56  template <class T> class CubicSpline
57  {
58  public:
60  CubicSpline() : N(0) {}
61 
65  CubicSpline(const std::vector<T>& X, const std::vector<T>& Y)
66  {
67  initialize(X, Y);
68  }
69 
78  void initialize(const std::vector<T>& X, const std::vector<T>& Y)
79  {
80  build(X, Y, false);
81  }
82 
92  void initialize(const std::vector<T>& X, const std::vector<T>& Y,
93  const T DYDX1, const T DYDXN)
94  {
95  fd1 = DYDX1;
96  fdN = DYDXN;
97  build(X, Y, true);
98  }
99 
109  bool testLimits(const T& x, T& y)
110  {
111  if (N == 0)
112  {
113  Exception e("Must call initialize() first");
114  GNSSTK_THROW(e);
115  }
116  if (x <= X[0])
117  {
118  y = Y[0];
119  return false;
120  }
121  if (x >= X[N - 1])
122  {
123  y = Y[N - 1];
124  return false;
125  }
126  return true;
127  }
128 
140  T evaluate(const T& x)
141  {
142  if (N == 0)
143  {
144  Exception e("Must call initialize() first");
145  GNSSTK_THROW(e);
146  }
147  if (x < X[0] || x > X[N - 1])
148  {
149  Exception e(
150  "Input value is outside range determined by initialize()");
151  GNSSTK_THROW(e);
152  }
153 
154  // find x in the array X
155  int i, k;
156  if (x == X[0])
157  {
158  return Y[0];
159  }
160  for (i = 1; i < N; i++)
161  {
162  if (x == X[i])
163  {
164  return Y[i];
165  }
166  if (X[i - 1] < x && x <= X[i])
167  {
168  k = i;
169  break;
170  }
171  }
172 
173  // interpolate
174  return interpolate(k, x);
175  }
176 
185  std::vector<T> evaluate(const std::vector<T>& x)
186  {
187  if (N == 0)
188  {
189  Exception e("Must call initialize() first");
190  GNSSTK_THROW(e);
191  }
192 
193  int n = x.size();
194  std::vector<T> y(n);
195 
196  int i, k = 0;
197  for (i = 0; i < n; i++)
198  {
199  if (x[i] < X[0] || x[i] > X[N - 1])
200  {
201  Exception e(
202  std::string("Input value at index ") +
204  std::string(" is outside range determined by initialize()"));
205  GNSSTK_THROW(e);
206  }
207 
208  // find x[i] in the array X: X[k-1] < x[i] <= X[k]
209  if (k < N && x[i] > X[k])
210  {
211  while (x[i] > X[k])
212  k++; // move up
213  }
214  else if (k > 0 && x[i] < X[k - 1])
215  {
216  while (x[i] <= X[k - 1])
217  k--; // move down
218  }
219 
220  if (x[i] == X[k])
221  {
222  y[i] = Y[k];
223  }
224  else if (x[i] == X[k - 1])
225  {
226  y[i] = Y[k - 1];
227  }
228  else
229  {
230  y[i] = interpolate(k, x[i]);
231  }
232  }
233 
234  return y;
235  }
236 
238  int size() const { return S.size(); }
239 
240  private:
253  void build(const std::vector<T>& x, const std::vector<T>& y, bool fixEnds)
254  {
255  int i;
256 
257  // clear old values
258  X.clear();
259  Y.clear();
260  S.clear();
261 
262  // size of array S
263  N = (x.size() < y.size() ? x.size() : y.size());
264  if (N == 0)
265  {
266  Exception e("Input data array(s) empty");
267  GNSSTK_THROW(e);
268  }
269 
270  // resize arrays
271  X = std::vector<T>(N);
272  Y = std::vector<T>(N);
273  S = std::vector<T>(N);
274 
275  // x must be strictly increasing; use this loop to copy out the data.
276  X[0] = x[0];
277  Y[0] = y[0];
278  for (i = 1; i < N; i++)
279  {
280  if (x[i - 1] >= x[i])
281  {
282  Exception e("Input data array X is not strictly increasing");
283  GNSSTK_THROW(e);
284  }
285  X[i] = x[i];
286  Y[i] = y[i];
287  }
288 
289  // min 4 points needed for cubic spline
290  if (N <= 3)
291  { // linear interpolation
292  for (i = 0; i < N; i++)
293  S[i] = T(0);
294  return;
295  }
296 
297  // fix derivatives at endpoints
298  T dx1, dx2;
299  if (!fixEnds)
300  {
301  // this fits parabola to endpoints
302  dx1 = X[1] - X[0];
303  dx2 = X[2] - X[0];
304  fd1 = ((Y[1] - Y[0]) / (dx1 * dx1) - (Y[2] - Y[0]) / (dx2 * dx2)) /
305  (T(1) / dx1 - T(1) / dx2);
306 
307  dx1 = X[N - 2] - X[N - 1];
308  dx2 = X[N - 3] - X[N - 1];
309  fdN = ((Y[N - 2] - Y[N - 1]) / (dx1 * dx1) -
310  (Y[N - 3] - Y[N - 1]) / (dx2 * dx2)) /
311  (T(1) / dx1 - T(1) / dx2);
312  }
313 
314  // second derivatives at endpoints...
315  S[0] = T(6) * ((Y[1] - Y[0]) / (X[1] - X[0]) - fd1);
316  S[N - 1] =
317  T(6) * (fdN + (Y[N - 2] - Y[N - 1]) / (X[N - 1] - X[N - 2]));
318 
319  // ...and at point in between
320  for (i = 1; i < N - 1; i++)
321  S[i] =
322  T(6) *
323  (Y[i - 1] / (X[i] - X[i - 1]) -
324  Y[i] * (T(1) / (X[i] - X[i - 1]) + T(1) / (X[i + 1] - X[i])) +
325  Y[i + 1] / (X[i + 1] - X[i]));
326 
327  // finish with recursion
328  std::vector<T> A(N);
329  A[0] = T(2) * (X[1] - X[0]);
330  A[1] = T(1.5) * (X[1] - X[0]) + T(2) * (X[2] - X[1]);
331  S[1] -= T(0.5) * S[0];
332  for (i = 2; i < N - 1; i++)
333  {
334  dx1 = (X[i] - X[i - 1]) / A[i - 1];
335  A[i] = T(2) * (X[i + 1] - X[i - 1]) - dx1 * (X[i] - X[i - 1]);
336  S[i] -= dx1 * S[i - 1];
337  }
338  dx1 = (X[N - 1] - X[N - 2]) / A[N - 2];
339  A[N - 1] = (T(2) - dx1) * (X[N - 1] - X[N - 2]);
340  S[N - 1] -= dx1 * S[N - 2];
341 
342  // back substitute to get second derivatives
343  S[N - 1] /= A[N - 1];
344  for (i = N - 2; i >= 0; i--)
345  {
346  S[i] -= (X[i + 1] - X[i]) * S[i + 1];
347  S[i] /= A[i];
348  }
349  }
350 
354  T interpolate(const int k, const T x)
355  {
356  T dxr(X[k] - x), dxl(x - X[k - 1]), dx(X[k] - X[k - 1]);
357  return ((dxl * (Y[k] - S[k] * dx * dx / T(6)) +
358  (S[k - 1] * dxr * dxr * dxr + S[k] * dxl * dxl * dxl) / T(6) +
359  dxr * (Y[k - 1] - S[k - 1] * dx * dx / T(6))) /
360  dx);
361  }
362 
364  std::vector<T> X, Y;
365 
369  std::vector<T> S;
370 
372  T fd1, fdN;
373 
375  int N;
376 
377  }; // end class CubicSpline
378 
380 
381 } // namespace gnsstk
382 
383 #endif
gnsstk::CubicSpline::N
int N
size of the arrays X,Y,S
Definition: CubicSpline.hpp:375
gnsstk::CubicSpline
Cubic spline interpolation.
Definition: CubicSpline.hpp:56
StringUtils.hpp
gnsstk::CubicSpline::evaluate
std::vector< T > evaluate(const std::vector< T > &x)
Definition: CubicSpline.hpp:185
gnsstk::StringUtils::asString
std::string asString(IonexStoreStrategy e)
Convert a IonexStoreStrategy to a whitespace-free string name.
Definition: IonexStoreStrategy.cpp:46
gnsstk::CubicSpline::evaluate
T evaluate(const T &x)
Definition: CubicSpline.hpp:140
gnsstk::CubicSpline::testLimits
bool testLimits(const T &x, T &y)
Definition: CubicSpline.hpp:109
gnsstk
For Sinex::InputHistory.
Definition: BasicFramework.cpp:50
gnsstk::CubicSpline::initialize
void initialize(const std::vector< T > &X, const std::vector< T > &Y)
Definition: CubicSpline.hpp:78
gnsstk::Exception
Definition: Exception.hpp:151
gnsstk::CubicSpline::build
void build(const std::vector< T > &x, const std::vector< T > &y, bool fixEnds)
Definition: CubicSpline.hpp:253
y
page HOWTO subpage DoxygenGuide Documenting Your Code page DoxygenGuide Documenting Your Code todo Flesh out this document section doctips Tips for Documenting When defining make sure that the prototype is identical between the cpp and hpp including both the namespaces and the parameter names for you have std::string as the return type in the hpp file and string as the return type in the cpp Doxygen may get confused and autolink to the cpp version with no documentation If you don t use the same parameter names between the cpp and hpp that will also confuse Doxygen Don t put type information in return or param documentation It doesn t really add anything and will often cause Doxygen to complain and not produce the documentation< br > use note Do not put a comma after a param name unless you mean to document multiple parameters< br/> the output stream</code >< br/> y
Definition: DOCUMENTING.dox:15
gnsstk::CubicSpline::fd1
T fd1
Values of the derivative dy/dx at the first and last data points.
Definition: CubicSpline.hpp:372
gnsstk::CubicSpline::Y
std::vector< T > Y
Definition: CubicSpline.hpp:364
gnsstk::CubicSpline::X
std::vector< T > X
Data arrays.
Definition: CubicSpline.hpp:364
gnsstk::CubicSpline::initialize
void initialize(const std::vector< T > &X, const std::vector< T > &Y, const T DYDX1, const T DYDXN)
Definition: CubicSpline.hpp:92
gnsstk::CubicSpline::size
int size() const
Return the current size of the second derivative array.
Definition: CubicSpline.hpp:238
gnsstk::CubicSpline::CubicSpline
CubicSpline()
Empty constructor - NB must call initialize() before Eval().
Definition: CubicSpline.hpp:60
Exception.hpp
gnsstk::CubicSpline::S
std::vector< T > S
Definition: CubicSpline.hpp:369
GNSSTK_THROW
#define GNSSTK_THROW(exc)
Definition: Exception.hpp:366
gnsstk::CubicSpline::CubicSpline
CubicSpline(const std::vector< T > &X, const std::vector< T > &Y)
Definition: CubicSpline.hpp:65
gnsstk::CubicSpline::fdN
T fdN
Definition: CubicSpline.hpp:372
gnsstk::CubicSpline::interpolate
T interpolate(const int k, const T x)
Definition: CubicSpline.hpp:354


gnsstk
Author(s):
autogenerated on Wed Oct 25 2023 02:40:38