不规则区域的填充算法

一、简单递归

利用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] 不规则区域的填充算法的更多相关文章

  1. Open gl 的不规则图形的4联通种子递归填充和扫描线种子递归填充算法实现

    实验题目:不规则区域的填充算法 实验目的:验证不规则区域的填充算法 实验内容:利用VC与OpenGL,实现不规则区域的填充算法. 1.必做:实现简单递归的不规则区域填充算法. 2.选做:针对简单递归算 ...

  2. openGL实现图形学扫描线种子填充算法

    title: "openGL实现图形学扫描线种子填充算法" date: 2018-06-11T19:41:30+08:00 tags: ["图形学"] cate ...

  3. 【GIS新探索】算法实现在不规则区域内均匀分布点

    1 概要 在不规则区域内均匀分布点,这个需求初看可能不好理解.如果设想一下需求场景就比较简单了. 场景1:在某个地区范围内,例如A市区有100W人口,需要将这100W人口在地图上面相对均匀的标识出来. ...

  4. CGA填充算法之种子填充算法

    CGA填充算法之种子填充算法 平面区域填充算法是计算机图形学领域的一个很重要的算法,区域填充即给出一个区域的边界 (也可以是没有边界,只是给出指定颜色),要求将边界范围内的所有象素单元都修改成指定的颜 ...

  5. 种子填充算法描述及C++代码实现

    项目需要看了种子填充算法,改进了算法主要去除面积小的部分.种子填充算法分为两种,简单的和基于扫描线的方法,简单的算法如下描述(笔者针对的是二值图像): (1)从上到下,从左到有,依次扫描每个像素: ( ...

  6. 图像处理之泛洪填充算法(Flood Fill Algorithm)

    泛洪填充算法(Flood Fill Algorithm) 泛洪填充算法又称洪水填充算法是在很多图形绘制软件中常用的填充算法,最熟悉不过就是 windows paint的油漆桶功能.算法的原理很简单,就 ...

  7. 漫水填充算法 - cvFloodFill() 实现

    前言 漫水填充算法是用来标记一片区域的:设置一个种子点,然后种子点附近的相似点都被填充同一种颜色. 该算法应用性很广,比如目标识别,photoshop 的魔术棒功能等等,是填充类算法中应用最为广泛的一 ...

  8. 图像处理------泛洪填充算法(Flood Fill Algorithm) 油漆桶功能

    泛洪填充算法(Flood Fill Algorithm) 泛洪填充算法又称洪水填充算法是在很多图形绘制软件中常用的填充算法,最熟悉不过就是 windows paint的油漆桶功能.算法的原理很简单,就 ...

  9. OpenCV空洞填充算法

    讨论帖: http://bbs.csdn.net/topics/391542633 在Matlab下,使用imfill可以很容易的完成孔洞填充操作,感觉这是一个极为常用的方法,然而不知道为什么Op ...

随机推荐

  1. 百度 Echarts 地图表 js 引用路径

    使用地图表格,除了需echarts,还需zrender,自行下载JS文件:   目标,做成这样的效果:http://echarts.baidu.com/doc/example/map3.html   ...

  2. Layui 是一款采用自身模块规范编写的国产前端UI框架(5600个Star)

    采用自身模块规范编写的前端UI框架,遵循原生HTML/CSS/JS的书写形式,极低门槛,拿来即用. http://www.layui.com Layui 是一款采用自身模块规范编写的国产前端UI框架, ...

  3. 教你做一个牛逼的DBA(在大数据下)

    一.基本概念 大数据量下,搞mysql,以下概念需要先达成一致 1)单库,不多说了,就是一个库 2)分片(sharding),水平拆分,用于解决扩展性问题,按天拆分表 3)复制(replication ...

  4. 八大排序算法 JAVA实现 亲自测试 可用!

    今天很高兴 终于系统的实现了八大排序算法!不说了 直接上代码 !代码都是自己敲的, 亲测可用没有问题! 另:说一下什么是八大排序算法: 插入排序 希尔排序 选择排序 堆排序 冒泡排序 快速排序 归并排 ...

  5. spring_three

    转账案例 坐标: ; } } 创建增强类Logger.java /** * 用于记录日志的工具类,它里面提供了公共的代码 */ @Component("logger") @Aspe ...

  6. linux运维人员常用150个命令汇总

    命令 功能说明 线上查询及帮助命令(2个) man 查看命令帮助,命令的词典,更复杂的还有info,但不常用. help 查看Linux内置命令的帮助,比如cd命令. 文件和目录操作命令(18个) l ...

  7. 【记录】Field required a single bean, but 2 were found:

    重构遇到个小问题,记录下: 错误信息: *************************** APPLICATION FAILED TO START ************************ ...

  8. 【mysql5.7】远程无法连接设置

    版本5.7 系统:ubuntu16.04 配置文件位置(apt安装): 1.链接设置 注释掉在/etc/mysql/mysql.conf.d/mysqld.cnf里面的bind-address = 1 ...

  9. 在java项目启动时就执行某操作

    在java启动时大概有四种,此处只介绍3种 1.在启动的方法上使用通过@PostConstruct方法实现初始化bean进行操作 2.通过bean实现InitializingBean接口 @Overr ...

  10. Jenkins Email Extension插件模板

    Jenkins Email Extension插件模板 <!DOCTYPE html> <html> <head> <meta charset="U ...