00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "CATCurveFit.h"
00014
00015 CATCurveFit::CATCurveFit(CATUInt32 degree)
00016 {
00017 fDirty = true;
00018 if (degree < 3)
00019 {
00020 CATASSERT(degree >= 3,"Degree must be 3 or greater for curve fitting. Use CATLineFit for lines.");
00021 degree = 3;
00022 }
00023 fDegree = degree;
00024 }
00025
00026 CATCurveFit::~CATCurveFit()
00027 {
00028 Clear();
00029 }
00030
00031 bool CATCurveFit::AddPoint( CATFloat64 x, CATFloat64 y)
00032 {
00033 fPointList.push_back(CATPoint(x,y));
00034 fDirty = true;
00035 return true;
00036 }
00037
00038 bool CATCurveFit::Clear()
00039 {
00040
00041 fCoef.clear();
00042 fPointList.clear();
00043
00044
00045 fDirty = true;
00046 return true;
00047 }
00048
00049
00050 bool CATCurveFit::GetDegree(CATUInt32 °ree)
00051 {
00052 degree = 0;
00053
00054
00055 if (fDirty)
00056 {
00057 if (!CalcFit())
00058 {
00059 return false;
00060 }
00061 }
00062
00063
00064 degree = (CATUInt32)fCoef.size();
00065 return degree > 0;
00066 }
00067
00068 bool CATCurveFit::GetCoefficient( CATUInt32 deg, CATFloat64& coef)
00069 {
00070
00071 if (fDirty)
00072 {
00073 if (!CalcFit())
00074 {
00075 return false;
00076 }
00077 }
00078
00079
00080 if (deg >= fCoef.size())
00081 {
00082 return false;
00083 }
00084
00085
00086 coef = fCoef[deg];
00087 return true;
00088 }
00089
00090
00091 CATUInt32 CATCurveFit::GetNumPoints()
00092 {
00093 return (CATUInt32)fPointList.size();
00094 }
00095
00096 bool CATCurveFit::GetDataPoint( CATUInt32 n, CATFloat64& x, CATFloat64& y)
00097 {
00098 if (n >= fPointList.size())
00099 {
00100 return false;
00101 }
00102
00103 CATPoint point = fPointList[n];
00104
00105 x = point.x;
00106 y = point.y;
00107
00108 return true;
00109 }
00110
00111 bool CATCurveFit::GetCurrentErr(CATFloat64 &err)
00112 {
00113 err = 0.0;
00114
00115 if (fDirty)
00116 {
00117 if (!CalcFit())
00118 {
00119 return false;
00120 }
00121 }
00122
00123
00124 err = fLastErr;
00125
00126 return true;
00127 }
00128
00129
00130
00131 bool CATCurveFit::CalcYVal( CATFloat64 x, CATFloat64& y)
00132 {
00133 y = 0.0;
00134
00135 if (fDirty)
00136 {
00137 if (!CalcFit())
00138 {
00139 return false;
00140 }
00141 }
00142
00143
00144 CATUInt32 degree = (CATUInt32)fCoef.size();
00145
00146 for (CATUInt32 i=0; i < degree; i++)
00147 {
00148 CATFloat64 coef = fCoef[i];
00149 y += (coef) * pow(x,(CATFloat64)i);
00150 }
00151
00152 return true;
00153 }
00154
00155
00156 bool CATCurveFit::CalcFit()
00157 {
00158
00159 CATUInt32 numPoints = GetNumPoints();
00160
00161 if (numPoints < fDegree)
00162 {
00163 CATTRACE("Too few points for calc fit.\n");
00164 return false;
00165 }
00166
00167
00168 void* data=0;
00169
00170 fCoef.clear();
00171
00172 this->fLastErr = 0.0;
00173
00174
00175
00176
00177
00178 CATMatrix primary(fDegree, (CATUInt32)fPointList.size() );
00179 CATMatrix ymatrix(1, (CATUInt32)fPointList.size() );
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198 CATUInt32 i;
00199 for (i=0; i < fPointList.size(); i++)
00200 {
00201 CATPoint curPoint = fPointList[i];
00202 ymatrix.Val(0,i) = curPoint.y;
00203
00204 for (CATUInt32 curDegree = 0; curDegree < fDegree; curDegree++)
00205 {
00206 primary.Val(curDegree,i) = pow(curPoint.x,(CATFloat64)curDegree);
00207 }
00208 }
00209
00210
00211 CATMatrix pseudoInverse = primary.GetPseudoInverse();
00212
00213
00214 CATMatrix coefs = pseudoInverse * ymatrix;
00215
00216
00217 for (i = 0; i < coefs.Height(); i++)
00218 {
00219 fCoef.push_back(coefs.cVal(0,i));
00220 }
00221
00222
00223 fDirty = false;
00224 return true;
00225 }
00226
00227 bool CATCurveFit::GetMinMax( CATFloat64& minX, CATFloat64& minY, CATFloat64& maxX, CATFloat64& maxY)
00228 {
00229 CATUInt32 numPoints = GetNumPoints();
00230 if (numPoints == 0)
00231 return false;
00232
00233 for (CATUInt32 i=0; i<numPoints; i++)
00234 {
00235 CATPoint curPoint = fPointList[i];
00236
00237 if (i == 0)
00238 {
00239 minX = maxX = curPoint.x;
00240 minY = maxY = curPoint.y;
00241 }
00242 else
00243 {
00244 minX = min(curPoint.x, minX);
00245 maxX = max(curPoint.x, maxX);
00246 minY = min(curPoint.y, minY);
00247 maxY = max(curPoint.y, maxY);
00248 }
00249 }
00250
00251 return true;
00252 }
00253
00254
00255
00256
00257
00258
00259
00260
00261 bool CATCurveFit::LangrangianCalcY( CATFloat64 x, CATFloat64& y)
00262 {
00263 y = 0.0;
00264
00265 CATFloat64 sum = 0;
00266 CATUInt32 degree = (CATUInt32)fPointList.size();
00267
00268 for (CATUInt32 i = 0; i < degree; i++)
00269 {
00270 CATPoint pi = fPointList[i];
00271
00272 CATFloat64 p = 1;
00273 for (CATUInt32 j=0; j < degree; j++)
00274 {
00275 if (j != i)
00276 {
00277 CATPoint pj = fPointList[j];
00278 p = p * (x - pj.x) / (pi.x - pj.x);
00279 }
00280 }
00281
00282 sum += p * pi.y;
00283 }
00284 y = sum;
00285 return true;
00286 }
00287