mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-11 20:39:15 +02:00
TAChart: Implement stacked area series
git-svn-id: trunk@27135 -
This commit is contained in:
parent
5ed0ea3d8e
commit
592cd0f85b
@ -169,6 +169,7 @@ type
|
|||||||
function GetXRange(AX: Double; AIndex: Integer): Double;
|
function GetXRange(AX: Double; AIndex: Integer): Double;
|
||||||
procedure PrepareGraphPoints(
|
procedure PrepareGraphPoints(
|
||||||
const AExtent: TDoubleRect; AFilterByExtent: Boolean);
|
const AExtent: TDoubleRect; AFilterByExtent: Boolean);
|
||||||
|
procedure UpdateGraphPoints(AIndex: Integer);
|
||||||
procedure UpdateMargins(ACanvas: TCanvas; var AMargins: TRect); override;
|
procedure UpdateMargins(ACanvas: TCanvas; var AMargins: TRect); override;
|
||||||
property UseReticule: Boolean
|
property UseReticule: Boolean
|
||||||
read FUseReticule write SetUseReticule default false;
|
read FUseReticule write SetUseReticule default false;
|
||||||
@ -728,6 +729,18 @@ begin
|
|||||||
UpdateParentChart;
|
UpdateParentChart;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TBasicPointSeries.UpdateGraphPoints(AIndex: Integer);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
if IsRotated then
|
||||||
|
for i := FLoBound to FUpBound do
|
||||||
|
FGraphPoints[i - FLoBound].X += AxisToGraphY(Source[i]^.YList[AIndex])
|
||||||
|
else
|
||||||
|
for i := FLoBound to FUpBound do
|
||||||
|
FGraphPoints[i - FLoBound].Y += AxisToGraphY(Source[i]^.YList[AIndex]);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TBasicPointSeries.UpdateMargins(ACanvas: TCanvas; var AMargins: TRect);
|
procedure TBasicPointSeries.UpdateMargins(ACanvas: TCanvas; var AMargins: TRect);
|
||||||
const
|
const
|
||||||
LABEL_TO_BORDER = 4;
|
LABEL_TO_BORDER = 4;
|
||||||
|
@ -128,6 +128,7 @@ type
|
|||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
|
||||||
procedure Draw(ACanvas: TCanvas); override;
|
procedure Draw(ACanvas: TCanvas); override;
|
||||||
|
function Extent: TDoubleRect; override;
|
||||||
published
|
published
|
||||||
property AxisIndexX;
|
property AxisIndexX;
|
||||||
property AxisIndexY;
|
property AxisIndexY;
|
||||||
@ -366,7 +367,7 @@ end;
|
|||||||
procedure TLineSeries.Draw(ACanvas: TCanvas);
|
procedure TLineSeries.Draw(ACanvas: TCanvas);
|
||||||
var
|
var
|
||||||
ext: TDoubleRect;
|
ext: TDoubleRect;
|
||||||
i, j: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
with Extent do begin
|
with Extent do begin
|
||||||
ext.a := AxisToGraph(a);
|
ext.a := AxisToGraph(a);
|
||||||
@ -380,12 +381,7 @@ begin
|
|||||||
PrepareGraphPoints(ext, LineType <> ltFromOrigin);
|
PrepareGraphPoints(ext, LineType <> ltFromOrigin);
|
||||||
DrawSingleLineInStack(ACanvas);
|
DrawSingleLineInStack(ACanvas);
|
||||||
for i := 0 to Source.YCount - 2 do begin
|
for i := 0 to Source.YCount - 2 do begin
|
||||||
if IsRotated then
|
UpdateGraphPoints(i);
|
||||||
for j := FLoBound to FUpBound do
|
|
||||||
FGraphPoints[j - FLoBound].X += AxisToGraphY(Source[j]^.YList[i])
|
|
||||||
else
|
|
||||||
for j := FLoBound to FUpBound do
|
|
||||||
FGraphPoints[j - FLoBound].Y += AxisToGraphY(Source[j]^.YList[i]);
|
|
||||||
DrawSingleLineInStack(ACanvas);
|
DrawSingleLineInStack(ACanvas);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -975,16 +971,18 @@ var
|
|||||||
pts: TPointArray;
|
pts: TPointArray;
|
||||||
numPts: Integer;
|
numPts: Integer;
|
||||||
|
|
||||||
procedure PushPoint(const A: TDoublePoint);
|
procedure PushPoint(const AP: TPoint); overload;
|
||||||
var
|
|
||||||
p: TPoint;
|
|
||||||
begin
|
begin
|
||||||
p := ParentChart.GraphToImage(A);
|
if (numPts > 0) and (AP = pts[numPts - 1]) then exit;
|
||||||
if (numPts > 0) and (p = pts[numPts - 1]) then exit;
|
pts[numPts] := AP;
|
||||||
pts[numPts] := p;
|
|
||||||
numPts += 1;
|
numPts += 1;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure PushPoint(const AP: TDoublePoint); overload;
|
||||||
|
begin
|
||||||
|
PushPoint(ParentChart.GraphToImage(AP));
|
||||||
|
end;
|
||||||
|
|
||||||
function ProjToLine(const APt: TDoublePoint; ACoord: Double): TDoublePoint;
|
function ProjToLine(const APt: TDoublePoint; ACoord: Double): TDoublePoint;
|
||||||
begin
|
begin
|
||||||
Result := APt;
|
Result := APt;
|
||||||
@ -993,14 +991,14 @@ var
|
|||||||
else
|
else
|
||||||
Result.Y := ACoord;
|
Result.Y := ACoord;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
i: Integer;
|
i, j, n2, numPrevPts: Integer;
|
||||||
a, b: TDoublePoint;
|
a, b: TDoublePoint;
|
||||||
ext, ext2: TDoubleRect;
|
ext, ext2: TDoubleRect;
|
||||||
z: Double;
|
z, z1, z2: Double;
|
||||||
|
prevPts: TPointArray;
|
||||||
begin
|
begin
|
||||||
if Count = 0 then exit;
|
if IsEmpty then exit;
|
||||||
|
|
||||||
ext := ParentChart.CurrentExtent;
|
ext := ParentChart.CurrentExtent;
|
||||||
ext2 := ext;
|
ext2 := ext;
|
||||||
@ -1010,52 +1008,70 @@ begin
|
|||||||
PrepareGraphPoints(ext, true);
|
PrepareGraphPoints(ext, true);
|
||||||
if Length(FGraphPoints) = 0 then exit;
|
if Length(FGraphPoints) = 0 then exit;
|
||||||
|
|
||||||
SetLength(pts, Length(FGraphPoints) * 2 + 2);
|
SetLength(pts, Length(FGraphPoints) * 4 + 4);
|
||||||
numPts := 0;
|
SetLength(prevPts, Length(pts));
|
||||||
|
numPrevPts := 0;
|
||||||
|
|
||||||
if UseZeroLevel then
|
if UseZeroLevel then
|
||||||
z := AxisToGraphY(ZeroLevel)
|
z := AxisToGraphY(ZeroLevel)
|
||||||
else if IsRotated then
|
|
||||||
z := ext2.a.X
|
|
||||||
else
|
else
|
||||||
z := ext2.a.Y;
|
z := IfThen(IsRotated, ext2.a.X, ext2.a.Y);
|
||||||
|
z1 := z;
|
||||||
|
z2 := z;
|
||||||
|
|
||||||
a := ProjToRect(FGraphPoints[0], ext2);
|
for j := 0 to Source.YCount - 1 do begin
|
||||||
PushPoint(ProjToLine(a, z));
|
if j > 0 then
|
||||||
PushPoint(a);
|
UpdateGraphPoints(j - 1);
|
||||||
for i := 0 to High(FGraphPoints) - 1 do begin
|
numPts := 0;
|
||||||
a := FGraphPoints[i];
|
a := ProjToRect(FGraphPoints[0], ext2);
|
||||||
b := FGraphPoints[i + 1];
|
PushPoint(ProjToLine(a, z1));
|
||||||
case ConnectType of
|
z1 := IfThen(IsRotated, a.X, a.Y);
|
||||||
ctLine: ;
|
for i := 0 to High(FGraphPoints) - 1 do begin
|
||||||
ctStepXY:
|
a := FGraphPoints[i];
|
||||||
if IsRotated then
|
b := FGraphPoints[i + 1];
|
||||||
b.X := a.X
|
case ConnectType of
|
||||||
else
|
ctLine: ;
|
||||||
b.Y := a.Y;
|
ctStepXY:
|
||||||
ctStepYX:
|
if IsRotated then
|
||||||
if IsRotated then
|
b.X := a.X
|
||||||
a.X := b.X
|
else
|
||||||
else
|
b.Y := a.Y;
|
||||||
a.Y := b.Y;
|
ctStepYX:
|
||||||
end;
|
if IsRotated then
|
||||||
// Avoid integer overflow at extreme zoom levels.
|
a.X := b.X
|
||||||
if LineIntersectsRect(a, b, ext2) then begin
|
else
|
||||||
PushPoint(a);
|
a.Y := b.Y;
|
||||||
PushPoint(b);
|
end;
|
||||||
|
// Avoid integer overflow at extreme zoom levels.
|
||||||
|
if LineIntersectsRect(a, b, ext2) then begin
|
||||||
|
PushPoint(a);
|
||||||
|
PushPoint(b);
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
PushPoint(ProjToRect(a, ext2));
|
||||||
|
PushPoint(ProjToRect(b, ext2));
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
a := ProjToRect(FGraphPoints[High(FGraphPoints)], ext2);
|
||||||
|
PushPoint(ProjToLine(a, z2));
|
||||||
|
z2 := IfThen(IsRotated, a.X, a.Y);
|
||||||
|
n2 := numPts;
|
||||||
|
|
||||||
|
for i := 0 to numPrevPts - 1 do
|
||||||
|
PushPoint(prevPts[numPrevPts - i - 1]);
|
||||||
|
for i := 0 to n2 - 1 do
|
||||||
|
prevPts[i] := pts[i];
|
||||||
|
numPrevPts := n2;
|
||||||
|
|
||||||
|
ACanvas.Brush.Assign(AreaBrush);
|
||||||
|
ACanvas.Pen.Assign(AreaContourPen);
|
||||||
|
if Depth > 0 then
|
||||||
|
// Rendering is incorrect when values cross zero level.
|
||||||
|
for i := 1 to n2 - 2 do
|
||||||
|
DrawLineDepth(ACanvas, pts[i], pts[i + 1], Depth);
|
||||||
|
ACanvas.Polygon(pts, false, 0, numPts);
|
||||||
|
DrawLabels(ACanvas);
|
||||||
end;
|
end;
|
||||||
a := ProjToRect(FGraphPoints[High(FGraphPoints)], ext2);
|
|
||||||
PushPoint(a);
|
|
||||||
PushPoint(ProjToLine(a, z));
|
|
||||||
|
|
||||||
ACanvas.Brush.Assign(AreaBrush);
|
|
||||||
ACanvas.Pen.Assign(AreaContourPen);
|
|
||||||
if Depth > 0 then
|
|
||||||
// Rendering is incorrect when values cross zero level.
|
|
||||||
for i := 0 to numPts - 2 do
|
|
||||||
DrawLineDepth(ACanvas, pts[i], pts[i + 1], Depth);
|
|
||||||
ACanvas.Polygon(pts, false, 0, numPts);
|
|
||||||
if AreaLinesPen.Style <> psClear then begin
|
if AreaLinesPen.Style <> psClear then begin
|
||||||
ACanvas.Pen.Assign(AreaLinesPen);
|
ACanvas.Pen.Assign(AreaLinesPen);
|
||||||
for i := 1 to High(FGraphPoints) - 1 do begin
|
for i := 1 to High(FGraphPoints) - 1 do begin
|
||||||
@ -1064,7 +1080,13 @@ begin
|
|||||||
ACanvas.Line(ParentChart.GraphToImage(a), ParentChart.GraphToImage(b));
|
ACanvas.Line(ParentChart.GraphToImage(a), ParentChart.GraphToImage(b));
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
DrawLabels(ACanvas);
|
end;
|
||||||
|
|
||||||
|
function TAreaSeries.Extent: TDoubleRect;
|
||||||
|
begin
|
||||||
|
Result := inherited Extent;
|
||||||
|
if not IsEmpty and UseZeroLevel then
|
||||||
|
UpdateMinMax(ZeroLevel, Result.a.Y, Result.b.Y);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAreaSeries.GetLabelDirection(AIndex: Integer): TLabelDirection;
|
function TAreaSeries.GetLabelDirection(AIndex: Integer): TLabelDirection;
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
unit TASources;
|
unit TASources;
|
||||||
|
|
||||||
{$mode objfpc}{$H+}
|
{$H+}
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user