algorytm.org

Implementacja w C#



Baza Wiedzy
wersja offline serwisu przeznaczona na urządzenia z systemem Android
Darowizny
darowiznaWspomóż rozwój serwisu
Nagłówki RSS
Artykuły
Implementacje
Komentarze
Forum
Bookmarki






Sonda
Implementacji w jakim języku programowania poszukujesz?

Kreślenie elipsy - Implementacja w C#
Ocena użytkownikóww: *****  / 2
SłabyŚwietny
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++;
                }
            }
        }
        
   }
}
Dodaj komentarz