GteIntpTricubic3.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 z)-values. The input samples
13 // must be stored in lexicographical order to represent f(x,y,z); that is,
14 // F[c + xBound*(r + yBound*s)] corresponds to f(x,y,z), where c is the index
15 // corresponding to x, r is the index corresponding to y, and s is the index
16 // corresponding to z. Exact interpolation is achieved by setting catmullRom
17 // to 'true', giving you the Catmull-Rom blending matrix. If a smooth
18 // interpolation is desired, set catmullRom to 'false' to obtain B-spline
19 // blending.
20 
21 namespace gte
22 {
23 
24 template <typename Real>
26 {
27 public:
28  // Construction.
29  IntpTricubic3(int xBound, int yBound, int zBound, Real xMin,
30  Real xSpacing, Real yMin, Real ySpacing, Real zMin, Real zSpacing,
31  Real const* F, bool catmullRom);
32 
33  // Member access.
34  inline int GetXBound() const;
35  inline int GetYBound() const;
36  inline int GetZBound() const;
37  inline int GetQuantity() const;
38  inline Real const* GetF() const;
39  inline Real GetXMin() const;
40  inline Real GetXMax() const;
41  inline Real GetXSpacing() const;
42  inline Real GetYMin() const;
43  inline Real GetYMax() const;
44  inline Real GetYSpacing() const;
45  inline Real GetZMin() const;
46  inline Real GetZMax() const;
47  inline Real GetZSpacing() const;
48 
49  // Evaluate the function and its derivatives. The functions clamp the
50  // inputs to xmin <= x <= xmax, ymin <= y <= ymax, and zmin <= z <= zmax.
51  // The first operator is for function evaluation. The second operator is
52  // for function or derivative evaluations. The xOrder argument is the
53  // order of the x-derivative, the yOrder argument is the order of the
54  // y-derivative, and the zOrder argument is the order of the z-derivative.
55  // All orders are zero to get the function value itself.
56  Real operator()(Real x, Real y, Real z) const;
57  Real operator()(int xOrder, int yOrder, int zOrder, Real x, Real y,
58  Real z) const;
59 
60 private:
65  Real const* mF;
66  Real mBlend[4][4];
67 };
68 
69 
70 template <typename Real>
71 IntpTricubic3<Real>::IntpTricubic3(int xBound, int yBound, int zBound,
72  Real xMin, Real xSpacing, Real yMin, Real ySpacing, Real zMin,
73  Real zSpacing, Real const* F, bool catmullRom)
74  :
75  mXBound(xBound),
76  mYBound(yBound),
77  mZBound(zBound),
78  mQuantity(xBound * yBound * zBound),
79  mXMin(xMin),
80  mXSpacing(xSpacing),
81  mYMin(yMin),
82  mYSpacing(ySpacing),
83  mZMin(zMin),
84  mZSpacing(zSpacing),
85  mF(F)
86 {
87  // At least a 4x4x4 block of data points are needed to construct the
88  // tricubic interpolation.
89  LogAssert(mXBound >= 4 && mYBound >= 4 && mZBound >= 4 && mF,
90  "Invalid input.");
91  LogAssert(mXSpacing > (Real)0 && mYSpacing > (Real)0 &&
92  mZSpacing > (Real)0, "Invalid input.");
93 
94  mXMax = mXMin + mXSpacing * static_cast<Real>(mXBound - 1);
95  mInvXSpacing = ((Real)1) / mXSpacing;
96  mYMax = mYMin + mYSpacing * static_cast<Real>(mYBound - 1);
97  mInvYSpacing = ((Real)1) / mYSpacing;
98  mZMax = mZMin + mZSpacing * static_cast<Real>(mZBound - 1);
99  mInvZSpacing = ((Real)1) / mZSpacing;
100 
101  if (catmullRom)
102  {
103  mBlend[0][0] = (Real)0;
104  mBlend[0][1] = (Real)-0.5;
105  mBlend[0][2] = (Real)1;
106  mBlend[0][3] = (Real)-0.5;
107  mBlend[1][0] = (Real)1;
108  mBlend[1][1] = (Real)0;
109  mBlend[1][2] = (Real)-2.5;
110  mBlend[1][3] = (Real)1.5;
111  mBlend[2][0] = (Real)0;
112  mBlend[2][1] = (Real)0.5;
113  mBlend[2][2] = (Real)2;
114  mBlend[2][3] = (Real)-1.5;
115  mBlend[3][0] = (Real)0;
116  mBlend[3][1] = (Real)0;
117  mBlend[3][2] = (Real)-0.5;
118  mBlend[3][3] = (Real)0.5;
119  }
120  else
121  {
122  mBlend[0][0] = (Real)1 / (Real)6;
123  mBlend[0][1] = (Real)-3 / (Real)6;
124  mBlend[0][2] = (Real)3 / (Real)6;
125  mBlend[0][3] = (Real)-1 / (Real)6;;
126  mBlend[1][0] = (Real)4 / (Real)6;
127  mBlend[1][1] = (Real)0 / (Real)6;
128  mBlend[1][2] = (Real)-6 / (Real)6;
129  mBlend[1][3] = (Real)3 / (Real)6;
130  mBlend[2][0] = (Real)1 / (Real)6;
131  mBlend[2][1] = (Real)3 / (Real)6;
132  mBlend[2][2] = (Real)3 / (Real)6;
133  mBlend[2][3] = (Real)-3 / (Real)6;
134  mBlend[3][0] = (Real)0 / (Real)6;
135  mBlend[3][1] = (Real)0 / (Real)6;
136  mBlend[3][2] = (Real)0 / (Real)6;
137  mBlend[3][3] = (Real)1 / (Real)6;
138  }
139 }
140 
141 template <typename Real> inline
143 {
144  return mXBound;
145 }
146 
147 template <typename Real> inline
149 {
150  return mYBound;
151 }
152 
153 template <typename Real> inline
155 {
156  return mZBound;
157 }
158 
159 template <typename Real> inline
161 {
162  return mQuantity;
163 }
164 
165 template <typename Real> inline
166 Real const* IntpTricubic3<Real>::GetF() const
167 {
168  return mF;
169 }
170 
171 template <typename Real> inline
173 {
174  return mXMin;
175 }
176 
177 template <typename Real> inline
179 {
180  return mXMax;
181 }
182 
183 template <typename Real> inline
185 {
186  return mXSpacing;
187 }
188 
189 template <typename Real> inline
191 {
192  return mYMin;
193 }
194 
195 template <typename Real> inline
197 {
198  return mYMax;
199 }
200 
201 template <typename Real> inline
203 {
204  return mYSpacing;
205 }
206 
207 template <typename Real> inline
209 {
210  return mZMin;
211 }
212 
213 template <typename Real> inline
215 {
216  return mZMax;
217 }
218 
219 template <typename Real> inline
221 {
222  return mZSpacing;
223 }
224 
225 template <typename Real>
226 Real IntpTricubic3<Real>::operator()(Real x, Real y, Real z) const
227 {
228  // Compute x-index and clamp to image.
229  Real xIndex = (x - mXMin) * mInvXSpacing;
230  int ix = static_cast<int>(xIndex);
231  if (ix < 0)
232  {
233  ix = 0;
234  }
235  else if (ix >= mXBound)
236  {
237  ix = mXBound - 1;
238  }
239 
240  // Compute y-index and clamp to image.
241  Real yIndex = (y - mYMin) * mInvYSpacing;
242  int iy = static_cast<int>(yIndex);
243  if (iy < 0)
244  {
245  iy = 0;
246  }
247  else if (iy >= mYBound)
248  {
249  iy = mYBound - 1;
250  }
251 
252  // Compute z-index and clamp to image.
253  Real zIndex = (z - mZMin) * mInvZSpacing;
254  int iz = static_cast<int>(zIndex);
255  if (iz < 0)
256  {
257  iz = 0;
258  }
259  else if (iz >= mZBound)
260  {
261  iz = mZBound - 1;
262  }
263 
264  Real U[4];
265  U[0] = (Real)1;
266  U[1] = xIndex - ix;
267  U[2] = U[1] * U[1];
268  U[3] = U[1] * U[2];
269 
270  Real V[4];
271  V[0] = (Real)1;
272  V[1] = yIndex - iy;
273  V[2] = V[1] * V[1];
274  V[3] = V[1] * V[2];
275 
276  Real W[4];
277  W[0] = (Real)1;
278  W[1] = zIndex - iz;
279  W[2] = W[1] * W[1];
280  W[3] = W[1] * W[2];
281 
282  // Compute P = M*U, Q = M*V, R = M*W.
283  Real P[4], Q[4], R[4];
284  for (int row = 0; row < 4; ++row)
285  {
286  P[row] = (Real)0;
287  Q[row] = (Real)0;
288  R[row] = (Real)0;
289  for (int col = 0; col < 4; ++col)
290  {
291  P[row] += mBlend[row][col] * U[col];
292  Q[row] += mBlend[row][col] * V[col];
293  R[row] += mBlend[row][col] * W[col];
294  }
295  }
296 
297  // Compute the tensor product (M*U)(M*V)(M*W)*D where D is the 4x4x4
298  // subimage containing (x,y,z).
299  --ix;
300  --iy;
301  --iz;
302  Real result = (Real)0;
303  for (int slice = 0; slice < 4; ++slice)
304  {
305  int zClamp = iz + slice;
306  if (zClamp < 0)
307  {
308  zClamp = 0;
309  }
310  else if (zClamp > mZBound - 1)
311  {
312  zClamp = mZBound - 1;
313  }
314 
315  for (int row = 0; row < 4; ++row)
316  {
317  int yClamp = iy + row;
318  if (yClamp < 0)
319  {
320  yClamp = 0;
321  }
322  else if (yClamp > mYBound - 1)
323  {
324  yClamp = mYBound - 1;
325  }
326 
327  for (int col = 0; col < 4; ++col)
328  {
329  int xClamp = ix + col;
330  if (xClamp < 0)
331  {
332  xClamp = 0;
333  }
334  else if (xClamp > mXBound - 1)
335  {
336  xClamp = mXBound - 1;
337  }
338 
339  result += P[col] * Q[row] * R[slice] *
340  mF[xClamp + mXBound * (yClamp + mYBound * zClamp)];
341  }
342  }
343  }
344 
345  return result;
346 }
347 
348 template <typename Real>
349 Real IntpTricubic3<Real>::operator()(int xOrder, int yOrder, int zOrder,
350  Real x, Real y, Real z) const
351 {
352  // Compute x-index and clamp to image.
353  Real xIndex = (x - mXMin) * mInvXSpacing;
354  int ix = static_cast<int>(xIndex);
355  if (ix < 0)
356  {
357  ix = 0;
358  }
359  else if (ix >= mXBound)
360  {
361  ix = mXBound - 1;
362  }
363 
364  // Compute y-index and clamp to image.
365  Real yIndex = (y - mYMin) * mInvYSpacing;
366  int iy = static_cast<int>(yIndex);
367  if (iy < 0)
368  {
369  iy = 0;
370  }
371  else if (iy >= mYBound)
372  {
373  iy = mYBound - 1;
374  }
375 
376  // Compute z-index and clamp to image.
377  Real zIndex = (z - mZMin) * mInvZSpacing;
378  int iz = static_cast<int>(zIndex);
379  if (iz < 0)
380  {
381  iz = 0;
382  }
383  else if (iz >= mZBound)
384  {
385  iz = mZBound - 1;
386  }
387 
388  Real U[4], dx, xMult;
389  switch (xOrder)
390  {
391  case 0:
392  dx = xIndex - ix;
393  U[0] = (Real)1;
394  U[1] = dx;
395  U[2] = dx * U[1];
396  U[3] = dx * U[2];
397  xMult = (Real)1;
398  break;
399  case 1:
400  dx = xIndex - ix;
401  U[0] = (Real)0;
402  U[1] = (Real)1;
403  U[2] = ((Real)2) * dx;
404  U[3] = ((Real)3) * dx * dx;
405  xMult = mInvXSpacing;
406  break;
407  case 2:
408  dx = xIndex - ix;
409  U[0] = (Real)0;
410  U[1] = (Real)0;
411  U[2] = (Real)2;
412  U[3] = ((Real)6) * dx;
413  xMult = mInvXSpacing * mInvXSpacing;
414  break;
415  case 3:
416  U[0] = (Real)0;
417  U[1] = (Real)0;
418  U[2] = (Real)0;
419  U[3] = (Real)6;
420  xMult = mInvXSpacing * mInvXSpacing * mInvXSpacing;
421  break;
422  default:
423  return (Real)0;
424  }
425 
426  Real V[4], dy, yMult;
427  switch (yOrder)
428  {
429  case 0:
430  dy = yIndex - iy;
431  V[0] = (Real)1;
432  V[1] = dy;
433  V[2] = dy * V[1];
434  V[3] = dy * V[2];
435  yMult = (Real)1;
436  break;
437  case 1:
438  dy = yIndex - iy;
439  V[0] = (Real)0;
440  V[1] = (Real)1;
441  V[2] = ((Real)2) * dy;
442  V[3] = ((Real)3) * dy * dy;
443  yMult = mInvYSpacing;
444  break;
445  case 2:
446  dy = yIndex - iy;
447  V[0] = (Real)0;
448  V[1] = (Real)0;
449  V[2] = (Real)2;
450  V[3] = ((Real)6) * dy;
451  yMult = mInvYSpacing * mInvYSpacing;
452  break;
453  case 3:
454  V[0] = (Real)0;
455  V[1] = (Real)0;
456  V[2] = (Real)0;
457  V[3] = (Real)6;
458  yMult = mInvYSpacing * mInvYSpacing * mInvYSpacing;
459  break;
460  default:
461  return (Real)0;
462  }
463 
464  Real W[4], dz, zMult;
465  switch (zOrder)
466  {
467  case 0:
468  dz = zIndex - iz;
469  W[0] = (Real)1;
470  W[1] = dz;
471  W[2] = dz * W[1];
472  W[3] = dz * W[2];
473  zMult = (Real)1;
474  break;
475  case 1:
476  dz = zIndex - iz;
477  W[0] = (Real)0;
478  W[1] = (Real)1;
479  W[2] = ((Real)2) * dz;
480  W[3] = ((Real)3) * dz * dz;
481  zMult = mInvZSpacing;
482  break;
483  case 2:
484  dz = zIndex - iz;
485  W[0] = (Real)0;
486  W[1] = (Real)0;
487  W[2] = (Real)2;
488  W[3] = ((Real)6) * dz;
489  zMult = mInvZSpacing * mInvZSpacing;
490  break;
491  case 3:
492  W[0] = (Real)0;
493  W[1] = (Real)0;
494  W[2] = (Real)0;
495  W[3] = (Real)6;
496  zMult = mInvZSpacing * mInvZSpacing * mInvZSpacing;
497  break;
498  default:
499  return (Real)0;
500  }
501 
502  // Compute P = M*U, Q = M*V, and R = M*W.
503  Real P[4], Q[4], R[4];
504  for (int row = 0; row < 4; ++row)
505  {
506  P[row] = (Real)0;
507  Q[row] = (Real)0;
508  R[row] = (Real)0;
509  for (int col = 0; col < 4; ++col)
510  {
511  P[row] += mBlend[row][col] * U[col];
512  Q[row] += mBlend[row][col] * V[col];
513  R[row] += mBlend[row][col] * W[col];
514  }
515  }
516 
517  // Compute the tensor product (M*U)(M*V)(M*W)*D where D is the 4x4x4
518  // subimage containing (x,y,z).
519  --ix;
520  --iy;
521  --iz;
522  Real result = (Real)0;
523  for (int slice = 0; slice < 4; ++slice)
524  {
525  int zClamp = iz + slice;
526  if (zClamp < 0)
527  {
528  zClamp = 0;
529  }
530  else if (zClamp > mZBound - 1)
531  {
532  zClamp = mZBound - 1;
533  }
534 
535  for (int row = 0; row < 4; ++row)
536  {
537  int yClamp = iy + row;
538  if (yClamp < 0)
539  {
540  yClamp = 0;
541  }
542  else if (yClamp > mYBound - 1)
543  {
544  yClamp = mYBound - 1;
545  }
546 
547  for (int col = 0; col < 4; ++col)
548  {
549  int xClamp = ix + col;
550  if (xClamp < 0)
551  {
552  xClamp = 0;
553  }
554  else if (xClamp > mXBound - 1)
555  {
556  xClamp = mXBound - 1;
557  }
558 
559  result += P[col] * Q[row] * R[slice] *
560  mF[xClamp + mXBound * (yClamp + mYBound * zClamp)];
561  }
562  }
563  }
564  result *= xMult * yMult * zMult;
565 
566  return result;
567 }
568 
569 
570 }
Real GetYSpacing() const
Real GetYMax() const
Real GetXSpacing() const
Real GetZMax() const
int GetZBound() const
Real GetYMin() const
#define LogAssert(condition, message)
Definition: GteLogger.h:86
Real GetXMin() const
Real GetZSpacing() const
GLint GLenum GLint x
Definition: glcorearb.h:404
int GetYBound() const
Real const * GetF() const
int GetQuantity() const
Real operator()(Real x, Real y, Real z) const
GLenum GLenum GLsizei void * row
Definition: glext.h:2725
int GetXBound() const
Real GetZMin() const
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:843
Real GetXMax() const
GLuint64EXT * result
Definition: glext.h:10003
GLint y
Definition: glcorearb.h:98
IntpTricubic3(int xBound, int yBound, int zBound, Real xMin, Real xSpacing, Real yMin, Real ySpacing, Real zMin, Real zSpacing, Real const *F, bool catmullRom)


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