UniformBSpline.h
Go to the documentation of this file.
1 #ifndef _UniformBSpline_Spline_Uniform_h_
2 #define _UniformBSpline_Spline_Uniform_h_
3 
4 #include <cmath>
5 #include <vector>
6 #include <algorithm>
7 #include <limits>
8 #include <iostream>
9 #include <utl/AugerException.h>
10 
11 
12 namespace Spline {
13 
14  typedef unsigned char dim_t;
15 
16 
17  template <dim_t ADimension, typename AKnotVector, typename ABasisFunction>
18  class Function;
19 
20 
21  namespace Uniform {
22 
23  class KnotVector {
24  public:
25  KnotVector() { }
26 
27  KnotVector(const size_t n, const double start, const double stop) :
28  fN(n),
29  fStart(start),
30  fDelta(stop-start)
31  {
32  if (n < 2)
33  throw utl::InvalidConfigurationException("KnotVector: size < 2");
34 
35  if (stop < start)
36  throw utl::InvalidConfigurationException("KnotVector: stop < start");
37  }
38 
39  void
40  PushBack(const double x)
41  {
42  if (fN == 0)
43  fStart = x;
44  fDelta = x - fStart;
45  ++fN;
46  }
47 
48  size_t
49  Locate(const double x)
50  const
51  {
52  if (x < fStart)
53  return 0;
54 
55  if (x >= fStart + fDelta)
56  return fN-2;
57 
58  return size_t((x - fStart)/fDelta*(fN-1));
59  }
60 
61  double operator[](const size_t i) const
62  { return fStart + double(i)/(fN-1)*fDelta; }
63 
64  size_t GetSize() const { return fN; }
65 
66  double GetStart() const { return fStart; }
67 
68  double GetStop() const { return fStart + fDelta; }
69 
70  protected:
71  size_t fN = 0;
72  double fStart = 0;
73  double fDelta = 1;
74  };
75 
76 
77  class BasisFunction {
78  public:
80 
81  BasisFunction(const KnotVector* const xknot, const int j)
82  : fKnotPtr(xknot), fIndex(j-3) { }
83 
84  BasisFunction(const BasisFunction& other) { *this = other; }
85 
87  operator=(const BasisFunction& other)
88  {
89  fKnotPtr = other.fKnotPtr;
90  fIndex = other.fIndex;
91  return *this;
92  }
93 
94  double
95  operator()(const double x, const char derivative = 0)
96  const
97  {
98  if (x < GetStart())
99  return 0;
100 
101  if (x > GetStop())
102  return (derivative == -1) ? Internal(fKnotPtr->Locate(x), GetStop(), -1) : 0;
103 
104  return Internal(fKnotPtr->Locate(x), x, derivative);
105  }
106 
107  double GetStart() const { return (*fKnotPtr)[std::max(fIndex, 0)]; }
108 
109  double GetStop() const { return (*fKnotPtr)[std::min(fIndex+4, int(fKnotPtr->GetSize())-1)]; }
110 
111  protected:
112  double
113  Internal(const size_t i, const double x, const char derivative)
114  const
115  {
116  const KnotVector& xknot = *fKnotPtr;
117 
118  const double dx = xknot[1] - xknot[0];
119  const double z = (x - xknot[i]) / dx;
120 
121  double t0, t1, t2, t3;
122  switch (i - fIndex) {
123  case 3:
124  t0 = 1./6;
125  t1 = -0.5;
126  t2 = 0.5;
127  t3 = -1./6;
128  break;
129  case 2:
130  t0 = 2./3;
131  t1 = 0;
132  t2 = -1;
133  t3 = 0.5;
134  break;
135  case 1:
136  t0 = 1./6;
137  t1 = 0.5;
138  t2 = 0.5;
139  t3 = -0.5;
140  break;
141  case 0:
142  t0 = 0;
143  t1 = 0;
144  t2 = 0;
145  t3 = 1./6;
146  break;
147  default:
148  t0 = 0;
149  t1 = 0;
150  t2 = 0;
151  t3 = 0;
152  }
153 
154  switch (derivative) {
155  case -1: {
156  double result = z*(t0 + z*(t1/2 + z*(t2/3 + z*t3/4)))*dx;
157  for (size_t j = std::max(fIndex, 0); j < i; ++j) {
158  switch (j - fIndex) {
159  case 3:
160  t0 = 1./6;
161  t1 = -0.5;
162  t2 = 0.5;
163  t3 = -1./6;
164  break;
165  case 2:
166  t0 = 2./3;
167  t1 = 0;
168  t2 = -1;
169  t3 = 0.5;
170  break;
171  case 1:
172  t0 = 1./6;
173  t1 = 0.5;
174  t2 = 0.5;
175  t3 = -0.5;
176  break;
177  case 0:
178  t0 = 0;
179  t1 = 0;
180  t2 = 0;
181  t3 = 1./6;
182  break;
183  default:
184  t0 = 0;
185  t1 = 0;
186  t2 = 0;
187  t3 = 0;
188  }
189  result += (t0 + (t1/2 + (t2/3 + t3/4)))*dx;
190  }
191  return result;
192  }
193  case 0:
194  return t0 + z*(t1 + z*(t2 + z*t3));
195  case 1:
196  return (t1 + z*(2*t2 + z*3*t3))/dx;
197  case 2:
198  return (2*t2 + z*6*t3)/(dx*dx);
199  case 3:
200  return 6*t3/(dx*dx*dx);
201  default:
202  return 0;
203  }
204  }
205 
206  const KnotVector* fKnotPtr = nullptr;
207  int fIndex = 0;
208 
209  template <dim_t ADimension, typename AKnotVector, typename ABasisFunction>
210  friend class ::Spline::Function;
211  };
212 
213  }
214 
215 }
216 
217 
218 #endif
double operator[](const size_t i) const
Base class for exceptions arising because configuration data are not valid.
void PushBack(const double x)
BasisFunction & operator=(const BasisFunction &other)
#define max(a, b)
const Data result[]
unsigned char dim_t
return size_t((x-fStart)/fDelta *(fN-1))
BasisFunction(const KnotVector *const xknot, const int j)
KnotVector(const size_t n, const double start, const double stop)
double operator()(const double x, const char derivative=0) const
BasisFunction(const BasisFunction &other)

, generated on Tue Sep 26 2023.