mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-28 00:24:04 +02:00
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:
parent
eee4ab0ff1
commit
ac880dd4b9
@ -920,12 +920,18 @@ end;
|
|||||||
|
|
||||||
function TChartSeries.GetGraphPointX(AIndex: Integer): Double;
|
function TChartSeries.GetGraphPointX(AIndex: Integer): Double;
|
||||||
begin
|
begin
|
||||||
Result := AxisToGraphX(Source[AIndex]^.X);
|
if Source.XCount = 0 then
|
||||||
|
Result := AxisToGraphX(Index)
|
||||||
|
else
|
||||||
|
Result := AxisToGraphX(Source[AIndex]^.X);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TChartSeries.GetGraphPointX(AIndex, AXIndex: Integer): Double;
|
function TChartSeries.GetGraphPointX(AIndex, AXIndex: Integer): Double;
|
||||||
begin
|
begin
|
||||||
Result := AxisToGraphX(Source[AIndex]^.GetX(AXIndex));
|
if Source.XCount = 0 then
|
||||||
|
Result := AxisToGraphX(AIndex)
|
||||||
|
else
|
||||||
|
Result := AxisToGraphX(Source[AIndex]^.GetX(AXIndex));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TChartSeries.GetGraphPointY(AIndex: Integer): Double;
|
function TChartSeries.GetGraphPointY(AIndex: Integer): Double;
|
||||||
@ -988,7 +994,7 @@ end;
|
|||||||
|
|
||||||
class procedure TChartSeries.GetXYCountNeeded(out AXCount, AYCount: Cardinal);
|
class procedure TChartSeries.GetXYCountNeeded(out AXCount, AYCount: Cardinal);
|
||||||
begin
|
begin
|
||||||
AXCount := 1;
|
AXCount := 0;
|
||||||
AYCount := 1;
|
AYCount := 1;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1004,15 +1010,18 @@ end;
|
|||||||
|
|
||||||
function TChartSeries.GetXValue(AIndex: Integer): Double;
|
function TChartSeries.GetXValue(AIndex: Integer): Double;
|
||||||
begin
|
begin
|
||||||
Result := Source[AIndex]^.X;
|
if Source.XCount > 0 then
|
||||||
|
Result := Source[AIndex]^.X
|
||||||
|
else
|
||||||
|
Result := AIndex;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TChartSeries.GetXValues(AIndex, AXIndex: Integer): Double;
|
function TChartSeries.GetXValues(AIndex, AXIndex: Integer): Double;
|
||||||
begin
|
begin
|
||||||
if AXIndex = 0 then
|
if AXIndex > 0 then
|
||||||
Result := Source[AIndex]^.X
|
Result := Source[AIndex]^.XList[AXIndex - 1]
|
||||||
else
|
else
|
||||||
Result := Source[AIndex]^.XList[AXIndex - 1];
|
Result := Source[AIndex]^.X;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TChartSeries.GetYImgValue(AIndex: Integer): Integer;
|
function TChartSeries.GetYImgValue(AIndex: Integer): Integer;
|
||||||
@ -1777,12 +1786,17 @@ begin
|
|||||||
FindExtentInterval(AExtent, AFilterByExtent);
|
FindExtentInterval(AExtent, AFilterByExtent);
|
||||||
|
|
||||||
SetLength(FGraphPoints, Max(FUpBound - FLoBound + 1, 0));
|
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.
|
// Optimization: bypass transformations in the default case.
|
||||||
for i := FLoBound to FUpBound do
|
if Source.XCount > 0 then
|
||||||
with Source[i]^ do
|
for i := FLoBound to FUpBound do
|
||||||
FGraphPoints[i - FLoBound] := DoublePoint(X, Y)
|
with Source[i]^ do
|
||||||
else
|
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
|
for i := FLoBound to FUpBound do
|
||||||
FGraphPoints[i - FLoBound] := GetGraphPoint(i);
|
FGraphPoints[i - FLoBound] := GetGraphPoint(i);
|
||||||
end;
|
end;
|
||||||
|
@ -827,6 +827,9 @@ begin
|
|||||||
end else
|
end else
|
||||||
for i:=0 to Count - 1 do
|
for i:=0 to Count - 1 do
|
||||||
UpdateMinMax(Item[i]^.X, FBasicExtent.a.X, FBasicExtent.b.X);
|
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;
|
end;
|
||||||
|
|
||||||
if YCount > 0 then begin
|
if YCount > 0 then begin
|
||||||
|
@ -1280,21 +1280,32 @@ var
|
|||||||
n, ok: Integer;
|
n, ok: Integer;
|
||||||
begin
|
begin
|
||||||
FIsUnorderedX := false;
|
FIsUnorderedX := false;
|
||||||
while (ASourceIndex < ASource.Count) and IsNan(ASource[ASourceIndex]^.Point) do
|
if ASource.XCount > 0 then
|
||||||
ASourceIndex += 1;
|
while (ASourceIndex < ASource.Count) and IsNan(ASource[ASourceIndex]^.Point) do
|
||||||
|
ASourceIndex += 1;
|
||||||
FSourceStartIndex := ASourceIndex;
|
FSourceStartIndex := ASourceIndex;
|
||||||
FFirstCacheIndex := ACacheIndex;
|
FFirstCacheIndex := ACacheIndex;
|
||||||
while (ASourceIndex < ASource.Count) and not IsNan(ASource[ASourceIndex]^.Point) do begin
|
if ASource.XCount > 0 then
|
||||||
with ASource[ASourceIndex]^ do
|
while (ASourceIndex < ASource.Count) and not IsNan(ASource[ASourceIndex]^.Point) do begin
|
||||||
if (ACacheIndex > FFirstCacheIndex) and (FOwner.FX[ACacheIndex - 1] >= X) then
|
with ASource[ASourceIndex]^ do
|
||||||
FIsUnorderedX := true
|
if (ACacheIndex > FFirstCacheIndex) and (FOwner.FX[ACacheIndex - 1] >= X) then
|
||||||
else begin
|
FIsUnorderedX := true
|
||||||
FOwner.FX[ACacheIndex] := X;
|
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;
|
FOwner.FY[ACacheIndex] := Y;
|
||||||
ACacheIndex += 1;
|
ACacheIndex += 1;
|
||||||
end;
|
end;
|
||||||
ASourceIndex += 1;
|
ASourceIndex += 1;
|
||||||
end;
|
end;
|
||||||
FLastCacheIndex := ACacheIndex - 1;
|
FLastCacheIndex := ACacheIndex - 1;
|
||||||
if FLastCacheIndex < FFirstCacheIndex then exit(false); // No points
|
if FLastCacheIndex < FFirstCacheIndex then exit(false); // No points
|
||||||
if IsFewPoints then exit(true);
|
if IsFewPoints then exit(true);
|
||||||
@ -1654,20 +1665,25 @@ procedure TFitSeries.CalcXRange(out AXMin, AXMax: Double);
|
|||||||
var
|
var
|
||||||
ext: TDoubleRect;
|
ext: TDoubleRect;
|
||||||
begin
|
begin
|
||||||
with Source.BasicExtent do begin
|
if Source.XCount > 0 then begin
|
||||||
ext.a := AxisToGraph(a);
|
with Source.BasicExtent do begin
|
||||||
ext.b := AxisToGraph(b);
|
ext.a := AxisToGraph(a);
|
||||||
end;
|
ext.b := AxisToGraph(b);
|
||||||
NormalizeRect(ext);
|
end;
|
||||||
if IsRotated then begin
|
NormalizeRect(ext);
|
||||||
AXMin := GraphToAxisY(ext.a.Y);
|
if IsRotated then begin
|
||||||
AXMax := GraphToAxisY(ext.b.Y);
|
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
|
end else begin
|
||||||
AXMin := GraphToAxisX(ext.a.X);
|
AXMin := 0;
|
||||||
AXMax := GraphToAxisX(ext.b.X);
|
AXMax := Source.Count - 1;
|
||||||
end;
|
end;
|
||||||
EnsureOrder(AXMin, AXMax);
|
|
||||||
FFitRange.Intersect(AXMin, AXMax);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFitSeries.Assign(ASource: TPersistent);
|
procedure TFitSeries.Assign(ASource: TPersistent);
|
||||||
@ -1786,7 +1802,10 @@ var
|
|||||||
|
|
||||||
function IsValidPoint(AX, AY: Double): Boolean; inline;
|
function IsValidPoint(AX, AY: Double): Boolean; inline;
|
||||||
begin
|
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;
|
end;
|
||||||
|
|
||||||
procedure TryFit;
|
procedure TryFit;
|
||||||
@ -1816,7 +1835,10 @@ var
|
|||||||
for i := 0 to ns - 1 do
|
for i := 0 to ns - 1 do
|
||||||
with Source.Item[i]^ do
|
with Source.Item[i]^ do
|
||||||
if IsValidPoint(X, Y) then begin
|
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);
|
yv[j] := TransformY(Y);
|
||||||
if hasErrorBars and Source.GetYErrorBarLimits(i, yp, yn) then
|
if hasErrorBars and Source.GetYErrorBarLimits(i, yp, yn) then
|
||||||
dy[j] := abs(TransformY(yp) - TransformY(yn)) / 2;
|
dy[j] := abs(TransformY(yp) - TransformY(yn)) / 2;
|
||||||
|
@ -1418,7 +1418,10 @@ begin
|
|||||||
if Length(FAngleCache) = Count then exit;
|
if Length(FAngleCache) = Count then exit;
|
||||||
SetLength(FAngleCache, Count);
|
SetLength(FAngleCache, Count);
|
||||||
for i := 0 to Count - 1 do begin
|
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].FSin := s;
|
||||||
FAngleCache[i].FCos := c;
|
FAngleCache[i].FCos := c;
|
||||||
end;
|
end;
|
||||||
|
@ -1243,6 +1243,7 @@ begin
|
|||||||
SetLength(heights, Source.YCount + 1);
|
SetLength(heights, Source.YCount + 1);
|
||||||
for pointIndex := FLoBound to FUpBound do begin
|
for pointIndex := FLoBound to FUpBound do begin
|
||||||
p := Source[pointIndex]^.Point;
|
p := Source[pointIndex]^.Point;
|
||||||
|
if Source.XCount = 0 then p.X := pointIndex + FLoBound;
|
||||||
if SkipMissingValues(pointIndex) then
|
if SkipMissingValues(pointIndex) then
|
||||||
continue;
|
continue;
|
||||||
p.X := AxisToGraphX(p.X);
|
p.X := AxisToGraphX(p.X);
|
||||||
@ -1518,19 +1519,25 @@ begin
|
|||||||
UpdateMinMax(GraphToAxisY(ZeroLevel), Result.a.Y, Result.b.Y);
|
UpdateMinMax(GraphToAxisY(ZeroLevel), Result.a.Y, Result.b.Y);
|
||||||
|
|
||||||
// Show first and last bars fully.
|
// Show first and last bars fully.
|
||||||
i := 0;
|
if Source.XCount = 0 then begin
|
||||||
x := NearestXNumber(i, +1); // --> x is in graph units
|
BarOffsetWidth(x, 0, ofs, w);
|
||||||
if not IsNan(x) then begin
|
Result.a.X -= (ofs + w);
|
||||||
BarOffsetWidth(x, i, ofs, w);
|
Result.b.X += (ofs + w);
|
||||||
x := GraphToAxisX(x + ofs - w); // x is in graph units, Extent in axis units!
|
end else begin
|
||||||
Result.a.X := Min(Result.a.X, x);
|
i := 0;
|
||||||
end;
|
x := NearestXNumber(i, +1); // --> x is in graph units
|
||||||
i := Count - 1;
|
if not IsNan(x) then begin
|
||||||
x := NearestXNumber(i, -1);
|
BarOffsetWidth(x, i, ofs, w);
|
||||||
if not IsNan(x) then begin
|
x := GraphToAxisX(x + ofs - w); // x is in graph units, Extent in axis units!
|
||||||
BarOffsetWidth(x, i, ofs, w);
|
Result.a.X := Min(Result.a.X, x);
|
||||||
x := GraphToAxisX(x + ofs + w);
|
end;
|
||||||
Result.b.X := Max(Result.b.X, x);
|
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;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1600,6 +1607,8 @@ begin
|
|||||||
// Iterate through all points of the series
|
// Iterate through all points of the series
|
||||||
for pointIndex := 0 to Count - 1 do begin
|
for pointIndex := 0 to Count - 1 do begin
|
||||||
sp := Source[pointindex]^.Point;
|
sp := Source[pointindex]^.Point;
|
||||||
|
if Source.XCount = 0 then
|
||||||
|
sp.X := pointIndex;
|
||||||
if IsNan(sp) then
|
if IsNan(sp) then
|
||||||
continue;
|
continue;
|
||||||
sp.X := AxisToGraphX(sp.X);
|
sp.X := AxisToGraphX(sp.X);
|
||||||
|
Loading…
Reference in New Issue
Block a user