?? spline.c
字號:
/****************************************************************************************
* 文件名:SPLINE.C
* 功能:二次參數樣條曲線生成程序。
* 作者:黃紹斌
* 日期:2003.09.09
****************************************************************************************/
#include "config.h"
#include "math.h"
/****************************************************************************
* 名稱:max()
* 功能:求兩個整數中最大的整數值。
* 入口參數:a 整數1
* b 整數2
* 出口參數:返回最大的整數值
****************************************************************************/
int max(int a, int b)
{ if(a>b) return(a);
else return(b);
}
/****************************************************************************
* 名稱:abs()
* 功能:求一個整數的絕對值。
* 入口參數:a 取絕對值的數據
* 出口參數:返回a的絕對值
****************************************************************************/
int abs(int a)
{ if(a>0) return(a);
else return(-a);
}
/* 曲線類變量及相關函數 */
typedef struct
{ float Ax, Ay; // 定義A、B、C點坐標變量
float Bx, By;
float Cx, Cy;
int Ndiv; // 定義曲線平滑參數變量
} CURVE;
#define DIV_FACTOR 8.0 /* 平滑控制參數 */
/****************************************************************************
* 名稱:CURVE_SetCurve()
* 功能:設置三點曲線參數。
* 入口參數: cl 要操作的曲線對象,CURVE結構
* ax a點x坐標值
* ay a點y坐標值
* bx b點x坐標值
* by b點y坐標值
* cx c點x坐標值
* cy c點y坐標值
* 出口參數:無
* 說明:
****************************************************************************/
void CURVE_SetCurve(CURVE *cl,
float ax, float ay,
float bx, float by,
float cx, float cy)
{ cl->Ax = ax;
cl->Ay = ay;
cl->Bx = bx;
cl->By = by;
cl->Cx = cx;
cl->Cy = cy;
cl->Ndiv = (int)(max( abs((int)ax), abs((int)ay) ) / DIV_FACTOR);
}
/****************************************************************************
* 名稱:CURVE_GetCount()
* 功能:取出平滑參數Ndiv+1的值。
* 入口參數:cl 要操作的曲線對象,CURVE結構
* 出口參數:返回Ndiv+1的值
* 說明:若Ndiv為0,則先設置其為1。
****************************************************************************/
int CURVE_GetCount(CURVE *cl)
{ if(0 == cl->Ndiv) cl->Ndiv=1;
return(cl->Ndiv+1);
}
/****************************************************************************
* 名稱:CURVE_GetCurve()
* 功能:增加曲線點到points。
* 入口參數:cl 要操作的曲線對象,CURVE結構
* x 新增點的x坐標值
* y 新增點的y坐標值
* points 曲線點緩沖區
* PointCount 緩沖區的當前指針
* 出口參數:無
* 說明:
****************************************************************************/
void CURVE_GetCurve(CURVE *cl, float x, float y, PointXY points[], int *PointCount)
{ int X, Y;
float t, f, g, h;
int i;
if(cl->Ndiv==0) cl->Ndiv = 1;
/* 新增一個點到結構 */
X = (int)x;
Y = (int)y;
points[*PointCount].x = X;
points[*PointCount].y = Y;
(*PointCount)++;
/* 變換出ndiv個點 */
for(i=1; i<=cl->Ndiv; i++)
{ t = 1.0f / (float)cl->Ndiv * (float)i;
f = t * t * (3.0f - 2.0f * t);
g = t * (t - 1.0f) * (t-1.0f);
h = t * t * (t-1.0f);
X = (int)(x + cl->Ax*f + cl->Bx*g + cl->Cx*h);
Y = (int)(y + cl->Ay*f + cl->By*g + cl->Cy*h);
points[*PointCount].x = X;
points[*PointCount].y = Y;
(*PointCount)++;
}
}
/***************************************************************************/
/****************************************************************************
* 名稱:SPLINE_Spline()
* 功能:樣條曲線初始化函數,將特征點輸入到樣條曲線對象中。
* 入口參數:sl 要操作的樣條曲線對象,SPLINE結構
* pt 特征點數據
* np 特征點個數
* 出口參數:無
* 說明:
****************************************************************************/
void SPLINE_SetSpline(SPLINE *sl, PointXY pt[], int np)
{ int i;
sl->Np = np;
/* 將點數據復制到sl對象 */
for(i=0; i<sl->Np; i++)
{ sl->Px[i] = (float)pt[i].x;
sl->Py[i] = (float)pt[i].y;
}
}
/****************************************************************************
* 名稱:SPLINE_MatrixSolve()
* 功能:求解矩陣。
* 入口參數:sl 要操作的樣條曲線對象,SPLINE結構
* B 需操作B點數據(數組)
* 出口參數:無
* 說明:由SPLINE_Generate()調用,計算值保存在B返回。
****************************************************************************/
void SPLINE_MatrixSolve(SPLINE *sl, float B[])
{ float Work[NPMAX];
float WorkB[NPMAX];
int i, j;
for(i=0; i<=(sl->Np-1); i++)
{ Work[i] = B[i] / sl->Mat[1][i];
WorkB[i] = Work[i];
}
for(j=0; j<10; j++)
{ Work[0] = (B[0] - sl->Mat[2][0] * WorkB[1]) / sl->Mat[1][0];
for(i=1; i<(sl->Np-1); i++ )
{ Work[i] = (B[i] - sl->Mat[0][i] * WorkB[i-1] - sl->Mat[2][i] * WorkB[i+1]) / sl->Mat[1][i];
}
Work[sl->Np-1] = (B[sl->Np-1] - sl->Mat[0][sl->Np-1] * WorkB[sl->Np-2]) / sl->Mat[1][sl->Np-1];
for(i=0; i<=(sl->Np-1); i++)
{ WorkB[i] = Work[i];
}
}
for(i=0; i<=(sl->Np-1); i++)
{ B[i] = Work[i];
}
}
/****************************************************************************
* 名稱:SPLINE_Generate()
* 功能:產生樣條曲線圖形。產生的各個端點保存到sl的結構內。
* 入口參數:sl 要操作的樣條曲線對象,SPLINE結構
* 出口參數:無
* 說明:sl要先使用SPLINE_SetSpline()設置各個特征點。
****************************************************************************/
void SPLINE_Generate(SPLINE *sl)
{ float k[NPMAX];
float AMag , AMagOld;
int i;
/* 設置A點值 */
for(i=0 ; i<=(sl->Np-2); i++ )
{ sl->Ax[i] = sl->Px[i+1] - sl->Px[i];
sl->Ay[i] = sl->Py[i+1] - sl->Py[i];
}
/* 計算k變量 */
AMagOld = (float)sqrt(sl->Ax[0] * sl->Ax[0] + sl->Ay[0] * sl->Ay[0]);
for(i=0 ; i<=(sl->Np-3); i++)
{ AMag = (float)sqrt(sl->Ax[i+1] * sl->Ax[i+1] + sl->Ay[i+1] * sl->Ay[i+1]);
k[i] = AMagOld / AMag;
AMagOld = AMag;
}
k[sl->Np-2] = 1.0f;
/* 矩陣計算 */
for(i=1; i<=(sl->Np-2); i++)
{ sl->Mat[0][i] = 1.0f;
sl->Mat[1][i] = 2.0f * k[i-1] * (1.0f + k[i-1]);
sl->Mat[2][i] = k[i-1] * k[i-1] * k[i];
}
sl->Mat[1][0] = 2.0f;
sl->Mat[2][0] = k[0];
sl->Mat[0][sl->Np-1] = 1.0f;
sl->Mat[1][sl->Np-1] = 2.0f * k[sl->Np-2];
for(i=1; i<=(sl->Np-2);i++)
{ sl->Bx[i] = 3.0f*(sl->Ax[i-1] + k[i-1] * k[i-1] * sl->Ax[i]);
sl->By[i] = 3.0f*(sl->Ay[i-1] + k[i-1] * k[i-1] * sl->Ay[i]);
}
sl->Bx[0] = 3.0f * sl->Ax[0];
sl->By[0] = 3.0f * sl->Ay[0];
sl->Bx[sl->Np-1] = 3.0f * sl->Ax[sl->Np-2];
sl->By[sl->Np-1] = 3.0f * sl->Ay[sl->Np-2];
SPLINE_MatrixSolve(sl, sl->Bx);
SPLINE_MatrixSolve(sl, sl->By);
for(i=0 ; i<=sl->Np-2 ; i++ )
{ sl->Cx[i] = k[i] * sl->Bx[i+1];
sl->Cy[i] = k[i] * sl->By[i+1];
}
}
/****************************************************************************
* 名稱:SPLINE_GetCurveCount()
* 功能:取得樣條曲線上端點個數值。
* 入口參數:sl 要操作的樣條曲線對象,SPLINE結構
* 出口參數:返回值即是樣條曲線各個端點個數
* 說明:sl要先使用SPLINE_SetSpline()設置各個特征點。
****************************************************************************/
int SPLINE_GetCurveCount(SPLINE *sl)
{ CURVE curve_bak;
int count = 0;
int i;
for(i=0; i<(sl->Np - 1); i++) // 歷遍所有特征點
{ /* 設置樣條曲線(三點)curve_bak */
CURVE_SetCurve(&curve_bak,
sl->Ax[i], sl->Ay[i],
sl->Bx[i], sl->By[i],
sl->Cx[i], sl->Cy[i]);
/* 取得曲線curve_bak上端點的個數 */
count += CURVE_GetCount(&curve_bak);
}
return(count);
}
/****************************************************************************
* 名稱:SPLINE_GetCurve()
* 功能:取出樣條曲線上各個端點,以便于使用GUI_Line()函數畫出曲線。
* 入口參數:sl 要操作的樣條曲線對象,SPLINE結構
* points 用于接收曲線點的緩沖區,PointXY數組
* PointCount 用于接收曲線點個數的指針
* 出口參數:無
* 說明:接收曲線點由points返回,曲線點個數由PointCount返回;
* sl要先使用SPLINE_SetSpline()設置各個特征點。
****************************************************************************/
void SPLINE_GetCurve(SPLINE *sl, PointXY points[], int *PointCount)
{ CURVE curve_bak;
int i;
*PointCount = 0; // 初始化點計數器為0
for(i=0; i<(sl->Np-1); i++) // 歷遍所有特征點
{ /* 設置樣條曲線(三點)curve_bak */
CURVE_SetCurve(&curve_bak,
sl->Ax[i], sl->Ay[i],
sl->Bx[i], sl->By[i],
sl->Cx[i], sl->Cy[i]);
/* 取得樣條曲線curve_bak的端點數據及個數 */
CURVE_GetCurve(&curve_bak,
sl->Px[i], sl->Py[i],
points,
PointCount);
}
}
/****************************************************************************
* 名稱:GUI_Spline()
* 功能:作出多個特征點(3個以上)樣條曲線。
* 入口參數
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -