OpenGL实现不规则区域填充算法

本文实例为大家分享了OpenGL实现不规则区域填充算法,供大家参考,具体内容如下

一、简单递归

利用Dfs实现简单递归填充。
核心代码:

// 简单深度搜索填充 (四连通)
void DfsFill(int x, int y)
{
 if (x < 0 || y < 0 || x>23 || y>23)
 {
 return;
 }
 if (a[x][y] == 0)
 {
 a[x][y] = 2;
 DfsFill(x - 1, y);
 DfsFill(x + 1, y);
 DfsFill(x, y - 1);
 DfsFill(x, y + 1);
 }
}

二、扫描线种子填充算法(四连通)

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]!=0)
 {
 return;
 }
 Pos first(x, y);
 s.push(first);
 while (!s.empty())
 {
 int rightX = 0;
 int leftX = 0;
 Pos cur = s.top();
 s.pop();
 a[cur.x][cur.y] = 2;
 // 遍历当前行
 for (int i = 1; i < 24; i++)
 {
  if (cur.x + i < 24)
  {
  if (a[cur.x + i][cur.y] == 0)
   a[cur.x + i][cur.y] = 2;
  else
  {
   rightX = cur.x + i - 1;
   break;
  }
  }
  if (i==23)
  {
  rightX = 23;
  }
 }
 for (int i = 1; i < 24; i++)
 {
  if (cur.x - i > -1)
  {
  if (a[cur.x - i][cur.y] == 0)
   a[cur.x - i][cur.y] = 2;
  else
  {
   leftX = cur.x - i + 1;
   break;
  }
  }
  if (i == 0)
  {
  leftX = 0;
  }
 }

 cout << leftX <<","<<rightX << endl;

 // 判断上行
 int upRightX = -1;
 for (int i = leftX;i<=rightX;i++)
 {
  if (a[i][cur.y+1]==0 && cur.y+1<24)
  {
  upRightX = i;
  }
 }
 if (upRightX!=-1)
 {
  Pos temPos(upRightX,cur.y+1);
  s.push(temPos);
 }

 // 判断下行
 int downRightX = -1;
 for (int i = leftX; i <= rightX; i++)
 {
  if (a[i][cur.y - 1] == 0 && cur.y - 1 >=0)
  {
  downRightX = i;
  }
 }
 if (downRightX != -1)
 {
  Pos temPos(downRightX, cur.y - 1);
  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(0), y(0) {};
};

stack<Pos> s;
int a[24][24] = { 0 };

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 = 200;//分段数
 float R = 10;//半径
 int i;
 if (color == 1)
 {
 glColor3f(1.0, 0.0, 0.0);
 }
 else if (color == 2)
 {
 glColor3f(0.0, 1.0, 0.0);
 }
 glBegin(GL_POLYGON);
 glVertex2f(x, y);
 for (i = 0; i <= n; i++)
 glVertex2f(R*cos(2 * PI / n * i)+x, R*sin(2 * PI / n * i)+y);
 glEnd();
 glPopMatrix();
}

// 绘制格线
void playMap()
{
 glColor3f(0.0, 0.0, 0.0);
 glBegin(GL_LINES);
 for (int i = 0; i < 600; i += 25)
 {
 glVertex2f(i, 0);
 glVertex2f(i, 600);
 }
 for (int j = 0; j < 600; j += 25)
 {
 glVertex2f(0, j);
 glVertex2f(600, j);
 }
 glEnd();
 for (int k = 0; k < 24; k++)
 {
 for (int l = 0; l < 24; l++)
 {
  if (a[k][l] == 1)
  {
  Drawtri(k * 25 + 12, l * 25 + 12,1);
  }
  else if (a[k][l] == 2)
  {
  Drawtri(k * 25 + 12, l * 25 + 12, 2);
  }
 }
 }
}

// 简单深度搜索填充 (四连通)
void DfsFill(int x, int y)
{
 if (x < 0 || y < 0 || x>23 || y>23)
 {
 return;
 }
 if (a[x][y] == 0)
 {
 a[x][y] = 2;
 DfsFill(x - 1, y);
 DfsFill(x + 1, y);
 DfsFill(x, y - 1);
 DfsFill(x, y + 1);
 }
}

// 扫描线种子填充算法(四连通)
void ScanFill(int x, int y)
{
 if (a[x][y]!=0)
 {
 return;
 }
 Pos first(x, y);
 s.push(first);
 while (!s.empty())
 {
 int rightX = 0;
 int leftX = 0;
 Pos cur = s.top();
 s.pop();
 a[cur.x][cur.y] = 2;
 // 遍历当前行
 for (int i = 1; i < 24; i++)
 {
  if (cur.x + i < 24)
  {
  if (a[cur.x + i][cur.y] == 0)
   a[cur.x + i][cur.y] = 2;
  else
  {
   rightX = cur.x + i - 1;
   break;
  }
  }
  if (i==23)
  {
  rightX = 23;
  }
 }
 for (int i = 1; i < 24; i++)
 {
  if (cur.x - i > -1)
  {
  if (a[cur.x - i][cur.y] == 0)
   a[cur.x - i][cur.y] = 2;
  else
  {
   leftX = cur.x - i + 1;
   break;
  }
  }
  if (i == 0)
  {
  leftX = 0;
  }
 }

 cout << leftX <<","<<rightX << endl;

 // 判断上行
 int upRightX = -1;
 for (int i = leftX;i<=rightX;i++)
 {
  if (a[i][cur.y+1]==0 && cur.y+1<24)
  {
  upRightX = i;
  }
 }
 if (upRightX!=-1)
 {
  Pos temPos(upRightX,cur.y+1);
  s.push(temPos);
 }

 // 判断下行
 int downRightX = -1;
 for (int i = leftX; i <= rightX; i++)
 {
  if (a[i][cur.y - 1] == 0 && cur.y - 1 >=0)
  {
  downRightX = i;
  }
 }
 if (downRightX != -1)
 {
  Pos temPos(downRightX, cur.y - 1);
  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 / 25;
 curY = (600 - y) / 25;
 a[curX][curY] = 1;
 glutPostRedisplay();//重绘窗口
 }
 if (button == GLUT_RIGHT_BUTTON && action == GLUT_DOWN)
 {
 curX = x / 25;
 curY = (600 - y) / 25;
 ScanFill(curX, curY);

 glutPostRedisplay();//重绘窗口
 }
}

void main(int argc, char** argv)
{
 glutInit(&argc, argv);
 glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
 glutInitWindowPosition(300, 100);
 glutInitWindowSize(600, 600);
 glutCreateWindow("mouse");

 init();
 glutDisplayFunc(displayFcn);

 glutMouseFunc(mouse);

 glutMainLoop();

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • OpenGL扫描线填充算法详解

    本文实例为大家分享了OpenGL扫描线填充算法,供大家参考,具体内容如下 说明 把最近一系列的图形学经典算法实现了一下.课业繁忙,关于该系列的推导随后再写.但是在注释里已经有较为充分的分析. 分情况讨论 注意对于横线需要特别讨论,但是对于垂直线却不必特别讨论.想一想为什么? 代码 #include <iostream> #include <GLUT/GLUT.h> #include <map> #include <vector> #include <l

  • OpenGL实现边缘填充算法

    边缘填充的思想:枚举每一条边,对这条边右边的像素进行求补操作,就是有填充则去掉,无填充就进行填充 #include <GL/gl.h> #include <GL/glut.h> #include <iostream> #include <cmath> #include <cstring> #include <string> using namespace std; int x[]= {10,70,70,60,40,30,20}; in

  • OpenGL实现不规则区域填充算法

    本文实例为大家分享了OpenGL实现不规则区域填充算法,供大家参考,具体内容如下 一.简单递归 利用Dfs实现简单递归填充. 核心代码: // 简单深度搜索填充 (四连通) void DfsFill(int x, int y) { if (x < 0 || y < 0 || x>23 || y>23) { return; } if (a[x][y] == 0) { a[x][y] = 2; DfsFill(x - 1, y); DfsFill(x + 1, y); DfsFill(

  • opengl实现直线扫描算法和区域填充算法

    本文实例为大家分享了opengl实现直线扫描算法和区域填充算法,供大家参考,具体内容如下 总体介绍 1.采用直线扫描算法绘制一条线段,直线由离散点组成 2.利用区域填充算法绘制多边形区域,区域由离散点组成 开发环境VS2012+OpenGL 开发平台 Intel core i5,Intel HD Graphics Family 设计思路 一.直线扫描算法 1.数值微分法(DDA) 已知过端点P0 (x0, y0), P1(x1, y1)的直线段L:y = kx + b,容易得知直线斜率为:k =

  • Python计算不规则图形面积算法实现解析

    这篇文章主要介绍了Python计算不规则图形面积算法实现解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 介绍:大三上做一个医学影像识别的项目,医生在原图上用红笔标记病灶点,通过记录红色的坐标位置可以得到病灶点的外接矩形,但是后续会涉及到红圈内的面积在外接矩形下的占比问题,有些外接矩形内有多个红色标记,在使用网上的opencv的fillPoly填充效果非常不理想,还有类似python计算任意多边形方法也不理想的情况下,自己探索出的一种效果还不

  • Android多边形区域递归种子填充算法的示例代码

    平面区域填充算法是计算机图形学领域的一个很重要的算法,区域填充即给出一个区域的边界(也可以是没有边界,只是给出指定颜色),要求将边界范围内的所有象素单元都修改成指定的颜色(也可能是图案填充).区域填充中最常用的是多边形填色,本文中我们就讨论几种多边形区域填充算法. 一.种子填充算法(Seed Filling) 如果要填充的区域是以图像元数据方式给出的,通常使用种子填充算法(Seed Filling)进行区域填充.种子填充算法需要给出图像数据的区域,以及区域内的一个点,这种算法比较适合人机交互方式

  • Android不规则封闭区域填充色彩的实例代码

    一.概述 在上一篇的叙述中,我们通过图层的方式完成了图片颜色的填充(详情请戳:Android不规则图像填充颜色小游戏),不过在着色游戏中更多的还是基于边界的图像的填充.本篇博客将详细描述. 图像的填充有2种经典算法. 一种是种子填充法. 种子填充法理论上能够填充任意区域和图形,但是这种算法存在大量的反复入栈和大规模的递归,降低了填充效率. 另一种是扫描线填充法. 注意:实际上图像填充的算法还是很多的,有兴趣可以去Google学术上去搜一搜. ok,下面先看看今天的效果图: ok,可以看到这样的颜

  • OpenGL中点Bresenham绘制直线算法

    本文实例为大家分享了OpenGL中点Bresenham绘制直线算法,供大家参考,具体内容如下 环境 macos xcode编译器 代码 #include <GLUT/GLUT.h> #include <iostream> #include<iostream> #include<cstdlib> #include<ctime> using namespace std; float wid = 400; //设置窗口的大小,约定窗口必须为正方形 fl

  • Android图像处理之泛洪填充算法

    泛洪填充算法(Flood Fill Algorithm) 泛洪填充算法又称洪水填充算法是在很多图形绘制软件中常用的填充算法,最熟悉不过就是windows paint的油漆桶功能.算法的原理很简单,就是从一个点开始附近像素点,填充成新的颜色,直到封闭区域内的所有像素点都被填充新颜色为止.泛红填充实现最常见有四邻域像素填充法,八邻域像素填充法,基于扫描线的像素填充方法.根据实现又可以分为递归与非递归(基于栈). 在介绍算法的三种实现方式之前,首先来看一下测试该算法的UI实现.基本思路是选择一张要填充

  • Android不规则图像填充颜色小游戏

    一.概述 近期群里偶然看到一哥们在群里聊不规则图像填充什么四联通.八联通什么的,就本身好学务实的态度去查阅了相关资料.对于这类着色的资料,最好的就是去搜索些相关app,根据我的观察呢,不规则图像填充在着色游戏里面应用居多,不过大致可以分为两种: 基于层的的填充 基于边界的填充 那么针对上述两种,我们会通过两篇博文来讲解,本篇就是叙述基于层的填充方式,那么什么基于层的填充方式呢?其实就是一张图实际上是由多个层组成的,每个层显示部分图像(无图像部分为透明),多层叠加后形成一张完整的图案,图层间是叠加

随机推荐