mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-11-01 22:19:39 +01:00
TAChart: Modify ValuesInRange to return extra value on both sides of requested interval.
This fixes display of minor axis the the graph edges. git-svn-id: trunk@31642 -
This commit is contained in:
parent
2f560c99e7
commit
007f525bd7
@ -165,6 +165,7 @@ type
|
||||
ACoord, AFixedCoord: Integer; const AText: String); virtual; abstract;
|
||||
function GraphToImage(AGraph: Double): Integer; virtual; abstract;
|
||||
procedure GridLine(ACoord: Integer); virtual; abstract;
|
||||
function IsInClipRange(ACoord: Integer): Boolean; virtual; abstract;
|
||||
procedure LineZ(AP1, AP2: TPoint); inline;
|
||||
function TryApplyStripes: Boolean; inline;
|
||||
public
|
||||
@ -192,6 +193,7 @@ type
|
||||
ACoord, AFixedCoord: Integer; const AText: String); override;
|
||||
function GraphToImage(AGraph: Double): Integer; override;
|
||||
procedure GridLine(ACoord: Integer); override;
|
||||
function IsInClipRange(ACoord: Integer): Boolean; override;
|
||||
public
|
||||
procedure BeginDrawing; override;
|
||||
procedure EndDrawing; override;
|
||||
@ -205,6 +207,7 @@ type
|
||||
ACoord, AFixedCoord: Integer; const AText: String); override;
|
||||
function GraphToImage(AGraph: Double): Integer; override;
|
||||
procedure GridLine(ACoord: Integer); override;
|
||||
function IsInClipRange(ACoord: Integer): Boolean; override;
|
||||
public
|
||||
procedure BeginDrawing; override;
|
||||
procedure EndDrawing; override;
|
||||
@ -213,7 +216,7 @@ type
|
||||
implementation
|
||||
|
||||
uses
|
||||
SysUtils,
|
||||
Math, SysUtils,
|
||||
TAGeometry, TAIntervalSources;
|
||||
|
||||
{ TAxisDrawHelper }
|
||||
@ -242,6 +245,7 @@ var
|
||||
coord: Integer;
|
||||
begin
|
||||
coord := GraphToImage(AMark);
|
||||
if not IsInClipRange(coord) then exit;
|
||||
|
||||
if FAxis.Grid.Visible then begin
|
||||
FDrawer.Pen := FAxis.Grid;
|
||||
@ -306,6 +310,11 @@ begin
|
||||
LineZ(Point(ACoord, FClipRect.Top), Point(ACoord, FClipRect.Bottom));
|
||||
end;
|
||||
|
||||
function TAxisDrawHelperX.IsInClipRange(ACoord: Integer): Boolean;
|
||||
begin
|
||||
Result := InRange(ACoord, FClipRect.Left, FClipRect.Right);
|
||||
end;
|
||||
|
||||
{ TAxisDrawHelperY }
|
||||
|
||||
procedure TAxisDrawHelperY.BeginDrawing;
|
||||
@ -346,6 +355,11 @@ begin
|
||||
LineZ(Point(FClipRect.Left, ACoord), Point(FClipRect.Right, ACoord));
|
||||
end;
|
||||
|
||||
function TAxisDrawHelperY.IsInClipRange(ACoord: Integer): Boolean;
|
||||
begin
|
||||
Result := InRange(ACoord, FClipRect.Top, FClipRect.Bottom);
|
||||
end;
|
||||
|
||||
{ TChartAxisTitle }
|
||||
|
||||
procedure TChartAxisTitle.Assign(Source: TPersistent);
|
||||
|
||||
@ -412,20 +412,37 @@ end;
|
||||
procedure TCustomChartSource.ValuesInRange(
|
||||
AMin, AMax: Double; const AFormat: String; AUseY: Boolean;
|
||||
var AValues: TDoubleDynArray; var ATexts: TStringDynArray);
|
||||
|
||||
var
|
||||
i, cnt: Integer;
|
||||
v: Double;
|
||||
cnt: Integer;
|
||||
|
||||
procedure Push(AValue: Double; AIndex: Integer);
|
||||
begin
|
||||
AValues[cnt] := AValue;
|
||||
ATexts[cnt] := FormatItem(AFormat, AIndex, 0);
|
||||
cnt += 1;
|
||||
end;
|
||||
|
||||
var
|
||||
i, li: Integer;
|
||||
pv, v: Double;
|
||||
begin
|
||||
cnt := Length(AValues);
|
||||
SetLength(AValues, cnt + Count);
|
||||
SetLength(ATexts, cnt + Count);
|
||||
v := 0;
|
||||
li := 0;
|
||||
for i := 0 to Count - 1 do begin
|
||||
pv := v;
|
||||
v := IfThen(AUseY, Item[i]^.Y, Item[i]^.X);
|
||||
if not InRange(v, AMin, AMax) then continue;
|
||||
AValues[cnt] := v;
|
||||
ATexts[cnt] := FormatItem(AFormat, i, 0);
|
||||
cnt += 1;
|
||||
if (cnt = 0) and (i > 0) then
|
||||
Push(pv, i - 1);
|
||||
Push(v, i);
|
||||
li := i;
|
||||
end;
|
||||
if not InRange(v, AMin, AMax) then
|
||||
Push(v, li);
|
||||
SetLength(AValues, cnt);
|
||||
SetLength(ATexts, cnt);
|
||||
end;
|
||||
|
||||
@ -111,7 +111,7 @@ begin
|
||||
AStart := 0
|
||||
else
|
||||
AStart := Round((AMin - AStep) * scale) / scale;
|
||||
while AStart > AMin do AStart -= AStep;
|
||||
while AStart >= AMin do AStart -= AStep;
|
||||
end;
|
||||
asDecreasing: begin
|
||||
// If 0 is in the interval, set it as a mark.
|
||||
@ -119,7 +119,7 @@ begin
|
||||
AStart := 0
|
||||
else
|
||||
AStart := Round((AMax + AStep) * scale) / scale;
|
||||
while AStart < AMax do AStart += AStep;
|
||||
while AStart <= AMax do AStart += AStep;
|
||||
end;
|
||||
asLogIncreasing: begin
|
||||
// FIXME: asLogIncreasing is still not implemented.
|
||||
@ -147,43 +147,34 @@ end;
|
||||
function GetIntervals(AMin, AMax: Double; AInverted: Boolean): TDoubleDynArray;
|
||||
const
|
||||
INV_TO_SCALE: array [Boolean] of TAxisScale = (asIncreasing, asDecreasing);
|
||||
K = 1e-10;
|
||||
var
|
||||
start, step, m, m1: Double;
|
||||
markCount: Integer;
|
||||
start, step, m: Double;
|
||||
markCount, crossCount: Integer;
|
||||
begin
|
||||
CalculateIntervals(AMin, AMax, INV_TO_SCALE[AInverted], start, step);
|
||||
AMin -= step * K;
|
||||
AMax += step * K;
|
||||
if AInverted then
|
||||
step := - step;
|
||||
m := start;
|
||||
markCount := 0;
|
||||
while true do begin
|
||||
if InRange(m, AMin, AMax) then
|
||||
Inc(markCount)
|
||||
else if markCount > 0 then
|
||||
break;
|
||||
m1 := m + step;
|
||||
if m1 = m then break;
|
||||
m := m1;
|
||||
end;
|
||||
crossCount := 0;
|
||||
markCount := 1;
|
||||
repeat
|
||||
markCount += 1;
|
||||
crossCount += Ord(InRange(m, AMin, AMax) <> InRange(m + step, AMin, AMax));
|
||||
m += step;
|
||||
until (crossCount = 2) or (m + step = m);
|
||||
SetLength(Result, markCount);
|
||||
m := start;
|
||||
crossCount := 0;
|
||||
markCount := 0;
|
||||
while true do begin
|
||||
if Abs(m / step) < K then
|
||||
repeat
|
||||
if IsZero(m) then
|
||||
m := 0;
|
||||
if InRange(m, AMin, AMax) then begin
|
||||
Result[markCount] := m;
|
||||
Inc(markCount);
|
||||
end
|
||||
else if markCount > 0 then
|
||||
break;
|
||||
m1 := m + step;
|
||||
if m1 = m then break;
|
||||
m := m1;
|
||||
end;
|
||||
Result[markCount] := m;
|
||||
markCount += 1;
|
||||
crossCount += Ord(InRange(m, AMin, AMax) <> InRange(m + step, AMin, AMax));
|
||||
m += step;
|
||||
until (crossCount = 2) or (m + step = m);
|
||||
Result[markCount] := m;
|
||||
end;
|
||||
|
||||
procedure Register;
|
||||
@ -305,10 +296,9 @@ begin
|
||||
end;
|
||||
start := Int(AMin / si - 1) * si;
|
||||
x := start;
|
||||
cnt := 0;
|
||||
cnt := 1;
|
||||
while x <= AMax do begin
|
||||
if x >= AMin then
|
||||
cnt += 1;
|
||||
cnt += 1;
|
||||
x += si;
|
||||
end;
|
||||
i := Length(AValues);
|
||||
@ -318,11 +308,9 @@ begin
|
||||
FillChar(prevSt, SizeOf(prevSt), $FF);
|
||||
x := start;
|
||||
while x <= AMax do begin
|
||||
if x >= AMin then begin
|
||||
AValues[i] := x;
|
||||
ATexts[i] := Format(AFormat, [x, 0.0, FormatLabel, 0.0, 0.0]);
|
||||
i += 1;
|
||||
end;
|
||||
AValues[i] := x;
|
||||
ATexts[i] := Format(AFormat, [x, 0.0, FormatLabel, 0.0, 0.0]);
|
||||
i += 1;
|
||||
case s of
|
||||
dtsCentury: x := IncYear(x, 100);
|
||||
dtsDecade: x := IncYear(x, 10);
|
||||
@ -331,6 +319,8 @@ begin
|
||||
otherwise x += si;
|
||||
end;
|
||||
end;
|
||||
AValues[i] := x;
|
||||
ATexts[i] := Format(AFormat, [x, 0.0, FormatLabel, 0.0, 0.0]);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user