mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-06 11:26:00 +02:00
TAChart: Add new properties Orientation and ViewAngle to TPieSeries. Update demo.
git-svn-id: trunk@60728 -
This commit is contained in:
parent
4259c682c9
commit
50b7e5b2a4
@ -2,10 +2,10 @@ object Form1: TForm1
|
|||||||
Left = 443
|
Left = 443
|
||||||
Height = 559
|
Height = 559
|
||||||
Top = 340
|
Top = 340
|
||||||
Width = 580
|
Width = 659
|
||||||
Caption = 'Form1'
|
Caption = 'Form1'
|
||||||
ClientHeight = 559
|
ClientHeight = 559
|
||||||
ClientWidth = 580
|
ClientWidth = 659
|
||||||
OnCreate = FormCreate
|
OnCreate = FormCreate
|
||||||
Position = poScreenCenter
|
Position = poScreenCenter
|
||||||
LCLVersion = '2.1.0.0'
|
LCLVersion = '2.1.0.0'
|
||||||
@ -13,7 +13,7 @@ object Form1: TForm1
|
|||||||
Left = 0
|
Left = 0
|
||||||
Height = 559
|
Height = 559
|
||||||
Top = 0
|
Top = 0
|
||||||
Width = 580
|
Width = 659
|
||||||
ActivePage = tsPie
|
ActivePage = tsPie
|
||||||
Align = alClient
|
Align = alClient
|
||||||
TabIndex = 0
|
TabIndex = 0
|
||||||
@ -21,12 +21,12 @@ object Form1: TForm1
|
|||||||
object tsPie: TTabSheet
|
object tsPie: TTabSheet
|
||||||
Caption = 'Pie'
|
Caption = 'Pie'
|
||||||
ClientHeight = 531
|
ClientHeight = 531
|
||||||
ClientWidth = 572
|
ClientWidth = 651
|
||||||
object ChartPie: TChart
|
object ChartPie: TChart
|
||||||
Left = 0
|
Left = 0
|
||||||
Height = 407
|
Height = 407
|
||||||
Top = 124
|
Top = 124
|
||||||
Width = 572
|
Width = 651
|
||||||
AxisList = <
|
AxisList = <
|
||||||
item
|
item
|
||||||
Visible = False
|
Visible = False
|
||||||
@ -71,14 +71,14 @@ object Form1: TForm1
|
|||||||
Left = 0
|
Left = 0
|
||||||
Height = 124
|
Height = 124
|
||||||
Top = 0
|
Top = 0
|
||||||
Width = 572
|
Width = 651
|
||||||
Align = alTop
|
Align = alTop
|
||||||
Alignment = taLeftJustify
|
Alignment = taLeftJustify
|
||||||
Anchors = [akTop, akRight]
|
Anchors = [akTop, akRight]
|
||||||
AutoSize = True
|
AutoSize = True
|
||||||
BevelOuter = bvNone
|
BevelOuter = bvNone
|
||||||
ClientHeight = 124
|
ClientHeight = 124
|
||||||
ClientWidth = 572
|
ClientWidth = 651
|
||||||
TabOrder = 1
|
TabOrder = 1
|
||||||
object seWords: TSpinEdit
|
object seWords: TSpinEdit
|
||||||
AnchorSideLeft.Control = lblWords
|
AnchorSideLeft.Control = lblWords
|
||||||
@ -400,6 +400,64 @@ object Form1: TForm1
|
|||||||
OnChange = seStartAngleChange
|
OnChange = seStartAngleChange
|
||||||
TabOrder = 12
|
TabOrder = 12
|
||||||
end
|
end
|
||||||
|
object seViewAngle: TSpinEdit
|
||||||
|
AnchorSideLeft.Control = lblViewAngle
|
||||||
|
AnchorSideLeft.Side = asrBottom
|
||||||
|
AnchorSideTop.Control = seDistance
|
||||||
|
AnchorSideTop.Side = asrCenter
|
||||||
|
AnchorSideRight.Side = asrBottom
|
||||||
|
Left = 549
|
||||||
|
Height = 23
|
||||||
|
Top = 64
|
||||||
|
Width = 62
|
||||||
|
BorderSpacing.Right = 6
|
||||||
|
Enabled = False
|
||||||
|
MaxValue = 89
|
||||||
|
OnChange = seViewAngleChange
|
||||||
|
TabOrder = 13
|
||||||
|
Value = 60
|
||||||
|
end
|
||||||
|
object lblViewAngle: TLabel
|
||||||
|
AnchorSideLeft.Control = seDepth
|
||||||
|
AnchorSideLeft.Side = asrBottom
|
||||||
|
AnchorSideTop.Control = seViewAngle
|
||||||
|
AnchorSideTop.Side = asrCenter
|
||||||
|
Left = 484
|
||||||
|
Height = 15
|
||||||
|
Top = 68
|
||||||
|
Width = 57
|
||||||
|
BorderSpacing.Left = 12
|
||||||
|
BorderSpacing.Right = 8
|
||||||
|
Caption = 'View angle'
|
||||||
|
Enabled = False
|
||||||
|
ParentColor = False
|
||||||
|
end
|
||||||
|
object cmbOrientation: TComboBox
|
||||||
|
AnchorSideLeft.Control = lblViewAngle
|
||||||
|
AnchorSideTop.Control = cbMarkAttachment
|
||||||
|
AnchorSideTop.Side = asrBottom
|
||||||
|
AnchorSideRight.Control = seViewAngle
|
||||||
|
AnchorSideRight.Side = asrBottom
|
||||||
|
Left = 484
|
||||||
|
Height = 23
|
||||||
|
Top = 93
|
||||||
|
Width = 127
|
||||||
|
Anchors = [akTop, akLeft, akRight]
|
||||||
|
AutoSize = False
|
||||||
|
BorderSpacing.Bottom = 8
|
||||||
|
Enabled = False
|
||||||
|
ItemHeight = 15
|
||||||
|
ItemIndex = 0
|
||||||
|
Items.Strings = (
|
||||||
|
'normal'
|
||||||
|
'horizontal'
|
||||||
|
'vertical'
|
||||||
|
)
|
||||||
|
OnChange = cmbOrientationChange
|
||||||
|
Style = csDropDownList
|
||||||
|
TabOrder = 14
|
||||||
|
Text = 'normal'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
object tsPolar: TTabSheet
|
object tsPolar: TTabSheet
|
||||||
|
@ -15,6 +15,7 @@ type
|
|||||||
|
|
||||||
TForm1 = class(TForm)
|
TForm1 = class(TForm)
|
||||||
cbMarkAttachment: TComboBox;
|
cbMarkAttachment: TComboBox;
|
||||||
|
cmbOrientation: TComboBox;
|
||||||
ChartPolar: TChart;
|
ChartPolar: TChart;
|
||||||
ChartPolarSeries1: TPolarSeries;
|
ChartPolarSeries1: TPolarSeries;
|
||||||
ChartPolarSeries2: TPolarSeries;
|
ChartPolarSeries2: TPolarSeries;
|
||||||
@ -29,9 +30,11 @@ type
|
|||||||
Cb3D: TCheckBox;
|
Cb3D: TCheckBox;
|
||||||
cbShowLabels: TCheckBox;
|
cbShowLabels: TCheckBox;
|
||||||
cbMarkPositionsCentered: TCheckBox;
|
cbMarkPositionsCentered: TCheckBox;
|
||||||
|
lblViewAngle: TLabel;
|
||||||
lblDistance: TLabel;
|
lblDistance: TLabel;
|
||||||
lblStartAngle: TLabel;
|
lblStartAngle: TLabel;
|
||||||
seDepth: TSpinEdit;
|
seDepth: TSpinEdit;
|
||||||
|
seViewAngle: TSpinEdit;
|
||||||
seDepthBrightnessDelta: TSpinEdit;
|
seDepthBrightnessDelta: TSpinEdit;
|
||||||
lblInnerRadius: TLabel;
|
lblInnerRadius: TLabel;
|
||||||
lblDepth: TLabel;
|
lblDepth: TLabel;
|
||||||
@ -63,6 +66,7 @@ type
|
|||||||
Shift: TShiftState; X, Y: Integer);
|
Shift: TShiftState; X, Y: Integer);
|
||||||
procedure cbShowPointsChange(Sender: TObject);
|
procedure cbShowPointsChange(Sender: TObject);
|
||||||
procedure Cb3DChange(Sender: TObject);
|
procedure Cb3DChange(Sender: TObject);
|
||||||
|
procedure cmbOrientationChange(Sender: TObject);
|
||||||
procedure seDepthBrightnessDeltaChange(Sender: TObject);
|
procedure seDepthBrightnessDeltaChange(Sender: TObject);
|
||||||
procedure seDepthChange(Sender: TObject);
|
procedure seDepthChange(Sender: TObject);
|
||||||
procedure seDistanceChange(Sender: TObject);
|
procedure seDistanceChange(Sender: TObject);
|
||||||
@ -70,6 +74,7 @@ type
|
|||||||
procedure FormCreate(Sender: TObject);
|
procedure FormCreate(Sender: TObject);
|
||||||
procedure sbTransparencyChange(Sender: TObject);
|
procedure sbTransparencyChange(Sender: TObject);
|
||||||
procedure seStartAngleChange(Sender: TObject);
|
procedure seStartAngleChange(Sender: TObject);
|
||||||
|
procedure seViewAngleChange(Sender: TObject);
|
||||||
procedure seWordsChange(Sender: TObject);
|
procedure seWordsChange(Sender: TObject);
|
||||||
procedure seLabelAngleChange(Sender: TObject);
|
procedure seLabelAngleChange(Sender: TObject);
|
||||||
end;
|
end;
|
||||||
@ -152,6 +157,14 @@ begin
|
|||||||
lblDepth.Enabled := cb3D.Checked;
|
lblDepth.Enabled := cb3D.Checked;
|
||||||
seDepthBrightnessDelta.Enabled := cb3D.Checked;
|
seDepthBrightnessDelta.Enabled := cb3D.Checked;
|
||||||
lblDepthBrightnessDelta.Enabled := cb3D.Checked;
|
lblDepthBrightnessDelta.Enabled := cb3D.Checked;
|
||||||
|
lblViewAngle.Enabled := cb3D.Checked;
|
||||||
|
seViewAngle.Enabled := cb3D.Checked;
|
||||||
|
cmbOrientation.Enabled := cb3D.Checked;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TForm1.cmbOrientationChange(Sender: TObject);
|
||||||
|
begin
|
||||||
|
ChartPiePieSeries1.Orientation := TPieOrientation(cmbOrientation.ItemIndex);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TForm1.seDepthBrightnessDeltaChange(Sender: TObject);
|
procedure TForm1.seDepthBrightnessDeltaChange(Sender: TObject);
|
||||||
@ -202,6 +215,11 @@ begin
|
|||||||
ChartPiePieSeries1.StartAngle := seStartAngle.Value;
|
ChartPiePieSeries1.StartAngle := seStartAngle.Value;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TForm1.seViewAngleChange(Sender: TObject);
|
||||||
|
begin
|
||||||
|
ChartPiePieSeries1.ViewAngle := seViewAngle.Value;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TForm1.seLabelAngleChange(Sender: TObject);
|
procedure TForm1.seLabelAngleChange(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
ChartPiePieSeries1.Marks.LabelFont.Orientation := seLabelAngle.Value * 10;
|
ChartPiePieSeries1.Marks.LabelFont.Orientation := seLabelAngle.Value * 10;
|
||||||
|
@ -62,13 +62,16 @@ type
|
|||||||
{ TCustomPieSeries }
|
{ TCustomPieSeries }
|
||||||
|
|
||||||
TSliceArray = array of TPieSlice;
|
TSliceArray = array of TPieSlice;
|
||||||
|
TPieOrientation = (poNormal, poHorizontal, poVertical);
|
||||||
|
|
||||||
TCustomPieSeries = class(TChartSeries)
|
TCustomPieSeries = class(TChartSeries)
|
||||||
private
|
private
|
||||||
|
FAspectRatio: Double;
|
||||||
FCenter: TPoint;
|
FCenter: TPoint;
|
||||||
FMarkDistancePercent: Boolean;
|
FMarkDistancePercent: Boolean;
|
||||||
FMarkPositionCentered: Boolean;
|
FMarkPositionCentered: Boolean;
|
||||||
FMarkPositions: TPieMarkPositions;
|
FMarkPositions: TPieMarkPositions;
|
||||||
|
FOrientation: TPieOrientation;
|
||||||
FRadius: Integer;
|
FRadius: Integer;
|
||||||
FInnerRadiusPercent: Integer;
|
FInnerRadiusPercent: Integer;
|
||||||
FSlices: array of TPieSlice;
|
FSlices: array of TPieSlice;
|
||||||
@ -78,6 +81,8 @@ type
|
|||||||
FExploded: Boolean;
|
FExploded: Boolean;
|
||||||
FFixedRadius: TChartDistance;
|
FFixedRadius: TChartDistance;
|
||||||
FRotateLabels: Boolean;
|
FRotateLabels: Boolean;
|
||||||
|
function FixAspectRatio(P: TPoint): TPoint;
|
||||||
|
function GetViewAngle: Integer;
|
||||||
procedure Measure(ADrawer: IChartDrawer);
|
procedure Measure(ADrawer: IChartDrawer);
|
||||||
procedure SetEdgePen(AValue: TPen);
|
procedure SetEdgePen(AValue: TPen);
|
||||||
procedure SetExploded(AValue: Boolean);
|
procedure SetExploded(AValue: Boolean);
|
||||||
@ -86,9 +91,12 @@ type
|
|||||||
procedure SetMarkDistancePercent(AValue: Boolean);
|
procedure SetMarkDistancePercent(AValue: Boolean);
|
||||||
procedure SetMarkPositionCentered(AValue: Boolean);
|
procedure SetMarkPositionCentered(AValue: Boolean);
|
||||||
procedure SetMarkPositions(AValue: TPieMarkPositions);
|
procedure SetMarkPositions(AValue: TPieMarkPositions);
|
||||||
|
procedure SetOrientation(AValue: TPieOrientation);
|
||||||
procedure SetRotateLabels(AValue: Boolean);
|
procedure SetRotateLabels(AValue: Boolean);
|
||||||
procedure SetStartAngle(AValue: Integer);
|
procedure SetStartAngle(AValue: Integer);
|
||||||
|
procedure SetViewAngle(AValue: Integer);
|
||||||
function SliceColor(AIndex: Integer): TColor;
|
function SliceColor(AIndex: Integer): TColor;
|
||||||
|
function SliceExploded(ASlice: TPieSlice): Boolean; inline;
|
||||||
function TryRadius(ADrawer: IChartDrawer): TRect;
|
function TryRadius(ADrawer: IChartDrawer): TRect;
|
||||||
protected
|
protected
|
||||||
function CalcInnerRadius: Integer; inline;
|
function CalcInnerRadius: Integer; inline;
|
||||||
@ -98,8 +106,13 @@ type
|
|||||||
read FInnerRadiusPercent write SetInnerRadiusPercent default 0;
|
read FInnerRadiusPercent write SetInnerRadiusPercent default 0;
|
||||||
property MarkPositionCentered: Boolean
|
property MarkPositionCentered: Boolean
|
||||||
read FMarkPositionCentered write SetMarkPositionCentered default false;
|
read FMarkPositionCentered write SetMarkPositionCentered default false;
|
||||||
|
property Orientation: TPieOrientation
|
||||||
|
read FOrientation write SetOrientation default poNormal;
|
||||||
property Radius: Integer read FRadius;
|
property Radius: Integer read FRadius;
|
||||||
property StartAngle: Integer read FStartAngle write SetStartAngle default 0;
|
property StartAngle: Integer
|
||||||
|
read FStartAngle write SetStartAngle default 0;
|
||||||
|
property ViewAngle: Integer
|
||||||
|
read GetViewAngle write SetViewAngle default 60;
|
||||||
public
|
public
|
||||||
constructor Create(AOwner: TComponent); override;
|
constructor Create(AOwner: TComponent); override;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
@ -283,11 +296,13 @@ procedure TCustomPieSeries.Assign(ASource: TPersistent);
|
|||||||
begin
|
begin
|
||||||
if ASource is TCustomPieSeries then
|
if ASource is TCustomPieSeries then
|
||||||
with TCustomPieSeries(ASource) do begin
|
with TCustomPieSeries(ASource) do begin
|
||||||
|
Self.FAspectRatio := FAspectRatio;
|
||||||
Self.FExploded := FExploded;
|
Self.FExploded := FExploded;
|
||||||
Self.FFixedRadius := FFixedRadius;
|
Self.FFixedRadius := FFixedRadius;
|
||||||
Self.FInnerRadiusPercent := FInnerRadiusPercent;
|
Self.FInnerRadiusPercent := FInnerRadiusPercent;
|
||||||
Self.FMarkDistancePercent := FMarkDistancePercent;
|
Self.FMarkDistancePercent := FMarkDistancePercent;
|
||||||
Self.FMarkPositionCentered := FMarkPositionCentered;
|
Self.FMarkPositionCentered := FMarkPositionCentered;
|
||||||
|
Self.FOrientation := FOrientation;
|
||||||
Self.FRotateLabels := FRotateLabels;
|
Self.FRotateLabels := FRotateLabels;
|
||||||
Self.FStartAngle := FStartAngle;
|
Self.FStartAngle := FStartAngle;
|
||||||
end;
|
end;
|
||||||
@ -302,6 +317,7 @@ end;
|
|||||||
constructor TCustomPieSeries.Create(AOwner: TComponent);
|
constructor TCustomPieSeries.Create(AOwner: TComponent);
|
||||||
begin
|
begin
|
||||||
inherited Create(AOwner);
|
inherited Create(AOwner);
|
||||||
|
ViewAngle := 60;
|
||||||
FEdgePen := TPen.Create;
|
FEdgePen := TPen.Create;
|
||||||
FEdgePen.OnChange := @StyleChanged;
|
FEdgePen.OnChange := @StyleChanged;
|
||||||
|
|
||||||
@ -345,16 +361,18 @@ var
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function SliceExploded(ASlice: TPieSlice): Boolean;
|
|
||||||
begin
|
|
||||||
Result := ASlice.FBase <> FCenter;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function StartEdgeVisible(ASlice: TPieSlice): Boolean;
|
function StartEdgeVisible(ASlice: TPieSlice): Boolean;
|
||||||
var
|
var
|
||||||
prev: TPieSlice;
|
prev: TPieSlice;
|
||||||
begin
|
begin
|
||||||
Result := InRange(ASlice.FPrevAngle, PI_1_4, PI_5_4);
|
case FOrientation of
|
||||||
|
poNormal:
|
||||||
|
Result := InRange(ASlice.FPrevAngle, PI_1_4, PI_5_4);
|
||||||
|
poHorizontal:
|
||||||
|
Result := not InRange(ASlice.FPrevAngle, PI_1_2, PI_3_2);
|
||||||
|
poVertical:
|
||||||
|
Result := InRange(ASlice.FPrevAngle, 0, pi);
|
||||||
|
end;
|
||||||
if Result then begin
|
if Result then begin
|
||||||
prev := PrevSlice(ASlice);
|
prev := PrevSlice(ASlice);
|
||||||
Result := SliceExploded(ASlice) or SliceExploded(prev) or not prev.FVisible;
|
Result := SliceExploded(ASlice) or SliceExploded(prev) or not prev.FVisible;
|
||||||
@ -365,7 +383,14 @@ var
|
|||||||
var
|
var
|
||||||
next: TPieSlice;
|
next: TPieSlice;
|
||||||
begin
|
begin
|
||||||
Result := not InRange(ASlice.FNextAngle, PI_1_4, PI_5_4);
|
case FOrientation of
|
||||||
|
poNormal:
|
||||||
|
Result := not InRange(ASlice.FNextAngle, PI_1_4, PI_5_4);
|
||||||
|
poHorizontal:
|
||||||
|
Result := InRange(ASlice.FNextAngle, PI_1_2, PI_3_2);
|
||||||
|
poVertical:
|
||||||
|
Result := InRange(ASlice.FNextAngle, pi, TWO_PI);
|
||||||
|
end;
|
||||||
if Result then begin
|
if Result then begin
|
||||||
next := NextSlice(ASlice);
|
next := NextSlice(ASlice);
|
||||||
Result := SliceExploded(ASlice) or SliceExploded(next) or not next.FVisible;
|
Result := SliceExploded(ASlice) or SliceExploded(next) or not next.FVisible;
|
||||||
@ -381,6 +406,7 @@ var
|
|||||||
clr: TColor;
|
clr: TColor;
|
||||||
r: Integer;
|
r: Integer;
|
||||||
isVisible: Boolean;
|
isVisible: Boolean;
|
||||||
|
ofs: TPoint;
|
||||||
begin
|
begin
|
||||||
if AInside and (FInnerRadiusPercent = 0) then
|
if AInside and (FInnerRadiusPercent = 0) then
|
||||||
exit;
|
exit;
|
||||||
@ -389,29 +415,84 @@ var
|
|||||||
isVisible := true
|
isVisible := true
|
||||||
else
|
else
|
||||||
if AInside then
|
if AInside then
|
||||||
isVisible := InRange(ASlice.FPrevAngle, PI_3_4, PI_7_4) or InRange(ASlice.FNextAngle, PI_3_4, PI_7_4)
|
case FOrientation of
|
||||||
|
poNormal:
|
||||||
|
isVisible := InRange(ASlice.FPrevAngle, PI_3_4, PI_7_4) or
|
||||||
|
InRange(ASlice.FNextAngle, PI_3_4, PI_7_4);
|
||||||
|
poHorizontal:
|
||||||
|
isVisible := InRange(ASlice.FPrevAngle, 0, pi) or
|
||||||
|
InRange(ASlice.FNextAngle, 0, pi);
|
||||||
|
poVertical:
|
||||||
|
isVisible := InRange(ASlice.FPrevAngle, PI_1_2, PI_3_2) or
|
||||||
|
InRange(ASlice.FNextAngle, PI_1_2, PI_3_2);
|
||||||
|
end
|
||||||
else
|
else
|
||||||
isVisible := (ASlice.FPrevAngle >= PI_7_4) or (ASlice.FPrevAngle <= PI_3_4) or
|
case FOrientation of
|
||||||
(ASlice.FNextAngle >= PI_7_4) or (ASlice.FNextAngle <= PI_3_4);
|
poNormal:
|
||||||
|
isVisible := (ASlice.FPrevAngle >= PI_7_4) or (ASlice.FPrevAngle <= PI_3_4) or
|
||||||
|
(ASlice.FNextAngle >= PI_7_4) or (ASlice.FNextAngle <= PI_3_4);
|
||||||
|
poHorizontal:
|
||||||
|
isVisible := InRange(ASlice.FPrevAngle, pi, TWO_PI) or
|
||||||
|
InRange(ASlice.FNextAngle, pi, TWO_PI);
|
||||||
|
poVertical:
|
||||||
|
isVisible := (ASlice.FPrevAngle >= PI_3_2) or (ASlice.FPrevAngle <= PI_1_2) or
|
||||||
|
(ASlice.FNextAngle >= PI_3_2) or (ASlice.FNextAngle <= PI_1_2);
|
||||||
|
end;
|
||||||
if not isVisible then
|
if not isVisible then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
if AInside then begin
|
if AInside then begin
|
||||||
r := innerRadius;
|
r := innerRadius;
|
||||||
angle1 := IfThen(InRange(ASlice.FPrevAngle, PI_3_4, PI_7_4), ASlice.FPrevAngle, PI_3_4);
|
case FOrientation of
|
||||||
angle2 := IfThen(InRange(ASlice.FNextAngle, PI_3_4, PI_7_4), ASlice.FNextAngle, PI_7_4);
|
poNormal:
|
||||||
|
begin
|
||||||
|
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;
|
||||||
|
poHorizontal:
|
||||||
|
begin
|
||||||
|
angle1 := IfThen(InRange(ASlice.FPrevAngle, 0, pi), ASlice.FPrevAngle, 0);
|
||||||
|
angle2 := IfThen(InRange(ASlice.FNextAngle, 0, pi), ASlice.FNextAngle, pi);
|
||||||
|
end;
|
||||||
|
poVertical:
|
||||||
|
begin
|
||||||
|
angle1 := IfThen(InRange(ASlice.FPrevAngle, PI_1_2, PI_3_2), ASlice.FPrevAngle, PI_1_2);
|
||||||
|
angle2 := IfThen(InRange(ASlice.FNextAngle, PI_1_2, PI_3_2), ASlice.FNextAngle, PI_3_2);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
end else begin
|
end else begin
|
||||||
r := FRadius;
|
r := FRadius;
|
||||||
angle1 := IfThen(InRange(ASlice.FPrevAngle, PI_3_4, PI_7_4), PI_7_4, ASlice.FPrevAngle);
|
case FOrientation of
|
||||||
angle2 := IfThen(InRange(ASlice.FNextAngle, PI_3_4, PI_7_4), PI_3_4, ASlice.FNextAngle);
|
poNormal:
|
||||||
|
begin
|
||||||
|
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;
|
||||||
|
poHorizontal:
|
||||||
|
begin
|
||||||
|
angle1 := IfThen(InRange(ASlice.FPrevAngle, 0, pi), pi, ASlice.FPrevAngle);
|
||||||
|
angle2 := Ifthen(InRange(ASlice.FNextAngle, 0, pi), TWO_PI, ASlice.FNextAngle);
|
||||||
|
end;
|
||||||
|
poVertical:
|
||||||
|
begin
|
||||||
|
angle1 := IfThen(InRange(ASlice.FPrevAngle, PI_1_2, PI_3_2), PI_3_2, ASlice.FPrevAngle);
|
||||||
|
angle2 := IfThen(InRange(ASlice.FNextAngle, PI_1_2, PI_3_2), PI_1_2, ASlice.FNextAngle);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
if angle2 < angle1 then angle2 += TWO_PI;
|
if angle2 < angle1 then angle2 += TWO_PI;
|
||||||
|
|
||||||
numSteps := Max(Round(TWO_PI * (angle2 - angle1) * r / STEP), 2);
|
numSteps := Max(Round(TWO_PI * (angle2 - angle1) * r / STEP), 2);
|
||||||
SetLength(p, 2 * numSteps + 1);
|
SetLength(p, 2 * numSteps + 1);
|
||||||
|
case FOrientation of
|
||||||
|
poNormal: ofs := Point(scaled_depth, -scaled_depth);
|
||||||
|
poHorizontal: ofs := Point(0, scaled_depth);
|
||||||
|
poVertical: ofs := Point(scaled_depth, 0);
|
||||||
|
end;
|
||||||
for i := 0 to numSteps - 1 do begin
|
for i := 0 to numSteps - 1 do begin
|
||||||
a := WeightedAverage(angle1, angle2, i / (numSteps - 1));
|
a := WeightedAverage(angle1, angle2, i / (numSteps - 1));
|
||||||
p[i] := ASlice.FBase + RotatePointX(r, -a);
|
p[i] := ASlice.FBase + FixAspectRatio(RotatePointX(r, -a));
|
||||||
p[High(p) - i - 1] := p[i] + Point(scaled_depth, -scaled_depth);
|
p[High(p) - i - 1] := p[i] + ofs;
|
||||||
end;
|
end;
|
||||||
p[High(p)] := p[0];
|
p[High(p)] := p[0];
|
||||||
clr := GetDepthColor(SliceColor(ASlice.FOrigIndex));
|
clr := GetDepthColor(SliceColor(ASlice.FOrigIndex));
|
||||||
@ -438,59 +519,101 @@ var
|
|||||||
p: Array of TPoint;
|
p: Array of TPoint;
|
||||||
begin
|
begin
|
||||||
angle1 := ASlice.FPrevAngle;
|
angle1 := ASlice.FPrevAngle;
|
||||||
if ASlice.FNextAngle < ASlice.FPrevAngle then
|
angle2 := ASlice.FixedNextAngle;
|
||||||
angle2 := TWO_PI + ASlice.FNextAngle
|
|
||||||
else
|
|
||||||
angle2 := ASlice.FNextAngle;
|
|
||||||
ni := Max(Round(TWO_PI * (angle2 - angle1) * innerRadius / STEP), 2);
|
ni := Max(Round(TWO_PI * (angle2 - angle1) * innerRadius / STEP), 2);
|
||||||
no := Max(Round(TWO_PI * (angle2 - angle1) * FRadius / STEP), 2);
|
no := Max(Round(TWO_PI * (angle2 - angle1) * FRadius / STEP), 2);
|
||||||
SetLength(p, ni + no);
|
SetLength(p, ni + no);
|
||||||
for i := 0 to no - 1 do begin
|
for i := 0 to no - 1 do begin
|
||||||
a := WeightedAverage(angle1, angle2, i / (no - 1));
|
a := WeightedAverage(angle1, angle2, i / (no - 1));
|
||||||
p[i] := ASlice.FBase + RotatePointX(FRadius, -a);
|
p[i] := ASlice.FBase + FixAspectRatio(RotatePointX(FRadius, -a));
|
||||||
end;
|
end;
|
||||||
for i := 0 to ni - 1 do begin
|
for i := 0 to ni - 1 do begin
|
||||||
a := WeightedAverage(angle1, angle2, i / (ni - 1));
|
a := WeightedAverage(angle1, angle2, i / (ni - 1));
|
||||||
p[no + ni - 1 - i] := ASlice.FBase + RotatePointX(innerRadius, -a);
|
p[no + ni - 1 - i] := ASlice.FBase + FixAspectRatio(RotatePointX(innerRadius , -a));
|
||||||
end;
|
end;
|
||||||
ADrawer.Polygon(p, 0, Length(p));
|
ADrawer.Polygon(p, 0, Length(p));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure DrawEdge3D(ASlice: TPieSlice; Angle: Double);
|
||||||
|
var
|
||||||
|
P1, P2, d: TPoint;
|
||||||
|
begin
|
||||||
|
ADrawer.SetBrushParams(
|
||||||
|
bsSolid, GetDepthColor(SliceColor(ASlice.FOrigIndex)));
|
||||||
|
P1 := ASlice.FBase + FixAspectRatio(RotatePointX(innerRadius, -Angle));
|
||||||
|
P2 := ASlice.FBase + FixAspectRatio(RotatePointX(FRadius, -Angle));
|
||||||
|
case FOrientation of
|
||||||
|
poNormal:
|
||||||
|
ADrawer.DrawLineDepth(P1, P2, scaled_depth);
|
||||||
|
poHorizontal:
|
||||||
|
begin
|
||||||
|
d := Point(0, scaled_depth);
|
||||||
|
ADrawer.Polygon([P1, P1 + d, P2 + d, P2], 0, 4);
|
||||||
|
end;
|
||||||
|
poVertical:
|
||||||
|
begin
|
||||||
|
d := Point(scaled_depth, 0);
|
||||||
|
ADrawer.Polygon([P1, P1 + d, P2 + d, P2], 0, 4);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure DrawStartEdge3D(ASlice: TPieSlice);
|
procedure DrawStartEdge3D(ASlice: TPieSlice);
|
||||||
begin
|
begin
|
||||||
if StartEdgeVisible(ASlice) then begin
|
if StartEdgeVisible(ASlice) then
|
||||||
ADrawer.SetBrushParams(
|
DrawEdge3D(ASlice, ASlice.FPrevAngle);
|
||||||
bsSolid, GetDepthColor(SliceColor(ASlice.FOrigIndex)));
|
|
||||||
ADrawer.DrawLineDepth(
|
|
||||||
ASlice.FBase + RotatePointX(innerRadius, -ASlice.FPrevAngle),
|
|
||||||
ASlice.FBase + RotatePointX(FRadius, -ASlice.FPrevAngle),
|
|
||||||
scaled_depth
|
|
||||||
);
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure DrawEndEdge3D(ASlice: TPieSlice);
|
procedure DrawEndEdge3D(ASlice: TPieSlice);
|
||||||
begin
|
begin
|
||||||
if EndEdgeVisible(ASlice) then begin
|
if EndEdgeVisible(ASlice) then
|
||||||
ADrawer.SetBrushParams(
|
DrawEdge3D(ASlice, ASlice.FNextAngle);
|
||||||
bsSolid, GetDepthColor(SliceColor(ASlice.FOrigIndex)));
|
end;
|
||||||
ADrawer.DrawLineDepth(
|
|
||||||
ASlice.FBase + RotatePointX(innerRadius, -ASlice.FNextAngle),
|
procedure FixJoin(ASlice: TPieSlice);
|
||||||
ASlice.FBase + RotatePointX(FRadius, -ASlice.FNextAngle),
|
var
|
||||||
scaled_depth
|
P1, P2: TPoint;
|
||||||
);
|
angle: Double;
|
||||||
|
r: Integer;
|
||||||
|
d: TPoint;
|
||||||
|
begin
|
||||||
|
if not ASlice.FVisible then
|
||||||
|
exit;
|
||||||
|
Angle := (ASlice.FPrevAngle + ASlice.FixedNextAngle) * 0.5;
|
||||||
|
case FOrientation of
|
||||||
|
poNormal:
|
||||||
|
begin
|
||||||
|
if not InRange(angle, PI_3_4, PI_7_4) then r := FRadius else r := CalcInnerRadius;
|
||||||
|
d := Point(scaled_depth, -scaled_depth);
|
||||||
|
end;
|
||||||
|
poHorizontal:
|
||||||
|
begin
|
||||||
|
if angle > pi then r := FRadius else r := CalcInnerRadius;
|
||||||
|
d := Point(0, scaled_depth);
|
||||||
|
end;
|
||||||
|
poVertical:
|
||||||
|
begin
|
||||||
|
if not InRange(angle, PI_1_2, PI_3_2) then r := FRadius else r := CalcInnerRadius;
|
||||||
|
d := Point(scaled_depth, 0);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
P1 := ASlice.FBase + FixAspectRatio(RotatePointX(r, -Angle));
|
||||||
|
P2 := P1 + d;
|
||||||
|
ADrawer.SetPenParams(psSolid, GetDepthColor(SliceColor(ASlice.FOrigIndex)));
|
||||||
|
ADrawer.Line(P1, P2);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
prevLabelPoly: TPointArray = nil;
|
prevLabelPoly: TPointArray = nil;
|
||||||
ps: TPieSlice;
|
ps: TPieSlice;
|
||||||
|
r: TPoint;
|
||||||
begin
|
begin
|
||||||
if IsEmpty then exit;
|
if IsEmpty then exit;
|
||||||
|
|
||||||
Marks.SetAdditionalAngle(0);
|
Marks.SetAdditionalAngle(0);
|
||||||
Measure(ADrawer);
|
Measure(ADrawer);
|
||||||
innerRadius := CalcInnerRadius;
|
innerRadius := CalcInnerRadius;
|
||||||
|
r := FixAspectRatio(Point(FRadius, FRadius));
|
||||||
|
|
||||||
ADrawer.SetPen(EdgePen);
|
ADrawer.SetPen(EdgePen);
|
||||||
if Depth > 0 then begin
|
if Depth > 0 then begin
|
||||||
@ -503,9 +626,9 @@ begin
|
|||||||
end;
|
end;
|
||||||
// Fix edge of ulta-long slice
|
// Fix edge of ulta-long slice
|
||||||
for ps in FSlices do
|
for ps in FSlices do
|
||||||
if ps.Angle >= pi then begin;
|
if ps.Angle >= pi then begin
|
||||||
DrawVisibleArc3D(ps);
|
//DrawVisibleArc3D(ps);
|
||||||
break;
|
FixJoin(ps);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -515,8 +638,8 @@ begin
|
|||||||
ADrawer.SetBrushParams(bsSolid, SliceColor(ps.FOrigIndex));
|
ADrawer.SetBrushParams(bsSolid, SliceColor(ps.FOrigIndex));
|
||||||
if FInnerRadiusPercent = 0 then
|
if FInnerRadiusPercent = 0 then
|
||||||
ADrawer.RadialPie(
|
ADrawer.RadialPie(
|
||||||
ps.FBase.X - FRadius, ps.FBase.Y - FRadius,
|
ps.FBase.X - r.x, ps.FBase.Y - r.y,
|
||||||
ps.FBase.X + FRadius, ps.FBase.Y + FRadius,
|
ps.FBase.X + r.x, ps.FBase.Y + r.y,
|
||||||
RadToDeg16(ps.FPrevAngle), RadToDeg16(ps.Angle))
|
RadToDeg16(ps.FPrevAngle), RadToDeg16(ps.Angle))
|
||||||
else
|
else
|
||||||
DrawRing(ps);
|
DrawRing(ps);
|
||||||
@ -545,6 +668,12 @@ begin
|
|||||||
for ps in FSlices do begin
|
for ps in FSlices do begin
|
||||||
if not ps.FVisible then continue;
|
if not ps.FVisible then continue;
|
||||||
c := APoint - ps.FBase;
|
c := APoint - ps.FBase;
|
||||||
|
if (FDepth > 0) then
|
||||||
|
case FOrientation of
|
||||||
|
poNormal: ;
|
||||||
|
poHorizontal: c.Y := round(c.Y / FAspectRatio);
|
||||||
|
poVertical: c.X := round(c.X / FAspectRatio);
|
||||||
|
end;
|
||||||
if not InRange(sqr(c.X) + sqr(c.Y), sqr(innerRadius), sqr(FRadius)) then
|
if not InRange(sqr(c.X) + sqr(c.Y), sqr(innerRadius), sqr(FRadius)) then
|
||||||
continue;
|
continue;
|
||||||
pointAngle := NormalizeAngle(ArcTan2(-c.Y, c.X));
|
pointAngle := NormalizeAngle(ArcTan2(-c.Y, c.X));
|
||||||
@ -561,6 +690,17 @@ begin
|
|||||||
Result := -1;
|
Result := -1;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TCustomPieSeries.FixAspectRatio(P: TPoint): TPoint;
|
||||||
|
begin
|
||||||
|
Result := P;
|
||||||
|
if FDepth > 0 then
|
||||||
|
case FOrientation of
|
||||||
|
poNormal: ;
|
||||||
|
poVertical: Result.X := round(P.X * FAspectRatio);
|
||||||
|
poHorizontal: Result.Y := round(P.Y * FAspectRatio);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TCustomPieSeries.GetLegendItems(AItems: TChartLegendItems);
|
procedure TCustomPieSeries.GetLegendItems(AItems: TChartLegendItems);
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
@ -603,6 +743,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TCustomPieSeries.GetViewAngle: Integer;
|
||||||
|
begin
|
||||||
|
Result := round(arccos(FAspectRatio) / pi * 180);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TCustomPieSeries.Measure(ADrawer: IChartDrawer);
|
procedure TCustomPieSeries.Measure(ADrawer: IChartDrawer);
|
||||||
const
|
const
|
||||||
MIN_RADIUS = 5;
|
MIN_RADIUS = 5;
|
||||||
@ -706,6 +851,13 @@ begin
|
|||||||
UpdateParentChart;
|
UpdateParentChart;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TCustomPieSeries.SetOrientation(AValue: TPieOrientation);
|
||||||
|
begin
|
||||||
|
if FOrientation = AValue then exit;
|
||||||
|
FOrientation := AValue;
|
||||||
|
UpdateParentChart;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TCustomPieSeries.SetRotateLabels(AValue: Boolean);
|
procedure TCustomPieSeries.SetRotateLabels(AValue: Boolean);
|
||||||
begin
|
begin
|
||||||
if FRotateLabels = AValue then exit;
|
if FRotateLabels = AValue then exit;
|
||||||
@ -720,6 +872,13 @@ begin
|
|||||||
UpdateParentChart;
|
UpdateParentChart;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TCustomPieSeries.SetViewAngle(AValue: Integer);
|
||||||
|
begin
|
||||||
|
if GetViewAngle = AValue then exit;
|
||||||
|
FAspectRatio := cos(pi * EnsureRange(AValue, 0, 89) / 180);
|
||||||
|
UpdateParentChart;
|
||||||
|
end;
|
||||||
|
|
||||||
function TCustomPieSeries.SliceColor(AIndex: Integer): TColor;
|
function TCustomPieSeries.SliceColor(AIndex: Integer): TColor;
|
||||||
const
|
const
|
||||||
SLICE_COLORS: array [0..14] of TColor = (
|
SLICE_COLORS: array [0..14] of TColor = (
|
||||||
@ -733,37 +892,79 @@ begin
|
|||||||
Result := ColorDef(Result, SLICE_COLORS[AIndex mod Length(SLICE_COLORS)]);
|
Result := ColorDef(Result, SLICE_COLORS[AIndex mod Length(SLICE_COLORS)]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TCustomPieSeries.SliceExploded(ASlice: TPieSlice): Boolean;
|
||||||
|
begin
|
||||||
|
Result := ASlice.FBase <> FCenter;
|
||||||
|
end;
|
||||||
|
|
||||||
|
type
|
||||||
|
TAngleFunc = function (ASlice: TPieSlice): Double;
|
||||||
|
|
||||||
|
function GetAngleForSortingNormal(ASlice: TPieSlice): Double;
|
||||||
|
var
|
||||||
|
next_angle: Double;
|
||||||
|
begin
|
||||||
|
next_angle := ASlice.FixedNextAngle;
|
||||||
|
if ((ASlice.FPrevAngle >= PI_5_4) or (ASlice.FPrevAngle <= PI_1_4)) and
|
||||||
|
InRange(ASlice.FNextAngle, PI_1_4, PI_5_4)
|
||||||
|
then
|
||||||
|
// Slice crossing the 45° point --> must be last slice to draw
|
||||||
|
Result := 0
|
||||||
|
else
|
||||||
|
if InRange(ASlice.FPrevAngle, PI_1_4, PI_5_4) and InRange(next_angle, PI_5_4, TWO_PI + PI_1_4)
|
||||||
|
then
|
||||||
|
// Slice crossing the 225° point --> must be first slice to draw
|
||||||
|
Result := pi
|
||||||
|
else
|
||||||
|
Result := IfThen(InRange(ASlice.FPrevAngle, PI_1_4, PI_5_4), ASlice.FPrevAngle, next_angle) - PI_1_4;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function GetAngleForSortingHoriz(ASlice: TPieSlice): Double;
|
||||||
|
begin
|
||||||
|
if (InRange(ASlice.FPrevAngle, 0, PI_1_2) or InRange(ASlice.FPrevAngle, PI_3_2, TWO_pi)) and
|
||||||
|
InRange(ASlice.FNextAngle, PI_1_2, PI_3_2)
|
||||||
|
then
|
||||||
|
// Most backward slice --> must be first to draw
|
||||||
|
Result := pi
|
||||||
|
else
|
||||||
|
if InRange(ASlice.FPrevAngle, PI_1_2, PI_3_2) and
|
||||||
|
(InRange(ASlice.FNextAngle, PI_3_2, TWO_PI) or InRange(ASlice.FNextAngle, 0, PI_1_2))
|
||||||
|
then
|
||||||
|
// Most foremost slice --> must be the last to draw
|
||||||
|
Result := 0
|
||||||
|
else
|
||||||
|
Result := IfThen(InRange(ASlice.FPrevAngle, PI_3_2, TWO_PI) or InRange(ASlice.FPrevAngle, 0, PI_1_2),
|
||||||
|
ASlice.FPrevAngle, ASlice.FNextAngle) - PI_3_2
|
||||||
|
end;
|
||||||
|
|
||||||
|
function GetAngleForSortingVert(ASlice: TPieSlice): Double;
|
||||||
|
var
|
||||||
|
next_angle: Double;
|
||||||
|
begin
|
||||||
|
next_angle := ASlice.FixedNextAngle;
|
||||||
|
if (ASlice.FPrevAngle <= pi) and (ASlice.FNextAngle > pi) then
|
||||||
|
// Slice crossing the 180° point, most backward slice --> first to draw
|
||||||
|
Result := pi
|
||||||
|
else
|
||||||
|
if (ASlice.FPrevAngle >= pi) and (ASlice.FNextAngle < pi) then
|
||||||
|
// Slice crossing the 0° point, most foreward slice --> last to draw
|
||||||
|
Result := 0
|
||||||
|
else
|
||||||
|
Result :=IfThen(ASlice.FPrevAngle > pi, ASlice.FPrevAngle, next_angle);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TCustomPieSeries.SortSlices(out ASlices: TSliceArray);
|
procedure TCustomPieSeries.SortSlices(out ASlices: TSliceArray);
|
||||||
|
|
||||||
function GetAngleForSorting(ASlice: TPieSlice): Double;
|
function CompareSlices(ASlice1, ASlice2: TPieSlice; AngleFunc: TAngleFunc): Integer;
|
||||||
var
|
|
||||||
next_angle: double;
|
|
||||||
begin
|
|
||||||
next_angle := ASlice.FixedNextAngle;
|
|
||||||
if ((ASlice.FPrevAngle >= PI_5_4) or (ASlice.FPrevAngle <= PI_1_4)) and
|
|
||||||
InRange(ASlice.FNextAngle, PI_1_4, PI_5_4)
|
|
||||||
then
|
|
||||||
// Slice crossing the 45° point --> must be last slice to draw
|
|
||||||
Result := PI_1_4
|
|
||||||
else
|
|
||||||
if InRange(ASlice.FPrevAngle, PI_1_4, PI_5_4) and InRange(next_angle, PI_5_4, TWO_PI + PI_1_4)
|
|
||||||
then
|
|
||||||
// Slice crossing the 225° point --> must be first slice to draw
|
|
||||||
Result := PI_5_4
|
|
||||||
else
|
|
||||||
Result := IfThen(InRange(ASlice.FPrevAngle, PI_1_4, PI_5_4), ASlice.FPrevAngle, next_angle);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function CompareSlices(ASlice1, ASlice2: TPieSlice): Integer;
|
|
||||||
var
|
var
|
||||||
angle1, angle2: Double;
|
angle1, angle2: Double;
|
||||||
begin
|
begin
|
||||||
angle1 := GetAngleForSorting(ASlice1) - PI_1_4;
|
angle1 := AngleFunc(ASlice1);
|
||||||
angle2 := GetAngleForSorting(ASlice2) - PI_1_4;
|
angle2 := AngleFunc(ASlice2);
|
||||||
Result := CompareValue(cos(angle1), cos(angle2));
|
Result := CompareValue(cos(angle1), cos(angle2));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure QuickSort(const L, R: Integer);
|
procedure QuickSort(const L, R: Integer; AngleFunc: TAngleFunc);
|
||||||
var
|
var
|
||||||
i, j, m: Integer;
|
i, j, m: Integer;
|
||||||
ps: TPieSlice;
|
ps: TPieSlice;
|
||||||
@ -772,8 +973,8 @@ procedure TCustomPieSeries.SortSlices(out ASlices: TSliceArray);
|
|||||||
j := R;
|
j := R;
|
||||||
m := (L + R) div 2;
|
m := (L + R) div 2;
|
||||||
while (i <= j) do begin
|
while (i <= j) do begin
|
||||||
while CompareSlices(ASlices[i], ASlices[m]) < 0 do inc(i);
|
while CompareSlices(ASlices[i], ASlices[m], AngleFunc) < 0 do inc(i);
|
||||||
while CompareSlices(ASlices[j], ASlices[m]) > 0 do dec(j);
|
while CompareSlices(ASlices[j], ASlices[m], AngleFunc) > 0 do dec(j);
|
||||||
if i <= j then begin
|
if i <= j then begin
|
||||||
ps := ASlices[i];
|
ps := ASlices[i];
|
||||||
ASlices[i] := ASlices[j];
|
ASlices[i] := ASlices[j];
|
||||||
@ -781,13 +982,14 @@ procedure TCustomPieSeries.SortSlices(out ASlices: TSliceArray);
|
|||||||
inc(i);
|
inc(i);
|
||||||
dec(j);
|
dec(j);
|
||||||
end;
|
end;
|
||||||
if L < j then QuickSort(L, j);
|
if L < j then QuickSort(L, j, AngleFunc);
|
||||||
if i < R then QuickSort(i, R);
|
if i < R then QuickSort(i, R, AngleFunc);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
i, j: Integer;
|
i, j: Integer;
|
||||||
|
f: TAngleFunc;
|
||||||
begin
|
begin
|
||||||
SetLength(ASlices, Length(FSlices) + 1);
|
SetLength(ASlices, Length(FSlices) + 1);
|
||||||
j := 0;
|
j := 0;
|
||||||
@ -803,15 +1005,20 @@ begin
|
|||||||
inc(j);
|
inc(j);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
case FOrientation of
|
||||||
|
poNormal: f := @GetAngleForSortingNormal;
|
||||||
|
poHorizontal: f := @GetAngleForSortingHoriz;
|
||||||
|
poVertical: f := @GetAngleForSortingVert;
|
||||||
|
end;
|
||||||
SetLength(ASlices, j);
|
SetLength(ASlices, j);
|
||||||
QuickSort(0, High(ASlices));
|
QuickSort(0, High(ASlices), f);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TCustomPieSeries.TryRadius(ADrawer: IChartDrawer): TRect;
|
function TCustomPieSeries.TryRadius(ADrawer: IChartDrawer): TRect;
|
||||||
|
|
||||||
function EndPoint(AAngle, ARadius: Double): TPoint;
|
function EndPoint(AAngle, ARadius: Double): TPoint;
|
||||||
begin
|
begin
|
||||||
Result := RotatePointX(ARadius, -AAngle);
|
Result := FixAspectRatio(RotatePointX(ARadius, -AAngle));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function LabelExtraDist(APoly: TPointArray; AAngle: Double): Double;
|
function LabelExtraDist(APoly: TPointArray; AAngle: Double): Double;
|
||||||
|
@ -133,9 +133,11 @@ type
|
|||||||
property MarkPositionCentered;
|
property MarkPositionCentered;
|
||||||
property MarkPositions;
|
property MarkPositions;
|
||||||
property Marks;
|
property Marks;
|
||||||
|
property Orientation;
|
||||||
property RotateLabels;
|
property RotateLabels;
|
||||||
property StartAngle;
|
property StartAngle;
|
||||||
property Source;
|
property Source;
|
||||||
|
property ViewAngle;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TConnectType = (ctLine, ctStepXY, ctStepYX);
|
TConnectType = (ctLine, ctStepXY, ctStepYX);
|
||||||
|
Loading…
Reference in New Issue
Block a user