Nadesłany przez Andrzej Borucki, 11 stycznia 2012 02:03
Kod przedstawiony poniżej przedstawia główną część rozwiązania problemu.Pobierz pełne rozwiązanie.
Jeżeli nie odpowiada Ci sposób formatowania kodu przez autora skorzystaj z pretty printer'a i dostosuj go automatycznie do siebie.
BresenhamEllipse/WriteableBitmapDrawer.cs:
//Andrzej Borucki
//www.algorytm.org
//Algorytm kreslenia elips
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media.Imaging;
namespace BresenhamEllipse
{
class WriteableBitmapDrawer
{
WriteableBitmap writeableBitmap;
IntPtr backBuffer;
int W, H;
public WriteableBitmapDrawer(WriteableBitmap writeableBitmap)
{
this.writeableBitmap = writeableBitmap;
backBuffer = writeableBitmap.BackBuffer;
W = (int)writeableBitmap.Width;
H = (int)writeableBitmap.Height;
}
public unsafe void SetPixel(int x, int y, int color)
{
if ((x >= 0) && (y >= 0) && (x < W) && (y < H))
{
byte* p = (byte*)backBuffer + y * writeableBitmap.BackBufferStride + x * 4;
*((int*)p) = color;
}
}
private void ElipsePoints(int x, int y, int x0, int y0, int color)
{
SetPixel(x + x0, y + y0, color);
SetPixel(x + x0, -y + y0, color);
SetPixel(-x + x0, -y + y0, color);
SetPixel(-x + x0, y + y0, color);
}
/*
* Algorytm rysowania elipsy, usunięte problemy pojawiające się przy radius = 1
* zastosowano long d i obliczanie limitu jako double do rozwiązania problemów z przepełnieniem
* obecna wersja działa dla promienia radius_a=radius_b = 32767
*/
public void DrawEllipse(int x0, int y0, int radius_a, int radius_b, int color)
{
int x, y, limit;
long d;
int radius_a2, radius_b2;
if ((radius_a == 0) && (radius_b == 0))
{
SetPixel(x0, y0, color);
return;
}
radius_a2 = radius_a * radius_a;
radius_b2 = radius_b * radius_b;
if (radius_b2 == 0)
d = 0;
else
d = 4 * radius_b2 - 4 * radius_b * radius_a2 + radius_a2;
limit = (int)(((double)radius_a2 * radius_a2) / (radius_a2 + radius_b2)+0.5);
x = 0;
y = radius_b;
while (x * x < limit)
{
ElipsePoints(x, y, x0, y0, color);
if (d > 0)
{
d += 8 * (long)radius_b2 * x + 12 * radius_b2 - 8 * (long)radius_a2 * y + 8 * radius_a2;
x++;
y--;
}
else
{
if (radius_b2 > 1)
d += 7 * (long)radius_b2 * x + 12 * radius_b2;
else if ((x + 2) * (x + 2) >= limit) y --;
x++;
}
}
//second part
int aux = radius_a;
radius_a = radius_b;
radius_b = aux;
radius_a2 = radius_a * radius_a;
radius_b2 = radius_b * radius_b;
if (radius_b == 0)
d = 0;
else
d = 4 * radius_b2 - 4 * radius_b * radius_a2 + radius_a2;
limit = (int)(((double)radius_a2 * radius_a2) / (radius_a2 + radius_b2) + 0.5);
x = 0;
y = radius_b;
while (x * x < limit)
{
ElipsePoints(y, x, x0, y0, color);
if (d > 0)
{
d += 8 * (long)radius_b2 * x + 12 * radius_b2 - 8 * (long)radius_a2 * y + 8 * radius_a2;
x++;
y--;
}
else
{
if (radius_b2 > 1)
d += 8 * (long)radius_b2 * x + 12 * radius_b2;
else if ((x + 2) * (x + 2) >= limit) y--;
x++;
}
}
}
}
}

