00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "matvec3D.h"
00016
00017 inline void FitParaboloid( vec3 *points, int numpts, double *coeffs );
00018 inline void RotateParaboloid( double *coeff, double *R1, double *R2, mat3 *Rot, double *rotAngle );
00019
00020 #define FIT_TINY 1.0e-6
00021 #define CONCAVE_WARNING 1.0e-3
00022
00023 void FitParaboloid( vec3 *points, int numpts, double *coeffs )
00024 {
00025
00026
00027
00028
00029 mat3 A, A_add, A_inverse;
00030 vec3 z, z_add, x;
00031
00032 z.set(0, 0, 0);
00033 A=mat3::ZERO;
00034
00035 for( int i = 0; i < numpts; i++ )
00036 {
00037 z_add.set(points[i].x()*points[i].x()*points[i].z(),
00038 points[i].y()*points[i].y()*points[i].z(),
00039 points[i].x()*points[i].y()*points[i].z());
00040 z+=z_add;
00041
00042 double M [9]={points[i].x()*points[i].x()*points[i].x()*points[i].x(),
00043 points[i].x()*points[i].x()*points[i].y()*points[i].y(),
00044 points[i].x()*points[i].x()*points[i].x()*points[i].y(),
00045 points[i].x()*points[i].x()*points[i].y()*points[i].y(),
00046 points[i].y()*points[i].y()*points[i].y()*points[i].y(),
00047 points[i].x()*points[i].y()*points[i].y()*points[i].y(),
00048 points[i].x()*points[i].x()*points[i].x()*points[i].y(),
00049 points[i].x()*points[i].y()*points[i].y()*points[i].y(),
00050 points[i].x()*points[i].x()*points[i].y()*points[i].y()};
00051
00052 A_add.set(M);
00053
00054 A+=A_add;
00055 }
00056
00057 A_inverse = A.inverse();
00058
00059 x=A_inverse*z;
00060
00061 coeffs[0] = x.x();
00062 coeffs[1] = x.y();
00063 coeffs[2] = x.z();
00064 for (int i=0; i<3; i++) {
00065
00066 if ( fabs(coeffs[i]) < FIT_TINY ) {
00067 coeffs[i] = 0.0;
00068 }
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 }
00081
00082
00083 }
00084
00085 void RotateParaboloid( double *coeff, double *R1, double *R2, mat3 *Rot, double *rotAngle )
00086 {
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 double theta, sintheta, costheta;
00098 vec3 col1, col2, col3;
00099
00100 if( fabs(coeff[2]) > FIT_TINY )
00101 {
00102 if( coeff[0] != coeff[1] )
00103 theta = atan( coeff[2]/(coeff[1] - coeff[0]) )/2.0;
00104 else
00105 theta = M_PI/2;
00106
00107 *rotAngle = theta;
00108 sintheta = sin(theta);
00109 costheta = cos(theta);
00110
00111 col1.set( costheta, sintheta, 0.0 );
00112 col2.set( -1.0*sintheta, costheta, 0.0 );
00113 col3.set( 0.0, 0.0, 1.0 );
00114 Rot->set( col1, col2, col3 );
00115
00116 double temp1 = (coeff[0]*costheta*costheta + coeff[1]*sintheta*sintheta
00117 - coeff[2] * sintheta*costheta)*2;
00118 double temp2 = (coeff[0]*sintheta*sintheta + coeff[1]*costheta*costheta
00119 + coeff[2] * sintheta*costheta)*2;
00120 if( fabs(temp1) > FIT_TINY ) {
00121 *R1 = 1/temp1;
00122 } else {
00123 *R1 = -1.0;
00124 }
00125 if( fabs(temp2) > FIT_TINY ) {
00126 *R2 = 1/temp2;
00127 } else {
00128 *R2 = -1.0;
00129 }
00130
00131
00132 }
00133 else
00134 {
00135 if( fabs(coeff[0]) > FIT_TINY ) {
00136 *R1 = 1/(2*coeff[0]);
00137 } else {
00138 *R1 = -1.0;
00139 }
00140 if( fabs(coeff[1]) > FIT_TINY ) {
00141 *R2 = 1/(2*coeff[1]);
00142 } else {
00143 *R2 = -1.0;
00144 }
00145
00146 *rotAngle = 0;
00147 *Rot = mat3::IDENTITY;
00148
00149 }
00150
00151
00152
00153
00154
00155 }