zoukankan      html  css  js  c++  java
  • 计算机图形学——圆的扫描转换(基本光栅图形算法)

           与直线的生成类似,圆弧生成算法的好坏直接影响到绘图的效率。本篇博客将讨论圆弧生成的3个主要算法,正负法、Bresenham法和圆的多边形迫近法,在介绍算法时,只考虑圆心在原点,半径为R的情况。

    一、正负法

    1、基本原理 

    假设已选取Pi-1为第i-1个像素,则如果Pi-1在圆内,就要向圆外方向走一步;若已在圆外就要向圆内走一步。
    总之,尽量贴近圆的轮廓线

    2、正负法的具体实现

    1)圆的表示:设圆的圆心为(0,0),半径为R,则圆的方程为:
          F(x,y)=x2+y2–R2=0  
    当点(x,y)在圆内时,F(x,y)<0。
    当点(x,y)在圆外时,F(x,y)>0。

    2)实现步骤
    第1步:x0=0,y0=R
    第2步:
     求得Pi(xi,yi)后找点Pi+1的原则为:

    当Pi在圆内时(F(xi,yi)≤0),要向右走一步得Pi+1,这是向圆外方向走去。取xi+1= xi+1, yi+1= yi
    当Pi在圆外时(F(xi,yi)>0),要向下走一步得Pi+1,这是向圆内方向走去,取xi+1= xi, yi+1= yi-1

    用来表示圆弧的点均在圆弧附近且 F(xi, yi)时正时负

    假设已经得到点(xi, yi),则容易算出F(xi, yi),即确定了下一个点(xi+1, yi+1),则如何计算F(xi+1, yi+1),以确定下下个点(xi+2, yi+2)?

    分为两种情况:
    右走一步后:xi+1=xi+1,yi+1=yi,此时:
    F(xi+1, yi+1)=xi+12+yi2-R2  =xi2+yi2-R2+2xi+1 = F(xi, yi)+2xi+1

    下走一步后:xi+1=xi,yi+1=yi-1, 此时:
    F(xi+1, yi+1)=xi2+(yi-1)2-R2   = F(xi, yi)-2yi+1

    由此可得:

    确定了F(xi+1, yi+1)之后,即可决定下一个点(xi+2, yi+2),选择道理同上。

    二、Bresenham 生成圆弧的算法

    Bresenham算法是最常用的画圆的算法之一假设圆心(0,0)为原点,考虑AB弧的画法,显示一个整圆时,只要在显示AB上任一点(x,y)时,同时显示在圆周上其它七个对称点(y,x), (y,-x), (x,-y), (-x,-y),(-y,-x), (-y,x), (-x,y)。

     1、基本原理

    考虑AB弧段,x每步增加1,从 x=0开始,到x=y结束。
    即有:
        xi+1=xi+1  相应的yi+1则在两种可能中选择 yi+1=yi (Hi)或者 yi+1=yi-1(Li)
    所以:
       选择的原则是确定这两个点哪一个更接近于圆弧。

     即:设Pi-1是已选中的一个表示圆弧上的点,下一个点应从Hi或Li中选择。设Hi和Li两点的坐标分别为(xhi, yhi)和(xli, yli)

    设R为弧AB的半径,记点P到原点的距离的平方与圆的半径的平方之差为D(P),即

     

     2、递推公式

       di决定的是(xi, yi),即Hi和Li哪个被选中
       di+1则决定的是(xi+1, yi+1),即Hi+1和Li+1哪个被选中

    当di<0时,点Hi被选中, xi= xi-1+1, yi=yi-1,由 (3.13)和(3.14)得
                      di+1= di+ 4xi+2= di+ 4xi-1+6                  
    当di≥0时,点Li被选中, xi= xi-1+1,yi= yi-1-1,由(3.13)和(3.14)得
                    di+1=di+4xi-4yi-1+6=di+4(xi-1-yi-1)+10

    3、代码实现

     根据上面得到的递推表达式,可以获得该算法生成弧AB的代码如下:

    void bresenham_arc(Graphics g,int radius)
    {
        int x,y,d;
        x = 0;
        y = radius;
        d = 3-2*radius;//d1
        while (x < y)
        {
            g.drawLine(x, y, x, y);
            if (d<0)
                d=d+4*x+6;
            else
            {
                d=d+4*(x-y)+10;
                y--;
            }
            x++;
        }
        if (x == y)
            g.drawLine(x,y,x,y);
    }

    Bresenham算法在候选的两个像素中,总是选定离圆弧最近的像素为圆弧的一个近似点,因此,Bresenham算法比正负法决定的像素更合理。

    三、圆的多边形迫近法

     1、基本思想

           将整个圆弧等分成一段段的短直线,用这些短直线形成的折线来逼近圆弧。为了获得这些短直线,只需按一定的方式计算给定圆弧轨迹上一系列顶点,短直线的绘制可采用直线的生成算法,如果将圆弧分割的足够密,则短直线将足够短,形成的折线将可以和圆弧接近到任意程度,因此在允许的误差范围内,可以用显示折线代替显示圆弧。

    2、圆弧的离散生成

    设圆的圆心为c(0,0),半径为R。假设圆弧的起始角和终止角分别为α0和α1,把圆弧分割为n份,则两个顶点之间的夹角为 α=( α1 - α0 )/n 。

    设内接正多边形的一个顶点为Pi(xi,yi),cPi的幅角为θi,则
              xi=Rcosθi
              yi=Rsinθi
    顶点Pi+1的坐标为
      xi+1=Rcos(θi+α)= xicosα-yisinα
      yi+1=Rsin(θi+α)= xisinα+yicosα

    或表示为矩阵形式:

     计算一个点(xi+1,yi+1)只要作四次乘法。

     由此决定了一系列顶点,两个定点确定一条直线,n条直线逼近了个整个圆。

  • 相关阅读:
    Openstack API 开发 快速入门
    virtualBox虚拟机到vmware虚拟机转换
    使用Blogilo 发布博客到cnblogs
    Openstack Troubleshooting
    hdoj 1051 Wooden Sticks(上升子序列个数问题)
    sdut 2430 pillars (dp)
    hdoj 1058 Humble Numbers(dp)
    uva 10815 Andy's First Dictionary(快排、字符串)
    sdut 2317 Homogeneous squares
    hdoj 1025 Constructing Roads In JGShining's Kingdom(最长上升子序列+二分)
  • 原文地址:https://www.cnblogs.com/wkfvawl/p/12080129.html
Copyright © 2011-2022 走看看