00001 #ifndef OPENTISSUE_CORE_SPLINE_SPLINE_COMPUTE_BASIS_DERIVATIVES_H
00002 #define OPENTISSUE_CORE_SPLINE_SPLINE_COMPUTE_BASIS_DERIVATIVES_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/math/math_value_traits.h>
00013
00014 #include <OpenTissue/core/spline/spline_compute_knot_span.h>
00015 #include <OpenTissue/core/spline/spline_initialize_m_table.h>
00016
00017 #include <stdexcept>
00018
00019 namespace OpenTissue
00020 {
00021 namespace spline
00022 {
00023 namespace detail
00024 {
00042 template<typename knot_container, typename matrix_type>
00043 inline void compute_basis_derivatives(
00044 typename knot_container::value_type const & u
00045 , int J
00046 , int const & k
00047 , knot_container const & U
00048 , matrix_type & dQ
00049 )
00050 {
00051 using std::min;
00052 using std::fabs;
00053
00054 typedef typename knot_container::value_type T;
00055 typedef OpenTissue::math::ValueTraits<T> value_traits;
00056
00057 if(J<1)
00058 throw std::invalid_argument( "The derivative must be at least of first-order" );
00059
00060 if(k<1)
00061 throw std::invalid_argument( "order must be greater than zero" );
00062
00063 if( U.size() < 2u*k)
00064 throw std::invalid_argument( "knot vector did not have enough entries" );
00065
00066 if( u < U[0] )
00067 throw std::invalid_argument( "u-parameter was out of lower bound" );
00068
00069 if( u > U[ U.size() - 1 ] )
00070 throw std::invalid_argument( "u-parameter was out of upper bound" );
00071
00072
00073 int const i = compute_knot_span(u, k, U);
00074
00075
00076 matrix_type M;
00077 initialize_m_table(i,u,k,U,M);
00078
00079
00080 dQ.resize(J+1,k,false);
00081
00082
00083
00084 J = min(J,k-1);
00085
00086
00087
00088
00089 for(int r=0; r<k; ++r)
00090 {
00091 dQ(0,r) = M(r,k-1);
00092 }
00093
00094
00095
00096 matrix_type a(2,k);
00097
00098
00099 for(int r=0; r<=k-1; ++r)
00100 {
00101 int s1 = 0;
00102 int s2 = 1;
00103 a(0,0) = value_traits::one();
00104
00105
00106 for(int j=1;j<=J;++j)
00107 {
00108 T djN = value_traits::zero();
00109
00110
00111 if(r >= j)
00112 {
00113 if( fabs( M(k-j,r-j) ) > value_traits::zero() )
00114 a(s2,0) = a(s1,0) / M(k-j,r-j);
00115 else
00116 a(s2,0) = value_traits::zero();
00117
00118 djN += a(s2,0) * M(r-j,k-j-1);
00119 }
00120
00121
00122 int pMin,pMax;
00123
00124 if((r + 1) >= j)
00125 {
00126 pMin = 1;
00127 }
00128 else
00129 {
00130 pMin = j-r;
00131 }
00132
00133 if(r <= (k-j))
00134 {
00135 pMax = j - 1;
00136 }
00137 else
00138 {
00139 pMax = k - 1 - r;
00140 }
00141
00142 for(int p=pMin; p<=pMax; ++p)
00143 {
00144 if( fabs( M(k-j,r-j+p) ) > value_traits::zero() )
00145 a(s2,p) = (a(s1,p)-a(s1,p-1)) / M(k-j,r-j+p);
00146 else
00147 a(s2,p) = value_traits::zero();
00148
00149 djN += a(s2,p)*M(r-j+p,k-j-1);
00150 }
00151
00152
00153 if(r <= (k-1-j))
00154 {
00155 if( fabs( M(k-j,r) ) > value_traits::zero() )
00156 a(s2,j) = - a(s1,j-1) / M(k-j,r);
00157 else
00158 a(s2,j) = value_traits::zero();
00159
00160 djN += a(s2,j) * M(r,k-j-1);
00161 }
00162
00163 dQ(j,r) = djN;
00164
00165
00166
00167
00168
00169 int tmp = s1;
00170 s1 = s2;
00171 s2 = tmp;
00172 }
00173 }
00174
00175
00176 T factor = k-1;
00177 for(int j=1;j<=J;++j)
00178 {
00179 for(int r=0;r<k;++r)
00180 {
00181 dQ(j,r) = factor * dQ(j,r);
00182 }
00183 factor = factor * (k-1-j);
00184 }
00185 }
00186
00187 }
00188 }
00189 }
00190
00191
00192 #endif
00193