【计算机图形学】2-2 圆的绘制

2.

  对于一个圆,这里给出的圆的中点坐标和圆的半径,同样有三种常用方法。最终使用的依旧是Bresenham法。

1)直角坐标法

  根据圆的方程(x– x0) ^ 2 + (y – y0) ^ 2 = r ^2,当一个坐标确定时,另外一个坐标也可以计算出来。为了画出一个完整的圆,因为圆本身具有完美的对称特性,我们画八个r/ sqrt(2)宽度的弧,组成一个圆。之所以选取r/ sqrt(2)是因为这点切线斜率为1,这样画出的圆不会间断。

基本代码:

void draw_circle_Coordinate_3i(int32 x, int32 y, int32 r)
{
  int32 i, t, rr = (int32)ceil(r / sqrt(2.0));
  for(i=0;i<=rr;++i)
  {
    t = (int32)sqrt(r * r - i * i);
    draw_point_2i(x + i, y + t);
    draw_point_2i(x + i, y - t);
    draw_point_2i(x + t, y + i);
    draw_point_2i(x - t, y + i);
    draw_point_2i(x - i, y + t);
    draw_point_2i(x - i, y - t);
    draw_point_2i(x + t, y - i);
    draw_point_2i(x - t, y - i);
  }
}

2)中点画圆法

  中点画圆法的基本思想不变,只不过增量的变化要根据圆的公式更改。定义F(x,y) = x ^ 2 + y ^ 2 – r ^ 2F(x,y) > 0说明点在圆外,F(x,y) < 0说明点在圆内。定义增量D(x,y) = F(x, y) – F(x0, y0),我们考虑圆上方顶点向右绘制的过程,则

  D(x+1,y-0.5) = (x+1)^2 + (y–0.5)^2 – x^2 – y^2 = 2x - y + 1.25

  D(x+1,y) = (x+1)^2 – x^2 = 2x + 1

  D(x+1,y-1) = (x+1)^2 + (y–1)^2 – x^2 – y^2 = 2x – 2y + 2

  为了避免浮点数运算,所有D乘以4,则

  D(x+1,y-0.5) = 8x - 4y + 5

  D(x+1,y) = 8x + 4

  D(x+1,y-1) = 8x – 8y + 8

  同样利用圆的对称性即可画出完整的圆。

基本代码:

void draw_circle_MidPoint_3i(int32 x, int32 y, int32 r)
{
  int32 d, i, j;
  int32 rr = (int32)ceil(r / sqrt(2.0));
  j = r;
  d = - (j<<2) + 5;
  for(i=0;i<=rr;++i)
  {
    draw_point_2i(x + i, y + j);
    draw_point_2i(x + i, y - j);
    draw_point_2i(x + j, y + i);
    draw_point_2i(x - j, y + i);
    draw_point_2i(x - i, y + j);
    draw_point_2i(x - i, y - j);
    draw_point_2i(x + j, y - i);
    draw_point_2i(x - j, y - i);
    if(d > 0)
    {
      d -= (i << 3) + 4;
    }
    else
    {
      -- j;
      d -= (i - j + 1) << 3;
    }
  }
}

3Bresenham

  Bresenham法本质依然与直线相同,交点与整点的距离e(x,y) = 2(x+1)^2 + y^2 + (y-1)^2 – 2r^2,带入初值的e(0,r) = 3 – 2r,选择上方点,e(x+1,y) – e(x, y) = 2(x+2)^2 – 2(x+1)^2 = 4x + 6,选择下方点,e(x+1,y+1) – e(x, y) = 4x + 6 + y^2 + (y-1)^2 – (y+1)^2 – y^2 = 4x –4y + 10

  注:给出代码的计算量和中点画圆法相同。

基本代码:

void draw_circle_Bresenham_3i(int32 x, int32 y, int32 r)
{
 int32 e;
 int32 i, j;
 int32 rr = (int32)ceil(r / sqrt(2.0));
 j = r;
 e = 3 - (r << 1);
 for(i=0;i<=rr;++i)
 {
  draw_point_2i(x + i, y + j);
  draw_point_2i(x + i, y - j);
  draw_point_2i(x + j, y + i);
  draw_point_2i(x - j, y + i);
  draw_point_2i(x - i, y + j);
  draw_point_2i(x - i, y - j);
  draw_point_2i(x + j, y - i);
  draw_point_2i(x - j, y - i);
  if(e < 0)
  {
   e += (i << 2) + 6;
  }
  else
  {
   e += ((i - j)<<2) + 10;
   -- j;
  }
 }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值