📄 curvfitt.pas
字号:
tmpMinXValue:=XValues.MinValue;
IMinYValue:=AList.MinValue;
if FFirstCalcPoint=-1 then tmpStart:=0
else tmpStart:=Math.Max(0,FFirstCalcPoint);
if FLastCalcPoint=-1 then tmpEnd:=Count-1
else tmpEnd:=Math.Min(Count-1,FLastCalcPoint);
tmpCount:=(tmpEnd-tmpStart+1);
if tmpCount>0 then
begin
SetLength(IXVector,tmpCount+1);
SetLength(IYVector,tmpCount+1);
try
for t:=1 to tmpCount do
begin
tmpPos:=t+tmpStart-1;
IXVector[t]:=XValues.Value[tmpPos]-tmpMinXValue;
IYVector[t]:=AList.Value[tmpPos]-IMinYValue;
end;
PolyFitting(tmpCount,FPolyDegree,IXVector,IYVector,IAnswerVector);
AddFittedPoints(Source);
finally
IYVector:=nil;
IXVector:=nil;
end;
end;
end;
end;
{ calculates and returns the Y value corresponding to a X value }
Function TCustomFittingFunction.GetCurveYValue(Source:TChartSeries; Const X:Double):Double;
Begin
result:=CalcFitting(FPolyDegree,IAnswerVector,X-Source.XValues.MinValue)+IMinYValue;
end;
{ TCustomTrendFunction }
constructor TCustomTrendFunction.Create(AOwner: TComponent);
begin
inherited;
IStyle:=tsNormal;
end;
Function TCustomTrendFunction.Calculate(SourceSeries:TChartSeries; First,Last:Integer):Double;
begin
result:=0;
end;
Function TCustomTrendFunction.CalculateMany(SourceSeriesList:TList; ValueIndex:Integer):Double;
begin
result:=0;
end;
Procedure TCustomTrendFunction.CalculateAllPoints( Source:TChartSeries;
NotMandatorySource:TChartValueList);
begin
CalculatePeriod(Source,0,0,Source.Count-1);
end;
Procedure TCustomTrendFunction.CalculatePeriod( Source:TChartSeries;
Const tmpX:Double;
FirstIndex,LastIndex:Integer);
Var m : Double;
b : Double;
Procedure AddPoint(Const Value:Double);
var tmp : Double;
begin
Case IStyle of
tsNormal : tmp:=m*Value+b;
tsLogarithmic: tmp:=m*Ln(Value*b);
else
tmp:=m*Exp(b*Value);
end;
if Source.YMandatory then ParentSeries.AddXY(Value, tmp)
else ParentSeries.AddXY(tmp, Value)
end;
begin
if CalculateTrend(m,b,Source,FirstIndex,LastIndex) then
With Source.NotMandatoryValueList do
begin
if Order=loNone then
begin
AddPoint(MinValue);
AddPoint(MaxValue);
end
else
begin
AddPoint(Value[FirstIndex]);
AddPoint(Value[LastIndex]);
end;
end;
end;
Function TCustomTrendFunction.CalculateValues(Source:TChartSeries; FirstIndex,LastIndex:Integer):Boolean;
var tmpAll : Boolean;
t : Integer;
x : TChartValue;
y : TChartValue;
begin
if FirstIndex=TeeAllValues then
begin
FirstIndex:=0;
LastIndex:=Source.Count-1;
end;
ICount:=LastIndex-FirstIndex+1;
result:=ICount>1;
if result then
With Source do
begin
tmpAll:=(IStyle=tsNormal) and (ICount=Count);
if tmpAll then
begin
SumX:=NotMandatoryValueList.Total;
SumY:=ValueList(Source).Total;
end
else
begin
SumX:=0;
SumY:=0;
end;
SumX2:=0;
SumY2:=0;
SumXY:=0;
With ValueList(Source) do
for t:=FirstIndex to LastIndex do
begin
x:=NotMandatoryValueList.Value[t];
if IStyle=tsNormal then y:=Value[t]
else
if Value[t]<>0 then y:=Ln(Value[t])
else y:=0;
SumXY:=SumXY+x*y;
SumX2:=SumX2+Sqr(x);
SumY2:=SumY2+Sqr(y);
if not tmpAll then
begin
SumX:=SumX+x;
SumY:=SumY+y;
end;
end;
end;
end;
Function TCustomTrendFunction.Coefficient(Source:TChartSeries; FirstIndex,LastIndex:Integer):Double;
var tmpNumerator : Double;
tmpDenominator : Double;
begin
if CalculateValues(Source,FirstIndex,LastIndex) then
begin
tmpNumerator:=SumXY - SumX*SumY/ICount;
tmpDenominator:=Sqrt( (SumX2 - SumX*SumX/ICount) * (SumY2 - SumY*SumY/ICount) );
if tmpDenominator=0 then
result:=1
else
result:=tmpNumerator/tmpDenominator;
end
else result:=1;
end;
Function TCustomTrendFunction.CalculateTrend(Var m,b:Double; Source:TChartSeries; FirstIndex,LastIndex:Integer):Boolean;
var Divisor : Double;
begin
result:=CalculateValues(Source,FirstIndex,LastIndex);
if result then
if IStyle=tsNormal then
begin
Divisor:=ICount*SumX2-Sqr(SumX);
if Divisor<>0 then
begin
m:=( (ICount*SumXY) - (SumX*SumY) ) / Divisor;
b:=( (SumY*SumX2) - (SumX*SumXY) ) / Divisor;
end
else
begin
m:=1;
b:=0;
end;
end
else
begin
SumX:=SumX/ICount;
SumY:=SumY/ICount;
Divisor:= (SumX2-(ICount*SumX*SumX));
if Divisor=0 then b:=1
else b:=(SumXY-(ICount*SumX*SumY))/Divisor;
if IStyle=tsLogarithmic then m:=SumY-b*SumX
else m:=Exp(SumY-b*SumX);
end;
end;
{ TExpTrendFunction }
constructor TExpTrendFunction.Create(AOwner: TComponent);
begin
inherited;
IStyle:=tsExponential;
end;
{ TCorrelationFunction }
function TCorrelationFunction.Calculate(SourceSeries: TChartSeries; First,
Last: Integer): Double;
begin
result:=Coefficient(SourceSeries,First,Last);
end;
function TCorrelationFunction.CalculateMany(SourceSeriesList: TList;
ValueIndex: Integer): Double;
begin
result:=0;
end;
procedure TCorrelationFunction.CalculatePeriod(Source: TChartSeries;
const tmpX: Double; FirstIndex, LastIndex: Integer);
procedure AddPoint(const x,y:Double);
begin
with ParentSeries do
if YMandatory then ParentSeries.AddXY(x,y)
else ParentSeries.AddXY(y,x);
end;
var tmp : Double;
begin
tmp:=Calculate(Source,FirstIndex,LastIndex);
if ParentSeries.AllowSinglePoint then
ParentSeries.Add(tmp)
else
begin
AddPoint(Source.NotMandatoryValueList.MinValue,tmp);
AddPoint(Source.NotMandatoryValueList.MaxValue,tmp);
end;
end;
initialization
RegisterTeeFunction( TCurveFittingFunction, {$IFNDEF CLR}@{$ENDIF}TeeMsg_FunctionCurveFitting,
{$IFNDEF CLR}@{$ENDIF}TeeMsg_GalleryExtended );
RegisterTeeFunction( TTrendFunction, {$IFNDEF CLR}@{$ENDIF}TeeMsg_FunctionTrend,
{$IFNDEF CLR}@{$ENDIF}TeeMsg_GalleryExtended );
RegisterTeeFunction( TExpTrendFunction, {$IFNDEF CLR}@{$ENDIF}TeeMsg_FunctionExpTrend,
{$IFNDEF CLR}@{$ENDIF}TeeMsg_GalleryExtended );
RegisterTeeFunction( TCorrelationFunction, {$IFNDEF CLR}@{$ENDIF}TeeMsg_FunctionCorrelation,
{$IFNDEF CLR}@{$ENDIF}TeeMsg_GalleryExtended );
finalization
UnRegisterTeeFunctions([ TCurveFittingFunction, TTrendFunction,
TExpTrendFunction, TCorrelationFunction ]);
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -