第3章代码-光栅化与裁剪

时间:2022-07-25
本文章向大家介绍第3章代码-光栅化与裁剪,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

3.2 直线段光栅化

3.2.1 数值微分算法

void LineDDA(int x1, int y1, int xn, int yn)
{
    int dm=0; 
    if (abs(xn-x1)>= abs(yn-y1) 	//abs是求绝对值的函数
        dm=abs(xn-x1);	//x为计长方向
    else
        dm=abs(yn-y1); 	//y为计长方向
    float dx=(float)(xn-x1)/dm;	//当x为计长方向时,dx的值为1
    float dy=(float)(yn-y1)/dm;	//当y为计长方向时,dy的值为1
    float x=x1;
    float y=y1;
    for (int i=0; i< dm; i++)
    {
        // putpixel是绘点的伪代码函数,需要根据具体编程环境替换
        putpixel( (int)(x+0.5), (int)(y+0.5));  
        x+=dx;
        y+=dy;
    }
}

3.2.2 Bresenham画线法

void BresenhamLine(int x1, int y1, int xn, int yn)
{
	int x, y, dx, dy, d, d1, d2;
    dx = xn-x1;
    dy = yn-y1; 
    d = 2*dy - dx; 
    d1 = 2*dy;
	d2 = 2*(dy – dx);
	x = x1;
	y = y1;
	putpixel (x,y);
    while (x<xn)
	{
	   x++;
        if (d<0) 
            d += d1;
        else
        {
			y += 1;
			d += d2; 
		}
		putpixel (x,y);
    }
}

3.2.3 中点画线算法

void MidPointLine(int x1, int y1, int xn, int yn)
{
	int dx, dy, d1, d2, d, x, y;
	dx = xn - x1;
	dy = yn - y1;
	d = dx - 2dy;           //即原初值d1
	dt = 2dx - 2dy;         //原1-k
	db = -2dy;             //原-k
	x = x1; y = y1;
	putpixel(x, y);
	while (x < xn)
	{
		if (d < 0)
		{
			x++;
			y++;
			d += dt;
		}
		else
		{
			x++;
			d += db;
		}
		putpixel(x, y);
	}
}

3.3 圆弧光栅化

3.3.1 圆的对称性及其应用

//圆周上八对称点生成
void CirclePoints(int x0, int y0, int x, int y, int color)
{
    putpixel (x0+x, y0+y, color);
    putpixel (x0+y, y0+x, color);
    putpixel (x0-y, y0+x, color);
    putpixel (x0-x, y0+y, color);
    putpixel (x0-x, y0-y, color);
    putpixel (x0-y, y0-x, color);
    putpixel (x0+y, y0-x, color);
    putpixel (x0+x, y0-y, color);
}

3.3.2 Bresenham画圆算法

void Bres_Circle(int x0, int y0, double r)
{
    int x,y,d;
    x=0;
    y=(int)r;
    d=int(3-2*r);
    while(x<y)
    {
        CirclePoints( x0,y0,x,y, color);
         if(d<0)
             d+=4*x+6;
         else
         {
             d+=4*(x-y)+10;
             y--;
         }
         x++;
    }
    if(x==y)
        CirclePoints( x0,y0,x,y, color);
}

3.3.3 中点画圆算法

void MidPoint_Circle (int x0, int y0, int r, int color)
{
    int x=0;
    int y=r;
    int d=1- r;	//是d=1.25 – r取整后的结果
    CirclePoints(x0, y0, x, y, color);
    while ( x<y)
    {
        if (d<0) 
            d+=2*x+3; 
        else 
        {
            d+= 2(x-y) +5;
            y--;
        }
        x++;
        CirclePoints( x0, y0, x, y, color);
    }
}

3.4 区 域 填 充

3.4.2 种子填充算法

void FloodFill4 (int x, int y, int oldColor, int newColor)
{
    if (getpixel(x, y)==oldColor)
    {
        setpixel(x, y, newColor);
        FloodFill4(x-1, y, oldColor, newColor);
        FloodFill4(x, y+1, oldColor, newColor); 
        FloodFill4(x+1, y, oldColor, newColor); 
        FloodFill4(x, y-1, oldColor, newColor);
    }
}

void BoundaryFill4(int x, int y, int boundaryColor, int newColor)
{	
	int color = GetPixel(x,y);
	if(color!= newColor && color!= boundaryColor)
	{	
		 setpixel (x, y, newColor);
		 BoundaryFill4(x,y+1, boundaryColor, newColor);
		 BoundaryFill4(x,y-1,fill, boundaryColor, newColor);
		 BoundaryFill4(x-1,y,fill, boundaryColor, newColor);
		 BoundaryFill4(x+1,y,fill, boundaryColor, newColor);
	 }
}

3.7 裁 剪

3.7.2 直线裁剪

1. Cohen-Sutherland编码裁剪算法

// Cohen-Sutherland编码裁剪算法
# define LEFT 1
# define RIGHT 2
# define BOTTOM 4
# define TOP 8

void encode(float x, float y, float XL, float XR, float YB, float YT, int* code)
{
    int c = 0;
    if (x<XL)	 c = c|LEFT;
    else if (x>XR)	c = c|RIGHT;
    if (y<YB)		c = c|BOTTOM;
    else if(y>YT)	c = c|TOP;
    *code=c;
    return;
}

void C_S_LineClip(float *x1, float *y1, float *x2, float *y2, float XL,
float XR, float YB, float YT)
{
    int code1,code2,code;
    float x, y;
    encode(x1, y1, XL, XR, YB, YT, &code1);
    encode(x2, y2, XL, XR, YB, YT, &code1);
    while (code1!=0 || code2!=0)
    {
        if ((code1 & code2)!=0)	return;
        code = code1;
        if (code1==0)	code = code2;
        if ((LEFT & code)!=0) {	//线段与左边界相交
            x = XL;
            y = y1+(y2-y1)*(XL-x1)/(x2-x1);
        }
        else if ((RIGHT & code)!=0)	//线段与右边界相交
        {
            x = XR;
            y = y1+(y2-y1)*(XR-x1)/(x2-x1);
        }
        else if ((BOTTOM & code)!=0)	//线段与下边界相交
        {
            y = YB;
            x= x1+(x2-x1)*(YB-y1)/(y2-y1);
        }
        else if ((TOP & code)!=0)	//线段与上边界相交
        {
            y = YT;
            x= x1+(x2-x1)*(YT-y1)/(y2-y1);
        }
        if (code==code1){ 
            *x1 = x;	*y1 = y;
            encode(x, y, XL, XR, YB, YT, &code1);
        }
        else{ 
            *x2 = x;	*y2 = y;
            encode(x, y, XL, XR, YB, YT, &code2);
        }
    }
    return;
}

2.Liang-Barsky参数化裁剪算法

// Liang-Barsky参数化裁剪算法
//x1,y1,x2,y2为直线端点坐标,XL,XR,YB,YT为窗口边界信息
int L_B_LineClip(float *x1, float *y1, float *x2, float *y2, float XL,float XR, float YB, float YT)
{
    float u1 = 0, u2 = 1, dx = x2 – x1, dy;
    //u1为始点参数,初值0;u2为终点参数,初值1
    if (clipTest(-dx, x1-XL, &u1, &u2)) 	//计算左边界交点参数,更新u1,u2
        if (clipTest(dx, XR-x1, &u1, &u2))	//计算右边界交点参数,更新u1,u2
        {
            dy=y2-y1;
            if(clipTest(-dy, y1-YB, &u1, &u2))	//计算下边界交点参数,更新u1,u2
                if (clipTest(dy, YT-y1, &u1, &u2))//计算上边界交点参数,更新u1,u2
                {
                    if(u2 < 1){
                        *x2 = x1+u2*dx; 	//根据u2计算终点坐标
                        *y2 = y1+u2*dy;
                    }
                    if(u1 > 0){
                        *x1 += u1*dx;   	//根据u1计算始点坐标
                        *y1 += u1*dy;
                    }
                    return 1;
                }
        }
        return 0;
}
int clipTest(float p, float q,float* u1,float* u2)	//计算交点参数
{
    float r;
    int retVal = 1;
    if (p < 0){
        r= q/p;
        if (r>*u2)	 retVal = 0;
        else if (r>*u1)	*u1 = r;
    }
    else if (p > 0){
        r= q/p;
        if (r<*u1)	 retVal = 0;
        else if (r < *u2) *u2 = r;
    }
    else if (q < 0)  retVal = 0;
    return retVal;
}