区域填充之扫描线算法
利用相邻像素之间的连贯性,提高算法效率。根据多边形内部点的连续性知:一条扫描线与多边形的交点中,入点和出点之间所有点都是多边形的内部点。所以,对所有的扫描线填充入点到出点之间所有的点就可填充多边形。
(1)处理对象:非自交多边形(边与边之间除了顶点外无其它交点)
判断扫描线上的点是否在多边形之内,根据多边形区域连续性,分为3个步骤:
– 求出扫描线与多边形所有边的交点;
– 把这些交点的x坐标值以升序排列;
– 对每一对交点间的区域进行填充。
– 第三个步骤是从奇数个交点出发到偶数个交点。如右图,对y=8的扫描线排序x坐标得到的表是(2,4,9,13),然后对交点2与4之间、9与13之间的所有象素点进行填充。
(2)几点规则:
边界上的象素:“左闭右开”,“下闭上开”(将左边界和下边界的点算为内部,而将右边界和上边界算为外部)
顶点:“上开下闭”。
(3)几种特殊情况:
1.扫描线交于一顶点,共享的两条边分另处于扫描线的两边,这时交点只取一个,如扫描线y=3,该点被填充一次。
2. 共享交点的两条边处于扫描线的上方,这时交点取二个,如扫描线y=1,该点被填充一次。
3.共享交点的两条边处于扫描线的下方,这时交点取0个,如扫描线y=9,无交点,不填充。
4.水平边在算法中不起任何作用,可不考虑。
活性边表(提高效率):
为了减少求交的计算量,要利用一条边与相继的两条扫描线的交点的连贯性。在处理一条扫描线时只对活性边(与它相交的多边形的边)进行求交运算。把交点按x增加方向存在一个链表(活性边表)中。
活性边:与当前扫描线相交的边。
活性边表(AEL):按交点x的增量顺序存放在一个链表中,该链表称作活性边表(AEL)。
源程序:
#include <stdio.h>
#include <GL/glut.h>
static int n;
static int y_max;
static int x_max;
typedef struct Point {int x;int y;
} Point1;
static Point1 seed;
Point *InitPoint() {n = 8;Point1 *tran = (Point*)malloc(n * sizeof(struct Point));tran[0].x = 10; tran[0].y = 10;tran[1].x = 90; tran[1].y = 10;tran[2].x = 90; tran[2].y = 60;tran[3].x = 140; tran[3].y = 60;tran[4].x = 140; tran[4].y = 160;tran[5].x = 80; tran[5].y = 160;tran[6].x = 80; tran[6].y = 70;tran[7].x = 10; tran[7].y = 70;seed.x = 50; seed.y = 50;return tran;
}void setEdge(int x, int y, int **NumGroup) {NumGroup[x][y] = 1;
}
void MidpointLine(int x0, int y0, int x1, int y1, int **NumGroup)
{int a, b, d1, d2, d, x, y; float m;if (x1<x0) {d = x0, x0 = x1, x1 = d;d = y0, y0 = y1, y1 = d;}a = y0 - y1, b = x1 - x0;if (b == 0)m = -1 * a * 100;elsem = (float)a / (x0 - x1); x = x0, y = y0;setEdge(x, y, NumGroup);if (m >= 0 && m <= 1) {d = 2 * a + b; d1 = 2 * a, d2 = 2 * (a + b);while (x<x1) {if (d <= 0) {x++, y++, d += d2;}else {x++, d += d1;}setEdge(x, y, NumGroup);}}else if (m <= 0 && m >= -1) {d = 2 * a - b; d1 = 2 * a - 2 * b, d2 = 2 * a;while (x<x1) {if (d>0) { x++, y--, d += d1; }else {x++, d += d2;}setEdge(x, y, NumGroup);}}else if (m>1) {d = a + 2 * b; d1 = 2 * (a + b), d2 = 2 * b;while (y<y1) {if (d>0) {x++, y++, d += d1;}else {y++, d += d2;}setEdge(x, y, NumGroup);}}else {d = a - 2 * b; d1 = -2 * b, d2 = 2 * (a - b);while (y>y1) {if (d <= 0) {x++, y--, d += d2;}else {y--, d += d1;}setEdge(x, y, NumGroup);}}
}void print(int **NumGroupMaxtrx, int x_num, int y_num) {int i;int j;for (i = 0; i < x_num; i++) {for (j = 0; j < y_num; j++) {//如果是边界点if (NumGroupMaxtrx[i][j] == 1) {glVertex2i(i, j);}}}
}
int **InitPointMatrixByPoint(Point *p) {int i;y_max = p[0].x;x_max = p[0].y;for (i = 0; i < n; i++) {if (p[i].x>x_max)x_max = p[i].x;if (p[i].y > y_max)y_max = p[i].y;}y_max++; x_max++;int **NumGroup_Matrix = (int**)malloc(x_max * sizeof(int *));for (i = 0; i < x_max; i++) {NumGroup_Matrix[i] = (int*)malloc(y_max * sizeof(int));}int j;for (i = 0; i < x_max; i++) {for (j = 0; j < y_max; j++) {//取值有-1,0,1三种情况分别表示无效,内点和边界点NumGroup_Matrix[i][j] = -1;}}for (i = 0; i < n; i++) {if (i != n - 1)MidpointLine(p[i].x, p[i].y, p[i + 1].x, p[i + 1].y, NumGroup_Matrix);elseMidpointLine(p[i].x, p[i].y, p[0].x, p[0].y, NumGroup_Matrix);}return NumGroup_Matrix;
}
struct STACKNODE {Point point;struct STACKNODE *next;
};
typedef struct STACKNODE *PtrToNode;
typedef struct STACKNODE *Stack;
Stack createStack() {Stack stack = (STACKNODE*)malloc(sizeof(struct STACKNODE));stack->next = NULL;return stack;
}
void *Push(Stack stack, Point point) {PtrToNode tempNode = (STACKNODE*)malloc(sizeof(struct STACKNODE));tempNode->point.x = point.x;tempNode->point.y = point.y;tempNode->next = stack->next;stack->next = tempNode;return 0;
}
Point *PopAndTop(Stack stack) {PtrToNode ptr = stack->next;stack->next = stack->next->next;return &ptr->point;
}
int IsNull(Stack s) {if (s->next == NULL)return 1;elsereturn 0;
}
void scanLineFixArea(int **numGroupMatrix) {Stack s = createStack();Push(s, seed);Point *tempPoint;Point left, right;int i;while (!IsNull(s)) {tempPoint = PopAndTop(s);glVertex2i(tempPoint->x, tempPoint->y); numGroupMatrix[tempPoint->x][tempPoint->y] = 0;left.y = tempPoint->y;right.y = tempPoint->y;left.x = tempPoint->x;right.x = tempPoint->x;while (numGroupMatrix[left.x][left.y] != 1) {glVertex2i(left.x, left.y); numGroupMatrix[left.x][left.y] = 0;left.x--;}while (numGroupMatrix[right.x][right.y] != 1) {glVertex2i(right.x, right.y); numGroupMatrix[right.x][right.y] = 0;right.x++;}for (i = right.x; i >= left.x; i--) {if (numGroupMatrix[i][right.y + 1] == -1) {right.y++;right.x = i;Push(s, right);break;}}right.y = tempPoint->y;for (i = right.x; i >= left.x; i--) {if (numGroupMatrix[i][right.y - 1] == -1) {right.y--;right.x = i;Push(s, right);break;}}}
}
void ProcessExcute() {//1.初始化待填充区域的边界线段端点和种子坐标Point *p = InitPoint();//2.栅格化边界线段端点表示的待填充区域到像素阵列数组里int **numGroupMatrix = InitPointMatrixByPoint(p);//3.用扫描线算法进行区域填充:scanLineFixArea(numGroupMatrix);
}
void display() {glClear(GL_COLOR_BUFFER_BIT);glColor3d(1.0, 1.0, 1.0);glBegin(GL_POINTS);ProcessExcute();glEnd();glFlush();;
}
void Init() {glClearColor(0, 0, 0, 0);glMatrixMode(GL_PROJECTION);glLoadIdentity();//定义裁剪区域gluOrtho2D(0, 240, 0, 240);
}
int main(int argc, char *argv[]) {glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowPosition(300, 300);glutInitWindowSize(400, 400);glutCreateWindow("扫描线区域填充算法");Init();glutDisplayFunc(display);glutMainLoop();system("pause");return 0;
}
要运行此代码,需要在编译器上自行导入OpenGL库哦!
区域填充之扫描线算法相关推荐
- 计算机图形学生活应用,计算机图形学的应用实例(计算机图形作业).doc
计算机图形学的应用实例(计算机图形作业).doc 计算机图形学大作业 计算机图形学的应用实例 班级: 学号: 姓名: 2012-03-12 计算机图形学的应用实例 一.计算机图像学简介 计算机图形学是 ...
- 计算机图形学复习(自用)
文章目录 1. dll文件与lib文件的区别与作用 :one: 各种文件 :two: 内存结构 2. 相机拍摄景物模型 3. OpenGL支持绘制的图元 GL_POINTS GL_LINE_STRI ...
- 计算机图形学课堂笔记
计算机图形学 第一章绪论 计算机图形学主要研究内容:计算机中图形的表示方法,以及利用计算机进行图形的计算.处理和显示的相关原理和算法 计算机图形学之父:Ivan Sutherland 1950年第一台 ...
- 图形学日记(一)光栅图形学
本文主要是概念的总结,并不会讲述具体的算法,如需查看详细内容,请点击相关博客. 1.基础概念: 光栅化(图形的扫描转换):确定最佳逼近图形的像素集合,并用指定属性写像素的过程. 一维图形的表示:在不考 ...
- 计算机图形学期末复习笔记
计图期末根据老师ppt整理期末复习笔记. 第二章 图形系统综述 1.视频显示设备 刷新式CRT(阴极射线管) 光栅扫描显示器 随机扫描显示器 彩色CRT监视器 直视存储管 平板显示器 三维观察设备 ...
- 计算机图形学基础教程学习总结
目录 第一章 绪论 计算机图形学概念 图形和图像的区别 主要研究内容 第二章 光栅图形学 光栅.理想直线与图形扫描转换的含义 DDA方法 中点画线法 Bresenham算法 中点画圆法 多边形的扫描转 ...
- 洪水填充算法_区域填充算法和多边形填充的扫描线算法
本文主要介绍几种区域填充算法,重点解释多边形的扫描线填充算法,最后实现了多边形填充算法,包括在附录文件中.在参考[5]中,作者详细介绍了一系列区域填充算法,可以查看相应网页.代码的下载地址为:http ...
- 【CV系列】扫描线算法区域填充
DATE:2019-5-19 1.参考 算法系列之十二:多边形区域填充算法--扫描线种子填充算法 扫描线种子填充算法 扫描线算法完全解析 Line Sweep Technique [翻译]扫描线算法( ...
- 《计算机图形学》实验报告区域填充扫描线算法
一.实验目的和要求 熟悉光栅图形学中的区域填充扫描线算法: 利用区域填充算法绘制多边形区域,区域由离散点组成: 应用OpenGL进行区域填充. 二.实验内容 用区域填充直线扫描法填充绘制六边形: 初始 ...
最新文章
- Debug enterprise search menu
- php 数组按个数分组,如何在PHP中基于内部数组键对数组进行分组?
- 【Anychat】理解POCO
- 今天博客园肿了吗?希望团队修复一下
- Linux 镜像文件ISO下载
- JAVA - JDK 1.8 API 帮助文档-中文版
- python + selenium 自动化测试框架
- html基本标记练习钱塘湖春行,《钱塘湖春行》练习题
- YARN队列优先级分配策略
- 【软件工程】软工视频(一)概论
- VMware workstation安装虚拟机--Windows XP
- 微信小程序图片实现宽度100%,高度自适应
- 天翼云 Ubuntu 22.04.1 LTS apt换源 (阿里云)
- 整理UI设计的三个分类,入门前要清楚!
- java网络编程案例9-1模拟微信聊天
- 16、爬取知乎大v张佳玮的文章“标题”、“摘要”、“链接”,并存储到本地文件...
- Android 根据银行卡号查询银行名称
- k8s源码分析 pdf_如何高效阅读 Kubernetes 源码?
- Elasticsearch 中的一些重要概念: cluster, node, index, document, shards 及 replica
- 做头条号和西瓜视频,新手小白要注意,这四个要点,别踩雷
热门文章
- 华为更新后计算机,华为手机升级到鸿蒙系统后,如果后悔了,怎样退回到EMUI系统?...
- [Unity3D]Unity3D游戏开发之角色控制漫谈
- 基于Python脚本和聚合数据实现手机号码归属地信息查询
- 使用漫步者wt800蓝牙耳机连接谷歌浏览器,自动关机
- 失业七个月,面试六十家公司的深圳体验
- python读取二进制文件_python读取二进制流 Python二进制方式读写文件 - 电脑常识 - 服务器之家...
- 2021-2027全球与中国甜椒粉市场现状及未来发展趋势
- mysql 学习笔记
- 【王喆-推荐系统】(task1)推荐系统的五大特征(特征工程篇)
- VMware给虚拟机设置固定IP