mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-30 12:09:45 +02:00
TAChart: Fix bar series shapes when axes are rotated.
git-svn-id: trunk@60767 -
This commit is contained in:
parent
0bfea66f90
commit
b72b08174e
4
.gitattributes
vendored
4
.gitattributes
vendored
@ -5034,8 +5034,8 @@ components/tachart/demo/axistransf/axistransfdemo.lpi svneol=native#text/plain
|
||||
components/tachart/demo/axistransf/axistransfdemo.lpr svneol=native#text/pascal
|
||||
components/tachart/demo/axistransf/main.lfm svneol=native#text/plain
|
||||
components/tachart/demo/axistransf/main.pas svneol=native#text/pascal
|
||||
components/tachart/demo/barseriesshapes/BarShapes_Demo.lpi svneol=native#text/xml
|
||||
components/tachart/demo/barseriesshapes/BarShapes_Demo.lpr svneol=native#text/pascal
|
||||
components/tachart/demo/barseriesshapes/barshapes_demo.lpi svneol=native#text/xml
|
||||
components/tachart/demo/barseriesshapes/barshapes_demo.lpr svneol=native#text/pascal
|
||||
components/tachart/demo/barseriesshapes/main.lfm svneol=native#text/plain
|
||||
components/tachart/demo/barseriesshapes/main.pas svneol=native#text/pascal
|
||||
components/tachart/demo/barseriestools/barseriestools.lpi svneol=native#text/plain
|
||||
|
@ -34,8 +34,9 @@
|
||||
</RequiredPackages>
|
||||
<Units Count="2">
|
||||
<Unit0>
|
||||
<Filename Value="BarShapes_Demo.lpr"/>
|
||||
<Filename Value="barshapes_demo.lpr"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="BarShapes_Demo"/>
|
||||
</Unit0>
|
||||
<Unit1>
|
||||
<Filename Value="main.pas"/>
|
@ -1,17 +1,17 @@
|
||||
object Form1: TForm1
|
||||
Left = 332
|
||||
Height = 278
|
||||
Height = 317
|
||||
Top = 127
|
||||
Width = 535
|
||||
Width = 495
|
||||
Caption = 'Form1'
|
||||
ClientHeight = 278
|
||||
ClientWidth = 535
|
||||
ClientHeight = 317
|
||||
ClientWidth = 495
|
||||
LCLVersion = '2.1.0.0'
|
||||
object Chart1: TChart
|
||||
Left = 0
|
||||
Height = 243
|
||||
Height = 282
|
||||
Top = 0
|
||||
Width = 535
|
||||
Width = 495
|
||||
AxisList = <
|
||||
item
|
||||
Marks.LabelBrush.Style = bsClear
|
||||
@ -38,6 +38,8 @@ object Form1: TForm1
|
||||
)
|
||||
Align = alClient
|
||||
object BarSeries: TBarSeries
|
||||
AxisIndexX = 1
|
||||
AxisIndexY = 0
|
||||
BarBrush.Color = clRed
|
||||
Depth = 20
|
||||
DepthBrightnessDelta = -32
|
||||
@ -48,13 +50,13 @@ object Form1: TForm1
|
||||
object Panel1: TPanel
|
||||
Left = 0
|
||||
Height = 35
|
||||
Top = 243
|
||||
Width = 535
|
||||
Top = 282
|
||||
Width = 495
|
||||
Align = alBottom
|
||||
AutoSize = True
|
||||
BevelOuter = bvNone
|
||||
ClientHeight = 35
|
||||
ClientWidth = 535
|
||||
ClientWidth = 495
|
||||
TabOrder = 1
|
||||
object lblShape: TLabel
|
||||
AnchorSideLeft.Control = cb3D
|
||||
@ -140,6 +142,20 @@ object Form1: TForm1
|
||||
TabOrder = 2
|
||||
Value = 3
|
||||
end
|
||||
object cbRotated: TCheckBox
|
||||
AnchorSideLeft.Control = seLevels
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = cmbShape
|
||||
AnchorSideTop.Side = asrCenter
|
||||
Left = 358
|
||||
Height = 19
|
||||
Top = 8
|
||||
Width = 61
|
||||
BorderSpacing.Left = 12
|
||||
Caption = 'Rotated'
|
||||
OnChange = cbRotatedChange
|
||||
TabOrder = 3
|
||||
end
|
||||
end
|
||||
object RandomChartSource1: TRandomChartSource
|
||||
PointsNumber = 6
|
||||
|
@ -17,6 +17,7 @@ type
|
||||
BarSeries: TBarSeries;
|
||||
cb3D: TCheckBox;
|
||||
ChartStyles1: TChartStyles;
|
||||
cbRotated: TCheckBox;
|
||||
cmbShape: TComboBox;
|
||||
lblLevels: TLabel;
|
||||
lblShape: TLabel;
|
||||
@ -24,6 +25,7 @@ type
|
||||
RandomChartSource1: TRandomChartSource;
|
||||
seLevels: TSpinEdit;
|
||||
procedure cb3DChange(Sender: TObject);
|
||||
procedure cbRotatedChange(Sender: TObject);
|
||||
procedure cmbShapeChange(Sender: TObject);
|
||||
procedure seLevelsChange(Sender: TObject);
|
||||
private
|
||||
@ -50,8 +52,24 @@ begin
|
||||
BarSeries.Depth := 20
|
||||
else
|
||||
BarSeries.Depth := 0;
|
||||
Chart1.Margins.Top := 4 + Barseries.Depth;
|
||||
Chart1.Margins.Right := 4 + IfThen(BarSeries.BarShape in [bsRectangular, bsPyramid], Barseries.Depth, 0);
|
||||
if BarSeries.IsRotated then begin
|
||||
Chart1.Margins.Top := 4 + IfThen(BarSeries.BarShape in [bsRectangular, bsPyramid], Barseries.Depth, 0);
|
||||
Chart1.Margins.Right := 4 + BarSeries.Depth;
|
||||
end else begin
|
||||
Chart1.Margins.Top := 4 + Barseries.Depth;
|
||||
Chart1.Margins.Right := 4 + IfThen(BarSeries.BarShape in [bsRectangular, bsPyramid], Barseries.Depth, 0);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TForm1.cbRotatedChange(Sender: TObject);
|
||||
begin
|
||||
if cbRotated.Checked then begin
|
||||
BarSeries.AxisIndexX := 0;
|
||||
BarSeries.AxisIndexY := 1;
|
||||
end else begin
|
||||
BarSeries.AxisIndexX := 1;
|
||||
BarSeries.AxisIndexY := 0;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TForm1.cmbShapeChange(Sender: TObject);
|
||||
|
@ -1200,20 +1200,44 @@ var
|
||||
SetLength(pts, 3);
|
||||
if Depth = 0 then begin
|
||||
pts[0] := Point(AR.Left, AR.Bottom);
|
||||
pts[1] := Point(AR.Right, AR.Bottom);
|
||||
pts[2] := Point((AR.Left + AR.Right) div 2, AR.Top);
|
||||
if IsRotated then begin
|
||||
pts[1] := Point(AR.Left, AR.Top);
|
||||
pts[2] := Point(AR.Right, (AR.Top + AR.Bottom) div 2);
|
||||
end else begin
|
||||
pts[1] := Point(AR.Right, AR.Bottom);
|
||||
pts[2] := Point((AR.Left + AR.Right) div 2, AR.Top);
|
||||
end;
|
||||
ADrawer.Polygon(pts, 0, 3);
|
||||
end else
|
||||
if IsRotated then begin
|
||||
pts[0] := Point(AR.Left + scaled_depth, AR.Bottom - scaled_depth);
|
||||
pts[1] := Point(AR.Left + scaled_depth, AR.Top - scaled_depth);
|
||||
pts[2] := Point(AR.Right + scaled_depth2, (AR.Top + AR.Bottom - scaled_depth) div 2);
|
||||
ADrawer.BrushColor := GetDepthColor(c);
|
||||
ADrawer.Polygon(pts, 0, 3);
|
||||
pts[1] := Point(AR.Left, AR.Bottom);
|
||||
ADrawer.Polygon(pts, 0, 3);
|
||||
pts[0] := Point(AR.Left + scaled_depth, AR.Top - scaled_depth);
|
||||
pts[1] := Point(AR.Left, AR.Top);
|
||||
ADrawer.Polygon(pts, 0, 3);
|
||||
ADrawer.BrushColor := c;
|
||||
pts[0] := Point(AR.Left, AR.Bottom);
|
||||
ADrawer.Polygon(pts, 0, 3);
|
||||
end else begin
|
||||
// rear side
|
||||
pts[0] := Point(AR.Left + scaled_depth, AR.Bottom - scaled_depth);
|
||||
pts[1] := Point(AR.Right + scaled_depth, AR.Bottom - scaled_depth);
|
||||
pts[2] := Point((AR.Left + AR.Right + scaled_depth) div 2, AR.Top - scaled_depth2);
|
||||
ADrawer.BrushColor := GetDepthColor(c);
|
||||
ADrawer.Polygon(pts, 0, 3);
|
||||
// left side
|
||||
pts[1] := Point(AR.Left, AR.Bottom);
|
||||
ADrawer.Polygon(pts, 0, 3);
|
||||
// right side
|
||||
pts[0] := Point(AR.Right + scaled_depth, AR.Bottom - scaled_depth);
|
||||
pts[1] := Point(AR.Right, AR.Bottom);
|
||||
ADrawer.Polygon(pts, 0, 3);
|
||||
// front face
|
||||
ADrawer.BrushColor := c;
|
||||
pts[0] := Point(AR.Left, AR.Bottom);
|
||||
ADrawer.Polygon(pts, 0, 3);
|
||||
@ -1223,7 +1247,15 @@ var
|
||||
begin
|
||||
if Depth = 0 then
|
||||
ADrawer.Rectangle(AR)
|
||||
else begin
|
||||
else
|
||||
if IsRotated then begin
|
||||
ADrawer.Ellipse(AR.Left, AR.Top, AR.Left + scaled_depth, AR.Bottom);
|
||||
ADrawer.FillRect(AR.Left + scaled_depth2, AR.Top, AR.Right + scaled_depth2, AR.Bottom);
|
||||
ADrawer.Line(AR.Left + scaled_depth2, AR.Top, AR.Right + scaled_depth2, AR.Top);
|
||||
ADrawer.Line(AR.Left + scaled_depth2, AR.Bottom, AR.Right + scaled_depth2, AR.Bottom);
|
||||
ADrawer.BrushColor := GetDepthColor(ADrawer.BrushColor, false);
|
||||
ADrawer.Ellipse(AR.Right, AR.Top, AR.Right + scaled_depth, AR.Bottom);
|
||||
end else begin
|
||||
ADrawer.Ellipse(AR.Left, AR.Bottom, AR.Right, AR.Bottom - scaled_depth);
|
||||
ADrawer.FillRect(AR.Left, AR.Bottom - scaled_depth2, AR.Right, AR.Top - scaled_depth2);
|
||||
ADrawer.Line(AR.Left, AR.Bottom - scaled_depth2, AR.Left, AR.Top - scaled_depth2);
|
||||
@ -1237,83 +1269,147 @@ var
|
||||
SetLength(pts, 3);
|
||||
if Depth = 0 then begin
|
||||
pts[0] := Point(AR.Left, AR.Bottom);
|
||||
pts[1] := Point(AR.Right, AR.Bottom);
|
||||
pts[2] := Point((AR.Left + AR.Right) div 2, AR.Top);
|
||||
if IsRotated then begin
|
||||
pts[1] := Point(AR.Left, AR.Top);
|
||||
pts[2] := Point(AR.Right, (AR.Top + AR.Bottom) div 2);
|
||||
end else begin
|
||||
pts[1] := Point(AR.Right, AR.Bottom);
|
||||
pts[2] := Point((AR.Left + AR.Right) div 2, AR.Top);
|
||||
end;
|
||||
ADrawer.Polygon(pts, 0, 3);
|
||||
end else begin
|
||||
ADrawer.Ellipse(AR.Left, AR.Bottom, AR.Right, AR.Bottom - scaled_depth);
|
||||
// https://www.emathzone.com/tutorials/geometry/equation-of-tangent-and-normal-to-ellipse.html
|
||||
// tangent to ellipse (x/a)² + (y/b)² = 1 at ellipse point (x1, y1):
|
||||
// (x1 x) / a² + (y1 x) / b² = 1
|
||||
h := AR.Bottom - AR.Top; // height of cone
|
||||
if h > scaled_depth2 then begin
|
||||
if IsRotated then begin
|
||||
ADrawer.Ellipse(AR.Left, AR.Top, AR.Left + scaled_depth, AR.Bottom);
|
||||
h := AR.Right - AR.Left;
|
||||
if h <= scaled_depth2 then
|
||||
exit;
|
||||
a := (AR.Bottom - AR.Top) * 0.5;
|
||||
b := scaled_depth2;
|
||||
cx := (AR.Top + AR.Bottom) * 0.5;
|
||||
cy := AR.Left + scaled_depth2;
|
||||
factor := sqrt(1 - sqr(b/h));
|
||||
pts[0] := Point(round(cy + sqr(b)/h), round(cx - a*factor));
|
||||
pts[1] := Point(AR.Right + scaled_depth2, round(cx));
|
||||
pts[2] := Point(round(cy + sqr(b)/h), round(cx + a*factor));
|
||||
end else begin
|
||||
ADrawer.Ellipse(AR.Left, AR.Bottom, AR.Right, AR.Bottom - scaled_depth);
|
||||
// https://www.emathzone.com/tutorials/geometry/equation-of-tangent-and-normal-to-ellipse.html
|
||||
// tangent to ellipse (x/a)² + (y/b)² = 1 at ellipse point (x1, y1):
|
||||
// (x1 x) / a² + (y1 x) / b² = 1
|
||||
h := AR.Bottom - AR.Top; // height of cone
|
||||
if h <= scaled_depth2 then
|
||||
exit;
|
||||
a := (AR.Right - AR.Left) * 0.5;
|
||||
b := scaled_depth2;
|
||||
cx := (AR.Left + AR.Right) * 0.5; // center of cone ground area
|
||||
cy := AR.Bottom - scaled_depth2;
|
||||
factor := sqrt(1 - sqr(b/h));
|
||||
pts[0] := Point(round(cx - a*factor), round(cy - sqr(b) / h));
|
||||
pts[1] := Point((AR.Left + AR.Right) div 2, AR.Top - scaled_depth2);
|
||||
pts[1] := Point(round(cx), AR.Top - scaled_depth2);
|
||||
pts[2] := Point(round(cx + a*factor), round(cy - sqr(b) / h));
|
||||
ADrawer.SetPenParams(psClear, clTAColor);
|
||||
ADrawer.Polygon(pts, 0, 3);
|
||||
ADrawer.Pen := BarPen;
|
||||
if Styles <> nil then
|
||||
Styles.Apply(ADrawer, stackIndex);
|
||||
ADrawer.PolyLine(pts, 0, 3);
|
||||
end;
|
||||
ADrawer.SetPenParams(psClear, clTAColor);
|
||||
ADrawer.Polygon(pts, 0, 3);
|
||||
ADrawer.Pen := BarPen;
|
||||
if Styles <> nil then
|
||||
Styles.Apply(ADrawer, stackIndex);
|
||||
ADrawer.PolyLine(pts, 0, 3);
|
||||
end;
|
||||
end;
|
||||
bsHexPrism:
|
||||
begin
|
||||
a := (AR.Right - AR.Left) * 0.5;
|
||||
cx := (AR.Left + AR.Right) * 0.5;
|
||||
a := IfThen(IsRotated, AR.Bottom - AR.Top, AR.Right - AR.Left) * 0.5;
|
||||
cx := IfThen(IsRotated, AR.Top + AR.Bottom, AR.Left + AR.Right) * 0.5;
|
||||
cy := scaled_depth2;
|
||||
SetLength(pts, 4);
|
||||
factor := sin(pi * 30 / 180);
|
||||
if Depth = 0 then begin
|
||||
pts[0] := Point(AR.Left, AR.Bottom);
|
||||
pts[1] := Point(round(cx - a*factor), AR.Bottom);
|
||||
pts[2] := Point(pts[1].X, AR.Top);
|
||||
pts[3] := Point(AR.Left, AR.Top);
|
||||
ADrawer.Polygon(pts, 0, 4);
|
||||
pts[0] := pts[1];
|
||||
pts[3] := pts[2];
|
||||
pts[1] := Point(round(cx + a*factor), AR.Bottom);
|
||||
pts[2] := Point(pts[1].X, AR.Top);
|
||||
ADrawer.Polygon(pts, 0, 4);
|
||||
pts[0] := pts[1];
|
||||
pts[3] := pts[2];
|
||||
pts[1] := Point(AR.Right, AR.Bottom);
|
||||
pts[2] := Point(AR.Right, AR.Top);
|
||||
ADrawer.Polygon(pts, 0, 4);
|
||||
if IsRotated then begin
|
||||
pts[1] := Point(AR.Left, round(cx + a*factor));
|
||||
pts[2] := Point(AR.Right, pts[1].Y);
|
||||
pts[3] := Point(AR.Right, AR.Bottom);
|
||||
ADrawer.Polygon(pts, 0, 4);
|
||||
pts[0] := pts[1];
|
||||
pts[3] := pts[2];
|
||||
pts[1] := Point(AR.Left, round(cx - a*factor));
|
||||
pts[2] := Point(AR.Right, pts[1].Y);
|
||||
ADrawer.Polygon(pts, 0, 4);
|
||||
pts[0] := pts[1];
|
||||
pts[3] := pts[2];
|
||||
pts[1] := Point(AR.Left, AR.Top);
|
||||
pts[2] := Point(AR.Right, AR.Top);
|
||||
ADrawer.Polygon(pts, 0, 4);
|
||||
end else begin
|
||||
pts[1] := Point(round(cx - a*factor), AR.Bottom);
|
||||
pts[2] := Point(pts[1].X, AR.Top);
|
||||
pts[3] := Point(AR.Left, AR.Top);
|
||||
ADrawer.Polygon(pts, 0, 4);
|
||||
pts[0] := pts[1];
|
||||
pts[3] := pts[2];
|
||||
pts[1] := Point(round(cx + a*factor), AR.Bottom);
|
||||
pts[2] := Point(pts[1].X, AR.Top);
|
||||
ADrawer.Polygon(pts, 0, 4);
|
||||
pts[0] := pts[1];
|
||||
pts[3] := pts[2];
|
||||
pts[1] := Point(AR.Right, AR.Bottom);
|
||||
pts[2] := Point(AR.Right, AR.Top);
|
||||
ADrawer.Polygon(pts, 0, 4);
|
||||
end;
|
||||
end else begin
|
||||
c := ADrawer.BrushColor;
|
||||
pts[0] := Point(AR.Left, AR.Bottom - scaled_depth2);
|
||||
pts[1] := Point(round(cx - a*factor), AR.Bottom);
|
||||
pts[2] := Point(pts[1].X, AR.Top);
|
||||
pts[3] := Point(AR.Left, AR.Top - scaled_depth2);
|
||||
ADrawer.BrushColor := GetDepthColor(c);
|
||||
ADrawer.Polygon(pts, 0, 4);
|
||||
pts[0] := pts[1];
|
||||
pts[3] := pts[2];
|
||||
pts[1] := Point(round(cx + a*factor), AR.Bottom);
|
||||
pts[2] := Point(pts[1].X, AR.Top);
|
||||
ADrawer.BrushColor := c;
|
||||
ADrawer.Polygon(pts, 0, 4);
|
||||
pts[0] := pts[1];
|
||||
pts[3] := pts[2];
|
||||
pts[1] := Point(AR.Right, AR.Bottom - scaled_depth2);
|
||||
pts[2] := Point(AR.Right, AR.Top - scaled_depth2);
|
||||
ADrawer.BrushColor := GetDepthColor(c);
|
||||
ADrawer.Polygon(pts, 0, 4);
|
||||
SetLength(pts, 6);
|
||||
pts[0] := Point(AR.Left, AR.Top - scaled_depth2);
|
||||
pts[1] := Point(round(cx - a*factor), AR.Top);
|
||||
pts[2] := Point(round(cx + a*factor), AR.Top);
|
||||
pts[3] := Point(AR.Right, AR.Top - scaled_depth2);
|
||||
pts[4] := Point(round(cx + a*factor), AR.Top - scaled_depth);
|
||||
pts[5] := Point(round(cx - a*factor), AR.Top - scaled_depth);
|
||||
if IsRotated then begin
|
||||
pts[0] := Point(AR.Left + scaled_depth2, AR.Bottom);
|
||||
pts[1] := Point(AR.Left, round(cx + a*factor));
|
||||
pts[2] := Point(AR.Right, pts[1].Y);
|
||||
pts[3] := Point(AR.Right + scaled_depth2, AR.Bottom);
|
||||
ADrawer.Polygon(pts, 0, 4);
|
||||
pts[0] := pts[1];
|
||||
pts[3] := pts[2];
|
||||
pts[1] := Point(AR.Left, round(cx - a*factor));
|
||||
pts[2] := Point(AR.Right, pts[1].Y);
|
||||
ADrawer.BrushColor := c;
|
||||
ADrawer.Polygon(pts, 0, 4);
|
||||
pts[0] := pts[1];
|
||||
pts[3] := pts[2];
|
||||
pts[1] := Point(AR.Left + scaled_depth2, AR.Top);
|
||||
pts[2] := Point(AR.Right + scaled_depth2, pts[1].Y);
|
||||
ADrawer.BrushColor := GetDepthColor(c);
|
||||
ADrawer.Polygon(pts, 0, 4);
|
||||
SetLength(pts, 6);
|
||||
pts[0] := Point(AR.Right + scaled_depth2, AR.Bottom);
|
||||
pts[1] := Point(AR.Right, round(cx + a*factor));
|
||||
pts[2] := Point(AR.Right, round(cx - a*factor));
|
||||
pts[3] := Point(AR.Right + scaled_depth2, AR.Top);
|
||||
pts[4] := Point(AR.Right + scaled_depth, round(cx - a*factor));
|
||||
pts[5] := Point(AR.Right + scaled_depth, round(cx + a*factor));
|
||||
end else begin
|
||||
pts[0] := Point(AR.Left, AR.Bottom - scaled_depth2);
|
||||
pts[1] := Point(round(cx - a*factor), AR.Bottom);
|
||||
pts[2] := Point(pts[1].X, AR.Top);
|
||||
pts[3] := Point(AR.Left, AR.Top - scaled_depth2);
|
||||
ADrawer.Polygon(pts, 0, 4);
|
||||
pts[0] := pts[1];
|
||||
pts[3] := pts[2];
|
||||
pts[1] := Point(round(cx + a*factor), AR.Bottom);
|
||||
pts[2] := Point(pts[1].X, AR.Top);
|
||||
ADrawer.BrushColor := c;
|
||||
ADrawer.Polygon(pts, 0, 4);
|
||||
pts[0] := pts[1];
|
||||
pts[3] := pts[2];
|
||||
pts[1] := Point(AR.Right, AR.Bottom - scaled_depth2);
|
||||
pts[2] := Point(AR.Right, AR.Top - scaled_depth2);
|
||||
ADrawer.BrushColor := GetDepthColor(c);
|
||||
ADrawer.Polygon(pts, 0, 4);
|
||||
SetLength(pts, 6);
|
||||
pts[0] := Point(AR.Left, AR.Top - scaled_depth2);
|
||||
pts[1] := Point(round(cx - a*factor), AR.Top);
|
||||
pts[2] := Point(round(cx + a*factor), AR.Top);
|
||||
pts[3] := Point(AR.Right, AR.Top - scaled_depth2);
|
||||
pts[4] := Point(round(cx + a*factor), AR.Top - scaled_depth);
|
||||
pts[5] := Point(round(cx - a*factor), AR.Top - scaled_depth);
|
||||
end;
|
||||
ADrawer.BrushColor := GetDepthColor(c, true);
|
||||
ADrawer.Polygon(pts, 0, 6);
|
||||
end;
|
||||
|
Loading…
Reference in New Issue
Block a user