TAChart: Allow XCount=0 for TChartSource meaning "replace X by point index". Still some issues.

git-svn-id: trunk@60995 -
This commit is contained in:
wp 2019-04-16 14:16:58 +00:00
parent eee4ab0ff1
commit ac880dd4b9
5 changed files with 101 additions and 50 deletions

View File

@ -920,12 +920,18 @@ end;
function TChartSeries.GetGraphPointX(AIndex: Integer): Double;
begin
Result := AxisToGraphX(Source[AIndex]^.X);
if Source.XCount = 0 then
Result := AxisToGraphX(Index)
else
Result := AxisToGraphX(Source[AIndex]^.X);
end;
function TChartSeries.GetGraphPointX(AIndex, AXIndex: Integer): Double;
begin
Result := AxisToGraphX(Source[AIndex]^.GetX(AXIndex));
if Source.XCount = 0 then
Result := AxisToGraphX(AIndex)
else
Result := AxisToGraphX(Source[AIndex]^.GetX(AXIndex));
end;
function TChartSeries.GetGraphPointY(AIndex: Integer): Double;
@ -988,7 +994,7 @@ end;
class procedure TChartSeries.GetXYCountNeeded(out AXCount, AYCount: Cardinal);
begin
AXCount := 1;
AXCount := 0;
AYCount := 1;
end;
@ -1004,15 +1010,18 @@ end;
function TChartSeries.GetXValue(AIndex: Integer): Double;
begin
Result := Source[AIndex]^.X;
if Source.XCount > 0 then
Result := Source[AIndex]^.X
else
Result := AIndex;
end;
function TChartSeries.GetXValues(AIndex, AXIndex: Integer): Double;
begin
if AXIndex = 0 then
Result := Source[AIndex]^.X
if AXIndex > 0 then
Result := Source[AIndex]^.XList[AXIndex - 1]
else
Result := Source[AIndex]^.XList[AXIndex - 1];
Result := Source[AIndex]^.X;
end;
function TChartSeries.GetYImgValue(AIndex: Integer): Integer;
@ -1777,12 +1786,17 @@ begin
FindExtentInterval(AExtent, AFilterByExtent);
SetLength(FGraphPoints, Max(FUpBound - FLoBound + 1, 0));
if (AxisIndexX < 0) and (AxisIndexY < 0) then
if (AxisIndexX < 0) and (AxisIndexY < 0) then begin
// Optimization: bypass transformations in the default case.
for i := FLoBound to FUpBound do
with Source[i]^ do
FGraphPoints[i - FLoBound] := DoublePoint(X, Y)
else
if Source.XCount > 0 then
for i := FLoBound to FUpBound do
with Source[i]^ do
FGraphPoints[i - FLoBound] := DoublePoint(X, Y)
else
for i := FLoBound to FUpBound do
with Source[i]^ do
FGraphPoints[i - FLoBound] := DoublePoint(i, Y);
end else
for i := FLoBound to FUpBound do
FGraphPoints[i - FLoBound] := GetGraphPoint(i);
end;

View File

@ -827,6 +827,9 @@ begin
end else
for i:=0 to Count - 1 do
UpdateMinMax(Item[i]^.X, FBasicExtent.a.X, FBasicExtent.b.X);
end else begin
UpdateMinMax(0, FBasicExtent.a.X, FBasicExtent.b.X);
UpdateMinMax(Count-1, FBasicExtent.a.X, FBasicExtent.b.X);
end;
if YCount > 0 then begin

View File

@ -1280,21 +1280,32 @@ var
n, ok: Integer;
begin
FIsUnorderedX := false;
while (ASourceIndex < ASource.Count) and IsNan(ASource[ASourceIndex]^.Point) do
ASourceIndex += 1;
if ASource.XCount > 0 then
while (ASourceIndex < ASource.Count) and IsNan(ASource[ASourceIndex]^.Point) do
ASourceIndex += 1;
FSourceStartIndex := ASourceIndex;
FFirstCacheIndex := ACacheIndex;
while (ASourceIndex < ASource.Count) and not IsNan(ASource[ASourceIndex]^.Point) do begin
with ASource[ASourceIndex]^ do
if (ACacheIndex > FFirstCacheIndex) and (FOwner.FX[ACacheIndex - 1] >= X) then
FIsUnorderedX := true
else begin
FOwner.FX[ACacheIndex] := X;
if ASource.XCount > 0 then
while (ASourceIndex < ASource.Count) and not IsNan(ASource[ASourceIndex]^.Point) do begin
with ASource[ASourceIndex]^ do
if (ACacheIndex > FFirstCacheIndex) and (FOwner.FX[ACacheIndex - 1] >= X) then
FIsUnorderedX := true
else begin
FOwner.FX[ACacheIndex] := X;
FOwner.FY[ACacheIndex] := Y;
ACacheIndex += 1;
end;
ASourceIndex += 1;
end
else
while ASourceIndex < ASource.Count do begin
with ASource[ASourceIndex]^ do begin
FOwner.FX[ACacheIndex] := ASourceIndex;
FOwner.FY[ACacheIndex] := Y;
ACacheIndex += 1;
end;
ASourceIndex += 1;
end;
ASourceIndex += 1;
end;
FLastCacheIndex := ACacheIndex - 1;
if FLastCacheIndex < FFirstCacheIndex then exit(false); // No points
if IsFewPoints then exit(true);
@ -1654,20 +1665,25 @@ procedure TFitSeries.CalcXRange(out AXMin, AXMax: Double);
var
ext: TDoubleRect;
begin
with Source.BasicExtent do begin
ext.a := AxisToGraph(a);
ext.b := AxisToGraph(b);
end;
NormalizeRect(ext);
if IsRotated then begin
AXMin := GraphToAxisY(ext.a.Y);
AXMax := GraphToAxisY(ext.b.Y);
if Source.XCount > 0 then begin
with Source.BasicExtent do begin
ext.a := AxisToGraph(a);
ext.b := AxisToGraph(b);
end;
NormalizeRect(ext);
if IsRotated then begin
AXMin := GraphToAxisY(ext.a.Y);
AXMax := GraphToAxisY(ext.b.Y);
end else begin
AXMin := GraphToAxisX(ext.a.X);
AXMax := GraphToAxisX(ext.b.X);
end;
EnsureOrder(AXMin, AXMax);
FFitRange.Intersect(AXMin, AXMax);
end else begin
AXMin := GraphToAxisX(ext.a.X);
AXMax := GraphToAxisX(ext.b.X);
AXMin := 0;
AXMax := Source.Count - 1;
end;
EnsureOrder(AXMin, AXMax);
FFitRange.Intersect(AXMin, AXMax);
end;
procedure TFitSeries.Assign(ASource: TPersistent);
@ -1786,7 +1802,10 @@ var
function IsValidPoint(AX, AY: Double): Boolean; inline;
begin
Result := not IsNaN(AX) and not IsNaN(AY) and InRange(AX, xmin, xmax);
if Source.XCount > 0 then
Result := not IsNaN(AX) and not IsNaN(AY) and InRange(AX, xmin, xmax)
else
Result := not IsNaN(AY);
end;
procedure TryFit;
@ -1816,7 +1835,10 @@ var
for i := 0 to ns - 1 do
with Source.Item[i]^ do
if IsValidPoint(X, Y) then begin
xv[j] := TransformX(X);
if Source.XCount > 0 then
xv[j] := TransformX(X)
else
xv[j] := TransformX(i);
yv[j] := TransformY(Y);
if hasErrorBars and Source.GetYErrorBarLimits(i, yp, yn) then
dy[j] := abs(TransformY(yp) - TransformY(yn)) / 2;

View File

@ -1418,7 +1418,10 @@ begin
if Length(FAngleCache) = Count then exit;
SetLength(FAngleCache, Count);
for i := 0 to Count - 1 do begin
SinCos(Source[i]^.X, s, c);
if Source.XCount > 0 then
SinCos(Source[i]^.X, s, c)
else
SinCos(i, s, c);
FAngleCache[i].FSin := s;
FAngleCache[i].FCos := c;
end;

View File

@ -1243,6 +1243,7 @@ begin
SetLength(heights, Source.YCount + 1);
for pointIndex := FLoBound to FUpBound do begin
p := Source[pointIndex]^.Point;
if Source.XCount = 0 then p.X := pointIndex + FLoBound;
if SkipMissingValues(pointIndex) then
continue;
p.X := AxisToGraphX(p.X);
@ -1518,19 +1519,25 @@ begin
UpdateMinMax(GraphToAxisY(ZeroLevel), Result.a.Y, Result.b.Y);
// Show first and last bars fully.
i := 0;
x := NearestXNumber(i, +1); // --> x is in graph units
if not IsNan(x) then begin
BarOffsetWidth(x, i, ofs, w);
x := GraphToAxisX(x + ofs - w); // x is in graph units, Extent in axis units!
Result.a.X := Min(Result.a.X, x);
end;
i := Count - 1;
x := NearestXNumber(i, -1);
if not IsNan(x) then begin
BarOffsetWidth(x, i, ofs, w);
x := GraphToAxisX(x + ofs + w);
Result.b.X := Max(Result.b.X, x);
if Source.XCount = 0 then begin
BarOffsetWidth(x, 0, ofs, w);
Result.a.X -= (ofs + w);
Result.b.X += (ofs + w);
end else begin
i := 0;
x := NearestXNumber(i, +1); // --> x is in graph units
if not IsNan(x) then begin
BarOffsetWidth(x, i, ofs, w);
x := GraphToAxisX(x + ofs - w); // x is in graph units, Extent in axis units!
Result.a.X := Min(Result.a.X, x);
end;
i := Count - 1;
x := NearestXNumber(i, -1);
if not IsNan(x) then begin
BarOffsetWidth(x, i, ofs, w);
x := GraphToAxisX(x + ofs + w);
Result.b.X := Max(Result.b.X, x);
end;
end;
end;
@ -1600,6 +1607,8 @@ begin
// Iterate through all points of the series
for pointIndex := 0 to Count - 1 do begin
sp := Source[pointindex]^.Point;
if Source.XCount = 0 then
sp.X := pointIndex;
if IsNan(sp) then
continue;
sp.X := AxisToGraphX(sp.X);