STK++ 1.0
STK_BSplineCoefficients.cpp
Go to the documentation of this file.
00001 /*--------------------------------------------------------------------*/
00002 /*     Copyright (C) 2004-2010  Serge Iovleff
00003 
00004  This program is free software; you can redistribute it and/or modify
00005  it under the terms of the GNU Lesser General Public License as
00006  published by the Free Software Foundation; either version 2 of the
00007  License, or (at your option) any later version.
00008 
00009  This program is distributed in the hope that it will be useful,
00010  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  GNU Lesser General Public License for more details.
00013 
00014  You should have received a copy of the GNU Lesser General Public
00015  License along with this program; if not, write to the
00016  Free Software Foundation, Inc.,
00017  59 Temple Place,
00018  Suite 330,
00019  Boston, MA 02111-1307
00020  USA
00021 
00022  Contact : Serge.Iovleff@stkpp.org
00023  */
00024 
00025 /*
00026  * Project:  stkpp::Regress
00027  * created on: 25 juin 2010
00028  * Purpose:  implement the BSplineCoefficients class.
00029  * Author:   iovleff, serge.iovleff@stkpp.org
00030  **/
00031 
00036 #include "../include/STK_BSplineCoefficients.h"
00037 #include "../../DManager/include/STK_HeapSort.h"
00038 #include "../../STKernel/include/STK_String_Util.h"
00039 
00040 #ifdef STK_VERBOSE
00041 #include "../../Arrays/include/STK_Display2D.h"
00042 #endif
00043 
00044 
00045 namespace STK
00046 {
00047 /* convert a String to a TypeReduction.
00048  *  @param type the type of reduction we want to define
00049  *  @return the TypeReduction represented by the String @c type. if the string
00050  *  does not match any known name, the @c unknown_ type is returned.
00051  **/
00052 BSplineCoefficients::KnotsPosition BSplineCoefficients::StringToKnotsPosition( String const& type)
00053 {
00054   if (toUpperString(type) == toUpperString(_T("uniform")))  return uniform_;
00055   if (toUpperString(type) == toUpperString(_T("periodic"))) return periodic_;
00056   if (toUpperString(type) == toUpperString(_T("density"))) return density_;
00057   return unknown_;
00058 }
00059 
00060 /* convert a TypeReduction to a String.
00061  *  @param type the type of reduction we want to convert
00062  *  @return the string associated to this type.
00063  **/
00064 String BSplineCoefficients::KnotsPositionToString( KnotsPosition const& type)
00065 {
00066   if (type == uniform_)  return String(_T("uniform"));
00067   if (type == periodic_) return String(_T("periodic"));
00068   if (type == density_) return String(_T("density"));
00069   return String(_T("unknown"));
00070 }
00071 
00072 /* constructor */
00073 BSplineCoefficients::BSplineCoefficients( Vector const* p_data
00074                                         , Integer const& nbControlPoints
00075                                         , Integer const& degree
00076                                         , const KnotsPosition& position
00077                                         )
00078                                         : p_data_(p_data)
00079                                         , nbKnots_(nbControlPoints + degree +1)
00080                                         , lastKnot_(nbKnots_-1)
00081                                         , nbControlPoints_(nbControlPoints)
00082                                         , lastControlPoint_(nbControlPoints_-1)
00083                                         , degree_(degree)
00084                                         , position_(position)
00085                                         , knots_(Range(0,lastKnot_))
00086                                         , coefficients_(p_data->range(), Range(0,lastControlPoint_), 0.0)
00087                                         , minValue_( Arithmetic<Real>::max())
00088                                         , maxValue_(-Arithmetic<Real>::max())
00089 {
00090 }
00091 
00092 /* constructor */
00093 BSplineCoefficients::BSplineCoefficients( Vector const& data
00094                                         , Integer const& nbControlPoints
00095                                         , Integer const& degree
00096                                         , const KnotsPosition& position
00097                                         )
00098                                         : p_data_(&data)
00099                                         , nbKnots_(nbControlPoints + degree +1)
00100                                         , lastKnot_(nbKnots_-1)
00101                                         , nbControlPoints_(nbControlPoints)
00102                                         , lastControlPoint_(nbControlPoints_-1)
00103                                         , degree_(degree)
00104                                         , position_(position)
00105                                         , knots_(Range(0,lastKnot_))
00106                                         , coefficients_(p_data_->range(), Range(0,lastControlPoint_), 0.0)
00107                                         , minValue_( Arithmetic<Real>::max())
00108                                         , maxValue_(-Arithmetic<Real>::max())
00109 {}
00110 
00111 // destructor
00112 BSplineCoefficients::~BSplineCoefficients() {}
00113 
00115 void BSplineCoefficients::run()
00116 {
00117   computeKnots();
00118   computeCoefficients();
00119 }
00120 
00121 
00122 /*
00123  *  run the computations for the given value.
00124  *  @param p_data the input data values
00125  **/
00126 void BSplineCoefficients::setData( Vector const* p_data
00127                                  , Integer const& nbControlPoints
00128                                  , Integer const& degree
00129                                  , KnotsPosition const& position
00130                                  )
00131 {
00132   // set data
00133   p_data_ = p_data;
00134   // resize coeficients
00135   coefficients_.resize(p_data->range(), Range(0, lastControlPoint_));
00136   // initialize array of coefficient
00137   coefficients_ = 0.0;
00138 }
00139 
00140 /* compute the knots of the B-Spline curves.*/
00141 void BSplineCoefficients::computeKnots()
00142 {
00143   // get dimensions
00144   Integer first = p_data_->first(), last = p_data_->last();
00145   // compute min value
00146   for (Integer i=first; i<= last; i++)
00147   {
00148     minValue_ = min(minValue_, (*p_data_)[i]);
00149     maxValue_ = max(maxValue_, (*p_data_)[i]);
00150   }
00151   // if all value are equals, all the knots are equals to this value
00152   if (minValue_ == maxValue_)
00153   {
00154     knots_ = minValue_;
00155     return;
00156   }
00157   // set knots values
00158   switch (position_)
00159   {
00160     // uniform position
00161     case uniform_:
00162       computeUniformKnots();
00163       break;
00164     // periodic position
00165     case periodic_:
00166       computePeriodicKnots();
00167       break;
00168     // density position
00169     case density_:
00170       computeDensityKnots();
00171       break;
00172       // periodic position
00173     case unknown_:
00174       // check if there exists data
00175       throw runtime_error("Error In BSplineCoefficients::computeKnots():"
00176                                " unknowns positions");
00177       break;
00178   }
00179   // shift knots
00180   Real range = (maxValue_ - minValue_);
00181   for (Integer k = 0; k <= lastKnot_; k++)
00182     knots_[k] = minValue_ + range * knots_[k];
00183 }
00184 
00185 /* compute the position of the uniform knots.*/
00186 void BSplineCoefficients::computeUniformKnots()
00187 {
00188   // compute step
00189   Real step = 1.0/(nbControlPoints_ - degree_);
00190   // set internal knots
00191   const Integer first = degree_ + 1, last = lastControlPoint_;
00192   for (Integer k = first, j = 1; k <= last; j++, k++)
00193     knots_[k] = j * step;
00194   // set external knots
00195   for ( Integer k=0, j = last+1; k < first; j++, k++)
00196   {
00197     knots_[k] = 0;
00198     knots_[j] = 1;
00199   }
00200 }
00201 /* compute the position of the periodic knots.*/
00202 void BSplineCoefficients::computePeriodicKnots()
00203 {
00204   // compute step
00205   Real step = 1.0/(nbControlPoints_ - degree_);
00206   // set knots
00207   for (Integer k = 0, j = -degree_; k <= lastKnot_; j++, k++)
00208     knots_[k] = j * step;
00209 ;
00210 }
00211 /* compute the position of the density knots. */
00212 void BSplineCoefficients::computeDensityKnots()
00213 {
00214   // sorted data
00215   Vector xtri;
00216   // sort the data
00217   heapSort<Real, Vector>(*p_data_, xtri);
00218 
00219   // compute step
00220   Real step = xtri.size()/(Real)lastKnot_;
00221   Integer first = xtri.first(), last = xtri.last();
00222   // set knots
00223   for (Integer k = 0; k < lastKnot_; k++)
00224   {
00225     Integer cell = first + Integer(k* step);
00226     knots_[k] = (xtri[cell] + xtri[cell+1])/2.;
00227   }
00228   // set last knots
00229   knots_[lastKnot_] = (xtri[last-1] + xtri[last])/2.;
00230 }
00231 
00232 /* Compute the coefficients of the B-Spline curves.*/
00233 void BSplineCoefficients::computeCoefficients()
00234 {
00235 #ifdef STK_VERBOSE
00236   stk_cout << _T("BSplineCoefficients::computeCoefficients()\n");
00237 #endif
00238   // get dimensions
00239   Integer first = p_data_->first(), last = p_data_->last();
00240   // compute the coefficients
00241   for (Integer i=first; i<= last; i++)
00242   {
00243     computeCoefficientsRow(i);
00244   }
00245 #ifdef STK_VERBOSE
00246   stk_cout << _T("BSplineCoefficients::computeCoefficients() done\n");
00247 #endif
00248 }
00249 
00250 /* Compute a row of the coefficients
00251  * @param irow index of the row
00252  **/
00253 void BSplineCoefficients::computeCoefficientsRow(Integer const& irow)
00254 {
00255   // get current value
00256   const Real value = (*p_data_)[irow];
00257   // value outside the range of the knots case
00258   if (value <= minValue_)
00259   {
00260     coefficients_(irow, 0) = 1.0;
00261     return;
00262   }
00263   if (value >= maxValue_)
00264   {
00265     coefficients_(irow, lastControlPoint_) = 1.0;
00266     return;
00267   }
00268   // find interval
00269   Integer k, k1;
00270   for (k=0, k1=1; k<lastControlPoint_; k++, k1++)
00271   {
00272     if (value < knots_[k1]) break;
00273   }
00274   // begin recursion
00275   coefficients_(irow, k) = 1.0;
00276   for (Integer d=1; d<=degree_; d++)
00277   {
00278     // right (south-west corner) term only
00279     coefficients_(irow, k-d) = ( (knots_[k1] - value)/(knots_[k1] - knots_[k1-d]) )
00280                                * coefficients_(irow, k1-d);
00281     // compute internal terms
00282     for (Integer i = k1-d; i<k; i++)
00283     {
00284       const Real knots_i = knots_[i], knots_id1 = knots_[i+d+1];
00285       coefficients_(irow, i) = ( (value - knots_i)/(knots_[i+d] - knots_i) )
00286                                * coefficients_(irow, i)
00287                              + ( (knots_id1 - value)/(knots_id1 - knots_[i+1]) )
00288                                * coefficients_(irow, i+1);
00289     }
00290     // left (north-west corner) term only
00291     coefficients_(irow, k) *= (value - knots_[k])/(knots_[k+d] - knots_[k]);
00292   }
00293 }
00294 
00295 } // namespace STK