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:
ask 2011-07-10 06:50:21 +00:00
parent 2f560c99e7
commit 007f525bd7
3 changed files with 64 additions and 43 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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.