计算机图形学-抛物线的中点Bresenham算法

抛物线 f ( x ) = a x 2 f(x)=ax^2 f(x)=ax2的中点Bresenham算法

语言:matlab

画图:plot

1 抛物线的特征

通常定义抛物线为到一条直线(准线)和直线外一点(焦点)距离相等的点的集合。这里只讨论顶点为原点,沿纵坐标轴对称且开口向上的情况。而对于其他情况可以通过图形的平移和旋转等线性变换得到。其描述方程如下:
F ( x , y ) = y − a x 2 ( a > 0 ) F(x,y)=y-ax^2(a>0) F(x,y)=yax2(a>0)
与椭圆不同,抛物线是无边界的非封闭图形,若要在屏幕上绘制,必须给定坐标范围,以绘制指定抛物线的一个片段。可以在函数中设置参数 x m xm xm,则横坐标约束其范围为 [ − x m , x m ] [-xm,xm] [xm,xm]

抛物线关于纵坐标轴对称,故只需绘制其第一象限内的点,第二象限中的点可以通过对称得到。

为确定最大位移方向,考虑抛物线的斜率范围。在第一象限,其上一点 ( x , y ) (x,y) (x,y)处的斜率为:
k ( x ) = ∂ F ( x , y ) ∂ x = 2 a x ∈ [ 0 , + ∞ ) k(x)=\frac{\partial F(x,y)}{\partial x}=2ax \in [0,+\infty) k(x)=xF(x,y)=2ax[0,+)

又由于斜率的变化率为:
d k ( x ) d x = d ( 2 a x ) d x = 2 a > 0 \frac {dk(x)}{dx}=\frac {d(2ax)}{dx}=2a>0 dxdk(x)=dxd(2ax)=2a>0

所以在第一象限内,抛物线斜率从0开始随 x x x递增至正无穷。用斜率为1的点对图形进行划分。容易解出,当斜率为1时, x = 1 2 a x=\frac {1}{2a} x=2a1。只需沿 x x x轴绘制图形,其 0 < x < 1 2 a 0<x<\frac {1}{2a} 0<x<2a1时,最大位移方向为 x x x方向; 1 2 a < x < x m \frac {1}{2a}<x<xm 2a1<x<xm时,最大位移方向为 y y y方向。

2 算法推导过程

假定当前与抛物线距离最近者已确定为 P ( x i , y i ) P(x_i,y_i) P(xi,yi)那么在抛物线前部分时,下一候选点是 P d ( x i + 1 , y i ) P_d(x_i+1,y_i) Pd(xi+1,yi) P d ( x i + 1 , y i + 1 ) P_d(x_i+1,y_i+1) Pd(xi+1,yi+1);而在抛物线的后半部分时,下一候选点是 P l ( x i , y i + 1 ) P_l(x_i,y_i+1) Pl(xi,yi+1) P r ( x i + 1 , y i + 1 ) P_r(x_i+1,y_i+1) Pr(xi+1,yi+1)。仍然使用中点进行判别候选点。

2.1 推导前半部分的抛物线绘制公式

对于 0 < x < 1 2 a 0<x<\frac {1}{2a} 0<x<2a1:构造判别式
d l i = F ( x i + 1 , y i + 0.5 ) = y i + 0.5 − a ( x i + 1 ) 2 d_{li}=F(x_i+1,y_i+0.5)=y_i+0.5-a(x_i+1)^2 dli=F(xi+1,yi+0.5)=yi+0.5a(xi+1)2
d l i ≥ 0 d_{li}\ge 0 dli0,中点在抛物线上方,应选取 P d ( x i + 1 , y i ) P_d(x_i+1,y_i) Pd(xi+1,yi),反之选取 P u ( x i + 1 , y i + 1 ) P_u(x_i+1,y_i+1) Pu(xi+1,yi+1)

误差项递推:

d l i ≥ 0 d_{li}\ge 0 dli0时,应计算:
d l ( i + 1 ) = F ( x i + 2 , y i + 0.5 ) = y i + 0.5 − a ( x i + 2 ) 2 = d l i + a [ ( x i + 1 ) 2 − ( x i + 2 ) 2 ] = d l i − 2 a x i − 3 a d_{l(i+1)}=F(x_i+2,y_i+0.5)\\ =y_i+0.5-a(x_i+2)^2\\ =d_{li}+a[(x_i+1)^2-(x_i+2)^2]\\ =d_{li}-2ax_i-3a\\ dl(i+1)=F(xi+2,yi+0.5)=yi+0.5a(xi+2)2=dli+a[(xi+1)2(xi+2)2]=dli2axi3a
d l i < 0 d_{li}< 0 dli<0时,应计算:
d l ( i + 1 ) = F ( x i + 2 , y i + 1.5 ) = y i + 1.5 − a ( x i + 2 ) 2 = d l i − 2 a x i − 3 a + 1 d_{l(i+1)}=F(x_i+2,y_i+1.5)\\ =y_i+1.5-a(x_i+2)^2\\ =d_{li}-2ax_i-3a+1\\ dl(i+1)=F(xi+2,yi+1.5)=yi+1.5a(xi+2)2=dli2axi3a+1
计算判别式的初始值。弧起点为 ( 0 , 0 ) (0,0) (0,0),因此第一个中点为 ( 1 , 0.5 ) (1,0.5) (1,0.5),对应的判别式为:
d l 0 = y 0 + 0.5 − a ( x 0 + 1 ) 2 = 0.5 − a d_{l0}=y_0+0.5-a(x_0+1)^2=0.5-a dl0=y0+0.5a(x0+1)2=0.5a

2.2 推导后半部分的抛物线绘制公式

对于 1 2 a < x < x m \frac {1}{2a}<x<xm 2a1<x<xm:构造判别式
d r i = F ( x i + 0.5 , y i + 1 ) = y i + 1 − a ( x i + 0.5 ) 2 d_{ri}=F(x_i+0.5,y_i+1)=y_i+1-a(x_i+0.5)^2 dri=F(xi+0.5,yi+1)=yi+1a(xi+0.5)2
d r i ≥ 0 d_{ri}\ge 0 dri0,中点在抛物线(左)上方,应选取 P l ( x i , y i + 1 ) P_l(x_i,y_i+1) Pl(xi,yi+1),反之选取 P r ( x i + 1 , y i + 1 ) P_r(x_i+1,y_i+1) Pr(xi+1,yi+1)

误差项递推:

d r i ≥ 0 d_{ri}\ge 0 dri0时,应计算:
d r ( i + 1 ) = F ( x i + 0.5 , y i + 2 ) = y i + 2 − a ( x i + 0.5 ) 2 = d r i + 1 d_{r(i+1)}=F(x_i+0.5,y_i+2)\\ =y_i+2-a(x_i+0.5)^2\\ =d_{ri}+1\\ dr(i+1)=F(xi+0.5,yi+2)=yi+2a(xi+0.5)2=dri+1
d r i < 0 d_{ri}< 0 dri<0时,应计算:
d r ( i + 1 ) = F ( x i + 1.5 , y i + 2 ) = y i + 2 − a ( x i + 1.5 ) 2 = d r i − 2 a x i − 2 a + 1 d_{r(i+1)} =F(x_i+1.5,y_i+2)\\ =y_i+2-a(x_i+1.5)^2\\ =d_{ri}-2ax_i-2a+1\\ dr(i+1)=F(xi+1.5,yi+2)=yi+2a(xi+1.5)2=dri2axi2a+1
计算判别式的初始值。弧起点横坐标为 ⌈ 1 2 a ⌉ \lceil \frac{1}{2a} \rceil 2a1,对应的判别式为:
d r 0 = y 0 + 1 − a ( x 0 + 0.5 ) 2 = 1 − a ⌈ 1 2 a ⌉ − 0.25 a d_{r0}=y_0+1-a(x_0+0.5)^2=1-a\lceil \frac{1}{2a} \rceil-0.25a dr0=y0+1a(x0+0.5)2=1a2a10.25a

算法代码(matlab)
function DrawBresenhamCurve(a,xm)
  div=0.5/a;
  x=0,y=0;
  d_pre=0.5-a;
  d_post=1-a*ceil(0.5/a)-0.25*a;
  while x<=xm
    plot(x,y);
    hold on;
    plot(-x,y);
    hold on;
    if x<div
      tmp=-2*a*x-3*a;
      x++;
      if d_pre<0
        y++;
        d_pre=d_pre+tmp+1;
      else
        d_pre=d_pre+tmp;
      endif
    else
      tmp=-2*a*x-2*a+1;
      y++;
      if d_post<0
        d_post=d_post+1;
      else
        d_post=d_post+tmp;
        x++;
      endif
    endif
  endwhile
end

运行情况:

测试代码:

a=0.01;
xm=100;
DrawBresenhamCurve(a,xm);
X=linspace(-xm,xm,1000);
Y=a.*X.^2.;
plot(X,Y);
grid on;

运行结果(点为算法生成的点集,曲线为所拟合的实际曲线):
在这里插入图片描述

  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值