GteIntpBicubic2.h
Go to the documentation of this file.
1 // David Eberly, Geometric Tools, Redmond WA 98052
2 // Copyright (c) 1998-2017
3 // Distributed under the Boost Software License, Version 1.0.
4 // http://www.boost.org/LICENSE_1_0.txt
5 // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
6 // File Version: 3.0.0 (2016/06/19)
7 
8 #pragma once
9 
10 #include <LowLevel/GteLogger.h>
11 
12 // The interpolator is for uniformly spaced (x,y)-values. The input samples
13 // F must be stored in row-major order to represent f(x,y); that is,
14 // F[c + xBound*r] corresponds to f(x,y), where c is the index corresponding
15 // to x and r is the index corresponding to y. Exact interpolation is
16 // achieved by setting catmullRom to 'true', giving you the Catmull-Rom
17 // blending matrix. If a smooth interpolation is desired, set catmullRom to
18 // 'false' to obtain B-spline blending.
19 
20 namespace gte
21 {
22 
23 template <typename Real>
25 {
26 public:
27  // Construction.
28  IntpBicubic2(int xBound, int yBound, Real xMin, Real xSpacing,
29  Real yMin, Real ySpacing, Real const* F, bool catmullRom);
30 
31  // Member access.
32  inline int GetXBound() const;
33  inline int GetYBound() const;
34  inline int GetQuantity() const;
35  inline Real const* GetF() const;
36  inline Real GetXMin() const;
37  inline Real GetXMax() const;
38  inline Real GetXSpacing() const;
39  inline Real GetYMin() const;
40  inline Real GetYMax() const;
41  inline Real GetYSpacing() const;
42 
43  // Evaluate the function and its derivatives. The functions clamp the
44  // inputs to xmin <= x <= xmax and ymin <= y <= ymax. The first operator
45  // is for function evaluation. The second operator is for function or
46  // derivative evaluations. The xOrder argument is the order of the
47  // x-derivative and the yOrder argument is the order of the y-derivative.
48  // Both orders are zero to get the function value itself.
49  Real operator()(Real x, Real y) const;
50  Real operator()(int xOrder, int yOrder, Real x, Real y) const;
51 
52 private:
56  Real const* mF;
57  Real mBlend[4][4];
58 };
59 
60 
61 template <typename Real>
62 IntpBicubic2<Real>::IntpBicubic2(int xBound, int yBound, Real xMin,
63  Real xSpacing, Real yMin, Real ySpacing, Real const* F, bool catmullRom)
64  :
65  mXBound(xBound),
66  mYBound(yBound),
67  mQuantity(xBound * yBound),
68  mXMin(xMin),
69  mXSpacing(xSpacing),
70  mYMin(yMin),
71  mYSpacing(ySpacing),
72  mF(F)
73 {
74  // At least a 3x3 block of data points are needed to construct the
75  // estimates of the boundary derivatives.
76  LogAssert(mXBound >= 3 && mYBound >= 3 && mF, "Invalid input.");
77  LogAssert(mXSpacing > (Real)0 && mYSpacing > (Real)0, "Invalid input.");
78 
79  mXMax = mXMin + mXSpacing * static_cast<Real>(mXBound - 1);
80  mInvXSpacing = ((Real)1) / mXSpacing;
81  mYMax = mYMin + mYSpacing * static_cast<Real>(mYBound - 1);
82  mInvYSpacing = ((Real)1) / mYSpacing;
83 
84  if (catmullRom)
85  {
86  mBlend[0][0] = (Real)0;
87  mBlend[0][1] = (Real)-0.5;
88  mBlend[0][2] = (Real)1;
89  mBlend[0][3] = (Real)-0.5;
90  mBlend[1][0] = (Real)1;
91  mBlend[1][1] = (Real)0;
92  mBlend[1][2] = (Real)-2.5;
93  mBlend[1][3] = (Real)1.5;
94  mBlend[2][0] = (Real)0;
95  mBlend[2][1] = (Real)0.5;
96  mBlend[2][2] = (Real)2;
97  mBlend[2][3] = (Real)-1.5;
98  mBlend[3][0] = (Real)0;
99  mBlend[3][1] = (Real)0;
100  mBlend[3][2] = (Real)-0.5;
101  mBlend[3][3] = (Real)0.5;
102  }
103  else
104  {
105  mBlend[0][0] = (Real)1 / (Real)6;
106  mBlend[0][1] = (Real)-3 / (Real)6;
107  mBlend[0][2] = (Real)3 / (Real)6;
108  mBlend[0][3] = (Real)-1 / (Real)6;;
109  mBlend[1][0] = (Real)4 / (Real)6;
110  mBlend[1][1] = (Real)0 / (Real)6;
111  mBlend[1][2] = (Real)-6 / (Real)6;
112  mBlend[1][3] = (Real)3 / (Real)6;
113  mBlend[2][0] = (Real)1 / (Real)6;
114  mBlend[2][1] = (Real)3 / (Real)6;
115  mBlend[2][2] = (Real)3 / (Real)6;
116  mBlend[2][3] = (Real)-3 / (Real)6;
117  mBlend[3][0] = (Real)0 / (Real)6;
118  mBlend[3][1] = (Real)0 / (Real)6;
119  mBlend[3][2] = (Real)0 / (Real)6;
120  mBlend[3][3] = (Real)1 / (Real)6;
121  }
122 }
123 
124 template <typename Real> inline
126 {
127  return mXBound;
128 }
129 
130 template <typename Real> inline
132 {
133  return mYBound;
134 }
135 
136 template <typename Real> inline
138 {
139  return mQuantity;
140 }
141 
142 template <typename Real> inline
143 Real const* IntpBicubic2<Real>::GetF() const
144 {
145  return mF;
146 }
147 
148 template <typename Real> inline
150 {
151  return mXMin;
152 }
153 
154 template <typename Real> inline
156 {
157  return mXMax;
158 }
159 
160 template <typename Real> inline
162 {
163  return mXSpacing;
164 }
165 
166 template <typename Real> inline
168 {
169  return mYMin;
170 }
171 
172 template <typename Real> inline
174 {
175  return mYMax;
176 }
177 
178 template <typename Real> inline
180 {
181  return mYSpacing;
182 }
183 
184 template <typename Real>
185 Real IntpBicubic2<Real>::operator()(Real x, Real y) const
186 {
187  // Compute x-index and clamp to image.
188  Real xIndex = (x - mXMin) * mInvXSpacing;
189  int ix = static_cast<int>(xIndex);
190  if (ix < 0)
191  {
192  ix = 0;
193  }
194  else if (ix >= mXBound)
195  {
196  ix = mXBound - 1;
197  }
198 
199  // Compute y-index and clamp to image.
200  Real yIndex = (y - mYMin) * mInvYSpacing;
201  int iy = static_cast<int>(yIndex);
202  if (iy < 0)
203  {
204  iy = 0;
205  }
206  else if (iy >= mYBound)
207  {
208  iy = mYBound - 1;
209  }
210 
211  Real U[4];
212  U[0] = (Real)1;
213  U[1] = xIndex - ix;
214  U[2] = U[1] * U[1];
215  U[3] = U[1] * U[2];
216 
217  Real V[4];
218  V[0] = (Real)1;
219  V[1] = yIndex - iy;
220  V[2] = V[1] * V[1];
221  V[3] = V[1] * V[2];
222 
223  // Compute P = M*U and Q = M*V.
224  Real P[4], Q[4];
225  for (int row = 0; row < 4; ++row)
226  {
227  P[row] = (Real)0;
228  Q[row] = (Real)0;
229  for (int col = 0; col < 4; ++col)
230  {
231  P[row] += mBlend[row][col] * U[col];
232  Q[row] += mBlend[row][col] * V[col];
233  }
234  }
235 
236  // Compute (M*U)^t D (M*V) where D is the 4x4 subimage containing (x,y).
237  --ix;
238  --iy;
239  Real result = (Real)0;
240  for (int row = 0; row < 4; ++row)
241  {
242  int yClamp = iy + row;
243  if (yClamp < 0)
244  {
245  yClamp = 0;
246  }
247  else if (yClamp > mYBound - 1)
248  {
249  yClamp = mYBound - 1;
250  }
251 
252  for (int col = 0; col < 4; ++col)
253  {
254  int xClamp = ix + col;
255  if (xClamp < 0)
256  {
257  xClamp = 0;
258  }
259  else if (xClamp > mXBound - 1)
260  {
261  xClamp = mXBound - 1;
262  }
263 
264  result += P[col] * Q[row] * mF[xClamp + mXBound * yClamp];
265  }
266  }
267 
268  return result;
269 }
270 
271 template <typename Real>
272 Real IntpBicubic2<Real>::operator()(int xOrder, int yOrder, Real x, Real y)
273 const
274 {
275  // Compute x-index and clamp to image.
276  Real xIndex = (x - mXMin) * mInvXSpacing;
277  int ix = static_cast<int>(xIndex);
278  if (ix < 0)
279  {
280  ix = 0;
281  }
282  else if (ix >= mXBound)
283  {
284  ix = mXBound - 1;
285  }
286 
287  // Compute y-index and clamp to image.
288  Real yIndex = (y - mYMin) * mInvYSpacing;
289  int iy = static_cast<int>(yIndex);
290  if (iy < 0)
291  {
292  iy = 0;
293  }
294  else if (iy >= mYBound)
295  {
296  iy = mYBound - 1;
297  }
298 
299  Real U[4], dx, xMult;
300  switch (xOrder)
301  {
302  case 0:
303  dx = xIndex - ix;
304  U[0] = (Real)1;
305  U[1] = dx;
306  U[2] = dx * U[1];
307  U[3] = dx * U[2];
308  xMult = (Real)1;
309  break;
310  case 1:
311  dx = xIndex - ix;
312  U[0] = (Real)0;
313  U[1] = (Real)1;
314  U[2] = ((Real)2) * dx;
315  U[3] = ((Real)3) * dx * dx;
316  xMult = mInvXSpacing;
317  break;
318  case 2:
319  dx = xIndex - ix;
320  U[0] = (Real)0;
321  U[1] = (Real)0;
322  U[2] = (Real)2;
323  U[3] = (Real)6 * dx;
324  xMult = mInvXSpacing * mInvXSpacing;
325  break;
326  case 3:
327  U[0] = (Real)0;
328  U[1] = (Real)0;
329  U[2] = (Real)0;
330  U[3] = (Real)6;
331  xMult = mInvXSpacing * mInvXSpacing * mInvXSpacing;
332  break;
333  default:
334  return (Real)0;
335  }
336 
337  Real V[4], dy, yMult;
338  switch (yOrder)
339  {
340  case 0:
341  dy = yIndex - iy;
342  V[0] = (Real)1;
343  V[1] = dy;
344  V[2] = dy * V[1];
345  V[3] = dy * V[2];
346  yMult = (Real)1;
347  break;
348  case 1:
349  dy = yIndex - iy;
350  V[0] = (Real)0;
351  V[1] = (Real)1;
352  V[2] = ((Real)2) * dy;
353  V[3] = ((Real)3) * dy * dy;
354  yMult = mInvYSpacing;
355  break;
356  case 2:
357  dy = yIndex - iy;
358  V[0] = (Real)0;
359  V[1] = (Real)0;
360  V[2] = (Real)2;
361  V[3] = ((Real)6) * dy;
362  yMult = mInvYSpacing * mInvYSpacing;
363  break;
364  case 3:
365  V[0] = (Real)0;
366  V[1] = (Real)0;
367  V[2] = (Real)0;
368  V[3] = (Real)6;
369  yMult = mInvYSpacing * mInvYSpacing * mInvYSpacing;
370  break;
371  default:
372  return (Real)0;
373  }
374 
375  // Compute P = M*U and Q = M*V.
376  Real P[4], Q[4];
377  for (int row = 0; row < 4; ++row)
378  {
379  P[row] = (Real)0;
380  Q[row] = (Real)0;
381  for (int col = 0; col < 4; ++col)
382  {
383  P[row] += mBlend[row][col] * U[col];
384  Q[row] += mBlend[row][col] * V[col];
385  }
386  }
387 
388  // Compute (M*U)^t D (M*V) where D is the 4x4 subimage containing (x,y).
389  --ix;
390  --iy;
391  Real result = (Real)0;
392  for (int row = 0; row < 4; ++row)
393  {
394  int yClamp = iy + row;
395  if (yClamp < 0)
396  {
397  yClamp = 0;
398  }
399  else if (yClamp > mYBound - 1)
400  {
401  yClamp = mYBound - 1;
402  }
403 
404  for (int col = 0; col < 4; ++col)
405  {
406  int xClamp = ix + col;
407  if (xClamp < 0)
408  {
409  xClamp = 0;
410  }
411  else if (xClamp > mXBound - 1)
412  {
413  xClamp = mXBound - 1;
414  }
415 
416  result += P[col] * Q[row] * mF[xClamp + mXBound * yClamp];
417  }
418  }
419  result *= xMult * yMult;
420 
421  return result;
422 }
423 
424 
425 }
#define LogAssert(condition, message)
Definition: GteLogger.h:86
Real GetYMin() const
Real GetYSpacing() const
Real GetYMax() const
Real GetXMax() const
GLint GLenum GLint x
Definition: glcorearb.h:404
IntpBicubic2(int xBound, int yBound, Real xMin, Real xSpacing, Real yMin, Real ySpacing, Real const *F, bool catmullRom)
int GetQuantity() const
int GetXBound() const
Real const * GetF() const
GLenum GLenum GLsizei void * row
Definition: glext.h:2725
Real operator()(Real x, Real y) const
Real GetXSpacing() const
Real GetXMin() const
int GetYBound() const
GLuint64EXT * result
Definition: glext.h:10003
GLint y
Definition: glcorearb.h:98


geometric_tools_engine
Author(s): Yijiang Huang
autogenerated on Thu Jul 18 2019 04:00:00