📄 curvfitt.pas
字号:
{**************************************************}
{ TCurveFittingFunction }
{ TTrendFunction }
{ Copyright (c) 1995-2005 by David Berneda }
{**************************************************}
unit CurvFitt;
{$I TeeDefs.inc}
interface
{ TCustomFittingFunction derives from standard TTeeFunction.
TCurveFittingFunction and TTrendFunction both derive from
TCustomFittingFunction.
Based on a Polynomial degree value (# of polynomy items), a curve
fitting is calculated for each X,Y pair value to determine the new
Y position for each source X value.
}
Uses Classes, TeePoly, StatChar, TeEngine;
Type
TTypeFitting=( cfPolynomial );
TCustomFittingFunction=class(TTeeFunction)
private
FFactor : Integer;
FFirstPoint : Integer;
FFirstCalcPoint : Integer;
FLastPoint : Integer;
FLastCalcPoint : Integer;
FPolyDegree : Integer; { <-- between 1 and 20 }
FTypeFitting : TTypeFitting;
{ internal }
IAnswerVector : TDegreeVector;
IMinYValue : Double;
Procedure SetFactor(const Value:Integer);
Procedure SetFirstCalcPoint(Value:Integer);
Procedure SetFirstPoint(Value:Integer);
Procedure SetIntegerProperty(Var Variable:Integer; Value:Integer);
Procedure SetLastCalcPoint(Value:Integer);
Procedure SetLastPoint(Value:Integer);
Procedure SetPolyDegree(Value:Integer);
Procedure SetTypeFitting(Value:TTypeFitting);
protected
Function GetAnswerVector(Index:Integer):Double;
procedure AddFittedPoints(Source:TChartSeries); virtual;
property Factor:Integer read FFactor write SetFactor;
public
Constructor Create(AOwner: TComponent); override;
procedure AddPoints(Source:TChartSeries); override;
Function GetCurveYValue(Source:TChartSeries; Const X:Double):Double;
// properties
property AnswerVector[Index:Integer]:Double read GetAnswerVector;
property FirstCalcPoint:Integer read FFirstCalcPoint write SetFirstCalcPoint default -1;
property FirstPoint:Integer read FFirstPoint write SetFirstPoint default -1;
property LastCalcPoint:Integer read FLastCalcPoint write SetLastCalcPoint default -1;
property LastPoint:Integer read FLastPoint write SetLastPoint default -1;
property PolyDegree:Integer read FPolyDegree write SetPolyDegree default 5;
property TypeFitting:TTypeFitting read FTypeFitting write SetTypeFitting default cfPolynomial;
end;
TCurveFittingFunction=class(TCustomFittingFunction)
published
property Factor default 1;
property FirstCalcPoint;
property FirstPoint;
property LastCalcPoint;
property LastPoint;
property PolyDegree;
property TypeFitting;
end;
TTrendStyle=(tsNormal,tsLogarithmic,tsExponential);
TCustomTrendFunction=class(TTeeFunction)
private
IStyle : TTrendStyle;
ICount : Integer;
SumX : Double;
SumXY : Double;
SumY : Double;
SumX2 : Double;
SumY2 : Double;
function CalculateValues(Source:TChartSeries; FirstIndex,LastIndex:Integer):Boolean;
protected
Procedure CalculatePeriod( Source:TChartSeries;
Const tmpX:Double;
FirstIndex,LastIndex:Integer); override;
Procedure CalculateAllPoints( Source:TChartSeries;
NotMandatorySource:TChartValueList); override;
public
Constructor Create(AOwner: TComponent); override;
Function Calculate(SourceSeries:TChartSeries; First,Last:Integer):Double; override;
Function CalculateMany(SourceSeriesList:TList; ValueIndex:Integer):Double; override;
Function CalculateTrend( Var m,b:Double; Source:TChartSeries;
FirstIndex,LastIndex:Integer):Boolean; // 6.02
Function Coefficient(Source:TChartSeries; FirstIndex,LastIndex:Integer):Double;
end;
TTrendFunction=class(TCustomTrendFunction);
TExpTrendFunction=class(TCustomTrendFunction)
public
Constructor Create(AOwner: TComponent); override;
end;
TCorrelationFunction=class(TCustomTrendFunction)
protected
Procedure CalculatePeriod( Source:TChartSeries;
Const tmpX:Double;
FirstIndex,LastIndex:Integer); override;
public
Function Calculate(SourceSeries:TChartSeries; First,Last:Integer):Double; override;
Function CalculateMany(SourceSeriesList:TList; ValueIndex:Integer):Double; override;
end;
implementation
Uses Math, SysUtils, TeeProCo, Chart, TeeProcs, TeeConst, TeCanvas;
{ TCurveFittingFunction }
Constructor TCustomFittingFunction.Create(AOwner: TComponent);
Begin
inherited;
CanUsePeriod:=False;
InternalSetPeriod(1);
FPolyDegree:=5;
FTypeFitting:=cfPolynomial;
FFirstPoint:=-1;
FLastPoint:=-1;
FFirstCalcPoint:=-1;
FLastCalcPoint:=-1;
FFactor:=1;
end;
Procedure TCustomFittingFunction.SetIntegerProperty(Var Variable:Integer; Value:Integer);
Begin
if Variable<>Value then
Begin
Variable:=Value;
Recalculate;
end;
end;
Procedure TCustomFittingFunction.SetFirstPoint(Value:Integer);
Begin
SetIntegerProperty(FFirstPoint,Value);
End;
Procedure TCustomFittingFunction.SetLastPoint(Value:Integer);
Begin
SetIntegerProperty(FLastPoint,Value);
End;
Procedure TCustomFittingFunction.SetFactor(const Value:Integer);
begin
SetIntegerProperty(FFactor,Math.Max(1,Value));
end;
Procedure TCustomFittingFunction.SetFirstCalcPoint(Value:Integer);
Begin
SetIntegerProperty(FFirstCalcPoint,Value);
End;
Procedure TCustomFittingFunction.SetLastCalcPoint(Value:Integer);
Begin
SetIntegerProperty(FLastCalcPoint,Value);
End;
Procedure TCustomFittingFunction.SetTypeFitting(Value:TTypeFitting);
Begin
if FTypeFitting<>Value then
Begin
FTypeFitting:=Value;
Recalculate;
end;
end;
Procedure TCustomFittingFunction.SetPolyDegree(Value:Integer);
Begin
if FPolyDegree<>Value then
begin
if (Value<1) or (Value>20) then
Raise Exception.Create(TeeMsg_PolyDegreeRange);
FPolyDegree:=Value;
Recalculate;
end;
end;
Function TCustomFittingFunction.GetAnswerVector(Index:Integer):Double;
Begin
if (Index<1) or (Index>FPolyDegree) then
Raise Exception.CreateFmt(TeeMsg_AnswerVectorIndex,[FPolyDegree]);
result:=IAnswerVector[Index];
End;
procedure TCustomFittingFunction.AddFittedPoints(Source:TChartSeries);
Var tmpX : Double;
tmpX2 : Double;
tmpMinXValue : Double;
tmpStep : Double;
t : Integer;
tt : Integer;
tmpStart : Integer;
tmpEnd : Integer;
begin
IMinYValue:=ValueList(Source).MinValue;
With Source do
begin
tmpMinXValue:=XValues.MinValue;
if FFirstPoint=-1 then tmpStart:=0
else tmpStart:=FFirstPoint;
if FLastPoint=-1 then tmpEnd:=Count-1
else tmpEnd:=FLastPoint;
FFactor:=Math.Max(1,Factor);
for t:=tmpStart to tmpEnd-1 do { 1 to 1 relationship between source and self }
begin
tmpX:=XValues.Value[t];
tmpStep:=(XValues.Value[t+1]-tmpX)/Factor;
for tt:=0 to Factor-1 do
begin
tmpX2:=tmpX+tmpStep*tt;
ParentSeries.AddXY( tmpX2, CalcFitting( FPolyDegree,
IAnswerVector,
tmpX2-tmpMinXValue)+IMinYValue);
end;
end;
tmpX2:=XValues.Value[tmpEnd];
ParentSeries.AddXY( tmpX2, CalcFitting( FPolyDegree,
IAnswerVector,
tmpX2-tmpMinXValue)+IMinYValue);
end;
end;
procedure TCustomFittingFunction.AddPoints(Source:TChartSeries);
var t : Integer;
tmpStart : Integer;
tmpEnd : Integer;
tmpCount : Integer;
tmpPos : Integer;
IXVector : TVector;
IYVector : TVector;
tmpMinXValue : Double;
AList : TChartValueList;
Begin
ParentSeries.Clear;
With Source do
if Count>=FPolyDegree then
begin
AList:=ValueList(Source);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -