Nedávno se na fóru vývojáře objevil dotaz, jak nahradit chybějící metodu FillPie v objektu Graphics na Compact .Net Frameworku, protože prý ani tradiční zuřivé googlování žádné výsledky nepřineslo. Zkusil jsem napsat implementaci metody FillPie, a protože se podobných dotazů na internetu dá najít více, dávám kód obohacený nyní i o metodu DrawPie na blog, aby nezůstal utopen jen v diskuzním fóru.
Compact .Net Framework sice nemá metodu FillPie ani DrawPie, ale má obecné metody DrawPolygon a FillPolygon, se kterými nakreslíte, co se vám zlíbí. Zhýrale jsem kód opět trochu zlinqovatěl, asi začínám být na LINQu a extenzních metodách závislý. Inu, jak říkáme my C# vývojáři, původně odříkané extenzní metody plný zásobník volání.
static class GraphicsExtensions
{
public static readonly float ANGLE_MULTIPLY = (float) Math.PI / 180;
public static void FillPie(this Graphics g, SolidBrush brush, int x, int y, int width, int height, float startAngle, float sweepAngle)
{
var tempPoints = GetTempPoints(sweepAngle, startAngle, x, y, width, height);
g.FillPolygon(brush, tempPoints);
}
public static void DrawPie(this Graphics g, Pen pen, int x, int y, int width, int height, float startAngle, float sweepAngle)
{
var tempPoints = GetTempPoints(sweepAngle, startAngle, x, y, width, height);
g.DrawPolygon(pen, tempPoints);
}
private static Point[] GetTempPoints(float sweepAngle, float startAngle, int x, int y, int width, int height)
{
const float HALF_FACTOR = 2f;
const int TEMP_POINT_FIRST = 0;
const int TEMP_POINT_LAST= 100;
const int TOTAL_POINTS = TEMP_POINT_LAST - TEMP_POINT_FIRST;
float angleInc = (sweepAngle - startAngle) / TOTAL_POINTS;
float halfWidth = width / HALF_FACTOR;
float halfHeight= height / HALF_FACTOR;
return (new[] {new Point
{
X = x,
Y = y
}
})
.Union(
(from i in Enumerable.Range(TEMP_POINT_FIRST, TOTAL_POINTS)
let angle = i == TEMP_POINT_LAST - 1? sweepAngle : startAngle + (i * angleInc)
select new Point
{
X = (int) (x + (Math.Cos(angle*(ANGLE_MULTIPLY))*(halfWidth))),
Y = (int) (y + (Math.Sin(angle*(ANGLE_MULTIPLY))*(halfHeight)))
})).ToArray();
}
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
using (var redBrush = new SolidBrush(Color.Red))
using (var blueBrush = new SolidBrush(Color.Blue))
using (var greenBrush = new SolidBrush(Color.ForestGreen))
{
e.Graphics.FillPie(redBrush, Width / 2, Height / 2, Width / 2, Height / 2, 0, 35f);
e.Graphics.FillPie(blueBrush, Width / 2, Height / 2, Width / 2, Height / 2, 35f, 80f);
e.Graphics.FillPie(greenBrush, Width / 2, Height / 2, Width / 2, Height / 2, 80f, 360f);
}
using (var redPen = new Pen(Color.IndianRed))
{
e.Graphics.DrawPie(redPen, Width / 5, Height / 5, Width / 5, Height / 5, 0, 60f);
}
}
}