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