123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 |
- #include "CubicFuncSpline.h"
- USING_NS_BF;
-
- CubicFuncSpline::CubicFuncSpline()
- {
- lagpoly = NULL;
- intpoly = NULL;
- slopes = NULL;
- }
- CubicFuncSpline::~CubicFuncSpline()
- {
- delete lagpoly;
- delete intpoly;
- delete slopes;
- }
- void CubicFuncSpline::AddPt(float x, float y)
- {
- delete lagpoly;
- delete intpoly;
- delete slopes;
- lagpoly = NULL;
- intpoly = NULL;
- slopes = NULL;
- mInputPoints.push_back(PointF(x, y));
- }
- int CubicFuncSpline::GetLength()
- {
- return (int) mInputPoints.size();
- }
- void CubicFuncSpline::Lagrange()
- {
- int nPts = (int) mInputPoints.size();
- int i, j, jj, k;
- for( j = 0; j < nPts; j++ )
- intpoly[j] = 0.0;
- for( i = 0; i < nPts; i++ )
- {
- lagpoly[i+0*nPts] = 1.0;
- float fac = mInputPoints[i].y;
- j = 0;
- for( k = 0; k < nPts; k++ )
- {
- if( k == i )
- continue;
- lagpoly[i+(j+1)*nPts] = lagpoly[i+j*nPts];
- for( jj = j; jj > 0; jj-- )
- lagpoly[i+jj*nPts] = lagpoly[i+(jj-1)*nPts] - lagpoly[i+jj*nPts]*mInputPoints[k].x;
- lagpoly[i+0*nPts] *= -mInputPoints[k].x;
- j++;
- fac /= ( mInputPoints[i].x - mInputPoints[k].x );
- }
- for( j = 0; j < nPts; j++ )
- lagpoly[i+j*nPts] *= fac;
- for( j = 0; j < nPts; j++ )
- intpoly[j] += lagpoly[i+j*nPts];
- }
- }
- void CubicFuncSpline::ComputeSplineSlopes()
- {
- int n = (int) mInputPoints.size() - 1;
- int i;
- float *h = new float[n];
- float *hinv = new float[n];
- float *g = new float[n];
- float *a = new float[n+1];
- float *b = new float[n+1];
- float fac;
- for( i = 0; i < n; i++ )
- {
- h[i] = mInputPoints[i+1].x - mInputPoints[i].x;
- hinv[i] = 1.0f / h[i];
- g[i] = 3 * ( mInputPoints[i+1].y-mInputPoints[i].y ) * hinv[i] * hinv[i];
- }
- a[0] = 2 * hinv[0];
- b[0] = g[0];
- for( i = 1; i <= n; i++ )
- {
- fac = hinv[i-1]/a[i-1];
- a[i] = (2-fac) * hinv[i-1];
- b[i] = g[i-1] - fac * b[i-1];
- if( i < n )
- {
- a[i] += 2 * hinv[i];
- b[i] += g[i];
- }
- }
- slopes[n] = b[n] / a[n];
- for( i = n-1; i >= 0; i-- )
- slopes[i] = ( b[i] - hinv[i] * slopes[i+1] ) / a[i];
- delete [] h;
- delete [] hinv;
- delete [] g;
- delete [] a;
- delete [] b;
- }
- void CubicFuncSpline::Calculate()
- {
- int n = (int) mInputPoints.size() - 1;
- slopes = new float[n+1];
- intpoly = new float[n+1];
- lagpoly = new float[(n+1)*(n+1)];
- Lagrange();
- ComputeSplineSlopes();
- }
- float CubicFuncSpline::Evaluate(float x)
- {
- if (lagpoly == NULL)
- Calculate();
-
- int idx = (int) 0;
- while ((idx < (int) mInputPoints.size()) && (x > mInputPoints[idx].x))
- idx++;
-
- if ((idx == mInputPoints.size()) || (idx == 0))
- {
- // Past end - extrapolate
- if (idx == mInputPoints.size())
- idx--;
- float s1 = slopes[idx];
- return mInputPoints[idx].y + (x - mInputPoints[idx].x) * s1;
- }
- float x0 = mInputPoints[idx-1].x;
- float x1 = mInputPoints[idx].x;
- float y0 = mInputPoints[idx-1].y;
- float y1 = mInputPoints[idx].y;
- float s0 = slopes[idx-1];
- float s1 = slopes[idx];
- float h = x1 - x0;
- float t = (x-x0)/h;
- float u = 1 - t;
- return u * u * ( y0 * ( 2 * t + 1 ) + s0 * h * t )
- + t * t * ( y1 * ( 3 - 2 * t ) - s1 * h * u );
- }
- ///
- CubicUnitFuncSpline::CubicUnitFuncSpline()
- {
- lagpoly = NULL;
- intpoly = NULL;
- slopes = NULL;
- }
- CubicUnitFuncSpline::~CubicUnitFuncSpline()
- {
- delete lagpoly;
- delete intpoly;
- delete slopes;
- }
- void CubicUnitFuncSpline::AddPt(float y)
- {
- delete lagpoly;
- delete intpoly;
- delete slopes;
- lagpoly = NULL;
- intpoly = NULL;
- slopes = NULL;
- mInputPoints.push_back(y);
- }
- int CubicUnitFuncSpline::GetLength()
- {
- return (int) mInputPoints.size();
- }
- void CubicUnitFuncSpline::Lagrange()
- {
- int nPts = (int) mInputPoints.size();
- int i, j, jj, k;
- for( j = 0; j < nPts; j++ )
- intpoly[j] = 0.0;
- for( i = 0; i < nPts; i++ )
- {
- lagpoly[i+0*nPts] = 1.0;
- float fac = mInputPoints[i];
- j = 0;
- for( k = 0; k < nPts; k++ )
- {
- if( k == i )
- continue;
- lagpoly[i+(j+1)*nPts] = lagpoly[i+j*nPts];
- for( jj = j; jj > 0; jj-- )
- lagpoly[i+jj*nPts] = lagpoly[i+(jj-1)*nPts] - lagpoly[i+jj*nPts]*k;
- lagpoly[i+0*nPts] *= -k;
- j++;
- fac /= ( i - k);
- }
- for( j = 0; j < nPts; j++ )
- lagpoly[i+j*nPts] *= fac;
- for( j = 0; j < nPts; j++ )
- intpoly[j] += lagpoly[i+j*nPts];
- }
- }
- void CubicUnitFuncSpline::ComputeSplineSlopes()
- {
- int n = (int) mInputPoints.size() - 1;
- int i;
- float *h = new float[n];
- float *hinv = new float[n];
- float *g = new float[n];
- float *a = new float[n+1];
- float *b = new float[n+1];
- float fac;
- for( i = 0; i < n; i++ )
- {
- h[i] = 1;
- hinv[i] = 1.0f / h[i];
- g[i] = 3 * ( mInputPoints[i+1] - mInputPoints[i] ) * hinv[i] * hinv[i];
- }
- a[0] = 2 * hinv[0];
- b[0] = g[0];
- for( i = 1; i <= n; i++ )
- {
- fac = hinv[i-1]/a[i-1];
- a[i] = (2-fac) * hinv[i-1];
- b[i] = g[i-1] - fac * b[i-1];
- if( i < n )
- {
- a[i] += 2 * hinv[i];
- b[i] += g[i];
- }
- }
- slopes[n] = b[n] / a[n];
-
- for( i = n-1; i >= 0; i-- )
- slopes[i] = ( b[i] - hinv[i] * slopes[i+1] ) / a[i];
- delete [] h;
- delete [] hinv;
- delete [] g;
- delete [] a;
- delete [] b;
- }
- void CubicUnitFuncSpline::Calculate()
- {
- int n = (int) mInputPoints.size() - 1;
- slopes = new float[n+1];
- intpoly = new float[n+1];
- lagpoly = new float[(n+1)*(n+1)];
- Lagrange();
- ComputeSplineSlopes();
- }
- float CubicUnitFuncSpline::Evaluate(float x)
- {
- if (lagpoly == NULL)
- Calculate();
-
- int idx = (int) x;
-
- float x0 = (float)idx;
- float x1 = (float)idx + 1;
- float y0 = mInputPoints[idx];
- float y1 = mInputPoints[idx+1];
- float s0 = slopes[idx];
- float s1 = slopes[idx+1];
- float h = x1 - x0;
- float t = (x-x0)/h;
- float u = 1 - t;
- return u * u * ( y0 * ( 2 * t + 1 ) + s0 * h * t )
- + t * t * ( y1 * ( 3 - 2 * t ) - s1 * h * u );
- }
|