TAChart: Caching of cumulative and x/y list extents of chart sources. Issue #35313, part of patch by Marcin Wiazowski.

git-svn-id: trunk@60846 -
This commit is contained in:
wp 2019-04-05 12:13:04 +00:00
parent db219396ae
commit 056f96d7b5
2 changed files with 102 additions and 46 deletions

View File

@ -189,6 +189,12 @@ type
strict protected
FBasicExtent: TDoubleRect;
FBasicExtentIsValid: Boolean;
FCumulativeExtent: TDoubleRect;
FCumulativeExtentIsValid: Boolean;
FXListExtent: TDoubleRect;
FXListExtentIsValid: Boolean;
FYListExtent: TDoubleRect;
FYListExtentIsValid: Boolean;
FValuesTotal: Double;
FValuesTotalIsValid: Boolean;
FXCount: Cardinal;
@ -309,7 +315,7 @@ begin
AItem.Color := clTAColor;
AItem.Text := '';
for i := 0 to High(AItem.XList) do
Aitem.XList[i] := 0;
AItem.XList[i] := 0;
for i := 0 to High(AItem.YList) do
AItem.YList[i] := 0;
end;
@ -832,40 +838,64 @@ var
jyp, jyn: Integer;
begin
Result := Extent;
if (YCount < 2) and (XCount < 2) then exit;
// Skip the x and y values used for error bars when calculating the list extent.
if UseXList and (XErrorBarData.Kind = ebkChartSource) then begin
jxp := XErrorBarData.IndexPlus - 1; // -1 because XList is offset by 1
jxn := XErrorBarData.IndexMinus - 1;
end else begin
jxp := -1;
jxn := -1;
end;
if YErrorBarData.Kind = ebkChartSource then begin
jyp := YErrorBarData.IndexPlus - 1; // -1 because YList is offset by 1
jyn := YErrorBarData.IndexMinus - 1;
end else begin
jyp := -1;
jyn := -1;
end;
if UseXList and (XCount > 1) then begin
if not FXListExtentIsValid then begin
FXListExtent := EmptyExtent;
if UseXList and (XCount > 1) then
for i := 0 to Count - 1 do
with Item[i]^ do begin
for j := 0 to High(XList) do
if (j <> jxp) and (j <> jxn) then
UpdateMinMax(XList[j], Result.a.X, Result.b.X);
// Skip the x values used for error bars when calculating the list extent.
if XErrorBarData.Kind = ebkChartSource then begin
jxp := XErrorBarData.IndexPlus - 1; // -1 because XList index is offset by 1
jxn := XErrorBarData.IndexMinus - 1;
end else begin
jxp := -1;
jxn := -1;
end;
for i := 0 to Count - 1 do
with Item[i]^ do begin
for j := 0 to High(YList) do
if (j <> jyp) and (j <> jyn) then
UpdateMinMax(YList[j], Result.a.Y, Result.b.Y);
end
for i := 0 to Count - 1 do
with Item[i]^ do begin
for j := 0 to High(XList) do
if (j <> jxp) and (j <> jxn) then
UpdateMinMax(XList[j], FXListExtent.a.X, FXListExtent.b.X);
end;
FXListExtentIsValid := true;
end;
Result.a.X := Min(Result.a.X, FXListExtent.a.X);
Result.b.X := Max(Result.b.X, FXListExtent.b.X);
end;
if (YCount > 1) then begin
if not FYListExtentIsValid then begin
FYListExtent := EmptyExtent;
// Skip the y values used for error bars when calculating the list extent.
if YErrorBarData.Kind = ebkChartSource then begin
jyp := YErrorBarData.IndexPlus - 1; // -1 because YList index is offset by 1
jyn := YErrorBarData.IndexMinus - 1;
end else begin
jyp := -1;
jyn := -1;
end;
for i := 0 to Count - 1 do
with Item[i]^ do begin
for j := 0 to High(YList) do
if (j <> jyp) and (j <> jyn) then
UpdateMinMax(YList[j], FYListExtent.a.Y, FYListExtent.b.Y);
end;
FYListExtentIsValid := true;
end;
Result.a.Y := Min(Result.a.Y, FYListExtent.a.Y);
Result.b.Y := Max(Result.b.Y, FYListExtent.b.Y);
end;
end;
class procedure TCustomChartSource.CheckFormat(const AFormat: String);
begin
Format(AFormat, [0.0, 0.0, '', 0.0, 0.0]);
@ -919,28 +949,40 @@ function TCustomChartSource.ExtentCumulative: TDoubleRect;
var
h: Double;
i, j: Integer;
jyp: Integer = -1;
jyn: Integer = -1;
jyp, jyn: Integer;
begin
Result := Extent;
if YCount < 2 then exit;
// Skip the y values used for error bars in calculating the cumulative sum.
if YErrorBarData.Kind = ebkChartSource then begin
jyp := YErrorBarData.IndexPlus - 1; // -1 because YList index is offset by 1
jyn := YErrorBarData.IndexMinus - 1;
end;
if (YCount > 1) then begin
if not FCumulativeExtentIsValid then begin
FCumulativeExtent := EmptyExtent;
for i := 0 to Count - 1 do
with Item[i]^ do begin
h := NumberOr(Y);
for j := 0 to High(YList) do
if (j <> jyp) and (j <> jyn) then begin
h += NumberOr(YList[j]);
// If some of the Y values are negative, h may be non-monotonic.
UpdateMinMax(h, Result.a.Y, Result.b.Y);
// Skip the y values used for error bars when calculating the cumulative sum.
if YErrorBarData.Kind = ebkChartSource then begin
jyp := YErrorBarData.IndexPlus - 1; // -1 because YList index is offset by 1
jyn := YErrorBarData.IndexMinus - 1;
end else begin
jyp := -1;
jyn := -1;
end;
for i := 0 to Count - 1 do
with Item[i]^ do begin
h := NumberOr(Y);
for j := 0 to High(YList) do
if (j <> jyp) and (j <> jyn) then begin
h += NumberOr(YList[j]);
// If some of the Y values are negative, h may be non-monotonic.
UpdateMinMax(h, FCumulativeExtent.a.Y, FCumulativeExtent.b.Y);
end;
end;
FCumulativeExtentIsValid := true;
end;
Result.a.Y := Min(Result.a.Y, FCumulativeExtent.a.Y);
Result.b.Y := Max(Result.b.Y, FCumulativeExtent.b.Y);
end;
end;
{ Calculates the extent including multiple y values (non-stacked) }

View File

@ -555,6 +555,12 @@ procedure TListChartSource.ClearCaches;
begin
FBasicExtent := EmptyExtent;
FBasicExtentIsValid := true;
FCumulativeExtent := EmptyExtent;
FCumulativeExtentIsValid := true;
FXListExtent := EmptyExtent;
FXListExtentIsValid := true;
FYListExtent := EmptyExtent;
FYListExtentIsValid := true;
FValuesTotal := 0;
FValuesTotalIsValid := true;
end;
@ -613,6 +619,9 @@ begin
if FValuesTotalIsValid then
FValuesTotal -= NumberOr(Y);
end;
FCumulativeExtentIsValid := false;
FXListExtentIsValid := false;
FYListExtentIsValid := false;
Dispose(Item[AIndex]);
FData.Delete(AIndex);
Notify;
@ -711,7 +720,7 @@ begin
with Item[AIndex]^ do
for i := 0 to Min(High(AXList), High(XList)) do
XList[i] := AXList[i];
// wp: Update x extent here ?
FXListExtentIsValid := false;
end;
function TListChartSource.SetXValue(AIndex: Integer; AValue: Double): Integer;
@ -777,6 +786,8 @@ begin
with Item[AIndex]^ do
for i := 0 to Min(High(AYList), High(YList)) do
YList[i] := AYList[i];
FCumulativeExtentIsValid := false;
FYListExtentIsValid := false;
end;
procedure TListChartSource.SetYValue(AIndex: Integer; AValue: Double);
@ -867,6 +878,9 @@ begin
end;
if FValuesTotalIsValid then
FValuesTotal += NumberOr(AY);
FCumulativeExtentIsValid := false;
FXListExtentIsValid := false;
FYListExtentIsValid := false;
Notify;
end;