VTK
vtkImageInterpolatorInternals.h
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Visualization Toolkit
4  Module: vtkInterpolatorInternals.h
5 
6  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7  All rights reserved.
8  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10  This software is distributed WITHOUT ANY WARRANTY; without even
11  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12  PURPOSE. See the above copyright notice for more information.
13 
14 =========================================================================*/
19 #ifndef vtkImageInterpolatorInternals_h
20 #define vtkImageInterpolatorInternals_h
21 
22 #include "vtkMath.h"
23 
24 // The interpolator info struct
26 {
27  const void *Pointer;
28  int Extent[6];
34  void *ExtraInfo;
35 };
36 
37 // The interpolation weights struct
39 {
41  void *Weights[3];
42  int WeightExtent[6];
43  int KernelSize[3];
44  int WeightType; // VTK_FLOAT or VTK_DOUBLE
45 
46  // partial copy contstructor from superclass
48  vtkInterpolationInfo(info) {}
49 };
50 
51 // The internal math functions for the interpolators
53 {
54  // floor with remainder (remainder can be double or float),
55  // includes a small tolerance for values just under an integer
56  template<class F>
57  static int Floor(double x, F &f);
58 
59  // round function optimized for various architectures
60  static int Round(double x);
61 
62  // border-handling functions for keeping index a with in bounds b, c
63  static int Clamp(int a, int b, int c);
64  static int Wrap(int a, int b, int c);
65  static int Mirror(int a, int b, int c);
66 };
67 
68 //--------------------------------------------------------------------------
69 // The 'floor' function is slow, so we want to do an integer
70 // cast but keep the "floor" behavior of always rounding down,
71 // rather than truncating, i.e. we want -0.6 to become -1.
72 // The easiest way to do this is to add a large value in
73 // order to make the value "unsigned", then cast to int, and
74 // then subtract off the large value.
75 
76 // On the old i386 architecture even a cast to int is very
77 // expensive because it requires changing the rounding mode
78 // on the FPU. So we use a bit-trick similar to the one
79 // described at http://www.stereopsis.com/FPU.html
80 
81 #if defined ia64 || defined __ia64__ || defined _M_IA64
82 #define VTK_INTERPOLATE_64BIT_FLOOR
83 #elif defined __ppc64__ || defined __x86_64__ || defined _M_X64
84 #define VTK_INTERPOLATE_64BIT_FLOOR
85 #elif defined __ppc__ || defined sparc || defined mips
86 #define VTK_INTERPOLATE_32BIT_FLOOR
87 #elif defined i386 || defined _M_IX86
88 #define VTK_INTERPOLATE_I386_FLOOR
89 #endif
90 
91 // We add a tolerance of 2^-17 (around 7.6e-6) so that float
92 // values that are just less than the closest integer are
93 // rounded up. This adds robustness against rounding errors.
94 
95 #define VTK_INTERPOLATE_FLOOR_TOL 7.62939453125e-06
96 
97 template<class F>
98 inline int vtkInterpolationMath::Floor(double x, F &f)
99 {
100 #if defined VTK_INTERPOLATE_64BIT_FLOOR
101  x += (103079215104.0 + VTK_INTERPOLATE_FLOOR_TOL);
102  long long i = static_cast<long long>(x);
103  f = static_cast<F>(x - i);
104  return static_cast<int>(i - 103079215104LL);
105 #elif defined VTK_INTERPOLATE_32BIT_FLOOR
106  x += (2147483648.0 + VTK_INTERPOLATE_FLOOR_TOL);
107  unsigned int i = static_cast<unsigned int>(x);
108  f = x - i;
109  return static_cast<int>(i - 2147483648U);
110 #elif defined VTK_INTERPOLATE_I386_FLOOR
111  union { double d; unsigned short s[4]; unsigned int i[2]; } dual;
112  dual.d = x + 103079215104.0; // (2**(52-16))*1.5
113  f = dual.s[0]*0.0000152587890625; // 2**(-16)
114  return static_cast<int>((dual.i[1]<<16)|((dual.i[0])>>16));
115 #else
117  int i = vtkMath::Floor(x);
118  f = x - i;
119  return i;
120 #endif
121 }
122 
123 
124 inline int vtkInterpolationMath::Round(double x)
125 {
126 #if defined VTK_INTERPOLATE_64BIT_FLOOR
127  x += (103079215104.5 + VTK_INTERPOLATE_FLOOR_TOL);
128  long long i = static_cast<long long>(x);
129  return static_cast<int>(i - 103079215104LL);
130 #elif defined VTK_INTERPOLATE_32BIT_FLOOR
131  x += (2147483648.5 + VTK_INTERPOLATE_FLOOR_TOL);
132  unsigned int i = static_cast<unsigned int>(x);
133  return static_cast<int>(i - 2147483648U);
134 #elif defined VTK_INTERPOLATE_I386_FLOOR
135  union { double d; unsigned int i[2]; } dual;
136  dual.d = x + 103079215104.5; // (2**(52-16))*1.5
137  return static_cast<int>((dual.i[1]<<16)|((dual.i[0])>>16));
138 #else
139  return vtkMath::Floor(x + (0.5 + VTK_INTERPOLATE_FLOOR_TOL));
140 #endif
141 }
142 
143 //----------------------------------------------------------------------------
144 // Perform a clamp to limit an index to [b, c] and subtract b.
145 
146 inline int vtkInterpolationMath::Clamp(int a, int b, int c)
147 {
148  a = (a <= c ? a : c);
149  a -= b;
150  a = (a >= 0 ? a : 0);
151  return a;
152 }
153 
154 //----------------------------------------------------------------------------
155 // Perform a wrap to limit an index to [b, c] and subtract b.
156 
157 inline int vtkInterpolationMath::Wrap(int a, int b, int c)
158 {
159  int range = c - b + 1;
160  a -= b;
161  a %= range;
162  // required for some % implementations
163  a = (a >= 0 ? a : a + range);
164  return a;
165 }
166 
167 //----------------------------------------------------------------------------
168 // Perform a mirror to limit an index to [b, c] and subtract b.
169 
170 inline int vtkInterpolationMath::Mirror(int a, int b, int c)
171 {
172 #ifndef VTK_IMAGE_BORDER_LEGACY_MIRROR
173  int range = c - b;
174  int ifzero = (range == 0);
175  int range2 = 2*range + ifzero;
176  a -= b;
177  a = (a >= 0 ? a : -a);
178  a %= range2;
179  a = (a <= range ? a : range2 - a);
180  return a;
181 #else
182  int range = c - b + 1;
183  int range2 = 2*range;
184  a -= b;
185  a = (a >= 0 ? a : -a - 1);
186  a %= range2;
187  a = (a < range ? a : range2 - a - 1);
188  return a;
189 #endif
190 }
191 
192 #endif
193 // VTK-HeaderTest-Exclude: vtkImageInterpolatorInternals.h
static int Mirror(int a, int b, int c)
static int Clamp(int a, int b, int c)
static int Wrap(int a, int b, int c)
int vtkIdType
Definition: vtkType.h:247
static int Floor(double x)
Definition: vtkMath.h:1029
static int Floor(double x, F &f)
#define VTK_INTERPOLATE_FLOOR_TOL
vtkInterpolationWeights(const vtkInterpolationInfo &info)