mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-29 08:50:16 +02:00
TAChart: Add new property InnerRadiusPercent to TPieSeries for achieving a "donut" series
git-svn-id: trunk@60666 -
This commit is contained in:
parent
b2b0533619
commit
a8812d76d2
@ -1,32 +1,32 @@
|
||||
object Form1: TForm1
|
||||
Left = 459
|
||||
Height = 433
|
||||
Height = 482
|
||||
Top = 346
|
||||
Width = 566
|
||||
Width = 580
|
||||
Caption = 'Form1'
|
||||
ClientHeight = 433
|
||||
ClientWidth = 566
|
||||
ClientHeight = 482
|
||||
ClientWidth = 580
|
||||
OnCreate = FormCreate
|
||||
Position = poScreenCenter
|
||||
LCLVersion = '2.1.0.0'
|
||||
object PageControl1: TPageControl
|
||||
Left = 0
|
||||
Height = 433
|
||||
Height = 482
|
||||
Top = 0
|
||||
Width = 566
|
||||
Width = 580
|
||||
ActivePage = tsPie
|
||||
Align = alClient
|
||||
TabIndex = 0
|
||||
TabOrder = 0
|
||||
object tsPie: TTabSheet
|
||||
Caption = 'Pie'
|
||||
ClientHeight = 405
|
||||
ClientWidth = 558
|
||||
ClientHeight = 454
|
||||
ClientWidth = 572
|
||||
object ChartPie: TChart
|
||||
Left = 0
|
||||
Height = 337
|
||||
Top = 68
|
||||
Width = 558
|
||||
Height = 336
|
||||
Top = 118
|
||||
Width = 572
|
||||
AxisList = <
|
||||
item
|
||||
Visible = False
|
||||
@ -54,6 +54,7 @@ object Form1: TForm1
|
||||
Color = clDefault
|
||||
OnMouseDown = ChartPieMouseDown
|
||||
object ChartPiePieSeries1: TPieSeries
|
||||
DepthBrightnessDelta = -32
|
||||
Exploded = True
|
||||
Marks.Distance = 40
|
||||
Marks.Format = '%2:s'
|
||||
@ -64,27 +65,26 @@ object Form1: TForm1
|
||||
object Panel1: TPanel
|
||||
AnchorSideTop.Side = asrCenter
|
||||
Left = 0
|
||||
Height = 68
|
||||
Height = 118
|
||||
Top = 0
|
||||
Width = 558
|
||||
Width = 572
|
||||
Align = alTop
|
||||
Alignment = taLeftJustify
|
||||
AutoSize = True
|
||||
Caption = ' Click on a slice to explode/unexplode it'
|
||||
ClientHeight = 68
|
||||
ClientWidth = 558
|
||||
ClientHeight = 118
|
||||
ClientWidth = 572
|
||||
TabOrder = 1
|
||||
object seWords: TSpinEdit
|
||||
AnchorSideTop.Control = Panel1
|
||||
AnchorSideRight.Control = Panel1
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 491
|
||||
AnchorSideRight.Control = lblInnerRadius
|
||||
Left = 326
|
||||
Height = 23
|
||||
Top = 9
|
||||
Width = 58
|
||||
Top = 7
|
||||
Width = 72
|
||||
Anchors = [akTop, akRight]
|
||||
BorderSpacing.Top = 8
|
||||
BorderSpacing.Right = 8
|
||||
BorderSpacing.Top = 6
|
||||
BorderSpacing.Right = 16
|
||||
MaxValue = 10
|
||||
OnChange = seWordsChange
|
||||
TabOrder = 0
|
||||
@ -94,9 +94,9 @@ object Form1: TForm1
|
||||
AnchorSideTop.Control = seWords
|
||||
AnchorSideTop.Side = asrCenter
|
||||
AnchorSideRight.Control = seWords
|
||||
Left = 420
|
||||
Left = 255
|
||||
Height = 15
|
||||
Top = 13
|
||||
Top = 11
|
||||
Width = 63
|
||||
Anchors = [akTop, akRight]
|
||||
BorderSpacing.Right = 8
|
||||
@ -104,14 +104,17 @@ object Form1: TForm1
|
||||
ParentColor = False
|
||||
end
|
||||
object seLabelAngle: TSpinEdit
|
||||
AnchorSideLeft.Control = seWords
|
||||
AnchorSideTop.Control = seWords
|
||||
AnchorSideRight.Control = lblWords
|
||||
Left = 354
|
||||
AnchorSideTop.Side = asrBottom
|
||||
AnchorSideRight.Control = seWords
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 326
|
||||
Height = 23
|
||||
Top = 9
|
||||
Width = 50
|
||||
Anchors = [akTop, akRight]
|
||||
BorderSpacing.Right = 16
|
||||
Top = 34
|
||||
Width = 72
|
||||
Anchors = [akTop, akLeft, akRight]
|
||||
BorderSpacing.Top = 4
|
||||
Increment = 5
|
||||
MaxValue = 360
|
||||
MinValue = -360
|
||||
@ -121,43 +124,43 @@ object Form1: TForm1
|
||||
object lblLabelAngle: TLabel
|
||||
AnchorSideTop.Control = seLabelAngle
|
||||
AnchorSideTop.Side = asrCenter
|
||||
Left = 291
|
||||
AnchorSideRight.Control = seLabelAngle
|
||||
Left = 258
|
||||
Height = 15
|
||||
Top = 13
|
||||
Top = 38
|
||||
Width = 60
|
||||
Anchors = [akTop, akRight]
|
||||
BorderSpacing.Right = 8
|
||||
Caption = 'Label angle'
|
||||
ParentColor = False
|
||||
end
|
||||
object cbRotate: TCheckBox
|
||||
AnchorSideLeft.Control = Cb3D
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideLeft.Control = cbMarkPositions
|
||||
AnchorSideTop.Control = cbMarkPositions
|
||||
AnchorSideTop.Side = asrCenter
|
||||
AnchorSideTop.Side = asrBottom
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 462
|
||||
Left = 255
|
||||
Height = 19
|
||||
Top = 38
|
||||
Top = 90
|
||||
Width = 87
|
||||
BorderSpacing.Left = 8
|
||||
BorderSpacing.Top = 4
|
||||
BorderSpacing.Bottom = 8
|
||||
Caption = 'Rotate labels'
|
||||
OnChange = cbRotateChange
|
||||
TabOrder = 2
|
||||
end
|
||||
object cbMarkPositions: TComboBox
|
||||
AnchorSideLeft.Control = lblWords
|
||||
AnchorSideTop.Control = lblLabelAngle
|
||||
AnchorSideTop.Side = asrBottom
|
||||
AnchorSideRight.Control = seLabelAngle
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 291
|
||||
Left = 255
|
||||
Height = 23
|
||||
Top = 36
|
||||
Width = 113
|
||||
Anchors = [akTop, akRight]
|
||||
Top = 61
|
||||
Width = 143
|
||||
Anchors = [akTop, akLeft, akRight]
|
||||
BorderSpacing.Top = 8
|
||||
BorderSpacing.Bottom = 8
|
||||
BorderSpacing.Bottom = 6
|
||||
ItemHeight = 15
|
||||
ItemIndex = 0
|
||||
Items.Strings = (
|
||||
@ -171,30 +174,126 @@ object Form1: TForm1
|
||||
Text = 'Around'
|
||||
end
|
||||
object Cb3D: TCheckBox
|
||||
AnchorSideLeft.Control = cbMarkPositions
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = cbMarkPositions
|
||||
AnchorSideLeft.Control = lblInnerRadius
|
||||
AnchorSideTop.Control = seLabelAngle
|
||||
AnchorSideTop.Side = asrCenter
|
||||
Left = 420
|
||||
Left = 414
|
||||
Height = 19
|
||||
Top = 38
|
||||
Top = 36
|
||||
Width = 34
|
||||
BorderSpacing.Left = 16
|
||||
Caption = '3D'
|
||||
OnChange = Cb3DChange
|
||||
TabOrder = 4
|
||||
end
|
||||
object seInnerRadius: TSpinEdit
|
||||
AnchorSideTop.Control = seWords
|
||||
AnchorSideRight.Control = Panel1
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 497
|
||||
Height = 23
|
||||
Top = 7
|
||||
Width = 62
|
||||
Anchors = [akTop, akRight]
|
||||
BorderSpacing.Right = 12
|
||||
OnChange = seInnerRadiusChange
|
||||
TabOrder = 5
|
||||
end
|
||||
object lblInnerRadius: TLabel
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = lblWords
|
||||
AnchorSideRight.Control = seInnerRadius
|
||||
Left = 414
|
||||
Height = 15
|
||||
Top = 11
|
||||
Width = 75
|
||||
Anchors = [akTop, akRight]
|
||||
BorderSpacing.Right = 8
|
||||
Caption = 'Inner radius %'
|
||||
ParentColor = False
|
||||
end
|
||||
object lblDepth: TLabel
|
||||
AnchorSideLeft.Control = Cb3D
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = Cb3D
|
||||
AnchorSideTop.Side = asrCenter
|
||||
AnchorSideRight.Control = seDepth
|
||||
Left = 457
|
||||
Height = 15
|
||||
Top = 38
|
||||
Width = 32
|
||||
Anchors = [akTop, akRight]
|
||||
BorderSpacing.Left = 12
|
||||
BorderSpacing.Right = 8
|
||||
Caption = 'Depth'
|
||||
Enabled = False
|
||||
ParentColor = False
|
||||
end
|
||||
object seDepth: TSpinEdit
|
||||
AnchorSideLeft.Control = seInnerRadius
|
||||
AnchorSideTop.Control = seLabelAngle
|
||||
AnchorSideTop.Side = asrCenter
|
||||
AnchorSideRight.Control = Panel1
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 497
|
||||
Height = 23
|
||||
Top = 34
|
||||
Width = 62
|
||||
Anchors = [akTop, akRight]
|
||||
BorderSpacing.Right = 12
|
||||
Enabled = False
|
||||
OnChange = seDepthChange
|
||||
TabOrder = 6
|
||||
Value = 20
|
||||
end
|
||||
object seDepthBrightnessDelta: TSpinEdit
|
||||
AnchorSideLeft.Control = seInnerRadius
|
||||
AnchorSideTop.Control = seDepth
|
||||
AnchorSideTop.Side = asrBottom
|
||||
AnchorSideRight.Control = Panel1
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 497
|
||||
Height = 23
|
||||
Top = 61
|
||||
Width = 62
|
||||
Anchors = [akTop, akRight]
|
||||
BorderSpacing.Top = 4
|
||||
BorderSpacing.Right = 12
|
||||
Enabled = False
|
||||
MaxValue = 255
|
||||
MinValue = -255
|
||||
OnChange = seDepthBrightnessDeltaChange
|
||||
TabOrder = 7
|
||||
Value = -32
|
||||
end
|
||||
object lblDepthBrightnessDelta: TLabel
|
||||
AnchorSideLeft.Control = cbMarkPositions
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = seDepthBrightnessDelta
|
||||
AnchorSideTop.Side = asrCenter
|
||||
AnchorSideRight.Control = seDepthBrightnessDelta
|
||||
Left = 398
|
||||
Height = 15
|
||||
Top = 65
|
||||
Width = 91
|
||||
Alignment = taRightJustify
|
||||
Anchors = [akTop, akLeft, akRight]
|
||||
BorderSpacing.Right = 8
|
||||
Caption = 'Brightness delta'
|
||||
Enabled = False
|
||||
ParentColor = False
|
||||
WordWrap = True
|
||||
end
|
||||
end
|
||||
end
|
||||
object tsPolar: TTabSheet
|
||||
Caption = 'Polar'
|
||||
ClientHeight = 405
|
||||
ClientWidth = 558
|
||||
ClientHeight = 454
|
||||
ClientWidth = 572
|
||||
object ChartPolar: TChart
|
||||
Left = 0
|
||||
Height = 405
|
||||
Height = 454
|
||||
Top = 0
|
||||
Width = 420
|
||||
Width = 457
|
||||
AxisList = <
|
||||
item
|
||||
Marks.LabelBrush.Style = bsClear
|
||||
@ -237,14 +336,14 @@ object Form1: TForm1
|
||||
end
|
||||
end
|
||||
object pnlPolar: TPanel
|
||||
Left = 420
|
||||
Height = 405
|
||||
Left = 457
|
||||
Height = 454
|
||||
Top = 0
|
||||
Width = 138
|
||||
Width = 115
|
||||
Align = alRight
|
||||
AutoSize = True
|
||||
ClientHeight = 405
|
||||
ClientWidth = 138
|
||||
ClientHeight = 454
|
||||
ClientWidth = 115
|
||||
TabOrder = 1
|
||||
object cbCloseCircle: TCheckBox
|
||||
AnchorSideLeft.Control = pnlPolar
|
||||
@ -296,7 +395,7 @@ object Form1: TForm1
|
||||
Left = 9
|
||||
Height = 17
|
||||
Top = 117
|
||||
Width = 120
|
||||
Width = 97
|
||||
BorderSpacing.Left = 8
|
||||
BorderSpacing.Top = 4
|
||||
BorderSpacing.Right = 8
|
||||
@ -324,23 +423,18 @@ object Form1: TForm1
|
||||
end
|
||||
object ListChartSource1: TListChartSource
|
||||
DataPoints.Strings = (
|
||||
'0|1|?|'
|
||||
'0|2|?|'
|
||||
'0|3|?|'
|
||||
'0|1|?|'
|
||||
'0|2|?|'
|
||||
'0|3|?|'
|
||||
'0|1|?|'
|
||||
'0|2|?|'
|
||||
'0|3|?|'
|
||||
'0|5|?|'
|
||||
'0|3|?|'
|
||||
'0|1|?|'
|
||||
'0.20000000000000001|0.20000000000000001|?|'
|
||||
'0|1|?|'
|
||||
)
|
||||
left = 488
|
||||
top = 296
|
||||
left = 64
|
||||
top = 256
|
||||
end
|
||||
object ChartToolset1: TChartToolset
|
||||
left = 488
|
||||
top = 240
|
||||
left = 64
|
||||
top = 200
|
||||
end
|
||||
object RandomChartSource1: TRandomChartSource
|
||||
PointsNumber = 15
|
||||
@ -350,7 +444,7 @@ object Form1: TForm1
|
||||
YCount = 2
|
||||
YMax = 10
|
||||
YMin = 2
|
||||
left = 488
|
||||
top = 356
|
||||
left = 64
|
||||
top = 316
|
||||
end
|
||||
end
|
||||
|
@ -26,6 +26,11 @@ type
|
||||
cbShowPoints: TCheckBox;
|
||||
cbFilled: TCheckBox;
|
||||
Cb3D: TCheckBox;
|
||||
seDepth: TSpinEdit;
|
||||
seDepthBrightnessDelta: TSpinEdit;
|
||||
lblInnerRadius: TLabel;
|
||||
lblDepth: TLabel;
|
||||
lblDepthBrightnessDelta: TLabel;
|
||||
lblTransparency: TLabel;
|
||||
lblWords: TLabel;
|
||||
lblLabelAngle: TLabel;
|
||||
@ -37,6 +42,7 @@ type
|
||||
sbTransparency: TScrollBar;
|
||||
seWords: TSpinEdit;
|
||||
seLabelAngle: TSpinEdit;
|
||||
seInnerRadius: TSpinEdit;
|
||||
tsPolar: TTabSheet;
|
||||
tsPie: TTabSheet;
|
||||
procedure cbCloseCircleChange(Sender: TObject);
|
||||
@ -47,6 +53,9 @@ type
|
||||
Shift: TShiftState; X, Y: Integer);
|
||||
procedure cbShowPointsChange(Sender: TObject);
|
||||
procedure Cb3DChange(Sender: TObject);
|
||||
procedure seDepthBrightnessDeltaChange(Sender: TObject);
|
||||
procedure seDepthChange(Sender: TObject);
|
||||
procedure seInnerRadiusChange(Sender: TObject);
|
||||
procedure FormCreate(Sender: TObject);
|
||||
procedure sbTransparencyChange(Sender: TObject);
|
||||
procedure seWordsChange(Sender: TObject);
|
||||
@ -95,10 +104,30 @@ begin
|
||||
end;
|
||||
|
||||
procedure TForm1.Cb3DChange(Sender: TObject);
|
||||
var
|
||||
DEPTH: array[boolean] of Integer = (0, 10);
|
||||
begin
|
||||
ChartPiePieSeries1.Depth := DEPTH[Cb3D.Checked];
|
||||
if cb3D.Checked then
|
||||
ChartPiePieSeries1.Depth := seDepth.Value
|
||||
else
|
||||
ChartPiePieSeries1.Depth := 0;
|
||||
seDepth.Enabled := cb3D.Checked;
|
||||
lblDepth.Enabled := cb3D.Checked;
|
||||
seDepthBrightnessDelta.Enabled := cb3D.Checked;
|
||||
lblDepthBrightnessDelta.Enabled := cb3D.Checked;
|
||||
end;
|
||||
|
||||
procedure TForm1.seDepthBrightnessDeltaChange(Sender: TObject);
|
||||
begin
|
||||
ChartPiePieSeries1.DepthBrightnessDelta := seDepthBrightnessDelta.Value;
|
||||
end;
|
||||
|
||||
procedure TForm1.seDepthChange(Sender: TObject);
|
||||
begin
|
||||
ChartPiePieSeries1.Depth := seDepth.Value;
|
||||
end;
|
||||
|
||||
procedure TForm1.seInnerRadiusChange(Sender: TObject);
|
||||
begin
|
||||
ChartPiePieSeries1.InnerRadiusPercent := seInnerRadius.Value;
|
||||
end;
|
||||
|
||||
procedure TForm1.FormCreate(Sender: TObject);
|
||||
|
@ -65,6 +65,7 @@ type
|
||||
FMarkDistancePercent: Boolean;
|
||||
FMarkPositions: TPieMarkPositions;
|
||||
FRadius: Integer;
|
||||
FInnerRadiusPercent: Integer;
|
||||
FSlices: array of TPieSlice;
|
||||
private
|
||||
FEdgePen: TPen;
|
||||
@ -75,14 +76,18 @@ type
|
||||
procedure SetEdgePen(AValue: TPen);
|
||||
procedure SetExploded(AValue: Boolean);
|
||||
procedure SetFixedRadius(AValue: TChartDistance);
|
||||
procedure SetInnerRadiusPercent(AValue: Integer);
|
||||
procedure SetMarkDistancePercent(AValue: Boolean);
|
||||
procedure SetMarkPositions(AValue: TPieMarkPositions);
|
||||
procedure SetRotateLabels(AValue: Boolean);
|
||||
function SliceColor(AIndex: Integer): TColor;
|
||||
function TryRadius(ADrawer: IChartDrawer): TRect;
|
||||
protected
|
||||
function CalcInnerRadius: Integer; inline;
|
||||
procedure GetLegendItems(AItems: TChartLegendItems); override;
|
||||
property Radius: Integer read FRadius;
|
||||
property InnerRadiusPercent: Integer
|
||||
read FInnerRadiusPercent write SetInnerRadiusPercent default 0;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
@ -243,11 +248,17 @@ begin
|
||||
with TCustomPieSeries(ASource) do begin
|
||||
Self.FExploded := FExploded;
|
||||
Self.FFixedRadius := FFixedRadius;
|
||||
Self.FInnerRadiusPercent := FInnerRadiusPercent;
|
||||
Self.FRotateLabels := FRotateLabels;
|
||||
end;
|
||||
inherited Assign(ASource);
|
||||
end;
|
||||
|
||||
function TCustomPieSeries.CalcInnerRadius: Integer;
|
||||
begin
|
||||
Result := Round(0.01 * FRadius * FInnerRadiusPercent);
|
||||
end;
|
||||
|
||||
constructor TCustomPieSeries.Create(AOwner: TComponent);
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
@ -275,6 +286,7 @@ const
|
||||
var
|
||||
ps: TPieSlice;
|
||||
scaled_depth: Integer;
|
||||
innerRadius: Integer;
|
||||
|
||||
function PrevSlice(ASlice: TPieSlice): TPieSlice;
|
||||
begin
|
||||
@ -309,23 +321,42 @@ var
|
||||
(SliceExploded(ASlice) or SliceExploded(NextSlice(ASlice)));
|
||||
end;
|
||||
|
||||
procedure DrawArc3D(ASlice: TPieSlice);
|
||||
procedure DrawArc3D(ASlice: TPieSlice; AInside: Boolean);
|
||||
var
|
||||
i, numSteps: Integer;
|
||||
a: Double;
|
||||
p: Array of TPoint;
|
||||
angle1, angle2: Double;
|
||||
clr: TColor;
|
||||
r: Integer;
|
||||
isVisible: Boolean;
|
||||
outsideVisible: Boolean;
|
||||
insideVisible: Boolean;
|
||||
begin
|
||||
if InRange(ASlice.FPrevAngle, PI_3_4, PI_7_4) and InRange(ASlice.FNextAngle, PI_3_4, PI_7_4) then
|
||||
if AInside and (FInnerRadiusPercent = 0) then
|
||||
exit;
|
||||
angle1 := IfThen(InRange(ASlice.FPrevAngle, PI_3_4, PI_7_4), PI_7_4, ASlice.FPrevAngle);
|
||||
angle2 := IfThen(InRange(ASlice.FNextAngle, PI_3_4, PI_7_4), PI_3_4, ASlice.FNextAngle);
|
||||
numSteps := Max(Round(TWO_PI * (angle2 - angle1) * FRadius / STEP), 2);
|
||||
if AInside then
|
||||
isVisible := (ASlice.FPrevAngle < PI_7_4) and (ASlice.FNextAngle > PI_3_4)
|
||||
else
|
||||
isVisible := not (InRange(ASlice.FPrevAngle, PI_3_4, PI_7_4) and
|
||||
InRange(ASlice.FNextAngle, PI_3_4, PI_7_4) );
|
||||
if not isVisible then
|
||||
exit;
|
||||
|
||||
if AInside then begin
|
||||
r := innerRadius;
|
||||
angle1 := IfThen(InRange(ASlice.FPrevAngle, PI_3_4, PI_7_4), ASlice.FPrevAngle, PI_3_4);
|
||||
angle2 := IfThen(InRange(ASlice.FNextAngle, PI_3_4, PI_7_4), ASlice.FNextAngle, PI_7_4);
|
||||
end else begin
|
||||
r := FRadius;
|
||||
angle1 := IfThen(InRange(ASlice.FPrevAngle, PI_3_4, PI_7_4), PI_7_4, ASlice.FPrevAngle);
|
||||
angle2 := IfThen(InRange(ASlice.FNextAngle, PI_3_4, PI_7_4), PI_3_4, ASlice.FNextAngle);
|
||||
end;
|
||||
numSteps := Max(Round(TWO_PI * (angle2 - angle1) * r / STEP), 2);
|
||||
SetLength(p, 2 * numSteps + 1);
|
||||
for i := 0 to numSteps - 1 do begin
|
||||
a := WeightedAverage(angle1, angle2, i / (numSteps - 1));
|
||||
p[i] := ASlice.FBase + RotatePointX(FRadius, -a);
|
||||
p[i] := ASlice.FBase + RotatePointX(r, -a);
|
||||
p[High(p) - i - 1] := p[i] + Point(scaled_depth, -scaled_depth);
|
||||
end;
|
||||
p[High(p)] := p[0];
|
||||
@ -337,12 +368,46 @@ var
|
||||
ADrawer.PolyLine(p, numSteps-1, numSteps+2);
|
||||
end;
|
||||
|
||||
procedure DrawVisibleArc3D(ASlice: TPieSlice);
|
||||
begin
|
||||
if ASlice.FVisible then begin
|
||||
DrawArc3D(ASlice, false);
|
||||
DrawArc3D(ASlice, true);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure DrawPieRing(ASlice: TPieSlice);
|
||||
var
|
||||
i: Integer;
|
||||
a, angle1, angle2: Double;
|
||||
ni, no: Integer;
|
||||
p: Array of TPoint;
|
||||
begin
|
||||
angle1 := ASlice.FPrevAngle;
|
||||
angle2 := ASlice.FNextAngle;
|
||||
ni := Max(Round(TWO_PI * (angle2 - angle1) * innerRadius / STEP), 2);
|
||||
no := Max(Round(TWO_PI * (angle2 - angle1) * FRadius / STEP), 2);
|
||||
SetLength(p, ni + no);
|
||||
for i := 0 to no - 1 do begin
|
||||
a := WeightedAverage(angle1, angle2, i / (no - 1));
|
||||
p[i] := ASlice.FBase + RotatePointX(FRadius, -a);
|
||||
end;
|
||||
for i := 0 to ni - 1 do begin
|
||||
a := WeightedAverage(angle1, angle2, i / (ni - 1));
|
||||
p[no + ni - 1 - i] := ASlice.FBase + RotatePointX(innerRadius, -a);
|
||||
end;
|
||||
ADrawer.Polygon(p, 0, Length(p));
|
||||
end;
|
||||
|
||||
procedure DrawStartEdge3D(ASlice: TPieSlice);
|
||||
begin
|
||||
ADrawer.SetBrushParams(
|
||||
bsSolid, GetDepthColor(SliceColor(ASlice.FOrigIndex)));
|
||||
ADrawer.DrawLineDepth(
|
||||
ASlice.FBase, ASlice.FBase + RotatePointX(FRadius, -ASlice.FPrevAngle), scaled_depth);
|
||||
ASlice.FBase + RotatePointX(innerRadius, -ASlice.FPrevAngle),
|
||||
ASlice.FBase + RotatePointX(FRadius, -ASlice.FPrevAngle),
|
||||
scaled_depth
|
||||
);
|
||||
end;
|
||||
|
||||
procedure DrawEndEdge3D(ASlice: TPieSlice);
|
||||
@ -350,7 +415,10 @@ var
|
||||
ADrawer.SetBrushParams(
|
||||
bsSolid, GetDepthColor(SliceColor(ASlice.FOrigIndex)));
|
||||
ADrawer.DrawLineDepth(
|
||||
ASlice.FBase, ASlice.FBase + RotatePointX(FRadius, -ASlice.FNextAngle), scaled_depth);
|
||||
ASlice.FBase + RotatePointX(innerRadius, -ASlice.FNextAngle),
|
||||
ASlice.FBase + RotatePointX(FRadius, -ASlice.FNextAngle),
|
||||
scaled_depth
|
||||
);
|
||||
end;
|
||||
|
||||
procedure FindLeftMostIndex(out AIndex: Integer);
|
||||
@ -373,6 +441,7 @@ begin
|
||||
|
||||
Marks.SetAdditionalAngle(0);
|
||||
Measure(ADrawer);
|
||||
innerRadius := CalcInnerRadius;
|
||||
|
||||
ADrawer.SetPen(EdgePen);
|
||||
if Depth > 0 then begin
|
||||
@ -384,7 +453,8 @@ begin
|
||||
DrawStartEdge3D(FSlices[iL]);
|
||||
if EndEdgeVisible(FSlices[iL]) then
|
||||
DrawEndEdge3D(FSlices[iL]);
|
||||
DrawArc3D(FSlices[iL]);
|
||||
DrawArc3D(FSlices[iL], false);
|
||||
DrawArc3D(FSlices[iL], true);
|
||||
end;
|
||||
|
||||
for i:=iL+1 to High(FSlices) do
|
||||
@ -393,7 +463,8 @@ begin
|
||||
DrawStartEdge3D(FSlices[i]);
|
||||
if EndEdgeVisible(FSlices[i]) then
|
||||
DrawEndEdge3D(FSlices[i]);
|
||||
DrawArc3D(FSlices[i]);
|
||||
DrawArc3D(FSlices[i], false);
|
||||
DrawArc3d(FSlices[i], true);
|
||||
end;
|
||||
|
||||
if iL <> 0 then
|
||||
@ -407,17 +478,20 @@ begin
|
||||
|
||||
// Draw arcs
|
||||
for i:= iL-1 downto 0 do
|
||||
if FSlices[i].FVisible then DrawArc3D(FSlices[i]);
|
||||
DrawVisibleArc3D(FSlices[i]);
|
||||
end;
|
||||
|
||||
ADrawer.SetPen(EdgePen);
|
||||
for ps in FSlices do begin
|
||||
if not ps.FVisible then continue;
|
||||
ADrawer.SetBrushParams(bsSolid, SliceColor(ps.FOrigIndex));
|
||||
ADrawer.RadialPie(
|
||||
ps.FBase.X - FRadius, ps.FBase.Y - FRadius,
|
||||
ps.FBase.X + FRadius, ps.FBase.Y + FRadius,
|
||||
RadToDeg16(ps.FPrevAngle), RadToDeg16(ps.Angle));
|
||||
if FInnerRadiusPercent = 0 then
|
||||
ADrawer.RadialPie(
|
||||
ps.FBase.X - FRadius, ps.FBase.Y - FRadius,
|
||||
ps.FBase.X + FRadius, ps.FBase.Y + FRadius,
|
||||
RadToDeg16(ps.FPrevAngle), RadToDeg16(ps.Angle))
|
||||
else
|
||||
DrawPieRing(ps);
|
||||
end;
|
||||
|
||||
if not Marks.IsMarkLabelsVisible then exit;
|
||||
@ -437,16 +511,18 @@ var
|
||||
c: TPoint;
|
||||
pointAngle: Double;
|
||||
ps: TPieSlice;
|
||||
innerRadius: Integer;
|
||||
begin
|
||||
for ps in FSlices do begin
|
||||
if not ps.FVisible then continue;
|
||||
c := APoint - ps.FBase;
|
||||
pointAngle := ArcTan2(-c.Y, c.X);
|
||||
innerRadius := CalcInnerRadius;
|
||||
if pointAngle < 0 then
|
||||
pointAngle += 2 * Pi;
|
||||
if
|
||||
InRange(pointAngle, ps.FPrevAngle, ps.FNextAngle) and
|
||||
(Sqr(c.X) + Sqr(c.Y) <= Sqr(FRadius))
|
||||
InRange(Sqr(c.X) + Sqr(c.Y), Sqr(innerRadius), Sqr(FRadius))
|
||||
then
|
||||
exit(ps.FOrigIndex);
|
||||
end;
|
||||
@ -569,6 +645,14 @@ begin
|
||||
UpdateParentChart;
|
||||
end;
|
||||
|
||||
procedure TCustomPieSeries.SetInnerRadiusPercent(AValue: Integer);
|
||||
begin
|
||||
AValue := EnsureRange(AValue, 0, 100);
|
||||
if FInnerRadiusPercent = AValue then exit;
|
||||
FInnerRadiusPercent := AValue;
|
||||
UpdateParentChart;
|
||||
end;
|
||||
|
||||
procedure TCustomPieSeries.SetMarkPositions(AValue: TPieMarkPositions);
|
||||
begin
|
||||
if FMarkPositions = AValue then exit;
|
||||
|
@ -128,6 +128,7 @@ type
|
||||
property DepthBrightnessDelta;
|
||||
property Exploded;
|
||||
property FixedRadius;
|
||||
property InnerRadiusPercent;
|
||||
property MarkDistancePercent;
|
||||
property MarkPositions;
|
||||
property Marks;
|
||||
|
Loading…
Reference in New Issue
Block a user