CubicFuncSpline.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. #include "CubicFuncSpline.h"
  2. USING_NS_BF;
  3. CubicFuncSpline::CubicFuncSpline()
  4. {
  5. lagpoly = NULL;
  6. intpoly = NULL;
  7. slopes = NULL;
  8. }
  9. CubicFuncSpline::~CubicFuncSpline()
  10. {
  11. delete lagpoly;
  12. delete intpoly;
  13. delete slopes;
  14. }
  15. void CubicFuncSpline::AddPt(float x, float y)
  16. {
  17. delete lagpoly;
  18. delete intpoly;
  19. delete slopes;
  20. lagpoly = NULL;
  21. intpoly = NULL;
  22. slopes = NULL;
  23. mInputPoints.push_back(PointF(x, y));
  24. }
  25. int CubicFuncSpline::GetLength()
  26. {
  27. return (int) mInputPoints.size();
  28. }
  29. void CubicFuncSpline::Lagrange()
  30. {
  31. int nPts = (int) mInputPoints.size();
  32. int i, j, jj, k;
  33. for( j = 0; j < nPts; j++ )
  34. intpoly[j] = 0.0;
  35. for( i = 0; i < nPts; i++ )
  36. {
  37. lagpoly[i+0*nPts] = 1.0;
  38. float fac = mInputPoints[i].y;
  39. j = 0;
  40. for( k = 0; k < nPts; k++ )
  41. {
  42. if( k == i )
  43. continue;
  44. lagpoly[i+(j+1)*nPts] = lagpoly[i+j*nPts];
  45. for( jj = j; jj > 0; jj-- )
  46. lagpoly[i+jj*nPts] = lagpoly[i+(jj-1)*nPts] - lagpoly[i+jj*nPts]*mInputPoints[k].x;
  47. lagpoly[i+0*nPts] *= -mInputPoints[k].x;
  48. j++;
  49. fac /= ( mInputPoints[i].x - mInputPoints[k].x );
  50. }
  51. for( j = 0; j < nPts; j++ )
  52. lagpoly[i+j*nPts] *= fac;
  53. for( j = 0; j < nPts; j++ )
  54. intpoly[j] += lagpoly[i+j*nPts];
  55. }
  56. }
  57. void CubicFuncSpline::ComputeSplineSlopes()
  58. {
  59. int n = (int) mInputPoints.size() - 1;
  60. int i;
  61. float *h = new float[n];
  62. float *hinv = new float[n];
  63. float *g = new float[n];
  64. float *a = new float[n+1];
  65. float *b = new float[n+1];
  66. float fac;
  67. for( i = 0; i < n; i++ )
  68. {
  69. h[i] = mInputPoints[i+1].x - mInputPoints[i].x;
  70. hinv[i] = 1.0f / h[i];
  71. g[i] = 3 * ( mInputPoints[i+1].y-mInputPoints[i].y ) * hinv[i] * hinv[i];
  72. }
  73. a[0] = 2 * hinv[0];
  74. b[0] = g[0];
  75. for( i = 1; i <= n; i++ )
  76. {
  77. fac = hinv[i-1]/a[i-1];
  78. a[i] = (2-fac) * hinv[i-1];
  79. b[i] = g[i-1] - fac * b[i-1];
  80. if( i < n )
  81. {
  82. a[i] += 2 * hinv[i];
  83. b[i] += g[i];
  84. }
  85. }
  86. slopes[n] = b[n] / a[n];
  87. for( i = n-1; i >= 0; i-- )
  88. slopes[i] = ( b[i] - hinv[i] * slopes[i+1] ) / a[i];
  89. delete [] h;
  90. delete [] hinv;
  91. delete [] g;
  92. delete [] a;
  93. delete [] b;
  94. }
  95. void CubicFuncSpline::Calculate()
  96. {
  97. int n = (int) mInputPoints.size() - 1;
  98. slopes = new float[n+1];
  99. intpoly = new float[n+1];
  100. lagpoly = new float[(n+1)*(n+1)];
  101. Lagrange();
  102. ComputeSplineSlopes();
  103. }
  104. float CubicFuncSpline::Evaluate(float x)
  105. {
  106. if (lagpoly == NULL)
  107. Calculate();
  108. int idx = (int) 0;
  109. while ((idx < (int) mInputPoints.size()) && (x > mInputPoints[idx].x))
  110. idx++;
  111. if ((idx == mInputPoints.size()) || (idx == 0))
  112. {
  113. // Past end - extrapolate
  114. if (idx == mInputPoints.size())
  115. idx--;
  116. float s1 = slopes[idx];
  117. return mInputPoints[idx].y + (x - mInputPoints[idx].x) * s1;
  118. }
  119. float x0 = mInputPoints[idx-1].x;
  120. float x1 = mInputPoints[idx].x;
  121. float y0 = mInputPoints[idx-1].y;
  122. float y1 = mInputPoints[idx].y;
  123. float s0 = slopes[idx-1];
  124. float s1 = slopes[idx];
  125. float h = x1 - x0;
  126. float t = (x-x0)/h;
  127. float u = 1 - t;
  128. return u * u * ( y0 * ( 2 * t + 1 ) + s0 * h * t )
  129. + t * t * ( y1 * ( 3 - 2 * t ) - s1 * h * u );
  130. }
  131. ///
  132. CubicUnitFuncSpline::CubicUnitFuncSpline()
  133. {
  134. lagpoly = NULL;
  135. intpoly = NULL;
  136. slopes = NULL;
  137. }
  138. CubicUnitFuncSpline::~CubicUnitFuncSpline()
  139. {
  140. delete lagpoly;
  141. delete intpoly;
  142. delete slopes;
  143. }
  144. void CubicUnitFuncSpline::AddPt(float y)
  145. {
  146. delete lagpoly;
  147. delete intpoly;
  148. delete slopes;
  149. lagpoly = NULL;
  150. intpoly = NULL;
  151. slopes = NULL;
  152. mInputPoints.push_back(y);
  153. }
  154. int CubicUnitFuncSpline::GetLength()
  155. {
  156. return (int) mInputPoints.size();
  157. }
  158. void CubicUnitFuncSpline::Lagrange()
  159. {
  160. int nPts = (int) mInputPoints.size();
  161. int i, j, jj, k;
  162. for( j = 0; j < nPts; j++ )
  163. intpoly[j] = 0.0;
  164. for( i = 0; i < nPts; i++ )
  165. {
  166. lagpoly[i+0*nPts] = 1.0;
  167. float fac = mInputPoints[i];
  168. j = 0;
  169. for( k = 0; k < nPts; k++ )
  170. {
  171. if( k == i )
  172. continue;
  173. lagpoly[i+(j+1)*nPts] = lagpoly[i+j*nPts];
  174. for( jj = j; jj > 0; jj-- )
  175. lagpoly[i+jj*nPts] = lagpoly[i+(jj-1)*nPts] - lagpoly[i+jj*nPts]*k;
  176. lagpoly[i+0*nPts] *= -k;
  177. j++;
  178. fac /= ( i - k);
  179. }
  180. for( j = 0; j < nPts; j++ )
  181. lagpoly[i+j*nPts] *= fac;
  182. for( j = 0; j < nPts; j++ )
  183. intpoly[j] += lagpoly[i+j*nPts];
  184. }
  185. }
  186. void CubicUnitFuncSpline::ComputeSplineSlopes()
  187. {
  188. int n = (int) mInputPoints.size() - 1;
  189. int i;
  190. float *h = new float[n];
  191. float *hinv = new float[n];
  192. float *g = new float[n];
  193. float *a = new float[n+1];
  194. float *b = new float[n+1];
  195. float fac;
  196. for( i = 0; i < n; i++ )
  197. {
  198. h[i] = 1;
  199. hinv[i] = 1.0f / h[i];
  200. g[i] = 3 * ( mInputPoints[i+1] - mInputPoints[i] ) * hinv[i] * hinv[i];
  201. }
  202. a[0] = 2 * hinv[0];
  203. b[0] = g[0];
  204. for( i = 1; i <= n; i++ )
  205. {
  206. fac = hinv[i-1]/a[i-1];
  207. a[i] = (2-fac) * hinv[i-1];
  208. b[i] = g[i-1] - fac * b[i-1];
  209. if( i < n )
  210. {
  211. a[i] += 2 * hinv[i];
  212. b[i] += g[i];
  213. }
  214. }
  215. slopes[n] = b[n] / a[n];
  216. for( i = n-1; i >= 0; i-- )
  217. slopes[i] = ( b[i] - hinv[i] * slopes[i+1] ) / a[i];
  218. delete [] h;
  219. delete [] hinv;
  220. delete [] g;
  221. delete [] a;
  222. delete [] b;
  223. }
  224. void CubicUnitFuncSpline::Calculate()
  225. {
  226. int n = (int) mInputPoints.size() - 1;
  227. slopes = new float[n+1];
  228. intpoly = new float[n+1];
  229. lagpoly = new float[(n+1)*(n+1)];
  230. Lagrange();
  231. ComputeSplineSlopes();
  232. }
  233. float CubicUnitFuncSpline::Evaluate(float x)
  234. {
  235. if (lagpoly == NULL)
  236. Calculate();
  237. int idx = (int) x;
  238. float x0 = (float)idx;
  239. float x1 = (float)idx + 1;
  240. float y0 = mInputPoints[idx];
  241. float y1 = mInputPoints[idx+1];
  242. float s0 = slopes[idx];
  243. float s1 = slopes[idx+1];
  244. float h = x1 - x0;
  245. float t = (x-x0)/h;
  246. float u = 1 - t;
  247. return u * u * ( y0 * ( 2 * t + 1 ) + s0 * h * t )
  248. + t * t * ( y1 * ( 3 - 2 * t ) - s1 * h * u );
  249. }