基于中点算法和Bresenham算法绘制椭圆

 方法一

一.设计思路

该实验利用中点算法和Bresenham算法寻找最逼近椭圆的理想像素集。 

对于(x_i,y_i),判断下一点取\left ( x_i+1,y_i \right )还是\left ( x_i+1,y_i+1 \right ),

先取中点\left ( x_i+1,y_i-0.5 \right ),判断该中点在圆内还是圆外,

若在圆外,说明椭圆上的点离下方的像素点\left ( x_i+1,y_i-1 \right )更近,

则下一个中点取\left ( x_i+2,y_i-1.5 \right )

  图1 中点在圆外      

若在圆内,说明椭圆上的点离上方像素点\left ( x_i+1,y_i \right )更近,则下一个中点取\left ( x_i+2,y_i-0.5 \right )

  图2 中点在圆内

则通过判断中点的位置来选择下一像素点。

                                                                

二.具体思路

  1. 由于椭圆的对称性,我们将椭圆以象限分为四部分,再通过将\left ( x,y \right )转变为\left ( x,-y \right )\left ( -x,y \right )\left ( -x,-y \right )得到其他象限的部分。
        glVertex2i(x, y);
        glVertex2i(-x, -y);
        glVertex2i(-x, y);
        glVertex2i(x, -y);
  2. 由于需要\left | k \right |<1,再将第一象限的椭圆分为两部分,一部分从x轴开始计算,一部分从y轴开始计算。b^{2}x>a^{2}y时,即\left | k \right |<1时,从x轴方向开始依次x++。
  3. 通过将椭圆方程构造成F(x,y)=b^{2}x^{2}+a^{2}y^{2}-a^{2}b^{2},则将判断中点与椭圆上的点的位置转换为判断F(x_i+1,y_i-0.5)的正负情况,用d表示该式。
  4. 可得d的初始值为F\left ( x_0+1,y_0-0.5 \right )=b^{2}\left ( x_0+1 \right )^{2}+a^{2}\left ( y_0 -0.5\right )^{2}-a^{2}b^{2}
  5. 为了得到中点误差项,需计算d_{i+1}-d_id_i=F(x_i+1,y_i-0.5)=b^{2}(x_i+1)^{2}+a^{2}(y_i-0.5)^{2}-a^{2}b^{2}  ,当下一中点取(x_i+2,y_i-1.5)则中点误差项d_{i+1}-d_i=b^{2}(2x_i+3)+a^{2}(-2y_i+2); 
  6. 同理可得,当下一中点取(x_i+2,y_i-0.5)时,d_{i+1}=d_i+b^{2}(2x_i+3)
  7.     d = b * b - a * a * 0.25 + a * a * b;//求的d初值
    
    	while (b * b * x < a * a * y) //求导、以x为轴,|k|<1
    	{
    		if (d < 0)//中点在圆内
    		{
    			d + = b * b * (2 * x + 3);
    			x++;
    		}
    		else //中点在圆外
            {
    			d + = b * b * (2 * x + 3) + a * a * (-2 * y + 2);
    			x++;
    			y--;
    		}
    	}
  8.  当\left | k \right |>=1,且y>0时,为保证\left | k \right |<1 ,k{}'=\frac{1}{k} ,从y轴方向向下依次y--。 同理, 当从y轴方向开始计算时,将d的初始值替换为为F\left ( x_0+0.5,y_0-1 \right )=b^{2}(x_0+0.5)^{2}+a^{2}(y_0-1)^{2}-a^{2}b^{2}进行计算。
d = b * b * (x + 0.5) * (x + 0.5) + a * a * (y - 1) * (y - 1) - a * a * b * b;
//从y轴方向开始计算,d的初始值
	while (y > 0) //以y为轴,|k|<1
	{
		if (d <= 0)
		{
			d += b * b * (2 * x + 2) + a * a * (-2 * y + 3);
			x++;
			y--;
		}
		else
		{
			d += a * a * (-2 * y + 3);
			y--;
		}
    }

三.具体函数

    void oval(int a, int b)
{
	int x = 0, y = b;//从(0,b)点开始

	float d;

	d = b * b - a * a * 0.25 + a * a * b;3)//求的d初值

	while (b * b * x < a * a * y) //求导、以x为轴,|k|<1
	{
		if (d < 0)//在圆外
		{
			d += b * b * (2 * x + 3);
			x++;
		}
		else //在圆内
        {
			d += b * b * (2 * x + 3) + a * a * (-2 * y + 2);
			x++;
			y--;
		}

		    glVertex2i(x, y);		
            glVertex2i(-x, -y);
		    glVertex2i(-x, y);
		    glVertex2i(x, -y);
	}

    //从y轴方向开始计算
	d = b * b * (x + 0.5) * (x + 0.5) + a * a * (y - 1) * (y - 1) - a * a * b * b;//d初始

	while (y > 0) //以y为轴,|k|<1
	{
		if (d <= 0)
		{
			d += b * b * (2 * x + 2) + a * a * (-2 * y + 3);
			x++;
			y--;
		}
		else
		{
			d += a * a * (-2 * y + 3);
			y--;
		}

		    glVertex2i(x, y);
		    glVertex2i(-x, -y);
		    glVertex2i(-x, y);
		    glVertex2i(x, -y);
	}
}

四.绘制效果

 方法二

一.设计思路

        将圆的坐标(x,y)用变形为(ax,by)来表示椭圆。

二.具体代码

void oval_circle(int r)
{
    int x, y;

    float d;
 
     x = 0, y = r;

     d = 1.25 - r;

    glVertex2i(ax, by);
    glVertex2i(-ax, -by);
    glVertex2i(-ax, by);
    glVertex2i(ax, -by);
    glVertex2i(ay, bx);
    glVertex2i(-ay, -bx);
    glVertex2i(-ay, bx);
    glVertex2i(ay, -bx);

     while(x < y)
     {

         if(d < 0)

         {

             d = d + 2 * x + 3;

         }

         else

         {

             d = d + 2 * ( x - y ) + 5;

             y--;

         }
         x++;

        glVertex2i(ax, by);
        glVertex2i(-ax, -by);
        glVertex2i(-ax, by);
        glVertex2i(ax, -by);
        glVertex2i(ay, bx);
        glVertex2i(-ay, -bx);
        glVertex2i(-ay, bx);
        glVertex2i(ay, -bx);

     }
}

三.优点

减少了k<1,k>1的分类,只需要计算1/8图形,将效率提高了一倍。

  • 5
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值