RefreshState 角度計算與修正
public void RefreshState()
{
double total = 0;
foreach (PieShapeItem item in this) total += item.Value;
float angleAccum = 0;
for (int i = Count - 1; i >= 0; i--) // 反向遍歷配合順時針繪製
{
PieShapeItem item = this[i];
float angle = (float)(360.0 * item.Value / total);
item.StartAngle = (float)Math.Round(angleAccum, 3);
item.EndAngle = (float)Math.Round(angleAccum + angle, 3);
angleAccum += angle;
// 橢圓修正:將圓形角度映射至橢圓弧度
item.StartAngle = (float)Math.Round(FixAngle(item.StartAngle), 3);
item.EndAngle = (float)Math.Round(FixAngle(item.EndAngle), 3);
}
}
private float FixAngle(float angle)
{
if (angle % 90 == 0) return angle; // 軸向無需修正
if (intWidth == intHeight) return angle; // 正圓無需修正
double x = intWidth * Math.Cos(angle * Math.PI / 180);
double y = intHeight * Math.Sin(angle * Math.PI / 180);
float result = (float)(Math.Atan2(y, x) * 180 / Math.PI);
if (result < 0) result += 360;
return result;
}
CreatePath 建構路徑
public GraphicsPath CreatePath(PieShapeItem item)
{
GraphicsPath path = new GraphicsPath();
path.AddPie(intLeft, intTop, intWidth, intHeight, item.StartAngle, item.EndAngle - item.StartAngle);
return path;
}
Draw 繪製實作
public void Draw(Graphics g, Rectangle clipRect)
{
foreach (PieShapeItem item in this)
using (GraphicsPath path = CreatePath(item))
using (SolidBrush b = new SolidBrush(item.Color))
{
g.FillPath(b, path);
g.DrawPath(Pens.Black, path);
}
}
關鍵觀念
- 橢圓餅圖需將圓形角度透過三角函數映射 (
FixAngle) 才能正確顯示比例。
- 反向遍歷 (Count-1 → 0) 使視覺順序符合慣例 (順時針)。
GraphicsPath.AddPie 直接支援扇形繪製,簡化路徑建構。