VTK
dox/Imaging/Core/vtkImageInterpolatorInternals.h
Go to the documentation of this file.
00001 /*=========================================================================
00002 
00003   Program:   Visualization Toolkit
00004   Module:    vtkInterpolatorInternals.h
00005 
00006   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
00007   All rights reserved.
00008   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
00009 
00010      This software is distributed WITHOUT ANY WARRANTY; without even
00011      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
00012      PURPOSE.  See the above copyright notice for more information.
00013 
00014 =========================================================================*/
00019 #ifndef __vtkInterpolatorInternals_h
00020 #define __vtkInterpolatorInternals_h
00021 
00022 #include "vtkMath.h"
00023 
00024 // The interpolator info struct
00025 struct vtkInterpolationInfo
00026 {
00027   const void *Pointer;
00028   int Extent[6];
00029   vtkIdType Increments[3];
00030   int ScalarType;
00031   int NumberOfComponents;
00032   int BorderMode;
00033   int InterpolationMode;
00034   void *ExtraInfo;
00035 };
00036 
00037 // The interpolation weights struct
00038 struct vtkInterpolationWeights : public vtkInterpolationInfo
00039 {
00040   vtkIdType *Positions[3];
00041   void *Weights[3];
00042   int WeightExtent[6];
00043   int KernelSize[3];
00044   int WeightType; // VTK_FLOAT or VTK_DOUBLE
00045 
00046   // partial copy contstructor from superclass
00047   vtkInterpolationWeights(const vtkInterpolationInfo &info) :
00048     vtkInterpolationInfo(info) {}
00049 };
00050 
00051 // The internal math functions for the interpolators
00052 struct vtkInterpolationMath
00053 {
00054   // floor with remainder (remainder can be double or float),
00055   // includes a small tolerance for values just under an integer
00056   template<class F>
00057   static int Floor(double x, F &f);
00058 
00059   // round function optimized for various architectures
00060   static int Round(double x);
00061 
00062   // border-handling functions for keeping index a with in bounds b, c
00063   static int Clamp(int a, int b, int c);
00064   static int Wrap(int a, int b, int c);
00065   static int Mirror(int a, int b, int c);
00066 };
00067 
00068 //--------------------------------------------------------------------------
00069 // The 'floor' function is slow, so we want to do an integer
00070 // cast but keep the "floor" behavior of always rounding down,
00071 // rather than truncating, i.e. we want -0.6 to become -1.
00072 // The easiest way to do this is to add a large value in
00073 // order to make the value "unsigned", then cast to int, and
00074 // then subtract off the large value.
00075 
00076 // On the old i386 architecture even a cast to int is very
00077 // expensive because it requires changing the rounding mode
00078 // on the FPU.  So we use a bit-trick similar to the one
00079 // described at http://www.stereopsis.com/FPU.html
00080 
00081 #if defined ia64 || defined __ia64__ || defined _M_IA64
00082 #define VTK_INTERPOLATE_64BIT_FLOOR
00083 #elif defined __ppc64__ || defined __x86_64__ || defined _M_X64
00084 #define VTK_INTERPOLATE_64BIT_FLOOR
00085 #elif defined __ppc__ || defined sparc || defined mips
00086 #define VTK_INTERPOLATE_32BIT_FLOOR
00087 #elif defined i386 || defined _M_IX86
00088 #define VTK_INTERPOLATE_I386_FLOOR
00089 #endif
00090 
00091 // We add a tolerance of 2^-17 (around 7.6e-6) so that float
00092 // values that are just less than the closest integer are
00093 // rounded up.  This adds robustness against rounding errors.
00094 
00095 #define VTK_INTERPOLATE_FLOOR_TOL 7.62939453125e-06
00096 
00097 template<class F>
00098 inline int vtkInterpolationMath::Floor(double x, F &f)
00099 {
00100 #if defined VTK_INTERPOLATE_64BIT_FLOOR
00101   x += (103079215104.0 + VTK_INTERPOLATE_FLOOR_TOL);
00102 #ifdef VTK_TYPE_USE___INT64
00103   __int64 i = static_cast<__int64>(x);
00104   f = x - i;
00105   return static_cast<int>(i - 103079215104i64);
00106 #else
00107   long long i = static_cast<long long>(x);
00108   f = x - i;
00109   return static_cast<int>(i - 103079215104LL);
00110 #endif
00111 #elif defined VTK_INTERPOLATE_32BIT_FLOOR
00112   x += (2147483648.0 + VTK_INTERPOLATE_FLOOR_TOL);
00113   unsigned int i = static_cast<unsigned int>(x);
00114   f = x - i;
00115   return static_cast<int>(i - 2147483648U);
00116 #elif defined VTK_INTERPOLATE_I386_FLOOR
00117   union { double d; unsigned short s[4]; unsigned int i[2]; } dual;
00118   dual.d = x + 103079215104.0;  // (2**(52-16))*1.5
00119   f = dual.s[0]*0.0000152587890625; // 2**(-16)
00120   return static_cast<int>((dual.i[1]<<16)|((dual.i[0])>>16));
00121 #else
00122   x += VTK_INTERPOLATE_FLOOR_TOL;
00123   int i = vtkMath::Floor(x);
00124   f = x - i;
00125   return i;
00126 #endif
00127 }
00128 
00129 
00130 inline int vtkInterpolationMath::Round(double x)
00131 {
00132 #if defined VTK_INTERPOLATE_64BIT_FLOOR
00133   x += (103079215104.5 + VTK_INTERPOLATE_FLOOR_TOL);
00134 #ifdef VTK_TYPE_USE___INT64
00135   __int64 i = static_cast<__int64>(x);
00136   return static_cast<int>(i - 103079215104i64);
00137 #else
00138   long long i = static_cast<long long>(x);
00139   return static_cast<int>(i - 103079215104LL);
00140 #endif
00141 #elif defined VTK_INTERPOLATE_32BIT_FLOOR
00142   x += (2147483648.5 + VTK_INTERPOLATE_FLOOR_TOL);
00143   unsigned int i = static_cast<unsigned int>(x);
00144   return static_cast<int>(i - 2147483648U);
00145 #elif defined VTK_INTERPOLATE_I386_FLOOR
00146   union { double d; unsigned int i[2]; } dual;
00147   dual.d = x + 103079215104.5;  // (2**(52-16))*1.5
00148   return static_cast<int>((dual.i[1]<<16)|((dual.i[0])>>16));
00149 #else
00150   return vtkMath::Floor(x + (0.5 + VTK_INTERPOLATE_FLOOR_TOL));
00151 #endif
00152 }
00153 
00154 //----------------------------------------------------------------------------
00155 // Perform a clamp to limit an index to [b, c] and subtract b.
00156 
00157 inline int vtkInterpolationMath::Clamp(int a, int b, int c)
00158 {
00159   a = (a <= c ? a : c);
00160   a -= b;
00161   a = (a >= 0 ? a : 0);
00162   return a;
00163 }
00164 
00165 //----------------------------------------------------------------------------
00166 // Perform a wrap to limit an index to [b, c] and subtract b.
00167 
00168 inline int vtkInterpolationMath::Wrap(int a, int b, int c)
00169 {
00170   int range = c - b + 1;
00171   a -= b;
00172   a %= range;
00173   // required for some % implementations
00174   a = (a >= 0 ? a : a + range);
00175   return a;
00176 }
00177 
00178 //----------------------------------------------------------------------------
00179 // Perform a mirror to limit an index to [b, c] and subtract b.
00180 
00181 inline int vtkInterpolationMath::Mirror(int a, int b, int c)
00182 {
00183 #ifndef VTK_IMAGE_BORDER_LEGACY_MIRROR
00184   int range = c - b;
00185   int ifzero = (range == 0);
00186   int range2 = 2*range + ifzero;
00187   a -= b;
00188   a = (a >= 0 ? a : -a);
00189   a %= range2;
00190   a = (a <= range ? a : range2 - a);
00191   return a;
00192 #else
00193   int range = c - b + 1;
00194   int range2 = 2*range;
00195   a -= b;
00196   a = (a >= 0 ? a : -a - 1);
00197   a %= range2;
00198   a = (a < range ? a : range2 - a - 1);
00199   return a;
00200 #endif
00201 }
00202 
00203 #endif
00204 // VTK-HeaderTest-Exclude: vtkImageInterpolatorInternals.h