Please try the current revision with the new even OnDrawPie of TPieSeries. When a handler is assigned you must fill all areas of the slices yourself. It gets several parameters to tell you where the currently drawn slice is:
type
TSlicePart = (spTop, spOuterArcSide, spInnerArcSide, spStartSide, spEndSide);
TPieSlice = object
FBase: TPoint;
FFlags: Integer; // 1: 1st part, 2: 2nd part of diviced slice
FLabel: TLabelParams;
FOrigIndex: Integer;
FPrevAngle, FNextAngle: Double; // in CCW direction
// FNextAngle may become < FPrevAngle when crossing 360°
FVisible: Boolean;
function Angle: Double; inline;
function CenterAngle: Double; inline;
function FixedNextAngle: Double; inline;
end;
TDrawPieEvent = procedure(ASeries: TCustomPieSeries; ADrawer: IChartDrawer;
ASlice: TPieSlice; APart: TSlicePart; const APoints: TPointArray) of object;
The event is called several times for drawing every slice, the parameter "Part" identifies the currently drawn part: the radial sides, the curved arcs, or the top face which is the only part visible also in 2D mode.
Tha parameter "ADrawer" is the drawing interface used, in your case TBGRABitmapDrawer. There is no need to modify the code of TBGRABitmapDrawer any more.
The parameter "ASlice" identifies the slice which is currently painted:
- FOrigIndex is the index of the slice, i.e. the index of the data point correspondingto the series. Note that slices are reordered to paint from "back" to "front".
- FPrevAngle is the angle at which the slice starts (in radians),
- FNextAngle is the angle at which the slice ends. Unlike your sketch, angles are oriented in counter-clockwise direction here. Usually FNextAngle is greater than FPrevAngle, but when the StartAngle of the series is changed it may happen that a slice crosses the 2 pi line. Use FixedNextAngle instead to make sure that the end angle is always greater than the start angle.
- FVisible can be ignored because the event fires only for visible slices.
- Angle is the opening angle spanned by the slice, i.e. FixedNextAngle - FPrevAngle.
- CenterAngle is the angle at the center of the slice, i.e. (FixedNextAngle + FPrevAngle) / 2.
- FBase tells you the coordinates of the center of the slice.
APoints is an array of TPoint records defining the polygon of the slice part being drawn.
Slices and faces are drawn in the correct order to (hopefully) guarantee that hidden faces are not painted or over-drawn by visible faces.
Call TPieSeries.SliceColor(ASlice.FOrigIndex) to get the color of the slice.
Call TPieSeries.GetDepthColor(-- slice color --) to get the color of the slice sides.
In order to determine the coordinates at the perimeter and the center of a slice (e.g., the points marked on your sketch by circles) call the method CalcBorderPoint:
var
pCenter: TPoint;
..
pCenter := PieSeries.CalcBorderPoint(ASlice, ARadius, AAngle);
The radius of the outer arc is given by the property Radius of the series, the radius of the inner arc of a donut series is given by method CalcInnerRadius. The method automatically takes care of the aspect ratio in case of an oblique viewing angle.
ATM, the border lines of the slices as drawn by the series. If you want to draw them yourself set the PieSeries.EdgePen.Style to psClear and just draw the PolyLine given by APoints. Be carefuly however, when a slice has an opening angle > 180° - to avoid 3D drawing artefacts, these slices are split in the center to two pieces having only half of the total opening angle. The FFlag tells you which slice is currently drawn: 1 = first part from FPrevAngle to CenterAngle, 2 = second part = CenterAngle to FNextAngle, 0 = non-split slice. Not all points of the polygon must be connected in the case of split slices, otherwise a radial line will appear in the center of the split slices. Have a look at the source code of TCustomPieSeries.Draw, local procedure DrawArc3D, to learn which points are affected.