绘制直线段一般需要进行栅格化(又叫光栅化)处理:将几何数据经过一系列变换后转换为像素呈现在显示设备上。
数值微分算法本质为用数值方法解微分方程,即通过同时对x和y个增加一个小增量,计算下一步的x,y的值。
void Line_DDA (CDC *pDC,int xs,int ys,int xe,int ye, COLORREF color)
{
int t; float x,y,k=(float)(ye-ys)/(xe-xs);
if( fbs(k) < 1){
if(xe<xs){
t=xe,xe=xs,xs=t,t=ye,ye=ys,ys=t;
}
y=ys;
for(x=xs;x<=xe;x++)
pDC->SetPixel(x,y,color), y=y+k;
}else{
if(ye<ys){
t=xe,xe=xs,xs=t,t=ye,ye=ys,ys=t;
}
x=xs;
for(y=ys;y<=ye;y++)
pDC->SetPixel(x,y,color),x=x+1/k;
}
}
用离散量表示连续量引起的图形失真,叫走样;减少走样现象的技术和方法称为反走样。
反走样处理:
1) 垂直线刷子:适用于直线斜率在[-1, 1]之间。把线刷子放置成垂直方向,刷子中点对准直线 一端点,然后让刷子中心往直线的另一端移动,即可“刷出”具有一定宽度的线段。
CDC *pDC=GetDC();
dx=xe-xs; dy=ye-ys; //( xs,ys),(xe,ye)为直线段的两个端点坐标
e=-dx; y=ys; dxx=dx+dx; dyy=dy+dy;
for(x=xs;x<=xe;x++){
pDC->SetPixel(x,y,RGB(0,0,0));
pDC->SetPixel(x-1,y,RGB(0,0,0));
pDC->SetPixel(x+1,y,RGB(0,0,0));
if(e>=0)
y=y++, e=e-dxx; e=e+dyy;
}
2) 水平线刷子:适用于直线斜率不在[1, 1]之间。把线刷子放置成水平方向,刷子中点对准直 线一端点并往直线的另一端移动,可“刷出”具有一定宽度的线。
3)方形刷子:把正方形(边宽为指定线宽)的中心沿直线做平行移动,即可获得具有线宽的线条。
void Arc_Para(CDC *pDC,int xc,int yc,int r,COLORREF color)
{
int x,y;float d=1/(2*3.14*r);
for(float t=0;t<6.283;t=t+d)
{
x=x0+r*cos(t);
y=y0+r*sin(t);
pDC->SetPixel (x,y,color);
}
}
void Circle_DDA(CDC *pDC,int x0,int y0,int r,COLORREF color)
{
int x=0, y=r, d=1-r;
while( y>=x ){
pDC->SetPixel (x+x0,y+y0,color);
pDC->SetPixel (-x+x0,y+y0,color);
pDC->SetPixel (-x+x0,-y+y0,color);
pDC->SetPixel (x+x0,-y+y0,color);
pDC->SetPixel (y+x0,x+y0,color);
pDC->SetPixel (-y+x0,x+y0,color);
pDC->SetPixel (-y+x0,-x+y0,color);
pDC->SetPixel (y+x0,-x+y0,color);
if(d<0)
d=d+2*x+3;
else
d=d+2*(x-y)+5, y--;
x++;
}
}
void Circle_W (CDC *pDC,int x0,int y0,int r,COLORREF color, int w)
{
int x,y; float d=1/(2*r*3.14);
for(float t=0;t<6.3;t=t+d){
x=x0+r*cos(t);
y=y0+r*sin(t);
float dt=1.0/(3.14*w);
for(float t=0;t<6.3;t=t+dt){
xx=x+w/2*cos(t);
yy=y+w/2*cos(t);
pDC->SetPixel(xx,yy,color);
}
}
}