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?

Algorytm Cohena-Sutherlanda - Implementacja w C#
Ocena użytkownikóww: *****  / 0
SłabyŚwietny
Nadesłany przez Andrzej Borucki, 31 stycznia 2012 12:44
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.

ClipLineWF/Form1.cs:
//Andrzej Borucki
//www.algorytm.org
//Algorytm obcinania odcinkow

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ClipLineWF
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        const int MinX = 0;
        const int MinY = 0;
        const int MaxX = 100;
        const int MaxY = 100;

        private void SwapPoints(ref int x0, ref int y0, ref int x1, ref int y1)
        {
            int tmpX, tmpY;
            tmpX = x0;
            tmpY = y0;
            x0 = x1;
            y0 = y1;
            x1 = tmpX;
            y1 = tmpY;
        }

        private void SwapCodes(ref int c1, ref int c2)
        {
            int tmp = c1;
            c1 = c2;
            c2 = tmp;
        }

        const int LEFT_EDGE = 1;
        const int RIGHT_EDGE = 2;
        const int BOTTOM_EDGE = 4;
        const int TOP_EDGE = 8;

        /* Algorytm obcinania odcinkow
         * return: 
         * 0 - inside; 1 - clip; 2 - outside
         */
        private int ClipLine1(ref int x0, ref int y0, ref int x1, ref int y1)
        {
            int code1, code2;
            bool clipped = false;
            double m;
            while (true)
            {
                code1 = 0;
                code2 = 0;
                if (x0 < MinX) code1 |= 1;
                if (x0 > MaxX) code1 |= 2;
                if (y0 < MinY) code1 |= 4;
                if (y0 > MaxY) code1 |= 8;
                if (x1 < MinX) code2 |= 1;
                if (x1 > MaxX) code2 |= 2;
                if (y1 < MinY) code2 |= 4;
                if (y1 > MaxY) code2 |= 8;

                if ((code1 | code2) == 0)
                {
                    if (clipped) return 1;
                    else return 0;
                }
                else if ((code1 & code2) != 0)
                {
                    return 2;
                }
                else
                {
                    clipped = true;
                    /*ensure that p1 is outside window*/
                    if (code1 == 0)
                    {
                        SwapPoints(ref x0, ref y0, ref x1, ref y1);
                        SwapCodes(ref code1, ref code2);
                    }
                    /* use slope (m) to find line_clip edge Intersection */
                    if (x1 != x0)
                        m = (double)(y1 - y0) / (x1 - x0);
                    else
                        m = Double.PositiveInfinity;

                    if ((code1 & TOP_EDGE) != 0)
                    {
                        if (x1 != x0)
                            x0 += (int)((MaxY - y0) / m);
                        y0 = MaxY;
                    }
                    else
                    if ((code1 & BOTTOM_EDGE) != 0)
                    {
                        if (x1 != x0)
                            x0 += (int)((MinY - y0) / m);
                        y0 = MinY;
                    }
                    else
                    if ((code1 & RIGHT_EDGE) != 0)
                    {
                        if (x1 != x0)
                        {
                            y0 += (int)((MaxX - x0) * m);
                            x0 = MaxX;
                        }
                    }
                    else
                    if ((code1 & LEFT_EDGE) != 0)
                    {
                        if (x1 != x0)
                        {
                            y0 += (int)((MinX - x0) * m);
                            x0 = MinX;
                        }
                    }                                                                             
                }
            }
        }

        /* Algorytm obcinania odcinkow
         * bardziej zwarta i szybsza implementacja algorytmu
         * return: 
         * 0 - inside; 1 - clip; 2 - outside
         */
        private int ClipLine2(ref int x0, ref int y0, ref int x1, ref int y1)
        {
            int V, C1, C2;
            C1 = 0;
            C2 = 0;

            if (x0 < MinX) C1 |= 1;
            if (x0 > MaxX) C1 |= 2;
            if (y0 < MinY) C1 |= 4;
            if (y0 > MaxY) C1 |= 8;
            if (x1 < MinX) C2 |= 1;
            if (x1 > MaxX) C2 |= 2;
            if (y1 < MinY) C2 |= 4;
            if (y1 > MaxY) C2 |= 8;

            if (((C1 & C2) == 0) && ((C1 | C2) != 0))
            {
                if ((C1 & 12) != 0)
                {
                    if (C1 < 8) V = MinY; else V = MaxY;
                    x0 += (int)((double)(V - y0) * (x1 - x0) / (y1 - y0));
                    y0 = V;
                    C1 = (x0 < MinX ? 1 : 0) + (x0 > MaxX ? 2 : 0);
                }

                if ((C2 & 12) != 0)
                {
                    if (C2 < 8) V = MinY; else V = MaxY;
                    x1 += (int)((double)(V - y1) * (x1 - x0) / (y1 - y0));
                    y1 = V;
                    C2 = (x1 < MinX ? 1 : 0) + (x1 > MaxX ? 2 : 0);
                }

                if (((C1 & C2) == 0) && ((C1 | C2) != 0))
                {
                    if (C1 != 0)
                    {
                        if (C1 == 1) V = MinX; else V = MaxX;
                        y0 += (int)((double)(V - x0) * (y1 - y0) / (x1 - x0));
                        x0 = V;
                        C1 = 0;
                    }

                    if (C2 != 0)
                    {
                        if (C2 == 1) V = MinX; else V = MaxX;
                        y1 += (int)((double)(V - x1) * (y1 - y0) / (x1 - x0));
                        x1 = V;
                        C2 = 0;
                    }
                }
                if ((C1 == 0) || (C2 == 0)) return 1; else return 2;
            }
            else
                if ((C1 | C2) == 0) return 0; else return 2;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Bitmap bmp = new Bitmap(pictureBox1.Width, pictureBox1.Height);
            pictureBox1.Image = bmp;
            Graphics g = Graphics.FromImage(bmp);
            g.Clear(Color.White);
            Pen pen = new Pen(Brushes.Black);
            using(pen)
            {
                g.DrawRectangle(pen, new Rectangle(100, 100, 100, 100));
            }
            g.Dispose();
            pictureBox1.Invalidate();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Bitmap bmp = (Bitmap)pictureBox1.Image;
            Random rand = new Random();

            int x0 = rand.Next(200) - 100;
            int y0 = rand.Next(200) - 100;
            int x1 = rand.Next(200);
            int y1 = rand.Next(200);
            Graphics g = Graphics.FromImage(bmp);
            g.Clear(Color.White);
            Pen pen = new Pen(Brushes.Black);
            using (pen)
            {
                g.DrawRectangle(pen, new Rectangle(100, 100, 100, 100));
                g.DrawLine(pen, x0+100, y0+100, x1+100, y1+100);
            }            
            int res = ClipLine2(ref x0, ref y0, ref x1, ref y1);
            switch (res)
            {
                case 0: pen = new Pen(Brushes.Red, 2); break;
                case 1: pen = new Pen(Brushes.Lime, 2); break;
                default: pen = new Pen(Brushes.Magenta, 2); break;
            }            
            using (pen)
            {                
                g.DrawLine(pen, x0 + 100, y0 + 100, x1 + 100, y1 + 100);
            }
            g.Dispose();
            pictureBox1.Invalidate();
        }
    }
}
Dodaj komentarz