中点画圆算法


一、中点画圆法

1、算法分析

利用圆的对称性,只须讨论1/8圆。

开局一张图:smile:

P为当前点亮象素,那么,下一个点亮的象素可能是P1(Xi+1,Yi)或P2(Xi +1,Yi -1)。

构造函数:

F(X,Y)=X2 + Y2 - R2 ;则

F(X,Y)= 0 (X,Y)在圆上;

F(X,Y)< 0 (X,Y)在圆内;

F(X,Y)> 0 (X,Y)在圆外。

设M为P1、P2间的中点,M=(Xi+1,Yi-1/2)

有如下结论:

F(M)< 0 → M在圆内 取P1

F(M)>= 0 → M在圆外 取P2

为此,可采用如下判别式:

di = F(M) = F (xi + 1,yi – 1/2)

​ =(xi + 1)2 + (yi - 1/2) 2 - R2

若d<0, 则P1 为下一个象素,那么再下一个象素的判别式为:

​ di+1 = F (xi + 2, yi – 1/2)

​ = (xi + 2)2 + (yi - 1/2) 2 - R2

​ = di + 2xi +3

即di 的增量为 2xi +3.

若d>=0, 则P2 为下一个象素,那么再下一个象素的判别式为:

​ di = F (xi + 2, yi – 3/2)

​ = (xi + 2)2 + (yi – 3/2) 2 - R2

​ = di + (2xi + 3)+(-2 yi + 2)

即di的增量为 2 (xi - yi) +5.

di的初值:

d0 = F(1, R-1/2)

​ = 1 + (R-1/2)2 - R2

​ = 1/4 - R

2、算法实现C#

①代码结构

:star:②算法部分:star:

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

namespace DDABresenham
{
    public partial class MainForm : Form
    {
        public void Circle(int x0,int y0,int r,Color color)
        {
            int x, y, p;//x、y为动态坐标,p为判别式
            x = 0;
            y = r;//初始化
            p = 1 / 4 - r;//2的整数次幂,对计算机来说很“简单”,1/4不足道也

            drawponits(x0, y0, x, y, color);
            while (x<=y)//当为True,为b系
            {
                x++;
                if (p<0)//真正圆上的点处于中点上方,y无增量
                {
                    p+=2*x + 3;
                }
                else //真正圆上的点处于中点下方,y-1
                {
                    p+=2*(x - y) + 5;
                    y--;
                }
                drawponits(x0, y0, x, y, color);
            }
        }
        public void drawponits(int x0,int y0,int x,int y,Color color)
        {
            #region 同时画八个象限的点

            bitmap.SetPixel(x0 + x, y0 + y, color);//1b
            bitmap.SetPixel(x0 + y, y0 + x, color);//1a

            bitmap.SetPixel(x0 - y, y0 + x, color);//2a
            bitmap.SetPixel(x0 - x, y0 + y, color);//2b

            bitmap.SetPixel(x0 - x, y0 - y, color);//3b
            bitmap.SetPixel(x0 - y, y0 - x, color);//3a

            bitmap.SetPixel(x0 + x, y0 - y, color);//4b
            bitmap.SetPixel(x0 + y, y0 - x, color);//4a

            #endregion
        }
    }
}

③实现部分

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

namespace DDABresenham
{
    public partial class MainForm : Form
    {
        Graphics graphics;
        Bitmap bitmap;
        public MainForm()
        {
            InitializeComponent();
            graphics = panel1.CreateGraphics();
            bitmap = new Bitmap(panel1.Width,panel1.Height);
        }

        private void buttonDDA_Click(object sender, EventArgs e)
        {
            DDA(300, 300, 800, 400, Color.Blue);//1a
            graphics.DrawImage(bitmap,0,0,panel1.Width,panel1.Height);
        }

        private void buttonBresenham_Click(object sender, EventArgs e)
        {
            Bresenham(300, 300, 500, 500, Color.Red);//一象限对角线
            Bresenham(300, 300, 100, 500, Color.Blue);//二象限对角线
            Bresenham(300, 300, 100, 100, Color.Black);//三象限对角线
            Bresenham(300, 300, 500, 100, Color.DarkOrange);//四象限对角线


            Bresenham(300, 300, 300, 600, Color.Red);//向下
            Bresenham(300, 300, 300, 100, Color.Blue);//2a
            Bresenham(300, 300, 100, 300, Color.Black);//3a
            Bresenham(300, 300, 500, 300, Color.Yellow);//4a


            Bresenham(300, 300, 400, 500, Color.Green);//1b
            Bresenham(300, 300, 250, 500, Color.Blue);//2b
            Bresenham(300, 300, 250, 100, Color.Black);//3b
            Bresenham(300, 300, 350, 100, Color.DarkBlue);//4b


            Bresenham(300, 300, 500, 400, Color.Red);//1a
            Bresenham(300, 300, 0, 400, Color.Blue);//2a
            Bresenham(300, 300, 100, 250, Color.Black);//3a
            Bresenham(300, 300, 500, 200, Color.Yellow);//4a

            graphics.DrawImage(bitmap, 0, 0, panel1.Width, panel1.Height);
        }

        private void buttonExit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void buttoncircle_Click(object sender, EventArgs e)
        {

            Circle(300, 300, 200, Color.Red);
            graphics.DrawImage(bitmap, 0, 0, panel1.Width, panel1.Height);

        }
    }
}

3、Visio流程图:cool::sparkles:

4、运行结果:+1:


二、圆弧扫描算法(未尝试)


三、角度DDA法(未尝试)



文章作者: 李世昱
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 李世昱 !
评论
  目录