• 已知空间N点坐标求圆心坐标,半径


    注意哦 这里是求圆心 不是球心哦

    条件:已知空间N点坐标,格式如下 求圆心坐标,半径

    -33.386698 -12.312448 -2301.396442
    -33.668120 -12.571431 -2300.390996
    -33.838611 -12.774933 -2299.691688
    -34.079235 -13.616660 -2298.326277
    -34.254998 -13.441280 -2298.192657
    -34.356542 -13.755525 -2297.796473

    ........................................................

    实现方法:用最小二乘法拟合出 球面方程 和 平面方程,两者相交即为所求圆曲线

    球面方程:(x - a)^2  + (y - b)^2 + (z - c)^2 = R^2

    展开:     x^2 + y^2 + z ^2 + a^2 +b^2 +c^2 - 2ax - 2by -2cz = R ^2

    令 A = 2a  ; B =2b ; C =2c  D=a^2 +b^2 +c^2 -R^2 

     得  x^2 + y^2 + z ^2 - Ax -By - Cz + D =0

    即:Ax +By +Cz -D = x^2 +y^2 +z^2

    用矩阵表示这N组数据如下形式

    现在就是求 A B C D 的问题了

    具体步骤如下

    平面方程 A' x + B' y + C' z + D' = 0

    可化为  A x + B y + C z  -1 =0

    用矩阵表示如下

    同样可以求出 A B C

    这样就有了球面方程 球心坐标 球半径 和 平面方程了

    如图所示(网络找的图,意思着看 囧)

    圆心为球心到平面的垂足(也就是 平面外一点到平面的坐标问题)

    半径为 sqrt(球半径^2 - 球心到平面的距离^2)

    设 平面方程为 A X + B Y + C Z +D = 0   ①    球心坐标(a,b,c) 

    平面外一点到平面的坐标问题:

    则 平面的法向量为 (A ,B ,C )

    设垂足即圆心 (x' y' z')   球心到圆心的连线 与法向量是平行的

    可以得到如下 (x' -a )/A = (y' -b)/B = (z' - c)/C  = t ②

    由 ②得 x' = At + a; y' = B t + b ;  z' = C t + c;

    带入① 可以得到(x' , y' , z')

    平面外一点到平面的距离问题

    d = abs(Ax' + By' + C z' +D) / sqrt(A^2 + B^2 +C^2)

    到此为止已经有了足够的理论知识,下面是代码 分别用 OPENCV 和C 实现

      1 // 最小二乘法拟合球.cpp : 定义控制台应用程序的入口点。
    2 //
    3
    4 #include "stdafx.h"
    5 #include <iostream>
    6 #include <fstream>
    7 #include <cmath>
    8 usingnamespace std;
    9
    10 #include <cv.h>
    11 #include <cxcore.h>
    12 #include <highgui.h>
    13
    14 #ifdef DEBUG
    15 #pragma comment(lib,"cxcore200d.lib")
    16 #pragma comment(lib,"cv200d.lib")
    17 #pragma comment(lib,"highgui200d.lib")
    18 #else
    19 #pragma comment(lib,"cxcore200.lib")
    20 #pragma comment(lib,"cv200.lib")
    21 #pragma comment(lib,"highgui200.lib")
    22
    23 #endif
    24
    25 void fitRound(char*filepath,int n)
    26 {
    27 ifstream file(filepath);
    28 //int n = 0; //数据组数
    29
    30 //file>>n;
    31 /*
    32 x ~ NX4
    33 | x1 y1 z1 -1 |
    34 |. .. .... .......... |
    35 | .. ...... ..........|
    36 |xn yn zn -1|
    37 */
    38 int xsize =4*n*sizeof(double);
    39 double*x = (double*)malloc(xsize);
    40 /*
    41 y ~ NX1
    42 |x1^2 + y1^2 +z1^2 |
    43 |.......................................|
    44 |.......................................|
    45 |xn^2+yn^2+zn^2 |
    46 */
    47 int ysize = n *sizeof(double);
    48 double*y = (double*)malloc(ysize);
    49
    50 /*
    51 z ~NX3
    52 |x1 y1 z1|
    53 |...............|
    54 |...............|
    55 |xn yn zn|
    56 */
    57 int zsize =3* n *sizeof(double);
    58 double*z = (double*)malloc(zsize);
    59
    60 /*
    61 p ~ Nx1
    62 | 1 |
    63 | .. |
    64 | .. |
    65 | 1 |
    66 */
    67 int psize = n *sizeof(double);
    68 double*p = (double*)malloc(psize);
    69
    70 for (int i=0;i<n;i++)
    71 {
    72 file>>*(x+i*4+0)>>*( x+i*4+1)>>*(x +i*4+2);
    73 *(x+i*4+3) =-1;
    74
    75 *(y +i) =*(x+i*4+0) **(x+i*4+0) +*(x+i*4+1) **(x+i*4+1) +*(x+i*4+2) **(x+i*4+2);
    76
    77 *(z+i*3+0) =*(x+i*4+0);
    78 *(z+i*3+1) =*(x+i*4+1);
    79 *(z+i*3+2) =*(x+i*4+2);
    80
    81 *(p+i) =1;
    82 }
    83
    84 // ---------------------------- 球面方程
    85 //x^2 +y^2 + z^2 - AX - BY - CZ +D =0
    86
    87 // x 对应的矩阵
    88 CvMat * MAT_X = cvCreateMat(n,4,CV_64FC1);
    89 memcpy(MAT_X->data.db,x,xsize);
    90
    91 // y 对应的矩阵
    92 CvMat *MAT_Y = cvCreateMat(n,1,CV_64FC1);
    93 memcpy(MAT_Y->data.db,y,ysize);
    94
    95 //xT -- x的转置矩阵
    96 CvMat *MAT_XT = cvCreateMat(4,n,CV_64FC1);
    97 cvTranspose(MAT_X,MAT_XT);
    98
    99 // xT (4xn) * x(n*4) = XT_X(4*4)
    100 CvMat *MAT_XT_X = cvCreateMat(4,4,CV_64FC1);
    101 cvMatMul(MAT_XT,MAT_X,MAT_XT_X);
    102
    103 //xT (4xn) * y(n*1) = xT_Y(4*1)
    104 CvMat *MAT_XT_Y = cvCreateMat(4,1,CV_64FC1);
    105 cvMatMul(MAT_XT,MAT_Y,MAT_XT_Y);
    106
    107 //MAT_XT_X_INVERT -- MAT_XT_X的逆矩阵
    108 CvMat *MAT_XT_X_INVERT = cvCreateMat(4,4,CV_64FC1);
    109 cvInvert(MAT_XT_X,MAT_XT_X_INVERT,CV_LU); // 高斯消去法
    110
    111 //MAT_ABCD 4X1结果矩阵
    112 CvMat *MAT_ABCD = cvCreateMat(4,1,CV_64FC1);
    113 cvMatMul(MAT_XT_X_INVERT,MAT_XT_Y,MAT_ABCD);
    114
    115 double c_x,c_y,c_z,c_r;
    116 double*ptr = MAT_ABCD->data.db;
    117 c_x =*ptr /2;
    118 c_y =*(ptr+1)/2;
    119 c_z =*(ptr+2)/2;
    120 c_r =sqrt (c_x *c_x +c_y *c_y +c_z *c_z -*(ptr+3));
    121
    122
    123 //-----------------------平面方程
    124 //E X + F y +G z =1
    125
    126 // z 对应矩阵
    127 CvMat * MAT_Z = cvCreateMat(n,3,CV_64FC1);
    128 memcpy(MAT_Z->data.db,z,zsize);
    129
    130 // p 对应矩阵
    131 CvMat *MAT_P = cvCreateMat(n,1,CV_64FC1);
    132 memcpy(MAT_P->data.db,p,psize);
    133
    134 //z 的转置矩阵
    135 CvMat *MAT_ZT = cvCreateMat(3,n,CV_64FC1);
    136 cvTranspose(MAT_Z,MAT_ZT);
    137
    138 //zt * z
    139 CvMat *MAT_ZT_Z = cvCreateMat(3,3,CV_64FC1);
    140 cvMatMul(MAT_ZT,MAT_Z,MAT_ZT_Z);
    141
    142 //ZT * P
    143 CvMat * MAT_ZT_P = cvCreateMat(3,1,CV_64FC1);
    144 cvMatMul(MAT_ZT,MAT_P,MAT_ZT_P);
    145
    146 // MAT_ZT_Z的逆矩阵
    147 CvMat *MAT_ZT_Z_INVERT = cvCreateMat(3,3,CV_64FC1);
    148 cvInvert(MAT_ZT_Z,MAT_ZT_Z_INVERT,CV_LU);
    149
    150 //MAT_EFG 3X1结果
    151 CvMat *MAT_EFG = cvCreateMat(3,1,CV_64FC1);
    152 cvMatMul(MAT_ZT_Z_INVERT,MAT_ZT_P,MAT_EFG);
    153
    154 double E,F,G;
    155 E =* MAT_EFG->data.db;
    156 F =*(MAT_EFG->data.db +1);
    157 G =*(MAT_EFG->data.db +2 );
    158 //圆心坐标 半径
    159 double n_x, n_y, n_z, n_r;
    160   n_x = ((F*F+G*G)*c_x +E *(-F*c_y - G*c_z +1))/ ( E *E + F *F+ G *G);
         n_y = ((E*E+G*G)*c_y +F* (-E*c_x -G*c_z +1))/ ( E *E + F *F+ G *G);
         n_z = ((E*E+F*F)*c_z +G*(-E*c_x -F *c_y +1))/( E *E + F *F+ G *G);
    162 
    163 
    164 n_r = sqrt( c_r *c_r - (E *c_x +F *c_y +G *c_z -1 ) *(E *c_x +F *c_y +G *c_z -1 ) /(E *E +F * F +G *G) );
    165
    166 printf("%f %f %f %f\n",n_x,n_y,n_z,n_r);
    167 file.close();
    168 }
    169
    170 int _tmain(int argc, _TCHAR* argv[])
    171 {
    172
    173
    174 for (int i =4 ; i<35;i++)
    175 {
    176 fitRound("log.txt",i);
    177 }
    178 getchar();
    179 return0;
    180 }

    C 实现方式

    // 最小二乘法求圆心CC++.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include <iostream>
    #include <fstream>
    #include  <cmath>   
    using namespace std; 
    
    int InverseMatrix(double *matrix,const int &row);
    void swap(double &a,double &b);
    int mulMatrix(double *matrixA,int m1,int n1,double *matrixB,int m2,int n2,double *matrixC);
    int transPoseMatrix(double *matrixA,int m,int n,double *matrixB);
    void fitRoud(char * filepath,int n);
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	for (int i=4 ;i<35;i++)
    	{
    		fitRoud("log.txt",i);
    	}
    	getchar();
    
    	return 0;
    }
    
    
    void swap(double &a,double &b)
    {
    	double temp=a;
    	a=b;
    	b=temp;
    }
    
    /**********************************************
    *函数名:InverseMatrix       
    *函数介绍:求逆矩阵(高斯—约当法) 
    *输入参数:矩阵首地址(二维数组)matrix,阶数row
    *输出参数:matrix原矩阵的逆矩阵
    *返回值:成功,0;失败,1
    *调用函数:swap(double &a,double &b)
    **********************************************/
    int InverseMatrix(double *matrix,const int &row)
    {
    	double *m=new double[row*row];
    	double *ptemp,*pt=m;
    
    	int i,j;
    
    	ptemp=matrix;
    	for (i=0;i<row;i++)
    	{
    		for (j=0;j<row;j++)
    		{
    			*pt=*ptemp;
    			ptemp++;
    			pt++;
    		}
    	}
    
    	int k;
    
    	int *is=new int[row],*js=new int[row];
    
    	for (k=0;k<row;k++)
    	{
    		double max=0;
    		//全选主元
    		//寻找最大元素
    		for (i=k;i<row;i++)
    		{
    			for (j=k;j<row;j++)
    			{
    				if (fabs(*(m+i*row+j))>max)
    				{
    					max=*(m+i*row+j);
    					is[k]=i;
    					js[k]=j;
    				}
    			}
    		}
    
    		if (0 == max)
    		{
    			return 1;
    		}
    
    		//行交换
    		if (is[k]!=k)
    		{
    			for (i=0;i<row;i++)
    			{
    				swap(*(m+k*row+i),*(m+is[k]*row+i));
    			}
    		}
    
    		//列交换
    		if (js[k]!=k)
    		{
    			for (i=0;i<row;i++)
    			{
    				swap(*(m+i*row+k),*(m+i*row+js[k]));
    			}
    		}
    
    		*(m+k*row+k)=1/(*(m+k*row+k));
    
    		for (j=0;j<row;j++)
    		{
    			if (j!=k)
    			{
    				*(m+k*row+j)*=*((m+k*row+k));
    			}
    		}
    
    		for (i=0;i<row;i++)
    		{
    			if (i!=k)
    			{
    				for (j=0;j<row;j++)
    				{
    					if(j!=k)
    					{
    						*(m+i*row+j)-=*(m+i*row+k)**(m+k*row+j);
    					}
    				}
    			}
    		}
    
    		for (i=0;i<row;i++)
    		{
    			if(i!=k)
    			{
    				*(m+i*row+k)*=-(*(m+k*row+k));
    			}
    		}
    	}
    
    	int r;
    	//恢复
    	for (r=row-1;r>=0;r--)
    	{
    		if (js[r]!=r)
    		{
    			for (j=0;j<row;j++)
    			{
    				swap(*(m+r*row+j),*(m+js[r]*row+j));
    			}
    		}
    		if (is[r]!=r)
    		{
    			for (i=0;i<row;i++)
    			{
    				swap(*(m+i*row+r),*(m+i*row+is[r]));
    			}
    		}
    	}
    
    	ptemp=matrix;
    	pt=m;
    	for (i=0;i<row;i++)
    	{
    		for (j=0;j<row;j++)
    		{
    			*ptemp=*pt;
    			ptemp++;
    			pt++;
    		}
    	}
    	delete []is;
    	delete []js;
    	delete []m;
    
    	return 0;
    }
    
    /*
    *函数名:mulMatrix       
    *函数介绍:矩阵相乘
    *输入参数 :matrixA ----矩阵首地址
    				m1,n1	-----	matrixA 行列数
    				matrixB -----矩阵首地址
    				m2,n2 ------matrixB 行列数
    *				matrixC 结果矩阵 行列数 m1 n2 
    *返回值 : 0 -- 失败 
    				1 -- 成功
    
    */
    int mulMatrix(double *matrixA,int m1,int n1,double *matrixB,int m2,int n2,double *matrixC)
    {
    	/*
    	if( n1 !=m2 )
    		return 0;
    	if( sizeof(matrixC) ! = m1 * n2 * sizeof(double) )
    		return 0;
    */
    	for (int i=0;i<m1;++i)
    	{
    		for (int j=0;j<n2;++j)
    		{
    			*(matrixC + i *n2 +j) =0.0;
    			// matrixA - i 行  *  matrixB -- j 列
    			for (int k = 0;k<m2;k++)
    			{
    				*(matrixC + i *n2 +j) +=*(matrixA + i*n1 + k) * *(matrixB +k * n2 + j);
    			}
    		}
    	}
    	return 1;
    }
    
    /*
    *函数名:transPoseMatrix       
    *函数介绍:矩阵转置
    *输入参数 :matrixA ----源矩阵
    				m1,n1	-----	matrixA 行列数
    				matrixB -----转置结果
    *返回值 : 0 -- 失败 
    				1 -- 成功
    
    */
    int transPoseMatrix(double *matrixA,int m,int n,double *matrixB)
    {
    	for (int i=0;i<m;++i)
    	{
    		for (int j=0;j<n;++j)
    		{
    			*(matrixB + j *m +i) = *(matrixA + i * n + j);
    		}
    	}
    	return 1;
    }
    
    void fitRoud(char * filepath,int n)
    {
    	ifstream file(filepath);
    	//int n = 0;    //数据组数
    
    	//file>>n;
    	/*
    	x ~ NX4	
    	| x1 y1 z1 -1 |
    	|. .. ....  .......... |
    	| .. ......  ..........|
    	|xn yn  zn -1|
    	*/
    	int xsize = 4*n*sizeof(double);
    	double *x = (double *)malloc(xsize);
    	/*
    		y ~ NX1
    		|x1^2 + y1^2 +z1^2 |
    		|.......................................|
    		|.......................................|
    		|xn^2+yn^2+zn^2  |
    	*/
    	int ysize = n * sizeof(double);
    	double *y = (double *)malloc(ysize);
    
    	/*
    		z ~NX3
    		|x1 y1 z1|
    		|...............|
    		|...............|
    		|xn yn zn|
    	*/
    	int zsize = 3 * n * sizeof(double);
    	double *z = (double *)malloc(zsize);
    
    	/*
    		p  ~ Nx1
    		| 1 |
    		| .. |
    		| .. |
    		| 1 |
    	*/
    	int psize = n * sizeof(double);
    	double *p = (double *)malloc(psize);
    
    	for (int i=0;i<n;i++)
    	{
    		file>>*(x+i*4+0)>>*( x+i*4+1)>>*(x +i*4 +2);
    		*(x+i*4+3) = -1;
    
    		*(y +i) = *(x+i*4+0) * *(x+i*4+0) +*(x+i*4+1) * *(x+i*4+1) + *(x+i*4+2) * *(x+i*4+2);
    
    		*(z+i*3+0) = *(x+i*4+0);
    		*(z+i*3+1) =  *(x+i*4+1);
    		*(z+i*3+2) =  *(x+i*4+2);
    
    		*(p+i) = 1;
    	}
    
    	file.close();
    	// ---------------------------- 球面方程
    	//x^2 +y^2 + z^2 - AX - BY - CZ +D  =0
    
    	// x 对应的矩阵
    	double * MAT_X = (double *)malloc(n * 4 * sizeof(double));
    	memcpy(MAT_X,x,xsize);
    
    	// y 对应的矩阵
    	double *MAT_Y = (double *)malloc(n * 1 *sizeof(double));
    	memcpy(MAT_Y,y,ysize);
    
    	//xT -- x的转置矩阵
    	double *MAT_XT =(double *)malloc(4 * n * sizeof(double));
    	transPoseMatrix(MAT_X,n,4,MAT_XT);
    
    	// xT (4xn)  *  x(n*4) = XT_X(4*4)
    	double *MAT_XT_X = (double *)malloc(4 * 4 * sizeof(double));
    	mulMatrix(MAT_XT,4,n,MAT_X,n,4,MAT_XT_X);
    
    	//xT (4xn)  *  y(n*1) = xT_Y(4*1)
    	double *MAT_XT_Y = (double *)malloc(4 * 1 * sizeof(double ));
    	mulMatrix(MAT_XT,4,n,MAT_Y,n,1,MAT_XT_Y);
    
    
    	//MAT_XT_X_INVERT -- MAT_XT_X的逆矩阵
    	double *MAT_XT_X_INVERT = NULL;
    	InverseMatrix(MAT_XT_X,4);
    	MAT_XT_X_INVERT = MAT_XT_X;
    
    	//MAT_ABCD 4X1结果矩阵
    	double *MAT_ABCD = (double *)malloc(4 * 1 * sizeof(double));
    	mulMatrix(MAT_XT_X_INVERT,4,4,MAT_XT_Y,4,1,MAT_ABCD);
    
    	double c_x,c_y,c_z,c_r;
    	double *ptr = MAT_ABCD;
    	c_x = *ptr /2;
    	c_y = *(ptr+1)/2;
    	c_z = *(ptr+2)/2;
    	c_r =sqrt (c_x *c_x +c_y *c_y +c_z *c_z -*(ptr+3));
    
    	//-----------------------平面方程
    	//E X + F y +G z  =1
    
    	// z 对应矩阵
    	double * MAT_Z = (double *)malloc(n * 3 * sizeof(double ));
    	memcpy(MAT_Z,z,zsize);
    
    	// p 对应矩阵
    	double *MAT_P =(double *)malloc(n * 1 * sizeof(double));
    	memcpy(MAT_P,p,psize);
    
    	//z 的转置矩阵
    	double *MAT_ZT = (double *)malloc(3 * n * sizeof(double));
    	transPoseMatrix(MAT_Z,n,3,MAT_ZT);
    
    	//zt * z
    	double * MAT_ZT_Z = (double *)malloc(3 * 3 * sizeof(double));
    	mulMatrix(MAT_ZT,3,n,MAT_Z,n,3,MAT_ZT_Z);
    
    	//ZT * P 
    	double * MAT_ZT_P =(double *)malloc( 3 * 1 * sizeof(double));
    	mulMatrix(MAT_ZT,3,n,MAT_P,n,1,MAT_ZT_P);
    
    	// MAT_ZT_Z的逆矩阵 
    	double *MAT_ZT_Z_INVERT = (double *)malloc(3 * 3 * sizeof(double));
    	InverseMatrix(MAT_ZT_Z,3);
    	MAT_ZT_Z_INVERT = MAT_ZT_Z;
    
    
    	//MAT_EFG 3X1
    	double *MAT_EFG = (double *)malloc(3 * 1*sizeof(double));
    	mulMatrix(MAT_ZT_Z_INVERT,3,3,MAT_ZT_P,3,1,MAT_EFG);
    
    	double E,F,G;
    	E =* MAT_EFG;
    	F = *(MAT_EFG+1);
    	G = *(MAT_EFG+2 );
    	//圆心坐标 半径
    	double n_x, n_y, n_z, n_r;
         n_x = ((F*F+G*G)*c_x +E *(-F*c_y - G*c_z +1))/ ( E *E + F *F+ G *G);
         n_y = ((E*E+G*G)*c_y +F* (-E*c_x -G*c_z +1))/ ( E *E + F *F+ G *G);
         n_z = ((E*E+F*F)*c_z +G*(-E*c_x -F *c_y +1))/( E *E + F *F+ G *G);
         n_r = sqrt( c_r *c_r - (E *c_x +F *c_y +G *c_z -1 ) *(E *c_x +F *c_y +G *c_z -1 ) /(E *E +F * F +G *G) );
    
    	printf("%f %f %f %f\n",n_x,n_y,n_z,n_r);
    	free(x);
    	free(y);
    	free(z);
    	free(MAT_X);
    	free(MAT_XT);
    	free(MAT_XT_X);
    	free(MAT_XT_Y);
    	free(MAT_Y);
    	free(MAT_Z);
    	free(MAT_ZT);
    	free(MAT_ZT_P);
    	free(MAT_ZT_Z);
    	free(MAT_P);
    	free(MAT_ABCD);
    	free(MAT_EFG);
    
    
    }
    
  • 相关阅读:
    ThreadLocal全面解析,一篇带你入门
    StringTable字符串常量池的垃圾回收跟踪案例
    air镶边引7yue
    性能优化与团队效率
    air 错误信息一览
    AS3 使用unloadAndStop()卸载加载的swf以及里面的声音
    flash/flex/as3应用程序加载as2、as1版本的swf遇到的问题
    查看swc的代码
    chart 属性
    flex动态控制 effect
  • 原文地址:https://www.cnblogs.com/xiaomaLV2/p/2159908.html
Copyright © 2020-2023  润新知