Go to the documentation of this file.00001 #ifndef OPENTISSUE_CORE_MATH_INTERPOLATION_INTERPOLATION_SPLINE_INTERPOLATOR_H
00002 #define OPENTISSUE_CORE_MATH_INTERPOLATION_INTERPOLATION_SPLINE_INTERPOLATOR_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/math/interpolation/interpolation_base_interpolator.h>
00013 #include <OpenTissue/core/math/math_constants.h>
00014
00015
00016 namespace OpenTissue
00017 {
00018
00019 namespace interpolation
00020 {
00021
00028 template<typename real_type_>
00029 class SplineInterpolator : public BaseInterpolator<SplineInterpolator<real_type_>, real_type_ >
00030 {
00031 public:
00032
00033 typedef typename real_type_ real_type;
00034
00035 private:
00036
00037 real_type * m_y2;
00038 real_type * m_u;
00039 int m_n;
00040 int m_N;
00041 real_type * m_xa;
00042 real_type * m_y2a;
00043 real_type * m_ya;
00044
00045 public:
00046
00047
00048 SplineInterpolator()
00049 :m_y2(0)
00050 ,m_u(0)
00051 ,m_n(0)
00052 ,m_N(0)
00053 ,m_xa(0)
00054 ,m_y2a(0)
00055 ,m_ya(0)
00056 {}
00057
00058 ~SplineInterpolator()
00059 {
00060 if(m_y2)
00061 delete [] m_y2;
00062 if(m_u)
00063 delete [] m_u;
00064 }
00065
00073 void set_tableau(real_type * x,real_type * y,int cnt)
00074 {
00075 set_tableau(x,y,cnt, math::detail::highest<real_type>(), math::detail::highest<real_type>() );
00076 }
00077
00081 void set_tableau(real_type * x,real_type * y,int cnt,real_type yDerivStart,real_type yDerivEnd)
00082 {
00083
00084 if(cnt>m_N)
00085 {
00086 m_N = cnt;
00087 if(m_y2)
00088 delete [] m_y2;
00089 m_y2 = new real_type[m_N];
00090 if(m_u)
00091 delete [] m_u;
00092 m_u = new real_type[m_N];
00093 }
00094 this ->m_n = cnt;
00095
00096 m_xa = x;
00097 m_ya = y;
00098 m_y2a = m_y2;
00099
00100
00101 real_type p,qn,sig,un;
00102
00103 if(yDerivStart >= math::detail::highest<real_type>() )
00104 m_y2[0]=m_u[0]=static_cast<real_type>(0.0);
00105 else
00106 {
00107 m_y2[0] = static_cast<real_type>(-0.5);
00108 m_u[0]=(3.0f/(x[1]-x[0]))*((y[1]-y[0])/(x[1]-x[0])-yDerivStart);
00109 }
00110 for(int i=1;i<=m_n-2;++i)
00111 {
00112 sig = (x[i]-x[i-1])/(x[i+1]-x[i-1]);
00113 p = sig*m_y2[i-1] + 2.0;
00114 m_y2[i] = (sig-1.0)/p;
00115 m_u[i] =(y[i+1]-y[i])/(x[i+1]-x[i]) - (y[i]-y[i-1])/(x[i]-x[i-1]);
00116 m_u[i] =(6.0f*m_u[i]/(x[i+1]-x[i-1])-sig*m_u[i-1])/p;
00117 }
00118 if(yDerivEnd >= math::detail::highest<real_type>() )
00119 qn=un=static_cast<real_type>(0.0);
00120 else
00121 {
00122 qn= static_cast<real_type>(0.5);
00123 un=(3.0f/(x[m_n-1]-x[m_n-2]))*(yDerivEnd-(y[m_n-1]-y[m_n-2])/(x[m_n-1]-x[m_n-2]));
00124 }
00125 m_y2[m_n-1]=(un-qn*m_u[m_n-2])/(qn*m_y2[m_n-2]+1.0);
00126
00127 for(int k=m_n-2;k>=0;--k)
00128 m_y2[k] =m_y2[k]*m_y2[k+1]+m_u[k];
00129 }
00130
00140 real_type get_value(real_type const & x)
00141 {
00142 int klo,khi,k;
00143 real_type h,b,a;
00144
00145 klo=0;
00146 khi=m_n-1;
00147
00148 while (khi-klo > 1)
00149 {
00150 k=(khi+klo) >> 1;
00151 if (m_xa[k] > x) khi=k;
00152 else klo=k;
00153 }
00154 h=m_xa[khi]-m_xa[klo];
00155
00156 if(std::fabs(h)> static_cast<real_type>(0.0) )
00157 {
00158 std::cerr << "SplineInterpolator::get_value(...): Bad x-array input in method set_tableau()" << std::endl;
00159 }
00160 a=(m_xa[khi]-x)/h;
00161 b=(x-m_xa[klo])/h;
00162
00163 real_type y = a*m_ya[klo]+b*m_ya[khi]+((a*a*a-a)*m_y2a[klo]+(b*b*b-b)*m_y2a[khi])*(h*h)/6.0;
00164
00165 return y;
00166 }
00167
00173 real_type get_error_estimate()const { return static_cast<real_type>(0.0);}
00174
00175 };
00176
00177 }
00178
00179 }
00180
00181
00182 #endif