|
STK++ 1.0
|
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