spline.c
上传用户:zfj3589
上传日期:2022-07-13
资源大小:635k
文件大小:10k
源码类别:

微处理器开发

开发平台:

C/C++

  1. /****************************************************************************************
  2. * 文件名:SPLINE.C
  3. * 功能:二次参数样条曲线生成程序。
  4. * 作者:黄绍斌
  5. * 日期:2003.09.09
  6. ****************************************************************************************/
  7. #include  "config.h"
  8. #include  "math.h"
  9. /****************************************************************************
  10. * 名称:max()
  11. * 功能:求两个整数中最大的整数值。
  12. * 入口参数:a 整数1
  13. *          b 整数2
  14. * 出口参数:返回最大的整数值
  15. ****************************************************************************/
  16. int  max(int a, int b)
  17. {  if(a>b) return(a);
  18.      else  return(b);
  19. }
  20. /****************************************************************************
  21. * 名称:abs()
  22. * 功能:求一个整数的绝对值。
  23. * 入口参数:a 取绝对值的数据
  24. * 出口参数:返回a的绝对值
  25. ****************************************************************************/
  26. int  abs(int a)
  27. {  if(a>0) return(a);
  28.      else  return(-a);
  29. }
  30. /* 曲线类变量及相关函数 */
  31. typedef  struct
  32. {  float   Ax, Ay; // 定义A、B、C点坐标变量
  33.    float   Bx, By;
  34.    float   Cx, Cy;
  35.    
  36.    int     Ndiv; // 定义曲线平滑参数变量     
  37. } CURVE;  
  38. #define  DIV_FACTOR  8.0 /* 平滑控制参数 */
  39. /****************************************************************************
  40. * 名称:CURVE_SetCurve()
  41. * 功能:设置三点曲线参数。
  42. * 入口参数: cl 要操作的曲线对象,CURVE结构
  43. *           ax a点x坐标值
  44. *           ay a点y坐标值
  45. * bx b点x坐标值
  46. *           by b点y坐标值
  47. * cx c点x坐标值
  48. *           cy c点y坐标值
  49. * 出口参数:无
  50. * 说明:
  51. ****************************************************************************/
  52. void  CURVE_SetCurve(CURVE *cl,
  53.                      float ax, float ay, 
  54.                  float bx, float by,
  55.                  float cx, float cy) 
  56. {  cl->Ax = ax;
  57.    cl->Ay = ay;
  58.    cl->Bx = bx; 
  59.    cl->By = by;
  60.    cl->Cx = cx; 
  61.    cl->Cy = cy;
  62.    
  63.    cl->Ndiv = (int)(max( abs((int)ax), abs((int)ay) ) / DIV_FACTOR);
  64. }
  65. /****************************************************************************
  66. * 名称:CURVE_GetCount()
  67. * 功能:取出平滑参数Ndiv+1的值。
  68. * 入口参数:cl 要操作的曲线对象,CURVE结构
  69. * 出口参数:返回Ndiv+1的值
  70. * 说明:若Ndiv为0,则先设置其为1。
  71. ****************************************************************************/
  72. int  CURVE_GetCount(CURVE *cl)
  73. {  if(0 == cl->Ndiv) cl->Ndiv=1;
  74.    return(cl->Ndiv+1);
  75. }
  76. /****************************************************************************
  77. * 名称:CURVE_GetCurve()
  78. * 功能:增加曲线点到points。
  79. * 入口参数:cl 要操作的曲线对象,CURVE结构
  80. *          x 新增点的x坐标值
  81. *    y  新增点的y坐标值
  82. *    points 曲线点缓冲区
  83. *          PointCount 缓冲区的当前指针
  84. * 出口参数:无
  85. * 说明:
  86. ****************************************************************************/
  87. void  CURVE_GetCurve(CURVE *cl, float x, float y, PointXY points[], int *PointCount)
  88. {  int    X, Y;
  89.    float  t, f, g, h;
  90.    int    i;
  91.    if(cl->Ndiv==0)  cl->Ndiv = 1;
  92.     /* 新增一个点到结构 */
  93. X = (int)x; 
  94. Y = (int)y;
  95. points[*PointCount].x = X;
  96. points[*PointCount].y = Y;
  97. (*PointCount)++;
  98.     /* 变换出ndiv个点 */
  99. for(i=1; i<=cl->Ndiv; i++)
  100. {  t = 1.0f / (float)cl->Ndiv * (float)i;
  101.    f = t * t * (3.0f - 2.0f * t);
  102.    g = t * (t - 1.0f) * (t-1.0f);
  103.    h = t * t * (t-1.0f);
  104.    X = (int)(x + cl->Ax*f + cl->Bx*g + cl->Cx*h);
  105.    Y = (int)(y + cl->Ay*f + cl->By*g + cl->Cy*h);
  106.    points[*PointCount].x = X;
  107.    points[*PointCount].y = Y;
  108.    (*PointCount)++;
  109. }
  110. }
  111. /***************************************************************************/
  112. /****************************************************************************
  113. * 名称:SPLINE_Spline()
  114. * 功能:样条曲线初始化函数,将特征点输入到样条曲线对象中。
  115. * 入口参数:sl 要操作的样条曲线对象,SPLINE结构
  116. *    pt 特征点数据
  117. *          np 特征点个数
  118. * 出口参数:无
  119. * 说明:
  120. ****************************************************************************/
  121. void  SPLINE_SetSpline(SPLINE *sl, PointXY pt[], int np)
  122. {  int  i;
  123.    sl->Np = np;
  124.    /* 将点数据复制到sl对象 */
  125.    for(i=0; i<sl->Np; i++) 
  126.    {  sl->Px[i] = (float)pt[i].x;  
  127.   sl->Py[i] = (float)pt[i].y;
  128.    }
  129. }
  130. /****************************************************************************
  131. * 名称:SPLINE_MatrixSolve()
  132. * 功能:求解矩阵。
  133. * 入口参数:sl 要操作的样条曲线对象,SPLINE结构
  134. *          B 需操作B点数据(数组)
  135. * 出口参数:无
  136. * 说明:由SPLINE_Generate()调用,计算值保存在B返回。
  137. ****************************************************************************/
  138. void  SPLINE_MatrixSolve(SPLINE *sl, float B[]) 
  139. {  float  Work[NPMAX];
  140.    float  WorkB[NPMAX];
  141.    int    i, j;
  142.    for(i=0; i<=(sl->Np-1); i++) 
  143.    {  Work[i] = B[i] / sl->Mat[1][i];
  144.   WorkB[i] = Work[i];
  145.    }
  146.    for(j=0; j<10; j++) 
  147.    {  Work[0] = (B[0] - sl->Mat[2][0] * WorkB[1]) / sl->Mat[1][0];
  148.   for(i=1; i<(sl->Np-1); i++ ) 
  149.      {  Work[i] = (B[i] - sl->Mat[0][i] * WorkB[i-1] - sl->Mat[2][i] * WorkB[i+1]) / sl->Mat[1][i];
  150.   }
  151.   Work[sl->Np-1] = (B[sl->Np-1] - sl->Mat[0][sl->Np-1] * WorkB[sl->Np-2]) / sl->Mat[1][sl->Np-1];
  152.   for(i=0; i<=(sl->Np-1); i++) 
  153.   {  WorkB[i] = Work[i];
  154.   }
  155.    }
  156.    
  157.    for(i=0; i<=(sl->Np-1); i++) 
  158.    {  B[i] = Work[i];
  159.    }
  160.    
  161. }
  162. /****************************************************************************
  163. * 名称:SPLINE_Generate()
  164. * 功能:产生样条曲线图形。产生的各个端点保存到sl的结构内。
  165. * 入口参数:sl 要操作的样条曲线对象,SPLINE结构
  166. * 出口参数:无
  167. * 说明:sl要先使用SPLINE_SetSpline()设置各个特征点。
  168. ****************************************************************************/
  169. void  SPLINE_Generate(SPLINE *sl) 
  170. {  float  k[NPMAX];
  171.    float  AMag , AMagOld;
  172.    int    i;
  173.    /* 设置A点值 */
  174.    for(i=0 ; i<=(sl->Np-2); i++ ) 
  175.    {  sl->Ax[i] = sl->Px[i+1] - sl->Px[i];
  176.   sl->Ay[i] = sl->Py[i+1] - sl->Py[i];
  177.    }
  178.    /* 计算k变量 */
  179.    AMagOld = (float)sqrt(sl->Ax[0] * sl->Ax[0] + sl->Ay[0] * sl->Ay[0]);
  180.    for(i=0 ; i<=(sl->Np-3); i++) 
  181.    {  AMag = (float)sqrt(sl->Ax[i+1] * sl->Ax[i+1] + sl->Ay[i+1] * sl->Ay[i+1]);
  182.   k[i] = AMagOld / AMag;
  183.   AMagOld = AMag;
  184.    }
  185.    k[sl->Np-2] = 1.0f;
  186.    /* 矩阵计算 */
  187.    for(i=1; i<=(sl->Np-2); i++) 
  188.    {  sl->Mat[0][i] = 1.0f;
  189.   sl->Mat[1][i] = 2.0f * k[i-1] * (1.0f + k[i-1]);
  190.   sl->Mat[2][i] = k[i-1] * k[i-1] * k[i];
  191.    }
  192.    sl->Mat[1][0] = 2.0f;
  193.    sl->Mat[2][0] = k[0];
  194.    sl->Mat[0][sl->Np-1] = 1.0f;
  195.    sl->Mat[1][sl->Np-1] = 2.0f * k[sl->Np-2];
  196.  
  197.    for(i=1; i<=(sl->Np-2);i++) 
  198.    {  sl->Bx[i] = 3.0f*(sl->Ax[i-1] + k[i-1] * k[i-1] * sl->Ax[i]);
  199.   sl->By[i] = 3.0f*(sl->Ay[i-1] + k[i-1] * k[i-1] * sl->Ay[i]);
  200.    }
  201.    sl->Bx[0] = 3.0f * sl->Ax[0];
  202.    sl->By[0] = 3.0f * sl->Ay[0];
  203.    sl->Bx[sl->Np-1] = 3.0f * sl->Ax[sl->Np-2];
  204.    sl->By[sl->Np-1] = 3.0f * sl->Ay[sl->Np-2];
  205.    SPLINE_MatrixSolve(sl, sl->Bx);
  206.    SPLINE_MatrixSolve(sl, sl->By);
  207.    for(i=0 ; i<=sl->Np-2 ; i++ ) 
  208.    {  sl->Cx[i] = k[i] * sl->Bx[i+1];
  209.   sl->Cy[i] = k[i] * sl->By[i+1];
  210.    }
  211. }
  212. /****************************************************************************
  213. * 名称:SPLINE_GetCurveCount()
  214. * 功能:取得样条曲线上端点个数值。
  215. * 入口参数:sl 要操作的样条曲线对象,SPLINE结构
  216. * 出口参数:返回值即是样条曲线各个端点个数
  217. * 说明:sl要先使用SPLINE_SetSpline()设置各个特征点。
  218. ****************************************************************************/
  219. int  SPLINE_GetCurveCount(SPLINE *sl)
  220. {  CURVE  curve_bak;
  221.    int    count = 0;
  222.    int    i;
  223.    
  224.    for(i=0; i<(sl->Np - 1); i++) // 历遍所有特征点 
  225.    {  /* 设置样条曲线(三点)curve_bak */
  226.       CURVE_SetCurve(&curve_bak, 
  227.                      sl->Ax[i], sl->Ay[i], 
  228.                      sl->Bx[i], sl->By[i], 
  229.                      sl->Cx[i], sl->Cy[i]);
  230.       /* 取得曲线curve_bak上端点的个数 */
  231.   count += CURVE_GetCount(&curve_bak);
  232.    }
  233.    
  234.    return(count);
  235. }
  236. /****************************************************************************
  237. * 名称:SPLINE_GetCurve()
  238. * 功能:取出样条曲线上各个端点,以便于使用GUI_Line()函数画出曲线。
  239. * 入口参数:sl 要操作的样条曲线对象,SPLINE结构
  240. *          points 用于接收曲线点的缓冲区,PointXY数组
  241. *          PointCount 用于接收曲线点个数的指针
  242. * 出口参数:无
  243. * 说明:接收曲线点由points返回,曲线点个数由PointCount返回;
  244. *      sl要先使用SPLINE_SetSpline()设置各个特征点。
  245. ****************************************************************************/
  246. void  SPLINE_GetCurve(SPLINE *sl, PointXY points[], int *PointCount)
  247. {  CURVE  curve_bak;
  248.    int    i;
  249.    *PointCount = 0; // 初始化点计数器为0
  250.    for(i=0; i<(sl->Np-1); i++)  // 历遍所有特征点
  251.    {  /* 设置样条曲线(三点)curve_bak */
  252.       CURVE_SetCurve(&curve_bak, 
  253.      sl->Ax[i], sl->Ay[i],
  254.                      sl->Bx[i], sl->By[i], 
  255.                      sl->Cx[i], sl->Cy[i]);
  256.                      
  257.       /* 取得样条曲线curve_bak的端点数据及个数 */               
  258.   CURVE_GetCurve(&curve_bak, 
  259.                  sl->Px[i], sl->Py[i], 
  260.                  points, 
  261.                  PointCount);
  262.    }
  263. }
  264. /****************************************************************************
  265. * 名称:GUI_Spline()
  266. * 功能:作出多个特征点(3个以上)样条曲线。
  267. * 入口参数