2012.10.11 周四

计算机图形学

*********直线段的扫描转换算法*********

DDA算法:

算法分析参考《计算机图形学实用教程》的41页。

void DDALine(int x1,int y1,int x2,int y2,CDC *pDC)
{
int xLength=x2-x1;
int yLength=y2-y1;
int steps=abs(xLength)>abs(yLength)?abs(xLength):abs(yLength);
assert(steps!=0);
float xDis=xLength/(float)steps;
float yDis=yLength/(float)steps;
float x=x1; //如果将这里的x、y声明为int会画出不符合要求的直线
float y=y1;
pDC->SetPixel((int)x,(int)y,RGB(255,0,0));
for(int i=0;i<steps;i++)
{
x+=xDis;
y+=yDis;
pDC->SetPixel((int)(x+0.5),(int)(y+0.5),RGB(255,0,0));
}

}

中点画线法(Midpoint Line Drawing Algorithm):

        过点(x0,y0)、(x1, y1)的直线段L的方程式为F(x, y)=ax+by+c=0,其中,a=y0-y1, b=x1-x0, c=x0y1-x1y0,欲判断中点M在Q点的上方还是下方,只要把M代入F(x,y),并判断它的符号即可。为此,我们构造判别式:
d=F(M)=F(xp+1, yp+0.5)=a(xp+1)+b(yp+0.5)+c
     当d<0时,M在L(Q点)下方,取P2为下一个象素;
     当d>0时,M在L(Q点)上方,取P1为下一个象素;
     当d=0时,选P1或P2均可,约定取P1为下一个象素;

算法分析参考《计算机图形学实用教程》的43页,本算法改进过程中有两个重要思想:

1、增量法递推计算d.

2、d的增量都是整数,只是初始值包含小数.为了消除小数运算,取2d代替d.

void CLineDemoView::MidpointLine(CPoint p1,CPoint p2,CDC *pDC)
{
CPoint pointStart=p1,pointEnd=p2;
if(p1.x>p2.x)
{
pointStart=p2;
pointEnd=p1;
}
int a=pointStart.y-pointEnd.y,b=pointEnd.x-pointStart.x;
int x=pointStart.x,y=pointStart.y;
int d,deta1,deta2,cases,xDis=1,yDis=1;
if(a*b<0&&(a+b)*b>0)// 0 <= k < 1
{
cases=0;
d=a*2+b;
deta1=a*2;
deta2=(a+b)*2;
}else if ((a+b)*b<=0)// k >= 1
{
cases=1;
d=a+b*2;
deta1=(a+b)*2;
deta2=b*2;

}else if((a-b)*b<=0)// -1 <= k < 0
{
cases=2;
d=a<<1;
deta1=(a-b)<<1;
deta2=a<<1;
}else if((a-b)*b>0)// k <= -1
{
cases=3;
d=a-b<<2;
deta1=(-b)<<1;
deta2=(a-b)<<1;
}else
{
MessageBox("K error!");
return;
}


int steps=(abs(pointEnd.y-pointStart.y)>abs(pointEnd.x-pointStart.x))?abs(pointEnd.y-pointStart.y):abs(pointEnd.x-pointStart.x);
for(int i=0;i<steps;i++)
{


if(d>=0)
{
switch(cases)
{
case 0:
x++;
break;
case 1:
x++;
y++;
break;
case 2:
x++;
y--;
break;
case 3:
y--;
break;
}
d+=deta1;
}else{
switch(cases)
{
case 0:
x++;
y++;
break;
case 1:
y++;
break;
case 2:
x++;
break;
case 3:
x++;
y--;
break;
}
d+=deta2;
}
pDC->SetPixel(x,y,RGB(255,0,0));
}
}

Bresenham画线法(B算法):

void CCgLSCDemoView::BresenhamLine(int x1, int y1, int x2, int y2, CDC *pDC) {
int dx = abs(x2 - x1),
dy = abs(y2 - y1),
yy = 0; // yy=0表示斜率K<1,即每次x方向+1


if (dx < dy) {
yy = 1;
swap(&x1, &y1); //将45~90度转换成0~45度
swap(&x2, &y2);
swap(&dx, &dy);
}  
int ix = (x2 - x1) > 0 ? 1 : -1,
iy = (y2 - y1) > 0 ? 1 : -1,
cx = x1,
cy = y1,
d1 = dy << 1,
vd2 = - dx << 1, //d2 =(dy - dx)*2,而d+=d2相当于d-=vd2
d = - dx;
while (cx != x2) {
d += d1;
if (d>0) {
cy += iy;
d += vd2;
}
if(yy) // if k > 1
pDC->SetPixel(cy,cx,RGB(0,255,0));
else
pDC->SetPixel(cx,cy,RGB(0,255,0));
cx += ix;
}
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值