TAChart: Publish error bar params for TUserDefinedChartSource. Add method to query effective error bar values from chart source.

git-svn-id: trunk@58604 -
This commit is contained in:
wp 2018-07-23 22:09:06 +00:00
parent 0fbcf86523
commit 9bfe23796d
2 changed files with 77 additions and 40 deletions

View File

@ -194,8 +194,8 @@ type
FYCount: Cardinal;
procedure ChangeErrorBars(Sender: TObject); virtual;
function GetCount: Integer; virtual; abstract;
function GetErrorBarLimits(APointIndex: Integer; Which: Integer;
out AUpperLimit, ALowerLimit: Double): Boolean;
function GetErrorBarValues(APointIndex: Integer; Which: Integer;
out AUpperDelta, ALowerDelta: Double): Boolean;
function GetHasErrorBars(Which: Integer): Boolean;
function GetItem(AIndex: Integer): PChartDataItem; virtual; abstract;
procedure InvalidateCaches;
@ -227,6 +227,10 @@ type
out AUpperLimit, ALowerLimit: Double): Boolean;
function GetYErrorBarLimits(APointIndex: Integer;
out AUpperLimit, ALowerLimit: Double): Boolean;
function GetXErrorBarValues(APointIndex: Integer;
out AUpperDelta, ALowerDelta: Double): Boolean;
function GetYErrorBarValues(APointIndex: Integer;
out AUpperDelta, ALowerDelta: Double): Boolean;
function HasXErrorBars: Boolean;
function HasYErrorBars: Boolean;
function IsXErrorIndex(AXIndex: Integer): Boolean;
@ -715,8 +719,8 @@ begin
FValue := TChartErrorBarData(ASource).FValue;
FIndex := TChartErrorBarData(ASource).FIndex;
FKind := TChartErrorBarData(ASource).Kind;
end;
inherited;
end else
inherited;
end;
procedure TChartErrorBarData.Changed;
@ -998,26 +1002,24 @@ begin
Result := FErrorBarData[AIndex];
end;
{ Returns the error bar limits in positive and negative direction for the
{ Returns the error bar values in positive and negative direction for the
x (which = 0) or y (which = 1) coordinates of the data point at the specified
index. The result is false if there is no error bar. }
function TCustomChartSource.GetErrorBarLimits(APointIndex: Integer;
Which: Integer; out AUpperLimit, ALowerLimit: Double): Boolean;
function TCustomChartSource.GetErrorBarValues(APointIndex: Integer;
Which: Integer; out AUpperDelta, ALowerDelta: Double): Boolean;
var
v: Double;
deltaP, deltaN: Double;
pidx, nidx: Integer;
begin
Result := false;
AUpperDelta := 0;
ALowerDelta := 0;
if Which = 0 then
v := Item[APointIndex]^.X
else
v := Item[APointIndex]^.Y;
AUpperLimit := v;
ALowerLimit := v;
if IsNaN(v) then
exit;
@ -1027,59 +1029,91 @@ begin
exit;
ebkConst:
begin
deltaP := FErrorBarData[Which].ValuePlus;
AUpperDelta := FErrorBarData[Which].ValuePlus;
if FErrorBarData[Which].ValueMinus = -1 then
deltaN := deltaP
ALowerDelta := AUpperDelta
else
deltaN := FErrorBarData[Which].ValueMinus;
ALowerDelta := FErrorBarData[Which].ValueMinus;
end;
ebkPercent:
begin
deltaP := v * FErrorBarData[Which].ValuePlus * PERCENT;
AUpperDelta := v * FErrorBarData[Which].ValuePlus * PERCENT;
if FErrorBarData[Which].ValueMinus = -1 then
deltaN := deltaP
ALowerDelta := AUpperDelta
else
deltaN := v * FErrorBarData[Which].ValueMinus * PERCENT;
ALowerDelta := v * FErrorBarData[Which].ValueMinus * PERCENT;
end;
ebkChartSource:
if Which = 0 then begin
pidx := FErrorBarData[0].IndexPlus;
nidx := FErrorBarData[0].IndexMinus;
if not InRange(pidx, 0, XCount - 1) then exit;
if (nidx <> -1) and not InRange(nidx, 0, XCount - 1) then exit;
deltaP := Item[APointIndex]^.GetX(pidx);
if not InRange(pidx, 0, XCount) then exit;
if (nidx <> -1) and not InRange(nidx, 0, XCount-1) then exit;
AUpperDelta := Item[APointIndex]^.GetX(pidx);
if nidx = -1 then
deltaN := deltaP
ALowerDelta := AUpperDelta
else
deltaN := Item[APointIndex]^.GetX(nidx);
ALowerDelta := Item[APointIndex]^.GetX(nidx);
end else begin
pidx := FErrorBarData[1].IndexPlus;
nidx := FErrorBarData[1].IndexMinus;
if not InRange(pidx, 0, YCount - 1) then exit;
if (nidx <> -1) and not InRange(nidx, 0, YCount - 1) then exit;
deltaP := Item[APointIndex]^.GetY(pidx);
if not InRange(pidx, 0, YCount-1) then exit;
if (nidx <> -1) and not InRange(nidx, 0, YCount-1) then exit;
AUpperDelta := Item[APointIndex]^.GetY(pidx);
if nidx = -1 then
deltaN := deltaP
ALowerDelta := AUpperDelta
else
deltaN := Item[APointIndex]^.GetY(nidx);
ALowerDelta := Item[APointIndex]^.GetY(nidx);
end;
end;
AUpperLimit := v + abs(deltaP);
ALowerLimit := v - abs(deltaN);
Result := (AUpperLimit <> ALowerLimit);
AUpperDelta := abs(AUpperDelta);
ALowerDelta := abs(ALowerDelta);
Result := (AUpperDelta <> 0) and (ALowerDelta <> 0);
end;
end;
function TCustomChartSource.GetXErrorBarLimits(APointIndex: Integer;
out AUpperLimit, ALowerLimit: Double): Boolean;
var
v, dxp, dxn: Double;
begin
Result := GetErrorBarLimits(APointIndex, 0, AUpperLimit, ALowerLimit);
Result := GetErrorBarValues(APointIndex, 0, dxp, dxn);
v := Item[APointIndex]^.X;
if Result and not IsNaN(v) then begin
AUpperLimit := v + dxp;
ALowerLimit := v - dxn;
end else begin
AUpperLimit := v;
ALowerLimit := v;
end;
end;
function TCustomChartSource.GetYErrorBarLimits(APointIndex: Integer;
out AUpperLimit, ALowerLimit: Double): Boolean;
var
v, dyp, dyn: Double;
begin
Result := GetErrorBarLimits(APointIndex, 1, AUpperLimit, ALowerLimit);
Result := GetErrorBarValues(APointIndex, 1, dyp, dyn);
v := Item[APointIndex]^.Y;
if Result and not IsNaN(v) then begin
AUpperLimit := v + dyp;
ALowerLimit := v - dyn;
end else begin
AUpperLimit := v;
ALowerLimit := v;
end;
end;
function TCustomChartSource.GetXErrorBarValues(APointIndex: Integer;
out AUpperDelta, ALowerDelta: Double): Boolean;
begin
Result := GetErrorBarValues(APointIndex, 0, AUpperDelta, ALowerDelta);
end;
function TCustomChartSource.GetYErrorBarValues(APointIndex: Integer;
out AUpperDelta, ALowerDelta: Double): Boolean;
begin
Result := GetErrorBarValues(APointIndex, 1, AUpperDelta, ALowerDelta);
end;
function TCustomChartSource.GetHasErrorBars(Which: Integer): Boolean;

View File

@ -173,6 +173,8 @@ type
property PointsNumber: Integer
read FPointsNumber write SetPointsNumber default 0;
property Sorted: Boolean read FSorted write FSorted default false;
property XErrorBarData;
property YErrorBarData;
end;
TChartAccumulationMethod = (
@ -812,6 +814,7 @@ function TRandomChartSource.GetItem(AIndex: Integer): PChartDataItem;
var
i: Integer;
fp, fn: Double;
begin
if FCurIndex > AIndex then begin
FRNG.Seed := FRandSeed;
@ -837,12 +840,12 @@ begin
end;
// Make sure that x values belonging to an error bar are random and
// multiplied by the percentage given by ErrorBarData.Pos/NegDelta.
fp := XErrorBarData.ValuePlus * PERCENT;
if XErrorBarData.ValueMinus = -1 then fn := fp else fn := XErrorBarData.ValueMinus * PERCENT;
for i := 0 to XCount - 2 do
if (XErrorBarData.Kind = ebkChartSource) then begin
if (i+1 = XErrorBarData.IndexPlus) and (XErrorBarData.ValuePlus > 0) then
FCurItem.XList[i] := GetRandomX * XErrorBarData.ValuePlus * PERCENT;
if (i+1 = XErrorBarData.IndexMinus) and (XErrorBarData.ValueMinus > 0) then
FCurItem.XList[i] := GetRandomX * XErrorBarData.ValueMinus * PERCENT;
if (i+1 = XErrorBarData.IndexPlus) then FCurItem.XList[i] := GetRandomX * fp;
if (i+1 = XErrorBarData.IndexMinus) then FCurItem.XList[i] := GetRandomX * fn;
end;
end;
if YCount > 0 then begin
@ -853,11 +856,11 @@ begin
// If this y value is that of an error bar assume that the error is
// a percentage of the y value calculated. The percentage is the
// ErrorBarData.Pos/NegDelta.
fp := YErrorBarData.ValuePlus * PERCENT;
if YErrorBarData.ValueMinus = -1 then fn := fp else fn := YErrorBarData.ValueMinus * PERCENT;
if (YErrorBarData.Kind = ebkChartSource) then begin
if (i+1 = YErrorBarData.IndexPlus) and (YErrorBarData.ValuePlus > 0) then
FCurItem.YList[i] := FCurItem.YList[i] * YErrorBarData.ValuePlus * PERCENT;
if (i+1 = YErrorBarData.IndexMinus) and (YErrorBarData.ValueMinus > 0) then
FCurItem.YList[i] := FCurItem.YList[i] * YErrorBarData.ValueMinus * PERCENT;
if (i+1 = YErrorBarData.IndexPlus) then FCurItem.YList[i] := GetRandomY * fp;
if (i+1 = YErrorBarData.IndexMinus) then FCurItem.YList[i] := GetRandomY * fn;
end;
end;
end;