计算机图形学(第四版)学习总结 一

图元算法

画线

  1. DDA算法
    简单的求点算法,下面直接给出实现
void DDALine(const screenPt& start,const screenPt& end)
{
	int dx = end.x - start.x;
	int dy = end.y - start.y;
	int steps;		//步长
	float xIncrement, yIncrement;		//x,y增长值
	float x = start.x, y = start.y;
	if (abs(dx)>abs(dy))
		steps = abs(dx);
	else
		steps = abs(dy);
	xIncrement = float(dx) / float(steps);
	yIncrement = float(dy) / float(steps);

	DrawPoint(x, y);
	for(int k = 0; k < steps; ++k)
	{
		x += xIncrement;
		y += yIncrement;
		DrawPoint(Round(x), Round(y));
	}
}

Bresenham算法

光栅化画线算法

void BreseLine(screenPt&& start,screenPt&& end,const colorPt& pt)
{
	glColor3f(pt.r,pt.g,pt.b);
	int x, y;
	if (start.x>end.x)
	{
		std::swap(start.x, end.x);
		std::swap(start.y, end.y);
	}
	if (start.x == end.x)	//竖直线
	{
		if (start.y > end.y)
		{
			std::swap(start.y, end.y);
		}
		x = start.x;
		y = start.y;
		while (y<end.y)
		{
			DrawPoint(x, y);
			y++;
		}
		return;
	}
	if (start.y == end.y)	//水平线
	{
		x = start.x;
		y = start.y;
		while (x<end.x)
		{
			DrawPoint(x, y);
			x++;
		}
		return;
	}
	int dx = end.x - start.x;
	int dy = end.y - start.y;
	float m = float(dy) / float(dx);
	int p;
	int twoDy = 2 * dy, twoMinusDx = 2 * (dy - dx), twoDx = 2 * dx, twoMinusDy = 2 * (dx - dy);
	int twoSum = 2 * (dy + dx);
	
	if (m>0&&m<1)
	{
		p = 2 * dy - dx;
		x = start.x;
		y = start.y;
		DrawPoint(x, y);
		while (x < end.x)
		{
			x ++;
			if (p < 0)
			{
				p += twoDy;
			}
			else
			{
				y ++;
				p += twoMinusDx;
			}
			DrawPoint(x, y);
		}
	}
	if(m>1)
	{
		p = 2 * dx;
		x = start.x;
		y = start.y;
		DrawPoint(x, y);
		while (y < end.y)
		{
			y++;
			if (p < 0)
			{
				p += twoDx;
			}
			else
			{
				x++;
				p += twoMinusDy;
			}
			DrawPoint(x, y);
		}
	}
	if (m>-1&&m<0)
	{
		p = 2 * dy + dx;
		x = start.x;
		y = start.y;
		DrawPoint(x, y);
		while (x<end.x)
		{
			x++;
			if (p>=0)
			{
				p += twoDy;
			}
			else
			{
				y--;
				p += twoSum;
			}
			DrawPoint(x, y);
		}
	}
	if (m<=-1)
	{
		p = 2 * dx - dy;
		x = start.x;
		y = start.y;
		DrawPoint(x, y);
		while (y>end.y)
		{
			y--;
			if (p>=0)
			{
				p -= twoDx;
			}
			else
			{
				x++;
				p -= twoSum;
			}
			DrawPoint(x, y);
		}
	}
}

具体的计算步骤见笔记(这里直接计算了四种情况下的点位置,也可以用对称性只计算第一象限且m为正的直线)

中点画圆算法

void cricleMiddle(screenPt&& centerPt,int radius)
{
	int p = 1 - radius;
	screenPt pt(0,radius);
	void circlePlotPoints(screenPt & pt, screenPt & center);
	circlePlotPoints(pt, centerPt);
	while (pt.x<pt.y)
	{
		++pt.x;
		if (p<0)
		{
			p += (2 * pt.x + 1);
		}
		else
		{
			--pt.y;
			p += (2 * pt.x + 1 - 2 * pt.y);
		}
		circlePlotPoints(pt, centerPt);
	}
}
void circlePlotPoints(screenPt& pt,screenPt &center)
{
	DrawPoint(center.x + pt.x, center.y + pt.y);
	DrawPoint(center.x - pt.x, center.y + pt.y);
	DrawPoint(center.x + pt.x, center.y - pt.y);
	DrawPoint(center.x - pt.x, center.y - pt.y);
	DrawPoint(center.x + pt.y, center.y + pt.x);
	DrawPoint(center.x - pt.y, center.y + pt.x);
	DrawPoint(center.x + pt.y, center.y - pt.x);
	DrawPoint(center.x - pt.y, center.y - pt.x);
}

中点画椭圆算法

void ellipseMiddle(screenPt&& centerPt,int Rx,int Ry)
{
	glColor3f(0.3, 0.2, 0.3);
	int Rx2 = Rx * Rx;
	int Ry2 = Ry * Ry;
	int twoRx2 = 2 * Rx2;
	int twoRy2 = 2 * Ry2;
	int p;
	screenPt pt(0, Ry);
	int px = 0;
	int py = twoRx2 * pt.y;
	void ellipsePlotPoints(screenPt & pt, screenPt & center);
	ellipsePlotPoints(pt, centerPt);
	//第一部
	p = Round(Ry2 - Rx2 * Ry + 0.25 * Rx2);
	while (px<py)
	{
		++pt.x;
		px += twoRy2;
		if (p < 0)
			p += (Ry2 + px);
		else
		{
			--pt.y;
			py -= twoRx2;
			p += (Ry2 + px - py);
		}
		ellipsePlotPoints(pt, centerPt);
	}
	//第二部分
	p = Round(Ry2 * (pt.x + 0.5) * (pt.x + 0.5) + Rx2 * (pt.y - 1) * (pt.y - 1) - Rx2 * Ry2);
	while (pt.y>0)
	{
		--pt.y;
		py -= twoRx2;
		if (p>0)
		{
			p += (Rx2 - py);
		}
		else
		{
			++pt.x;
			px += twoRy2;
			p += (Rx2 - py + px);
		}
		ellipsePlotPoints(pt, centerPt);
	}
}
void ellipsePlotPoints(screenPt& pt,screenPt& center)
{
	DrawPoint(center.x + pt.x, center.y + pt.y);
	DrawPoint(center.x - pt.x, center.y + pt.y);
	DrawPoint(center.x + pt.x, center.y - pt.y);
	DrawPoint(center.x - pt.x, center.y - pt.y);
}

中点画抛物线算法

void parabolicCurveMiddle(screenPt&& center,float m)
{
	glColor3f(0.3, 0.6, 0.2);
	float a = abs(m);
	int p = a - 1 / 2;
	screenPt pt(0,0);
	void parabolicCurvePlotPoints(screenPt & pt, screenPt & center, float m);
	parabolicCurvePlotPoints(pt,center,m);
	//第一区域
	while ((2*a*pt.x)<1)
	{
		p += (2 * a * pt.x + 3 * a);
		if (p>=0)
		{
			p += (-1);
			++pt.y;
		}
		pt.x++;
		parabolicCurvePlotPoints(pt, center, m);
	}
	p = (a*a*(pt.x+1/2)*(pt.x+1/2) - (pt.y+1));
	while ((center.y+pt.y)<=Height)
	{
		if (p<0)
		{
			p += (2 * pt.x * a + 2 * a - 1);
			++pt.x;
		}
		else
		{
			p += (-1);
		}
		++pt.y;
		parabolicCurvePlotPoints(pt, center, m);
	}
}
void parabolicCurvePlotPoints(screenPt& pt, screenPt& center, float a)
{
	if (a>0)
	{
		DrawPoint(center.x + pt.x, center.y + pt.y);
		DrawPoint(center.x - pt.x, center.y + pt.y);
	}
	else if(a<0)
	{
		DrawPoint(center.x + pt.x, center.y - pt.y);
		DrawPoint(center.x - pt.x, center.y - pt.y);
	}
	
}

结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值