控制台“图形学”(1)

本文介绍了作者通过阅读计算机图形学书籍后,使用C++在控制台环境中创建图形类,利用控制台字符模拟像素来显示图形。文章详细讲解了如何建立图形类的基本架构,并实现了一个paint函数。作者提到了DDA算法,一种用于绘制直线的简单算法,解释了算法的步骤,并给出了测试代码。后续内容将涉及更多图形学基础算法。
摘要由CSDN通过智能技术生成

近来因一些事情从图书馆借了些 计算机图形学的书籍瞅瞅,感觉不少东西还是蛮有意思的。

没事就用c++写个小类,用控制台的字符模仿像素,简单地实现下!

一张16*16的图片,仿出来就是 unsigned char *image = new unsigned char [16*16],这点接受后,我们就开始建立这个图形类的基本架构。

class MyGL
{
public:
	MyGL(int width = 16, int height =16);
	~MyGL();
private:
	unsigned char *image_;
	int width_, height_;
};
MyGL::MyGL(int width /*= 16*/, int height /*=16*/)
:width_(width), height_(height)
{
	if (width_ == 0 || height_ == 0)
		++width_, ++height_;
	image_ = new unsigned char[width_*height_];
	for (int i = 0; i < width_*height_; ++i)
	{
		image_[i] = ' ';
	}
}

MyGL::~MyGL()
{
	delete [] image_;
}

要把图形显示出来,因此添加一个paint函数。注意包含iostream头文件。

void MyGL::paint()
{
	for (int i = 0; i < width_*height_; ++i)
	{
		if (i%width_ == 0 && i > 0)
		{
			std::cout << std::endl;
		}
		std::cout << image_[i] << " ";
	}
	std::cout << std::endl;
}

因为每一行之间有间隔,所以这里每“像素”后添加一个空格从而使x、y俩方向更协调。

这是我们的image都还是空的。

下面添加一个私有函数setPixel来设置特定位置的像素。这个函数在后面会被反复调用。
void MyGL::setPixel(int x, int y, unsigned char c /*= 'X'*/)
{
	if (x <= 0 || x > width_ || y <= 0 || y > height_)
		return;
	image_[(x - 1) + (y - 1)*width_] = c;
}
到目前为止,所有的准备工作都已完成。

大家可以借这个框架自己添加画线,画矩形,画圆,画椭圆 等函数,可以和我给出的函数做一些比较。

测试代码先给出。

int main()
{
	MyGL g(30,30);

//     此函数根据自己情况调整。
//	g.drawRect(15, 10, 5, 10);
	g.paint();
	std::cin.get();
	return 0;
}

后面的部分会涉及到图形学的一些基本算法。

先给出比较简单的DDA算法。

DDA算法主要是根据直线公式y = kx + b来推导出来的。

算法的具体思路如下:

1. 输入直线的起点、终点;

2. 计算x方向的间距:△X和y方向的间距:△Y。

3. 确定单位步进。这里确保单位步进未跨过x,y其中某一方向的一个像素的单位。步进取小,则要求步数取大。

取MaxSteps = max(△X,△Y); 若△X>=△Y,则X方向的步进为单位步进,X方向步进一个单位,Y方向步进△Y/MaxSteps;否则相反。

在后面曲线部分更要注意到这一点。

4. 设置第一个点的像素值

5. 令循环初始值为1,循环次数为MaxSteps,定义变量x,y,执行以下计算:
a. x增加一个单位步进,y增加一个单位步进
b. 设置位置为(x,y)的像素值

函数如下:

//DDA算法

void MyGL::drawLine(int x0, int y0, int xEnd, int yEnd, unsigned char c /*= '+'*/)
{
	int dx = xEnd - x0;
	int dy = yEnd - y0;

	int steps = (std::abs(dx) > std::abs(dy)) ? std::abs(dx) : std::abs(dy);
	double xIncrement = static_cast<double>(dx) / steps;
	double yIncrement = static_cast<double>(dy) / steps;

	double x = static_cast<double>(x0), y = static_cast<double>(y0);
	setPixel(round(x), round(y), c);
	for (int i = 0; i < steps; ++i)
	{
		x += xIncrement;
		y += yIncrement;
		setPixel(round(x), round(y), c);
	}
}
第一部分完。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值