利用相邻像素之间的连贯性,提高算法效率。根据多边形内部点的连续性知:一条扫描线与多边形的交点中,入点和出点之间所有点都是多边形的内部点。所以,对所有的扫描线填充入点到出点之间所有的点就可填充多边形。

(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库哦!

区域填充之扫描线算法相关推荐

  1. 计算机图形学生活应用,计算机图形学的应用实例(计算机图形作业).doc

    计算机图形学的应用实例(计算机图形作业).doc 计算机图形学大作业 计算机图形学的应用实例 班级: 学号: 姓名: 2012-03-12 计算机图形学的应用实例 一.计算机图像学简介 计算机图形学是 ...

  2. 计算机图形学复习(自用)

    文章目录 1. dll文件与lib文件的区别与作用 :one: 各种文件 :two: ​内存结构 2. 相机拍摄景物模型 3. OpenGL支持绘制的图元 GL_POINTS GL_LINE_STRI ...

  3. 计算机图形学课堂笔记

    计算机图形学 第一章绪论 计算机图形学主要研究内容:计算机中图形的表示方法,以及利用计算机进行图形的计算.处理和显示的相关原理和算法 计算机图形学之父:Ivan Sutherland 1950年第一台 ...

  4. 图形学日记(一)光栅图形学

    本文主要是概念的总结,并不会讲述具体的算法,如需查看详细内容,请点击相关博客. 1.基础概念: 光栅化(图形的扫描转换):确定最佳逼近图形的像素集合,并用指定属性写像素的过程. 一维图形的表示:在不考 ...

  5. 计算机图形学期末复习笔记

      计图期末根据老师ppt整理期末复习笔记. 第二章 图形系统综述 1.视频显示设备 刷新式CRT(阴极射线管) 光栅扫描显示器 随机扫描显示器 彩色CRT监视器 直视存储管 平板显示器 三维观察设备 ...

  6. 计算机图形学基础教程学习总结

    目录 第一章 绪论 计算机图形学概念 图形和图像的区别 主要研究内容 第二章 光栅图形学 光栅.理想直线与图形扫描转换的含义 DDA方法 中点画线法 Bresenham算法 中点画圆法 多边形的扫描转 ...

  7. 洪水填充算法_区域填充算法和多边形填充的扫描线算法

    本文主要介绍几种区域填充算法,重点解释多边形的扫描线填充算法,最后实现了多边形填充算法,包括在附录文件中.在参考[5]中,作者详细介绍了一系列区域填充算法,可以查看相应网页.代码的下载地址为:http ...

  8. 【CV系列】扫描线算法区域填充

    DATE:2019-5-19 1.参考 算法系列之十二:多边形区域填充算法--扫描线种子填充算法 扫描线种子填充算法 扫描线算法完全解析 Line Sweep Technique [翻译]扫描线算法( ...

  9. 《计算机图形学》实验报告区域填充扫描线算法

    一.实验目的和要求 熟悉光栅图形学中的区域填充扫描线算法: 利用区域填充算法绘制多边形区域,区域由离散点组成: 应用OpenGL进行区域填充. 二.实验内容 用区域填充直线扫描法填充绘制六边形: 初始 ...

最新文章

  1. Debug enterprise search menu
  2. php 数组按个数分组,如何在PHP中基于内部数组键对数组进行分组?
  3. 【Anychat】理解POCO
  4. 今天博客园肿了吗?希望团队修复一下
  5. Linux 镜像文件ISO下载
  6. JAVA - JDK 1.8 API 帮助文档-中文版
  7. python + selenium 自动化测试框架
  8. html基本标记练习钱塘湖春行,《钱塘湖春行》练习题
  9. YARN队列优先级分配策略
  10. 【软件工程】软工视频(一)概论
  11. VMware workstation安装虚拟机--Windows XP
  12. 微信小程序图片实现宽度100%,高度自适应
  13. 天翼云 Ubuntu 22.04.1 LTS apt换源 (阿里云)
  14. 整理UI设计的三个分类,入门前要清楚!
  15. java网络编程案例9-1模拟微信聊天
  16. 16、爬取知乎大v张佳玮的文章“标题”、“摘要”、“链接”,并存储到本地文件...
  17. Android 根据银行卡号查询银行名称
  18. k8s源码分析 pdf_如何高效阅读 Kubernetes 源码?
  19. Elasticsearch 中的一些重要概念: cluster, node, index, document, shards 及 replica
  20. 做头条号和西瓜视频,新手小白要注意,这四个要点,别踩雷

热门文章

  1. 华为更新后计算机,华为手机升级到鸿蒙系统后,如果后悔了,怎样退回到EMUI系统?...
  2. [Unity3D]Unity3D游戏开发之角色控制漫谈
  3. 基于Python脚本和聚合数据实现手机号码归属地信息查询
  4. 使用漫步者wt800蓝牙耳机连接谷歌浏览器,自动关机
  5. 失业七个月,面试六十家公司的深圳体验
  6. python读取二进制文件_python读取二进制流 Python二进制方式读写文件 - 电脑常识 - 服务器之家...
  7. 2021-2027全球与中国甜椒粉市场现状及未来发展趋势
  8. mysql 学习笔记
  9. 【王喆-推荐系统】(task1)推荐系统的五大特征(特征工程篇)
  10. VMware给虚拟机设置固定IP