Nadesłany przez Andrzej Borucki, 10 stycznia 2012 21:37
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.
BresenhamCircle/WriteableBitmapDrawer.cs:
//Andrzej Borucki
//www.algorytm.org
//Algorytm kreslenia okregow
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media.Imaging;
namespace BresenhamCircle
{
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 CirclePoints(int x, int y, int x0, int y0, int color)
{
SetPixel(x+x0, y+y0, color);
SetPixel(y+x0, x+y0, color);
SetPixel(y+x0, -x+y0, color);
SetPixel(x+x0, -y+y0, color);
SetPixel(-y+x0, -x+y0, color);
SetPixel(-x+x0, -y+y0, color);
SetPixel(-y+x0, x+y0, color);
SetPixel(-x+x0, y+y0, color);
}
/*
* Algorytm rysowania okręgu; dla każdego punktyu sprawdzane jest czy jest w zakresie
* bitmapy, co trochę spowalnia rysowanie
*/
public void DrawCircle(int x0, int y0, int radius, int color)
{
int x, y, d;
x = 0;
y = radius;
d = 5 - 4 * radius;
CirclePoints(x, y, x0, y0, color);
while (y > x)
{
if (d < 0)
{ /* Select E */
d += x * 8 + 12;
x++;
}
else
{ /* Select SE */
d += (x - y) * 8 + 20;
x++;
y--;
}
CirclePoints(x, y, x0, y0, color);
}
}
private void p4(int x, int y, int px, int py, int color)
{
SetPixel(px + x, py + y, color);
SetPixel(px + y, py - x, color);
SetPixel(px - x, py - y, color);
SetPixel(px - y, py + x, color);
}
/*
* Maksymalnie prosta wersja algorytmu, podobny czas wykonania, minimalne róznice
* sprawiuające że okrąg jest bardziej kanciasty, więc lepiej stosować DrawCircle
*/
public void DrawCircleSimplified(int px, int py, int r, int color)
{
int x, y, d;
x = 0; y = r; d =(r-1) / 2;
while (true)
{
p4(x,y,px,py,color);
if (d>=0)
{
x++; d-=x;
}
if (d<0)
{
y--; d+=y;
}
if (y<=0) return;
}
}
}
}

