VTK
|
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