不规则区域的填充算法

一、简单递归

利用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. 关于JDK和JRE的一些总结

    一.关于JDK和JRE JDK (Java Development Kit)即java开发工具,包括JER及代码编译器(javac).文档注释器(JavaDoc).代码调试器(Java Debugge ...

  2. python中的函数名,闭包,迭代器

    一.函数名 函数名是一个变量,但它是一个特殊的变量,与括号配合可以执行函数的变量,单纯print()出的是一个内存地址. def func(): print('你说你有点难追') print(func ...

  3. vue+TS(CLI3)

    1.用CLI3创建项目 查看当前CLI的版本,如果没有安装CLI3的  使用npm install --global vue-cli来安装CLI 安装好CLI 可以创建项目了 使用vue create ...

  4. asp.net core系列 66 Dapper介绍--Micro-ORM

    一.概述 目前对于.net的数据访问ORM工具很多,EF和EF Core是一个重量级的框架.最近在搭建新的项目架构,来学习一下轻量级的数据访问ORM工具Dapper.Dapper支持SQL Serve ...

  5. Storm —— 集群环境搭建

    一.集群规划 这里搭建一个3节点的Storm集群:三台主机上均部署Supervisor和LogViewer服务.同时为了保证高可用,除了在hadoop001上部署主Nimbus服务外,还在hadoop ...

  6. (1)Linux文件系统的目录组成

    记忆秘诀:BBDEH OPRLM TLSUV 宝贝的恩惠 欧派入联盟 偷了suv,19   目录 英文释义 简写 详解 1 /   根目录 整个文件系统的唯一根目录 2 /bin Binary 普通命 ...

  7. centos7搭建基于SAMBA的网络存储

    学习目标: 通过本实验理解Linux系统下SAMBA服务器和客户端的配置,实现客户机可自动挂载服务端的共享存储. 操作步骤: 1.  SAMBA服务器搭建 2.  SAMBA客户端配置 参考命令:   ...

  8. Vue兄弟组件(非父子组件)状态共享与传值

      前言:网上大部分文章写的有点乱,很少有讲得易懂的文章. 所以,我写了篇在我能看得懂的基础上又照顾到大家的文章 =.= 作者:X1aoYE 备注:此文原创,转载请注明~  内容里的<br> ...

  9. HDU 1811:Rank of Tetris(并查集+拓扑排序)

    http://acm.hdu.edu.cn/showproblem.php?pid=1811 Rank of Tetris Problem Description   自从Lele开发了Rating系 ...

  10. Win10自动更新关闭方法

    一.为什么很多人会选择禁用Win10自动更新? 1.win10自动更新定义: Win 10的自动更新功能,即 Windows Update.这项功能本意是为一些软件.漏洞等提供更新服务.一般来说,只要 ...