Files
player/Project_App_Chat/App_Src/calc/ellipsoid.c
2025-07-05 19:47:28 +08:00

210 lines
4.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "ellipsoid.h"
#include "stdio.h"
#include "string.h"
#include "math.h"
#define printf(a,fmt...)
/*=================================计算用的私有函数=====================================*/
//取绝对值
static float Abs(float a)
{
return a < 0 ? -a : a;
}
//交换两行元素位置
static void Row2_swop_Row1(float matrix[MATRIX_SIZE][MATRIX_SIZE+1],int row1, int row2)
{
float tmp = 0;
for (int column = 0; column < MATRIX_SIZE + 1; column++)
{
tmp = matrix[row1][column];
matrix[row1][column] = matrix[row2][column];
matrix[row2][column] = tmp;
}
}
//用把row行的元素乘以一个系数k
static void k_muiltply_Row(float matrix[MATRIX_SIZE][MATRIX_SIZE+1],float k, int row)
{
for (int column = 0; column < MATRIX_SIZE + 1; column++)
matrix[row][column] *= k;
}
//用一个数乘以row1行加到row2行上去
static void Row2_add_kRow1(float matrix[MATRIX_SIZE][MATRIX_SIZE+1],float k, int row1, int row2)
{
for (int column = 0; column < MATRIX_SIZE + 1; column++)
matrix[row2][column] += k*matrix[row1][column];
}
//列主元第k次消元之前把k行到MATRIX_SIZE的所有行进行冒泡排出最大排序的依据是k列的元素的大小
static void MoveBiggestElement_to_Top(float matrix[MATRIX_SIZE][MATRIX_SIZE+1],int k)
{
int row = 0, column = 0;
for (row = k + 1; row < MATRIX_SIZE; row++)
{
if (Abs(matrix[k][k]) < Abs(matrix[row][k]))
{
Row2_swop_Row1(matrix,k, row);
}
}
}
//高斯消元法,求行阶梯型矩阵,返回0成功
static int Matrix_GaussElimination(float matrix[MATRIX_SIZE][MATRIX_SIZE+1])
{
float k = 0;
for (int cnt = 0; cnt < MATRIX_SIZE; cnt++)//进行第k次的运算主要是针对k行以下的行数把k列的元素都变成0
{
//把k行依据k列的元素大小进行排序
MoveBiggestElement_to_Top(matrix,cnt);
if (matrix[cnt][cnt] == 0)
return(1);//返回值表示错误
//把k行下面的行元素全部消成0整行变化
for (int row = cnt + 1; row < MATRIX_SIZE; row++)
{
k = -matrix[row][cnt] / matrix[cnt][cnt];
Row2_add_kRow1(matrix,k, cnt, row);
}
// DispMatrix();
}
return 0;
}
//求行最简型矩阵即把对角线的元素全部化成1
static void Matrix_RowSimplify(float matrix[MATRIX_SIZE][MATRIX_SIZE+1])
{
float k = 0;
for (int row = 0; row < MATRIX_SIZE; row++)
{
k = 1 / matrix[row][row];
k_muiltply_Row(matrix,k, row);
}
// DispMatrix();
}
//求非齐次线性方程组的解
static void Matrix_Solve(float matrix[MATRIX_SIZE][MATRIX_SIZE+1],float* solve)
{
for (short row = MATRIX_SIZE - 1; row >= 0; row--)
{
solve[row] = matrix[row][MATRIX_SIZE];
for (int column = MATRIX_SIZE - 1; column >= row + 1; column--)
solve[row] -= matrix[row][column] * solve[column];
}
printf(" a = %f| b = %f| c = %f| d = %f| e = %f| f = %f ", solve[0], solve[1], solve[2], solve[3], solve[4], solve[5]);
printf("\r\n");
printf("\r\n");
}
/*=================================计算用的私有函数End=====================================*/
//清零
void ellipsoid_reset(ellipsoid_struct *ell)
{
if(ell==0) return;
memset(ell,0,sizeof(ellipsoid_struct));
}
//添加点并求和
void ellipsoid_add_point(ellipsoid_struct *ell,float x,float y,float z)
{
if(ell==0) return;
ell->num++;
double V[MATRIX_SIZE + 1];
V[0] = y*y;
V[1] = z*z;
V[2] = x;
V[3] = y;
V[4] = z;
V[5] = 1.0;
V[6] = -x*x;
//构建系数矩阵,并进行累加
for (int row = 0; row < MATRIX_SIZE; row++)
{
for (int column = 0; column < MATRIX_SIZE + 1; column++)
{
ell->sum[row][column] += V[row] * V[column];
}
}
//b向量是m_matrix[row][6]
}
//求平均值
void ellipsoid_average(ellipsoid_struct *ell)
{
if(ell==0) return;
for (int row = 0; row < MATRIX_SIZE; row++)
for (int column = 0; column < MATRIX_SIZE + 1; column++)
ell->avr[row][column]=ell->sum[row][column] / ell->num;
//b向量是m_matrix[row][6]
}
//开始拟合
void ellipsoid_fitting(ellipsoid_struct *ell)
{
if(ell==0) return;
float solve[6]={0};
//在添加一定数量的点之后求取平均值
ellipsoid_average(ell);
//求矩阵
if(Matrix_GaussElimination(ell->avr)==0)
{
Matrix_RowSimplify(ell->avr);
Matrix_Solve(ell->avr,solve);
float a = 0, b = 0, c = 0, d = 0, e = 0, f = 0;
a = solve[0];
b = solve[1];
c = solve[2];
d = solve[3];
e = solve[4];
f = solve[5];
ell->x = -c / 2;
ell->y = -d / (2 * a);
ell->z = -e / (2 * b);
ell->a = sqrt(ell->x*ell->x + a*ell->y*ell->y + b*ell->z*ell->z - f);
ell->b = ell->a / sqrtf(a);
ell->c = ell->a / sqrtf(b);
printf(" ((x - x0) / A) ^ 2 + ((y - y0) / B) ^ 2 + ((z - z0) / C) ^ 2 = 1 Ellipsoid result as below\r\n");
printf("\r\n");
printf(" X0 = %f| Y0 = %f| Z0 = %f| A = %f| B = %f| C = %f \r\n", ell->x, ell->y,ell->z, ell->a, ell->b, ell->c);
}
}