直线拟合算法
函数说明:
通过一些点拟合出一条直线。
参数:
pt_input
指向传入的点的指针。
ptNumbers
传入的点数量。
k
指向拟合直线参数k的指针。
b
指向拟合直线参数b的指针。
返回值:
返回一个代数值判断拟合是否成功。如果成功,则返回 0。如果返回-1,表示点的数量<2。如果返回-2,表示x坐标无变化。
代码:
typedef struct tagPOINT_2 {
double x;
double y;
}POINT_2, *PPOINT_2;
int LineInfo(POINT_2 *pt_input, int ptNumbers, double * k, double * b)
{
int nRet = 0;
double X_aver = 0;
double Y_aver = 0;
double A = 0;
double B = 0;
double _2_XY_av = 0;
double _2_XX_av = 0;
do
{
if (ptNumbers < 2)
{
nRet = -1;
break;
}
for (int loop = 0; loop < ptNumbers; loop++)
{
X_aver += pt_input[loop].x;
Y_aver += pt_input[loop].y;
_2_XY_av += pt_input[loop].x * pt_input[loop].y;
_2_XX_av += pt_input[loop].x * pt_input[loop].x;
}
X_aver /= ptNumbers;
Y_aver /= ptNumbers;
_2_XY_av /= ptNumbers;
_2_XX_av /= ptNumbers;
for (int loop = 0; loop < ptNumbers; loop++)
{
A += fabs((pt_input[loop].x - X_aver) * (pt_input[loop].y - Y_aver));
B += fabs((pt_input[loop].x - X_aver) * (pt_input[loop].x - X_aver));
}
if (B < 0.000001)
{
nRet = -2;
break;
}
//方式一
//*k = A / B;
//*b = Y_aver - *k * X_aver;
//方式二
*k = (_2_XY_av - X_aver * Y_aver) / (_2_XX_av - X_aver * X_aver);
*b = Y_aver - (*k) * X_aver;
} while (0);
return nRet;
}
测试代码:
#include <stdio.h>
#include <math.h>
int main()
{
POINT_2 pt[10] = {
{0.1 , 0.3},
{1.2 , 2.0},
{2.2 , 4.3},
{3.1 , 5.8},
{4.0 , 8.5},
{5.3 , 10.8},
{5.9 , 11.1},
{6.8 , 13.9},
{8.1 , 16.5},
{9.0 , 17.9},
};
int ret;
double k = 0, b = 0;
ret = LineInfo(pt, 10, &k, &b);
switch (ret)
{
case 0: printf("拟合成功,直线为y = %lf * x + %lf\n", k, b); break;
case -1: printf("拟合失败,传入的点少于二点\n"); break;
case -2: printf("拟合失败,传入的点x坐标重合\n"); break;
default:printf("error\n"); break;
}
return 0;
}