Go to the documentation of this file.00001 #ifndef OPENTISSUE_CORE_SPLINE_SPLINE_MAKE_CUBIC_INTERPOLATION_H
00002 #define OPENTISSUE_CORE_SPLINE_SPLINE_MAKE_CUBIC_INTERPOLATION_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/math/math_value_traits.h>
00013 #include <OpenTissue/core/math/math_is_number.h>
00014
00015 #include <OpenTissue/core/spline/spline_nubs.h>
00016 #include <OpenTissue/core/spline/spline_solve_tridiagonal.h>
00017
00018 #include <stdexcept>
00019 #include <cassert>
00020
00021 namespace OpenTissue
00022 {
00023 namespace spline
00024 {
00033 template<typename knot_container, typename point_container>
00034 inline NUBSpline<knot_container, point_container>
00035 make_cubic_interpolation(
00036 knot_container const & U
00037 , point_container const & X
00038 )
00039 {
00040 typedef typename point_container::value_type V;
00041 typedef typename knot_container::value_type T;
00042 typedef OpenTissue::math::ValueTraits<T> value_traits;
00043
00044 int const k = 4;
00045
00046
00047
00048
00049
00050
00051
00052
00053 size_t const n = X.size() + 1u;
00054 size_t const dim = X[0].size();
00055
00056 if( dim <= 0u )
00057 throw std::invalid_argument("can not make a non-positive dimensional spline");
00058
00059 if( U.size() != (n + k + 1u) )
00060 throw std::invalid_argument("Mismatch between dimension of U and X");
00061
00062 point_container P;
00063
00064
00065 P.resize(n-1u);
00066 size_t i;
00067 for(i=0u;i< n-1u;++i)
00068 {
00069 P[i].resize(dim);
00070 }
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 V a(n - 1u);
00087 V b(n - 1u);
00088 V c(n - 1u);
00089
00090 a[0] = value_traits::zero(); b[0] = value_traits::one(); c[0] = value_traits::zero();
00091 a[n-2] = value_traits::zero(); b[n-2] = value_traits::one(); c[n-2] = value_traits::zero();
00092
00093 for(i=1u;i<n-2u;++i)
00094 {
00095 T const & t1 = U[i+1u];
00096 T const & t2 = U[i+2u];
00097 T const & t3 = U[i+3u];
00098 T const & t4 = U[i+4u];
00099 T const & t5 = U[i+5u];
00100
00101 assert( t5 >= t4 || !"make_cubic_interpolation(): invalid knot vector");
00102 assert( t4 >= t3 || !"make_cubic_interpolation(): invalid knot vector");
00103 assert( t3 >= t2 || !"make_cubic_interpolation(): invalid knot vector");
00104 assert( t2 >= t1 || !"make_cubic_interpolation(): invalid knot vector");
00105
00106 a[i] = (t4-t3)*(t4-t3)/(t4-t1);
00107 b[i] = (t3-t1)*(t4-t3)/(t4-t1) + (t5-t3)*(t3-t2)/(t5-t2);
00108 c[i] = (t3-t2)*(t3-t2)/(t5-t2);
00109 a[i] /= (t4-t2);
00110 b[i] /= (t4-t2);
00111 c[i] /= (t4-t2);
00112
00113 assert( is_number( a[i] ) || !"make_cubic_interpolation(): not a number encountered");
00114 assert( is_number( b[i] ) || !"make_cubic_interpolation(): not a number encountered");
00115 assert( is_number( c[i] ) || !"make_cubic_interpolation(): not a number encountered");
00116 }
00117
00118
00119 detail::solve_tridiagonal(a,b,c,P,X,n-1u);
00120
00121
00122 P.insert(P.begin(), 1, X[0]);
00123
00124
00125 P.push_back(X[n-2u]);
00126
00127 return NUBSpline<knot_container, point_container>(k,U,P);
00128 }
00129
00130 }
00131 }
00132
00133
00134 #endif