mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-17 05:49:23 +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;
|
Classes, Types, TAChartUtils;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
EBufferError = class(EChartError);
|
||||||
EEditableSourceRequired = class(EChartError);
|
EEditableSourceRequired = class(EChartError);
|
||||||
EYCountError = class(EChartError);
|
EYCountError = class(EChartError);
|
||||||
|
|
||||||
@ -87,6 +88,26 @@ type
|
|||||||
property YCount: Cardinal read FYCount write SetYCount default 1;
|
property YCount: Cardinal read FYCount write SetYCount default 1;
|
||||||
end;
|
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);
|
procedure SetDataItemDefaults(var AItem: TChartDataItem);
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@ -106,6 +127,89 @@ begin
|
|||||||
AItem.YList[i] := 0;
|
AItem.YList[i] := 0;
|
||||||
end;
|
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 }
|
{ TCustomChartSource }
|
||||||
|
|
||||||
procedure TCustomChartSource.AfterDraw;
|
procedure TCustomChartSource.AfterDraw;
|
||||||
|
@ -205,7 +205,7 @@ type
|
|||||||
private
|
private
|
||||||
FAccumulationMethod: TChartAccumulationMethod;
|
FAccumulationMethod: TChartAccumulationMethod;
|
||||||
FAccumulationRange: Integer;
|
FAccumulationRange: Integer;
|
||||||
FHistory: array of TChartDataItem;
|
FHistory: TChartSourceBuffer;
|
||||||
FIndex: Integer;
|
FIndex: Integer;
|
||||||
FItem: TChartDataItem;
|
FItem: TChartDataItem;
|
||||||
FListener: TListener;
|
FListener: TListener;
|
||||||
@ -218,7 +218,7 @@ type
|
|||||||
procedure CalcAccumulation(AIndex: Integer);
|
procedure CalcAccumulation(AIndex: Integer);
|
||||||
procedure CalcPercentage;
|
procedure CalcPercentage;
|
||||||
procedure Changed(ASender: TObject); inline;
|
procedure Changed(ASender: TObject); inline;
|
||||||
procedure ExtractItem(var AItem: TChartDataItem; AIndex: Integer);
|
procedure ExtractItem(out AItem: TChartDataItem; AIndex: Integer);
|
||||||
procedure SetAccumulationMethod(AValue: TChartAccumulationMethod);
|
procedure SetAccumulationMethod(AValue: TChartAccumulationMethod);
|
||||||
procedure SetAccumulationRange(AValue: Integer);
|
procedure SetAccumulationRange(AValue: Integer);
|
||||||
procedure SetOrigin(AValue: TCustomChartSource);
|
procedure SetOrigin(AValue: TCustomChartSource);
|
||||||
@ -999,28 +999,25 @@ end;
|
|||||||
|
|
||||||
procedure TCalculatedChartSource.CalcAccumulation(AIndex: Integer);
|
procedure TCalculatedChartSource.CalcAccumulation(AIndex: Integer);
|
||||||
var
|
var
|
||||||
i, j: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
SetLength(FHistory, AccumulationRange);
|
FHistory.Capacity := AccumulationRange;
|
||||||
if FIndex = AIndex - 1 then begin
|
if FIndex = AIndex - 1 then begin
|
||||||
for i := High(FHistory) downto 1 do
|
ExtractItem(FItem, AIndex);
|
||||||
FHistory[i] := FHistory[i - 1];
|
FHistory.AddLast(FItem);
|
||||||
ExtractItem(FHistory[0], AIndex);
|
|
||||||
end
|
end
|
||||||
else
|
else begin
|
||||||
for i := 0 to Min(High(FHistory), AIndex) do
|
FHistory.Clear;
|
||||||
ExtractItem(FHistory[i], AIndex - i);
|
for i := Max(AIndex - AccumulationRange + 1, 0) to AIndex do begin
|
||||||
SetDataItemDefaults(FItem);
|
ExtractItem(FItem, i);
|
||||||
for i := 0 to Min(High(FHistory), AIndex) do begin
|
FHistory.AddLast(FItem);
|
||||||
FItem.Y += FHistory[i].Y;
|
|
||||||
for j := 0 to High(FItem.YList) do
|
|
||||||
FItem.YList[j] += FHistory[i].YList[j];
|
|
||||||
end;
|
end;
|
||||||
FItem.X := FHistory[0].X;
|
end;
|
||||||
|
FHistory.GetSum(FItem);
|
||||||
if AccumulationMethod = camAverage then begin
|
if AccumulationMethod = camAverage then begin
|
||||||
FItem.Y /= Min(AccumulationRange, AIndex + 1);
|
FItem.Y /= Min(AccumulationRange, AIndex + 1);
|
||||||
for j := 0 to High(FItem.YList) do
|
for i := 0 to High(FItem.YList) do
|
||||||
FItem.YList[j] /= Min(AccumulationRange, AIndex + 1);
|
FItem.YList[i] /= Min(AccumulationRange, AIndex + 1);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1051,17 +1048,19 @@ constructor TCalculatedChartSource.Create(AOwner: TComponent);
|
|||||||
begin
|
begin
|
||||||
inherited Create(AOwner);
|
inherited Create(AOwner);
|
||||||
FIndex := -1;
|
FIndex := -1;
|
||||||
|
FHistory := TChartSourceBuffer.Create;
|
||||||
FListener := TListener.Create(@FOrigin, @Changed);
|
FListener := TListener.Create(@FOrigin, @Changed);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TCalculatedChartSource.Destroy;
|
destructor TCalculatedChartSource.Destroy;
|
||||||
begin
|
begin
|
||||||
|
FreeAndNil(FHistory);
|
||||||
FreeAndNil(FListener);
|
FreeAndNil(FListener);
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCalculatedChartSource.ExtractItem(
|
procedure TCalculatedChartSource.ExtractItem(
|
||||||
var AItem: TChartDataItem; AIndex: Integer);
|
out AItem: TChartDataItem; AIndex: Integer);
|
||||||
var
|
var
|
||||||
t: TDoubleDynArray;
|
t: TDoubleDynArray;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
|
@ -74,11 +74,14 @@ begin
|
|||||||
FSource.AccumulationMethod := camSum;
|
FSource.AccumulationMethod := camSum;
|
||||||
FSource.AccumulationRange := 2;
|
FSource.AccumulationRange := 2;
|
||||||
AssertEquals(3, FSource.YCount);
|
AssertEquals(3, FSource.YCount);
|
||||||
|
AssertEquals(1, FSource[0]^.X);
|
||||||
AssertEquals(102, FSource[0]^.Y);
|
AssertEquals(102, FSource[0]^.Y);
|
||||||
|
AssertEquals(2, FSource[1]^.X);
|
||||||
AssertEquals(102 + 202, FSource[1]^.Y);
|
AssertEquals(102 + 202, FSource[1]^.Y);
|
||||||
AssertEquals(202 + 302, FSource[2]^.Y);
|
AssertEquals(202 + 302, FSource[2]^.Y);
|
||||||
FSource.AccumulationMethod := camAverage;
|
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, FSource[0]^.Y);
|
||||||
AssertEquals((102 + 202) / 2, FSource[1]^.Y);
|
AssertEquals((102 + 202) / 2, FSource[1]^.Y);
|
||||||
end;
|
end;
|
||||||
@ -114,15 +117,16 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCalculatedSourceTest.SetUp;
|
procedure TCalculatedSourceTest.SetUp;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
inherited SetUp;
|
inherited SetUp;
|
||||||
FOrigin := TListChartSource.Create(nil);
|
FOrigin := TListChartSource.Create(nil);
|
||||||
FSource := TCalculatedChartSource.Create(nil);
|
FSource := TCalculatedChartSource.Create(nil);
|
||||||
FSource.Origin := FOrigin;
|
FSource.Origin := FOrigin;
|
||||||
FOrigin.YCount := 3;
|
FOrigin.YCount := 3;
|
||||||
FOrigin.SetYList(FOrigin.Add(1, 102), [103, 104]);
|
for i := 1 to 100 do
|
||||||
FOrigin.SetYList(FOrigin.Add(2, 202), [203, 204]);
|
FOrigin.SetYList(FOrigin.Add(i, i * 100 + 2), [i * 100 + 3, i * 100 + 4]);
|
||||||
FOrigin.SetYList(FOrigin.Add(3, 302), [303, 304]);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCalculatedSourceTest.TearDown;
|
procedure TCalculatedSourceTest.TearDown;
|
||||||
|
Loading…
Reference in New Issue
Block a user