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++; } } } } }