BSpline.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #include "BSpline.h"
  2. USING_NS_BF;
  3. static void compute_intervals(int *u, int n, int t) // figure out the knots
  4. {
  5. int j;
  6. for (j=0; j<=n+t; j++)
  7. {
  8. if (j<t)
  9. u[j]=0;
  10. else
  11. if ((t<=j) && (j<=n))
  12. u[j]=j-t+1;
  13. else
  14. if (j>n)
  15. u[j]=n-t+2; // if n-t=-2 then we're screwed, everything goes to 0
  16. }
  17. }
  18. BSpline2D::BSpline2D()
  19. {
  20. mUVals = NULL;
  21. }
  22. BSpline2D::~BSpline2D()
  23. {
  24. delete mUVals;
  25. }
  26. void BSpline2D::AddPt(float x, float y)
  27. {
  28. delete mUVals;
  29. mUVals = NULL;
  30. PointF pt;
  31. pt.x = x;
  32. pt.y = y;
  33. mInputPoints.push_back(pt);
  34. }
  35. void BSpline2D::Calculate()
  36. {
  37. int n = (int) mInputPoints.size();
  38. int t = 1;
  39. PointF* control = &mInputPoints[0];
  40. mUVals=new int[n+t+1];
  41. compute_intervals(mUVals, n, t);
  42. //increment=(float) (n-t+2)/(num_output-1); // how much parameter goes up each time
  43. //interval=0;
  44. /*for (output_index=0; output_index<num_output-1; output_index++)
  45. {
  46. compute_point(u, n, t, interval, control, &calcxyz);
  47. output[output_index].x = calcxyz.x;
  48. output[output_index].y = calcxyz.y;
  49. output[output_index].z = calcxyz.z;
  50. interval=interval+increment; // increment our parameter
  51. }
  52. output[num_output-1].x=control[n].x; // put in the last point
  53. output[num_output-1].y=control[n].y;
  54. output[num_output-1].z=control[n].z;
  55. delete u;*/
  56. }
  57. static float blend(int k, int t, int *u, float v) // calculate the blending value
  58. {
  59. float value;
  60. if (t==1) // base case for the recursion
  61. {
  62. if ((u[k]<=v) && (v<u[k+1]))
  63. value=1;
  64. else
  65. value=0;
  66. }
  67. else
  68. {
  69. if ((u[k+t-1]==u[k]) && (u[k+t]==u[k+1])) // check for divide by zero
  70. value = 0;
  71. else
  72. if (u[k+t-1]==u[k]) // if a term's denominator is zero,use just the other
  73. value = (u[k+t] - v) / (u[k+t] - u[k+1]) * blend(k+1, t-1, u, v);
  74. else
  75. if (u[k+t]==u[k+1])
  76. value = (v - u[k]) / (u[k+t-1] - u[k]) * blend(k, t-1, u, v);
  77. else
  78. value = (v - u[k]) / (u[k+t-1] - u[k]) * blend(k, t-1, u, v) +
  79. (u[k+t] - v) / (u[k+t] - u[k+1]) * blend(k+1, t-1, u, v);
  80. }
  81. return value;
  82. }
  83. /*void compute_point(int *u, int n, int t, float v, point *control,
  84. point *output)*/
  85. void BSpline2D::Evaluate(float pct, float* x, float* y)
  86. {
  87. if (mUVals == NULL)
  88. Calculate();
  89. int k;
  90. float temp;
  91. int n = (int) mInputPoints.size();
  92. int t = (int)mInputPoints.size() - 3; // ????
  93. t = 1;
  94. PointF* control = &mInputPoints[0];
  95. // initialize the variables that will hold our outputted point
  96. float oX = 0;
  97. float oY = 0;
  98. for (k=0; k<=n; k++)
  99. {
  100. temp = blend(t,t,mUVals,pct); // same blend is used for each dimension coordinate
  101. oX = oX + (control[k]).x * temp;
  102. oY = oY + (control[k]).y * temp;
  103. }
  104. *x = oX;
  105. *y = oY;
  106. }