[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 ...
随机推荐
- linux程序机制入门
GCC环境 类debian系统运行 apt-get install build-essential 安装gcc环境. 编写c语言程序后,运行 gcc ./hello.c 会得到一个名为 a.out 的 ...
- MongoDB自学日记3——架构及HA
在对mongoDB的操作有了一定基础后,终于可以扯扯HA和架构这两个高大上的概念了.在这之前当然还得弄清楚mongoDB的Key feature:Sharding. 1. Sharding Shard ...
- C++中的new,operator new与placement new
以下是C++中的new,operator new与placement new进行了详细的说明介绍,需要的朋友可以过来参考下 new operator/delete operator就是new和 ...
- C语言实现常用数据结构——图
#include<stdio.h> #include<stdlib.h> #define SIZE 20 #define LENGTH(a) (sizeof(a)/sizeof ...
- 高并发 Nginx+Lua OpenResty系列(7)——Lua开发库json
JSON库 在进行数据传输时JSON格式目前应用广泛,因此从Lua对象与JSON字符串之间相互转换是一个非常常见的功能:目前Lua也有几个JSON库,如:cjson.dkjson.其中cjson的语法 ...
- SSM(六)JDK动态代理和Cglib动态代理
1.Cglib动态代理 目标类: package cn.happy.proxy.cglib; public class Service { public Service() { System.out. ...
- python安装Django常见错误
今天没事安装了一下python的web框架,Django.自己踩了一些雷,记录下来,留给后面的学者们,不要踩同样的雷了. 1.pip版本过低,安装不了,升级pip指令 python -m pip in ...
- Linux CentOS删除或重命名文件夹和文件的办法
Linux.CentOS操作系统下如何删除和重命名文件夹呢?办法如下: 一.Linux.CentOS下重命名文件和文件夹 mv:move 用移动文件命令就可以了,因为linux系统没有专门的重命名命令 ...
- MySQL数据库修改字段的长度
数据库版本:5.7.22 使用DDL语句:alter table 表名 modify 字段名 字符类型(长度) 例如: alter table db2.admin modify password );
- PCA(主成分分析)算法
设有\(m\)个指标,\(n\)个样本的原始数据 将原始数据按列组成矩阵 \(X _ { n \times m }\) 将\(X\) 的每一列进行中心化 求\(X\)的协方差矩阵\(\Sigma _ ...