计算机图形学06:中点Bresenham画圆(并填充边界,例如:边界用红色,内部用绿色填充)

在这里插入图片描述

作者:非妃是公主
专栏:《计算机图形学》
博客地址:https://blog.csdn.net/myf_666
个性签:顺境不惰,逆境不馁,以心制境,万事可成。——曾国藩
在这里插入图片描述

文章目录

  • 专栏推荐
  • 专栏系列文章
  • 一、算法原理
  • 二、OpenGL代码实现
  • 三、圆的内部填充
  • 四、效果展示
  • the end……

专栏推荐

专栏名称 专栏地址
软件工程 专栏——软件工程
计算机图形学 专栏——计算机图形学
操作系统 专栏——操作系统
软件测试 专栏——软件测试
机器学习 专栏——机器学习
数据库 专栏——数据库
算法 专栏——算法

专栏系列文章

文章名称 文章地址
直线生成算法(DDA算法) 计算机图形学01——DDA算法
中点BH算法绘制直线 计算机图形学02——中点BH算法
改进的中点BH算法 计算机图形学03——改进的中点BH算法
中点Bresenham画椭圆 计算机图形学04——中点BH绘制椭圆
中点BH算法绘制任意斜率直线 计算机图形学05——中点BH算法绘制任意斜率的直线
中点Bresenham画圆 计算机图形学06——中点BH算法画圆
有效边表法的多边形扫描转换 计算机图形学07——有效边表法绘制填充多边形
中点BH算法绘制抛物线 100 x = y 2 100x = y^2 100x=y2 计算机图形学08——中点BH绘制抛物线
二维观察之点的裁剪 计算机图形学09——二维观察之点裁剪
二维观察之线的裁剪 计算机图形学10——二维观察之线裁剪
二维观察之多边形的裁剪 计算机图形学11——二维观察之多边形裁剪
二维图形的几何变换 计算机图形学12——二维图形几何变换
三维图形的几何变换 计算机图形学13——三维图形几何变换
三维图形的投影变换 计算机图形学14——三维图形投影变换

计算机图形学(英语:computer graphics,缩写为CG)是研究计算机在硬件和软件的帮助下创建计算机图形的科学学科,是计算机科学的一个分支领域,主要关注数字合成与操作视觉的图形内容。虽然这个词通常被认为是指三维图形,事实上同时包括了二维图形以及影像处理。


一、算法原理

主要思路为:将圆分为8个部分,通过堆成就可以得到各个部分的坐标,这样我们只需要绘制圆的 1 8 \frac{1}{8} 81 ,就可以实现对整个圆的绘制,如下:

计算机图形学06:中点Bresenham画圆(并填充边界,例如:边界用红色,内部用绿色填充)_第1张图片

计算机图形学06:中点Bresenham画圆(并填充边界,例如:边界用红色,内部用绿色填充)_第2张图片

计算机图形学06:中点Bresenham画圆(并填充边界,例如:边界用红色,内部用绿色填充)_第3张图片

计算机图形学06:中点Bresenham画圆(并填充边界,例如:边界用红色,内部用绿色填充)_第4张图片

计算机图形学06:中点Bresenham画圆(并填充边界,例如:边界用红色,内部用绿色填充)_第5张图片

由于,d中存在一个1.25这个小数,不利于硬件进行计算,故将模型进行优化,如下:

计算机图形学06:中点Bresenham画圆(并填充边界,例如:边界用红色,内部用绿色填充)_第6张图片

整体算法步骤如下:

计算机图形学06:中点Bresenham画圆(并填充边界,例如:边界用红色,内部用绿色填充)_第7张图片


二、OpenGL代码实现

OpenGL代码实现如下:

// 中点Bh算法绘制圆
void   MidBhcircle(int  r) {
	int  x = 0, y = r, d = 1 - r;
	glBegin(GL_POINTS);
	while (x <= y) {
		glVertex2i(x, y);    glVertex2i(y, x);   // 八分画圆
		glVertex2i(-y, x);   glVertex2i(-x, y);
		glVertex2i(-x, -y);  glVertex2i(-y, -x);
		glVertex2i(y, -x);   glVertex2i(x, -y);

		if (d < 0)					// 根据d的值更新下一个点的坐标
			d += 2 * x + 3;
		else {						// d<0时要y--,即点在圆的内部
			d += 2 * (x - y) + 5;
			y--;
		}
		x++;						// x默认+1
	}
	glEnd();
}

三、圆的内部填充

主体思路:从原点向外扩充,利用一个队列作为数据结构,然后向外扩充(泛洪)。值得注意的是:

  • 由于像素点的像素值是存储在显存中的,不好获取。所以我们采用一个vector数组进行存储,记录当前像素是否已经访问过。
  • 判断该点是否在圆内,是利用了一个isInRound函数进行判断的。

具体代码如下:

// 判断点pnt是否在以半径r做出的圆内
bool isInRound(Point& pnt, int r) {
	double d = sqrt(pow(pnt.x, 2) + pow(pnt.y, 2));
	if (d < r)
		return true;
	else
		return false;
}
// 椭圆或圆的边界填充
void fillRound(int r) {
	vector<vector<int>> con(3 * r, vector<int>(3 * r, 0));
	Point pnt = Point(0, 0);
	queue<Point> que;
	que.push(pnt);
	con[r][r] = 1;							// 用于记录当前像素点是否已经填充
	glColor3f(0.0f, 1.0f, 0.0f);			// 设置颜色为绿色进行填充
	glBegin(GL_POINTS);
	while (!que.empty()) {					// 如果队列不为空,就继续填充
		Point tmp = que.front();			// 填充队列种的第一个元素
		que.pop();
		Point tmp1 = Point(tmp.x + 1, tmp.y);
		Point tmp2 = Point(tmp.x - 1, tmp.y);
		Point tmp3 = Point(tmp.x, tmp.y + 1);
		Point tmp4 = Point(tmp.x, tmp.y - 1);
		if (isInRound(tmp1, r) && con[tmp1.x + r][tmp1.y + r] == 0) {	// 如果在圆内,而且之前也没有访问过,那么加入到队列,并标记
			que.push(tmp1);
			con[tmp1.x + r][tmp1.y + r] = 1;
		}
		if (isInRound(tmp2, r) && con[tmp2.x + r][tmp2.y + r] == 0) {
			que.push(tmp2);
			con[tmp2.x + r][tmp2.y + r] = 1;
		}
		if (isInRound(tmp3, r) && con[tmp3.x + r][tmp3.y + r] == 0) {
			que.push(tmp3);
			con[tmp3.x + r][tmp3.y + r] = 1;
		}
		if (isInRound(tmp4, r) && con[tmp4.x + r][tmp4.y + r] == 0) {
			que.push(tmp4);
			con[tmp4.x + r][tmp4.y + r] = 1;
		}
		glVertex2i(tmp.x, tmp.y);		// 用泛洪方式进行画点
	}
	glEnd();
}

四、效果展示

中点BH算法画圆效果如下:

计算机图形学06:中点Bresenham画圆(并填充边界,例如:边界用红色,内部用绿色填充)_第8张图片

内部用绿色填充后,绘制效果如下:

计算机图形学06:中点Bresenham画圆(并填充边界,例如:边界用红色,内部用绿色填充)_第9张图片


the end……

中点Bresenham画圆(并填充边界,例如:边界用红色,内部用蓝色填充)的内容到这里就要结束啦~~到此既是缘分,欢迎您的点赞评论收藏关注我,不迷路,我们下期再见!!

我是Cherries,一位计算机科班在校大学生,写博客用来记录自己平时的所思所想!
内容繁杂,又才疏学浅,难免存在错误,欢迎各位大佬的批评指正!
我们相互交流,共同进步!

:本文由非妃是公主发布于https://blog.csdn.net/myf_666,转载请务必标明原文链接:https://blog.csdn.net/myf_666/article/details/128166947

你可能感兴趣的:(计算机图形学,图形渲染,c++,OpenGL,算法,数据结构)