mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-22 13:42:50 +02:00
TAChart: Add TChartSourceBuffer utility class
git-svn-id: trunk@28800 -
This commit is contained in:
parent
7cc2d96db6
commit
b669510279
@ -25,6 +25,7 @@ uses
|
||||
Classes, Types, TAChartUtils;
|
||||
|
||||
type
|
||||
EBufferError = class(EChartError);
|
||||
EEditableSourceRequired = class(EChartError);
|
||||
EYCountError = class(EChartError);
|
||||
|
||||
@ -87,6 +88,26 @@ type
|
||||
property YCount: Cardinal read FYCount write SetYCount default 1;
|
||||
end;
|
||||
|
||||
{ TChartSourceBuffer }
|
||||
|
||||
TChartSourceBuffer = class
|
||||
private
|
||||
FBuf: array of TChartDataItem;
|
||||
FCount: Cardinal;
|
||||
FStart: Cardinal;
|
||||
FSum: TChartDataItem;
|
||||
function GetCapacity: Cardinal; inline;
|
||||
procedure Put(AIndex: Integer; const AItem: TChartDataItem);
|
||||
procedure Remove(AIndex: Integer);
|
||||
procedure SetCapacity(AValue: Cardinal); inline;
|
||||
public
|
||||
procedure AddFirst(const AItem: TChartDataItem);
|
||||
procedure AddLast(const AItem: TChartDataItem);
|
||||
procedure Clear; inline;
|
||||
procedure GetSum(var AItem: TChartDataItem);
|
||||
property Capacity: Cardinal read GetCapacity write SetCapacity;
|
||||
end;
|
||||
|
||||
procedure SetDataItemDefaults(var AItem: TChartDataItem);
|
||||
|
||||
implementation
|
||||
@ -106,6 +127,89 @@ begin
|
||||
AItem.YList[i] := 0;
|
||||
end;
|
||||
|
||||
{ TChartSourceBuffer }
|
||||
|
||||
procedure TChartSourceBuffer.AddFirst(const AItem: TChartDataItem);
|
||||
begin
|
||||
if Capacity = 0 then
|
||||
raise EBufferError.Create('');
|
||||
FStart := (FStart + Cardinal(High(FBuf))) mod Capacity;
|
||||
if FCount = Capacity then
|
||||
Remove(FStart)
|
||||
else
|
||||
FCount += 1;
|
||||
Put(FStart, AItem);
|
||||
end;
|
||||
|
||||
procedure TChartSourceBuffer.AddLast(const AItem: TChartDataItem);
|
||||
begin
|
||||
if Capacity = 0 then
|
||||
raise EBufferError.Create('');
|
||||
if FCount = Capacity then begin
|
||||
Remove(FStart);
|
||||
Put(FStart, AItem);
|
||||
FStart += 1;
|
||||
end
|
||||
else begin
|
||||
Put((FStart + FCount) mod Capacity, AItem);
|
||||
FCount += 1;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TChartSourceBuffer.Clear;
|
||||
begin
|
||||
FCount := 0;
|
||||
FSum.Y := 0;
|
||||
FSum.YList := nil;
|
||||
end;
|
||||
|
||||
function TChartSourceBuffer.GetCapacity: Cardinal;
|
||||
begin
|
||||
Result := Length(FBuf);
|
||||
end;
|
||||
|
||||
procedure TChartSourceBuffer.GetSum(var AItem: TChartDataItem);
|
||||
begin
|
||||
if FCount = 0 then
|
||||
raise EBufferError.Create('Empty');
|
||||
AItem.Y := FSum.Y;
|
||||
AItem.YList := Copy(FSum.YList);
|
||||
end;
|
||||
|
||||
procedure TChartSourceBuffer.Put(AIndex: Integer; const AItem: TChartDataItem);
|
||||
var
|
||||
i, oldLen: Integer;
|
||||
begin
|
||||
FBuf[AIndex] := AItem;
|
||||
with FSum do begin
|
||||
Y += AItem.Y;
|
||||
oldLen := Length(YList);
|
||||
SetLength(YList, Max(Length(AItem.YList), oldLen));
|
||||
for i := oldLen to High(YList) do
|
||||
YList[i] := 0;
|
||||
for i := 0 to Min(High(YList), High(AItem.YList)) do
|
||||
YList[i] += AItem.YList[i];
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TChartSourceBuffer.Remove(AIndex: Integer);
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
with FBuf[AIndex] do begin
|
||||
FSum.Y -= Y;
|
||||
for i := 0 to Min(High(FSum.YList), High(YList)) do
|
||||
FSum.YList[i] -= YList[i];
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TChartSourceBuffer.SetCapacity(AValue: Cardinal);
|
||||
begin
|
||||
if AValue = Capacity then exit;
|
||||
SetLength(FBuf, AValue);
|
||||
Clear;
|
||||
end;
|
||||
|
||||
{ TCustomChartSource }
|
||||
|
||||
procedure TCustomChartSource.AfterDraw;
|
||||
|
@ -205,7 +205,7 @@ type
|
||||
private
|
||||
FAccumulationMethod: TChartAccumulationMethod;
|
||||
FAccumulationRange: Integer;
|
||||
FHistory: array of TChartDataItem;
|
||||
FHistory: TChartSourceBuffer;
|
||||
FIndex: Integer;
|
||||
FItem: TChartDataItem;
|
||||
FListener: TListener;
|
||||
@ -218,7 +218,7 @@ type
|
||||
procedure CalcAccumulation(AIndex: Integer);
|
||||
procedure CalcPercentage;
|
||||
procedure Changed(ASender: TObject); inline;
|
||||
procedure ExtractItem(var AItem: TChartDataItem; AIndex: Integer);
|
||||
procedure ExtractItem(out AItem: TChartDataItem; AIndex: Integer);
|
||||
procedure SetAccumulationMethod(AValue: TChartAccumulationMethod);
|
||||
procedure SetAccumulationRange(AValue: Integer);
|
||||
procedure SetOrigin(AValue: TCustomChartSource);
|
||||
@ -999,28 +999,25 @@ end;
|
||||
|
||||
procedure TCalculatedChartSource.CalcAccumulation(AIndex: Integer);
|
||||
var
|
||||
i, j: Integer;
|
||||
i: Integer;
|
||||
begin
|
||||
SetLength(FHistory, AccumulationRange);
|
||||
FHistory.Capacity := AccumulationRange;
|
||||
if FIndex = AIndex - 1 then begin
|
||||
for i := High(FHistory) downto 1 do
|
||||
FHistory[i] := FHistory[i - 1];
|
||||
ExtractItem(FHistory[0], AIndex);
|
||||
ExtractItem(FItem, AIndex);
|
||||
FHistory.AddLast(FItem);
|
||||
end
|
||||
else
|
||||
for i := 0 to Min(High(FHistory), AIndex) do
|
||||
ExtractItem(FHistory[i], AIndex - i);
|
||||
SetDataItemDefaults(FItem);
|
||||
for i := 0 to Min(High(FHistory), AIndex) do begin
|
||||
FItem.Y += FHistory[i].Y;
|
||||
for j := 0 to High(FItem.YList) do
|
||||
FItem.YList[j] += FHistory[i].YList[j];
|
||||
else begin
|
||||
FHistory.Clear;
|
||||
for i := Max(AIndex - AccumulationRange + 1, 0) to AIndex do begin
|
||||
ExtractItem(FItem, i);
|
||||
FHistory.AddLast(FItem);
|
||||
end;
|
||||
end;
|
||||
FItem.X := FHistory[0].X;
|
||||
FHistory.GetSum(FItem);
|
||||
if AccumulationMethod = camAverage then begin
|
||||
FItem.Y /= Min(AccumulationRange, AIndex + 1);
|
||||
for j := 0 to High(FItem.YList) do
|
||||
FItem.YList[j] /= Min(AccumulationRange, AIndex + 1);
|
||||
for i := 0 to High(FItem.YList) do
|
||||
FItem.YList[i] /= Min(AccumulationRange, AIndex + 1);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -1051,17 +1048,19 @@ constructor TCalculatedChartSource.Create(AOwner: TComponent);
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
FIndex := -1;
|
||||
FHistory := TChartSourceBuffer.Create;
|
||||
FListener := TListener.Create(@FOrigin, @Changed);
|
||||
end;
|
||||
|
||||
destructor TCalculatedChartSource.Destroy;
|
||||
begin
|
||||
FreeAndNil(FHistory);
|
||||
FreeAndNil(FListener);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TCalculatedChartSource.ExtractItem(
|
||||
var AItem: TChartDataItem; AIndex: Integer);
|
||||
out AItem: TChartDataItem; AIndex: Integer);
|
||||
var
|
||||
t: TDoubleDynArray;
|
||||
i: Integer;
|
||||
|
@ -74,11 +74,14 @@ begin
|
||||
FSource.AccumulationMethod := camSum;
|
||||
FSource.AccumulationRange := 2;
|
||||
AssertEquals(3, FSource.YCount);
|
||||
AssertEquals(1, FSource[0]^.X);
|
||||
AssertEquals(102, FSource[0]^.Y);
|
||||
AssertEquals(2, FSource[1]^.X);
|
||||
AssertEquals(102 + 202, FSource[1]^.Y);
|
||||
AssertEquals(202 + 302, FSource[2]^.Y);
|
||||
FSource.AccumulationMethod := camAverage;
|
||||
AssertEquals((202 + 302) / 2, FSource[2]^.Y);
|
||||
AssertEquals((2002 + 2102) / 2, FSource[20]^.Y);
|
||||
AssertEquals(1, FSource[0]^.X);
|
||||
AssertEquals(102, FSource[0]^.Y);
|
||||
AssertEquals((102 + 202) / 2, FSource[1]^.Y);
|
||||
end;
|
||||
@ -114,15 +117,16 @@ begin
|
||||
end;
|
||||
|
||||
procedure TCalculatedSourceTest.SetUp;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
inherited SetUp;
|
||||
FOrigin := TListChartSource.Create(nil);
|
||||
FSource := TCalculatedChartSource.Create(nil);
|
||||
FSource.Origin := FOrigin;
|
||||
FOrigin.YCount := 3;
|
||||
FOrigin.SetYList(FOrigin.Add(1, 102), [103, 104]);
|
||||
FOrigin.SetYList(FOrigin.Add(2, 202), [203, 204]);
|
||||
FOrigin.SetYList(FOrigin.Add(3, 302), [303, 304]);
|
||||
for i := 1 to 100 do
|
||||
FOrigin.SetYList(FOrigin.Add(i, i * 100 + 2), [i * 100 + 3, i * 100 + 4]);
|
||||
end;
|
||||
|
||||
procedure TCalculatedSourceTest.TearDown;
|
||||
|
Loading…
Reference in New Issue
Block a user