TAChart: Add camDerivative value to TCalculatedChartSource.AccumulationMethod

git-svn-id: trunk@32184 -
This commit is contained in:
ask 2011-09-05 11:09:12 +00:00
parent ac40960c17
commit 842f2e1772
2 changed files with 69 additions and 8 deletions

View File

@ -90,6 +90,7 @@ type
Text: String;
YList: TDoubleDynArray;
function GetY(AIndex: Integer): Double;
procedure ClearY;
end;
PChartDataItem = ^TChartDataItem;
@ -176,7 +177,8 @@ type
procedure AddFirst(const AItem: TChartDataItem);
procedure AddLast(const AItem: TChartDataItem);
procedure Clear; inline;
function GetPLast: PChartDataItem;
function GetPLast: PChartDataItem; overload;
function GetPLast(AOffset: Cardinal): PChartDataItem; overload;
procedure GetSum(var AItem: TChartDataItem);
procedure RemoveLast; overload;
procedure RemoveValue(const AItem: TChartDataItem);
@ -324,6 +326,15 @@ end;
{ TChartDataItem }
procedure TChartDataItem.ClearY;
var
i: Integer;
begin
Y := 0;
for i := 0 to High(YList) do
YList[i] := 0;
end;
function TChartDataItem.GetY(AIndex: Integer): Double;
begin
AIndex := EnsureRange(AIndex, 0, Length(YList));
@ -395,6 +406,14 @@ begin
Result := Length(FBuf);
end;
function TChartSourceBuffer.GetPLast(AOffset: Cardinal): PChartDataItem;
begin
if AOffset >= FCount then
raise EBufferError.Create('AOffset');
AOffset := FCount - 1 - AOffset;
Result := @FBuf[(FStart + AOffset + Capacity) mod Capacity];
end;
function TChartSourceBuffer.GetPLast: PChartDataItem;
begin
Result := @FBuf[EndIndex];

View File

@ -157,7 +157,7 @@ type
property Sorted: Boolean read FSorted write FSorted default false;
end;
TChartAccumulationMethod = (camNone, camSum, camAverage);
TChartAccumulationMethod = (camNone, camSum, camAverage, camDerivative);
{ TCalculatedChartSource }
@ -176,8 +176,9 @@ type
FYOrder: array of Integer;
procedure CalcAccumulation(AIndex: Integer);
procedure CalcDerivative(AIndex: Integer);
procedure CalcPercentage;
procedure Changed(ASender: TObject); inline;
procedure Changed(ASender: TObject);
procedure ExtractItem(out AItem: TChartDataItem; AIndex: Integer);
procedure SetAccumulationMethod(AValue: TChartAccumulationMethod);
procedure SetAccumulationRange(AValue: Integer);
@ -846,12 +847,53 @@ begin
FHistory.AddLast(FItem);
end;
end;
FHistory.GetSum(FItem);
if AccumulationMethod = camAverage then begin
FItem.Y /= Min(ar, AIndex + 1);
for i := 0 to High(FItem.YList) do
FItem.YList[i] /= Min(ar, AIndex + 1);
case AccumulationMethod of
camSum:
FHistory.GetSum(FItem);
camAverage: begin
FHistory.GetSum(FItem);
FItem.Y /= Min(ar, AIndex + 1);
for i := 0 to High(FItem.YList) do
FItem.YList[i] /= Min(ar, AIndex + 1);
end;
camDerivative:
CalcDerivative(AIndex);
end;
end;
// Derivative is approximated by backwards finite difference
// with accuracy order of (AccumulationRange - 1).
procedure TCalculatedChartSource.CalcDerivative(AIndex: Integer);
const
COEFFS: array [2..7, 0..6] of Double = (
( 1, -1, 0, 0, 0, 0, 0),
( 3/2, -2, 1/2, 0, 0, 0, 0),
( 11/6, -3, 3/2, -1/3, 0, 0, 0),
( 25/12, -4, 3, -4/3, 1/4, 0, 0),
(137/60, -5, 5, -10/3, 5/4, -1/5, 0),
( 49/20, -6, 15/2, -20/3, 15/4, -6/5, 1/6));
var
prevItem: PChartDataItem;
i, j, ar: Integer;
dx: Double;
begin
FItem.ClearY;
if AIndex = 0 then exit;
dx := FItem.X - FHistory.GetPLast(1)^.X;
if dx = 0 then exit;
ar := Min(AccumulationRange, AIndex);
if (ar = 0) or (ar > High(COEFFS)) then
ar := High(COEFFS);
for j := 0 to ar - 1 do begin
prevItem := FHistory.GetPLast(j);
FItem.Y += prevItem^.Y * COEFFS[ar, j];
for i := 0 to High(FItem.YList) do
FItem.YList[i] += prevItem^.YList[i] * COEFFS[ar, j];
end;
FItem.Y /= dx;
for i := 0 to High(FItem.YList) do
FItem.YList[i] /= dx;
end;
procedure TCalculatedChartSource.CalcPercentage;