zoukankan      html  css  js  c++  java
  • Bresenham画圆算法 与中点画圆法 冷夜

    Bresenham画圆算法

    不失一般性,假设圆的圆心位于坐标原点(如果圆心不在原点,可以通过坐标平移使其与原点重合),半径为R。以原点为圆心的圆C有四条对称轴:x = 0, y = 0, x = y和x = -y。若已知圆弧上一点P1=C(x, y),利用其对称性便可以得到关于四条对称轴的其它7个点,即:

      P2=C(x,-y),

      P3=C(-x, y),

      P4=C(-x,-y),

      P5=C(y,x),

      P6=C(-y,x),

      P7=C(y,-x),

      P8=C(-y,-x)。

    这种性质称为八对称性。

    因此,只要扫描转换八分之一圆弧,就可以通过圆弧的八对称性得到整个圆。

    【Bresenham算法】

        简单图形的扫描转换常用算法是Bresenham算法。它的思想在于用误差量来衡量点选取的逼近程度。其过程如下:

    以平面二维图形的扫描转换为例,设要画的图形方程为F(x, y)=0,要画的区域为[x0, x](不妨设x方向是最大位移方向,即△x > △y),则F(x,y) 也是一个误差度量函数,我们拿离散的点值代入如果大于0则正向偏离,否则负向偏离,等于0的情况比较少,它表示的是不偏离即恰好与真实点重合。既然x是最大位移方向,那每次对x自增1,相应的y可以选择不增或增1(或-1,具体问题具体分析),选择的方法就是d = F(x + 1, y ± 0.5)的正负情况进行判断从而选择y的值。

    实际情况中还要考虑到浮点数的计算问题,因为基本的图形扫描转换算法最好能够硬件实现,所以摆脱浮点数是最好的,常用的方法是对d进行递推,而不是直接由F(x,y)给出(直接给出速度会慢)。

    【圆的扫描转换算法】

        以画圆为例,给出圆心的坐标(0, 0)和半径R,求圆图像的最佳逼近点。

    圆是中心对称的特殊图形,所以可以将圆八等分,则只须对八分之一圆孤求解,其它圆孤可以由对称变换得到,我们求的八分之一圆孤为(0, R) -(R√2,R√2),可知最大位移方向是x方向,x0 = 0, y0 = R,每次对x自增,然后判断y是否减1,直到x >= y为止(从点(0, R)到圆的八分之一处就有这种情况)。误差量由F(x, y) = x^2 + y^2 - R^2给出。

    先找递推关系,若当前d = F(x + 1, y - 0.5) > 0,则y须减1,则下一d值为

    d =  F(x + 2, y - 1.5) = (x + 2)^2 + (y - 1.5)^2 - R^2 = (x + 1)^2 + (x - 0.5)^2 - R^2 + 2x + 3 - 2y + 2 = d + 2x - 2y + 5,若当前d = F(x + 1, y - 0.5) < 0,则y不变,只有x增1,则下一d值为d = F(x + 2, y - 0.5) = d + 2x + 3。

        d的初值,d0 = F(1, R - 0.5) = 1.25 - R,则可以对d - 0.25进行判断,因为递推关系中只有整数运算,所以d - 0.25 > 0即d > 0.25,这和d > 0等价,所以d取初值1 - R。

    代码:

    bool CEnginApp::DrawCircle(ScPoint point,int radius,UNINT *vb_start,int lpitch)
    {
        if (!vb_start||lpitch<=0)
            return false;
    
        int mx=point.x,my=point.y;
        int x=0,y=radius;
    
        int r=0,g=255,b=0;
    
        int d=1-radius;    //起点(0,R),下一点中点(1,R-0.5),d=1*1+(R-0.5)*(R-0.5)-R*R=1.25-R,d只参与整数运算,所以小数部分可省略
    
        while (y>x)    // y>x即第一象限的第1区八分圆
        {
            Plot_Pixel_32(x+mx,y+my,0,r,g,b,vb_start,lpitch);
            Plot_Pixel_32(y+mx,x+my,0,r,g,b,vb_start,lpitch);
            Plot_Pixel_32(-x+mx,y+my,0,r,g,b,vb_start,lpitch);
            Plot_Pixel_32(-y+mx,x+my,0,r,g,b,vb_start,lpitch);
    
            Plot_Pixel_32(-x+mx,-y+my,0,r,g,b,vb_start,lpitch);
            Plot_Pixel_32(-y+mx,-x+my,0,r,g,b,vb_start,lpitch);
            Plot_Pixel_32(x+mx,-y+my,0,r,g,b,vb_start,lpitch);
            Plot_Pixel_32(y+mx,-x+my,0,r,g,b,vb_start,lpitch);
            if (d<0)
            {
                d=d+2*x+3;
            }
            else
            {
                d=d+2*(x-y)+5;
                y--;
            }
            x++;
        }
    
    
        return true;
    }

    效果图:

    参考:

    http://blog.csdn.net/cay22/article/details/5774628

    http://www.cnblogs.com/phinecos/archive/2007/07/28/834407.html

    http://dolphin-magstar.blogbus.com/logs/73759291.html

  • 相关阅读:
    XML转义符简易版
    MarkDown语法
    判断javaScript变量是Ojbect类型还是Array类型
    Springboot实现VNC的反向代理
    MySql事务隔离的特点与实现
    MySql索引入门
    windows、Linux 批量执行 redis脚本命令
    iis 灰度发布
    iis 负载
    docker中部署.netcore2.2项目
  • 原文地址:https://www.cnblogs.com/gamesky/p/2668932.html
Copyright © 2011-2022 走看看