[OpenGL] 不规则区域的填充算法
不规则区域的填充算法
一、简单递归
利用Dfs实现简单递归填充。
核心代码:
// 简单深度搜索填充 (四连通)
void DfsFill(int x, int y)
{
if (x < || y < || x> || y>)
{
return;
}
if (a[x][y] == )
{
a[x][y] = ;
DfsFill(x - , y);
DfsFill(x + , y);
DfsFill(x, y - );
DfsFill(x, y + );
}
}
二、扫描线种子填充算法(四连通)
1. 种子点(x,y)入栈。
2. 栈顶元素(x,y)出栈作为种子点。
3. 从种子点(x,y)开始沿着扫描线向左右两个方向逐个像素进行填充,直到到达边界像素为止。
4. 将上述填充区段的左右端点的横坐标分别记为xleft和xright.
5. 在与当前扫描线相邻的上下两条扫描线的[xleft,xright]范围内进行检查,
看看是否全部为边界像素或已填充像素,若存在着非边界且未填充的像素,那么将该区段的最右端像素作为种子点入栈。
// 扫描线种子填充算法(四连通)
void ScanFill(int x, int y)
{
if (a[x][y]!=)
{
return;
}
Pos first(x, y);
s.push(first);
while (!s.empty())
{
int rightX = ;
int leftX = ;
Pos cur = s.top();
s.pop();
a[cur.x][cur.y] = ;
// 遍历当前行
for (int i = ; i < ; i++)
{
if (cur.x + i < )
{
if (a[cur.x + i][cur.y] == )
a[cur.x + i][cur.y] = ;
else
{
rightX = cur.x + i - ;
break;
}
}
else
{
rightX = ;
}
}
for (int i = ; i < ; i++)
{
if (cur.x - i > -)
{
if (a[cur.x - i][cur.y] == )
a[cur.x - i][cur.y] = ;
else
{
leftX = cur.x - i + ;
break;
}
}
else
{
leftX = ;
}
} cout << leftX <<","<<rightX << endl; // 判断上行
int upRightX = -;
for (int i = leftX;i<=rightX;i++)
{
upRightX = -;
if (a[i][cur.y+]== && cur.y+<)
{
upRightX = i;
}
if (upRightX != -)
{
Pos temPos(upRightX, cur.y + );
s.push(temPos);
}
} // 判断下行
int downRightX = -;
for (int i = leftX; i <= rightX; i++)
{
downRightX = -;
if (a[i][cur.y - ] == && cur.y - >=)
{
downRightX = i;
}
if (downRightX != -)
{
Pos temPos(downRightX, cur.y - );
s.push(temPos);
}
} }
}
完整代码:
#include <cmath>
#include <stack>
#include "gl/glut.h"
#include "iostream"
using namespace std; #define PI 3.14 struct Pos
{
int x;
int y;
Pos(int mx, int my) :x(mx), y(my) {};
Pos() :x(), y() {};
}; stack<Pos> s;
int a[][] = { }; void init(void)
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glMatrixMode(GL_PROJECTION);//设置投影矩阵
gluOrtho2D(0.0, 600.0, 0.0, 600.0);//二维视景区域
glPointSize(12.0f);
}
// 画棋子
void Drawtri(int x,int y,int color)
{
double n = ;//分段数
float R = ;//半径
int i;
if (color == )
{
glColor3f(1.0, 0.0, 0.0);
}
else if (color == )
{
glColor3f(0.0, 1.0, 0.0);
}
glBegin(GL_POLYGON);
glVertex2f(x, y);
for (i = ; i <= n; i++)
glVertex2f(R*cos( * PI / n * i)+x, R*sin( * PI / n * i)+y);
glEnd();
glPopMatrix();
} // 绘制格线
void playMap()
{
glColor3f(0.0, 0.0, 0.0);
glBegin(GL_LINES);
for (int i = ; i < ; i += )
{
glVertex2f(i, );
glVertex2f(i, );
}
for (int j = ; j < ; j += )
{
glVertex2f(, j);
glVertex2f(, j);
}
glEnd();
for (int k = ; k < ; k++)
{
for (int l = ; l < ; l++)
{
if (a[k][l] == )
{
Drawtri(k * + , l * + ,);
}
else if (a[k][l] == )
{
Drawtri(k * + , l * + , );
}
}
}
} // 简单深度搜索填充 (四连通)
void DfsFill(int x, int y)
{
if (x < || y < || x> || y>)
{
return;
}
if (a[x][y] == )
{
a[x][y] = ;
DfsFill(x - , y);
DfsFill(x + , y);
DfsFill(x, y - );
DfsFill(x, y + );
}
} // 扫描线种子填充算法(四连通)
void ScanFill(int x, int y)
{
if (a[x][y]!=)
{
return;
}
Pos first(x, y);
s.push(first);
while (!s.empty())
{
int rightX = ;
int leftX = ;
Pos cur = s.top();
s.pop();
a[cur.x][cur.y] = ;
// 遍历当前行
for (int i = ; i < ; i++)
{
if (cur.x + i < )
{
if (a[cur.x + i][cur.y] == )
a[cur.x + i][cur.y] = ;
else
{
rightX = cur.x + i - ;
break;
}
}
else
{
rightX = ;
}
}
for (int i = ; i < ; i++)
{
if (cur.x - i > -)
{
if (a[cur.x - i][cur.y] == )
a[cur.x - i][cur.y] = ;
else
{
leftX = cur.x - i + ;
break;
}
}
else
{
leftX = ;
}
} cout << leftX <<","<<rightX << endl; // 判断上行
int upRightX = -;
for (int i = leftX;i<=rightX;i++)
{
upRightX = -;
if (a[i][cur.y+]== && cur.y+<)
{
upRightX = i;
}
if (upRightX != -)
{
Pos temPos(upRightX, cur.y + );
s.push(temPos);
}
} // 判断下行
int downRightX = -;
for (int i = leftX; i <= rightX; i++)
{
downRightX = -;
if (a[i][cur.y - ] == && cur.y - >=)
{
downRightX = i;
}
if (downRightX != -)
{
Pos temPos(downRightX, cur.y - );
s.push(temPos);
}
} }
} void displayFcn(void)
{
glClear(GL_COLOR_BUFFER_BIT);
playMap();
glFlush();
} void mouse(GLint button, GLint action, GLint x, GLint y)
{
int curX, curY;
if (button == GLUT_LEFT_BUTTON && action == GLUT_DOWN)
{
curX = x / ;
curY = ( - y) / ;
a[curX][curY] = ;
glutPostRedisplay();//重绘窗口
}
if (button == GLUT_RIGHT_BUTTON && action == GLUT_DOWN)
{
curX = x / ;
curY = ( - y) / ;
ScanFill(curX, curY); glutPostRedisplay();//重绘窗口
}
} void main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowPosition(, );
glutInitWindowSize(, );
glutCreateWindow("mouse"); init();
glutDisplayFunc(displayFcn); glutMouseFunc(mouse); glutMainLoop(); }
[OpenGL] 不规则区域的填充算法的更多相关文章
- Open gl 的不规则图形的4联通种子递归填充和扫描线种子递归填充算法实现
实验题目:不规则区域的填充算法 实验目的:验证不规则区域的填充算法 实验内容:利用VC与OpenGL,实现不规则区域的填充算法. 1.必做:实现简单递归的不规则区域填充算法. 2.选做:针对简单递归算 ...
- openGL实现图形学扫描线种子填充算法
title: "openGL实现图形学扫描线种子填充算法" date: 2018-06-11T19:41:30+08:00 tags: ["图形学"] cate ...
- 【GIS新探索】算法实现在不规则区域内均匀分布点
1 概要 在不规则区域内均匀分布点,这个需求初看可能不好理解.如果设想一下需求场景就比较简单了. 场景1:在某个地区范围内,例如A市区有100W人口,需要将这100W人口在地图上面相对均匀的标识出来. ...
- CGA填充算法之种子填充算法
CGA填充算法之种子填充算法 平面区域填充算法是计算机图形学领域的一个很重要的算法,区域填充即给出一个区域的边界 (也可以是没有边界,只是给出指定颜色),要求将边界范围内的所有象素单元都修改成指定的颜 ...
- 种子填充算法描述及C++代码实现
项目需要看了种子填充算法,改进了算法主要去除面积小的部分.种子填充算法分为两种,简单的和基于扫描线的方法,简单的算法如下描述(笔者针对的是二值图像): (1)从上到下,从左到有,依次扫描每个像素: ( ...
- 图像处理之泛洪填充算法(Flood Fill Algorithm)
泛洪填充算法(Flood Fill Algorithm) 泛洪填充算法又称洪水填充算法是在很多图形绘制软件中常用的填充算法,最熟悉不过就是 windows paint的油漆桶功能.算法的原理很简单,就 ...
- 漫水填充算法 - cvFloodFill() 实现
前言 漫水填充算法是用来标记一片区域的:设置一个种子点,然后种子点附近的相似点都被填充同一种颜色. 该算法应用性很广,比如目标识别,photoshop 的魔术棒功能等等,是填充类算法中应用最为广泛的一 ...
- 图像处理------泛洪填充算法(Flood Fill Algorithm) 油漆桶功能
泛洪填充算法(Flood Fill Algorithm) 泛洪填充算法又称洪水填充算法是在很多图形绘制软件中常用的填充算法,最熟悉不过就是 windows paint的油漆桶功能.算法的原理很简单,就 ...
- OpenCV空洞填充算法
讨论帖: http://bbs.csdn.net/topics/391542633 在Matlab下,使用imfill可以很容易的完成孔洞填充操作,感觉这是一个极为常用的方法,然而不知道为什么Op ...
随机推荐
- QtZint编译过程记录(要使用 QTMAKE_CFLAGS += /TP 参数)
1,下载zint后,在zint-2.4.3\win32\vcx目录下找到zlib.props和libpng.props文件,分别改为zlib和libpng的源码目录.这2个开源库最好是找工程中使用的版 ...
- PHP PSR4自动加载代码赏析
第一部分是引入自动加载配置文件 1.入口文件:autoload.php里面没什么东西,就是导入ComposerAutoloader主题文件,一般由一个复杂的名字,不过不用担心就是机器随机生成的一个码而 ...
- python常用数据结构(1)
python中有四种最常用的数据结构,分别是列表(list),字典(dict),集合(set)和元组(tuple) 下面简单描述下它们的区别和联系 1.初始化 不得不说,python数据结构的初始化比 ...
- 通往Google之路:***
*** & BBR 安装 系统支持:CentOS 6+, Debian 7+, Ubuntu 12+ 内存要求:≥128M --- 前提 满足以上要求的VPS服务器一台 安装基础命令工具:yu ...
- Python 爬虫从入门到进阶之路(七)
在之前的文章中我们一直用到的库是 urllib.request,该库已经包含了平常我们使用的大多数功能,但是它的 API 使用起来让人感觉不太好,而 Requests 自称 “HTTP for Hum ...
- Android 即时通讯开发小结(二)
<Android 即时通讯开发小结>基于IM Andriod 开发的各种常见问题,结合网易云信即时通讯技术的实践,对IM 开发做一个全面的总结. 相关推荐阅读:. Android 即时通讯 ...
- 高并发IM系统架构优化实践
互联网+时代,消息量级的大幅上升,消息形式的多元化,给即时通讯云服务平台带来了非常大的挑战.高并发的IM系统背后究竟有着什么样的架构和特性? 以上内容由网易云信首席架构师内部分享材料整理而成 相关阅读 ...
- Python自学day-10
一.多进程 程序中, 大量的计算占用CPU资源,而IO操作不占CPU资源.当程序需要进行大量计算时,Python采用多线程运行的速度不一定比单线程快多少.但是当程序是IO密集型的,那就应该使用多线程来 ...
- 【JVM】虚拟机初见-运行时数据区图解
本文是听咕泡XX公开课视频整理的笔记,较书本更为总结,感谢. 计算机模型(汇编知识):数据集(数据).指令集(操作指令,+-等).控制集(分支循环) JVM运行时的数据区: 程序计数器(每个线程都有) ...
- Redis 密码设置和查看密码(二)
Redis 密码设置和查看密码 redis没有实现访问控制这个功能,但是它提供了一个轻量级的认证方式,可以编辑redis.conf配置来启用认证. 1.初始化Redis密码: 在配置文件中有个参数: ...