算法系列之十二:多边形区域填充算法--扫描线填充算法(有序边表法)

news2024/10/22 15:24:38

二、扫描线算法(Scan-Line Filling)

        扫描线算法适合对矢量图形进行区域填充,只需要直到多边形区域的几何位置,不需要指定种子点,适合计算机自动进行图形处理的场合使用,比如电脑游戏和三维CAD软件的渲染等等。

        对矢量多边形区域填充,算法核心还是求交。《计算几何与图形学有关的几种常用算法》一文给出了判断点与多边形关系的算法――扫描交点的奇偶数判断算法,利用此算法可以判断一个点是否在多边形内,也就是是否需要填充,但是实际工程中使用的填充算法都是只使用求交的思想,并不直接使用这种求交算法。究其原因,除了算法效率问题之外,还存在一个光栅图形设备和矢量之间的转换问题。比如某个点位于非常靠近边界的临界位置,用矢量算法判断这个点应该是在多边形内,但是光栅化后,这个点在光栅图形设备上看就有可能是在多边形外边(矢量点没有大小概念,光栅图形设备的点有大小概念),因此,适用于矢量图形的填充算法必须适应光栅图形设备。

2.1扫描线算法的基本思想

        扫描线填充算法的基本思想是:用水平扫描线从上到下(或从下到上)扫描由多条首尾相连的线段构成的多边形,每根扫描线与多边形的某些边产生一系列交点。将这些交点按照x坐标排序,将排序后的点两两成对,作为线段的两个端点,以所填的颜色画水平直线。多边形被扫描完毕后,颜色填充也就完成了。扫描线填充算法也可以归纳为以下4个步骤:

(1)       求交,计算扫描线与多边形的交点

(2)       交点排序,对第2步得到的交点按照x值从小到大进行排序;

(3)       颜色填充,对排序后的交点两两组成一个水平线段,以画线段的方式进行颜色填充;

(4)       是否完成多边形扫描?如果是就结束算法,如果不是就改变扫描线,然后转第1步继续处理;

        整个算法的关键是第1步,需要用尽量少的计算量求出交点,还要考虑交点是线段端点的特殊情况,最后,交点的步进计算最好是整数,便于光栅设备输出显示。

        对于每一条扫描线,如果每次都按照正常的线段求交算法进行计算,则计算量大,而且效率底下,如图(6)所示:

图(6) 多边形与扫描线示意图

观察多边形与扫描线的交点情况,可以得到以下两个特点:

(1)       每次只有相关的几条边可能与扫描线有交点,不必对所有的边进行求交计算;

(2)       相邻的扫描线与同一直线段的交点存在步进关系,这个关系与直线段所在直线的斜率有关;

        第一个特点是显而易见的,为了减少计算量,扫描线算法需要维护一张由“活动边”组成的表,称为“活动边表(AET)”。例如扫描线4的“活动边表”由P1P2和P3P4两条边组成,而扫描线7的“活动边表”由P1P2、P6P1、P5P6和P4P5四条边组成。

        第二个特点可以进一步证明,假设当前扫描线与多边形的某一条边的交点已经通过直线段求交算法计算出来,得到交点的坐标为(x, y),则下一条扫描线与这条边的交点不需要再求交计算,通过步进关系可以直接得到新交点坐标为(x + △x, y + 1)。前面提到过,步进关系△x是个常量,与直线的斜率有关,下面就来推导这个△x。

        假设多边形某条边所在的直线方程是:ax + by + c = 0,扫描线yi和下一条扫描线yi+1与该边的两个交点分别是(xi,yi)和(xi+1,yi+1),则可得到以下两个等式:

axi + byi + c = 0                        (等式 1)

axi+1 + byi+1 + c = 0                     (等式 2)

由等式1可以得到等式3:

xi = -(byi + c) / a                           (等式 3)

同样,由等式2可以得到等式4:

xi+1 = -(byi+1 + c) / a                      (等式 4)

由等式 4 – 等式3可得到

xi+1 – xi = -b (yi+1 - yi) / a

由于扫描线存在yi+1 = yi + 1的关系,将代入上式即可得到:

xi+1 – xi = -b / a

即△x = -b / a,是个常量(直线斜率的倒数)。

        “活动边表”是扫描线填充算法的核心,整个算法都是围绕者这张表进行处理的。要完整的定义“活动边表”,需要先定义边的数据结构。每条边都和扫描线有个交点,扫描线填充算法只关注交点的x坐标。每当处理下一条扫描线时,根据△x直接计算出新扫描线与边的交点x坐标,可以避免复杂的求交计算。一条边不会一直待在“活动边表”中,当扫描线与之没有交点时,要将其从“活动边表”中删除,判断是否有交点的依据就是看扫描线y是否大于这条边两个端点的y坐标值,为此,需要记录边的y坐标的最大值。根据以上分析,边的数据结构可以定义如下:

65 typedef struct tagEDGE

66 {

67     double xi;

68     double dx;

69     int ymax;

74 }EDGE;

 根据EDGE的定义,扫描线4和扫描线7的“活动边表”就分别如图(7)和图(8)所示:

 

 图(7) 扫描线4的活动边表

 图(8) 扫描线7的活动边表

        前面提到过,扫描线算法的核心就是围绕“活动边表(AET)”展开的,为了方便活性边表的建立与更新,我们为每一条扫描线建立一个“新边表(NET)”,存放该扫描线第一次出现的边。当算法处理到某条扫描线时,就将这条扫描线的“新边表”中的所有边逐一插入到“活动边表”中。“新边表”通常在算法开始时建立,建立“新边表”的规则就是:如果某条边的较低端点(y坐标较小的那个点)的y坐标与扫描线y相等,则该边就是扫描线y的新边,应该加入扫描线y的“新边表”。上例中各扫描线的“新边表”如下图所示:

图(9) 各扫描线的新边表

        讨论完“活动边表(AET)”和“新边表(NET)”,就可以开始算法的具体实现了,但是在进一步详细介绍实现算法之前,还有以下几个关键的细节问题需要明确:

(1)      多边形顶点处理

        在对多边形的边进行求交的过程中,在两条边相连的顶点处会出现一些特殊情况,因为此时两条边会和扫描线各求的一个交点,也就是说,在顶点位置会出现两个交点。当出现这种情况的时候,会对填充产生影响,因为填充的过程是成对选择交点的过程,错误的计算交点个数,会造成填充异常。

        假设多边形按照顶点P1、P2和P3的顺序产生两条相邻的边,P2就是所说的顶点。多边形的顶点一般有四种情况,如图(10)所展示的那样,分别被称为左顶点、右顶点、上顶点和下顶点:

图(10) 多边形顶点的四种类型

左顶点――P1、P2和P3的y坐标满足条件 :y1 < y2 < y3;

右顶点――P1、P2和P3的y坐标满足条件 :y1 > y2 > y3;

上顶点――P1、P2和P3的y坐标满足条件 :y2 > y1 && y2 > y3;

下顶点――P1、P2和P3的y坐标满足条件 :y2 < y1 && y2 < y3;

        对于左顶点和右顶点的情况,如果不做特殊处理会导致奇偶奇数错误,常采用的修正方法是修改以顶点为终点的那条边的区间,将顶点排除在区间之外,也就是删除这条边的终点,这样在计算交点时,就可以少计算一个交点,平衡和交点奇偶个数。结合前文定义的“边”数据结构:EDGE,只要将该边的ymax修改为ymax – 1就可以了。

        对于上顶点和下顶点,一种处理方法是将交点计算做0个,也就是修正两条边的区间,将交点从两条边中排除;另一种处理方法是不做特殊处理,就计算2个交点,这样也能保证交点奇偶个数平衡。

(1)      水平边的处理

    水平边与扫描线重合,会产生很多交点,通常的做法是将水平边直接画出(填充),然后在后面的处理中就忽略水平边,不对其进行求交计算。

(2)      如何避免填充越过边界线

        边界像素的取舍问题也需要特别注意。多边形的边界与扫描线会产生两个交点,填充时如果对两个交点以及之间的区域都填充,容易造成填充范围扩大,影响最终光栅图形化显示的填充效果。为此,人们提出了“左闭右开”的原则,简单解释就是,如果扫描线交点是1和9,则实际填充的区间是[1,9),即不包括x坐标是9的那个点。

2.2扫描线算法实现

        扫描线算法的整个过程都是围绕“活动边表(AET)”展开的,为了正确初始化“活动边表”,需要初始化每条扫描线的“新边表(NET)”,首先定义“新边表”的数据结构。定义“新边表”为一个数组,数组的每个元素存放对应扫描线的所有“新边”。因此定义“新边表”如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2213559.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【洛谷】- P1923 【深基9.例4】求第 k 小的数

文章目录 一、 P1923 【深基9.例4】求第 k 小的数二、思想方法2、代码3、细节 一、 P1923 【深基9.例4】求第 k 小的数 题目&#xff1a; 二、思想方法 首先我们来看核心代码&#xff0c;也就是通过快排&#xff0c;将K的位置找出 void my_sort(int arr[],int left,int right,…

170页满分PPT | 某大型集团信息安全管理体系优化咨询项目

某大型集团信息安全管理体系优化咨询项目是一项全面的规划报告&#xff0c;旨在根据ISO 27001:2013信息安全管理国际标准&#xff0c;对甲方集团的信息安全现状进行调研分析&#xff0c;并提出优化建议。该报告共170页可编辑PPT格式&#xff0c;详细列出了信息安全建设的各个阶…

css的思考

CSS思考[vue react tailwindcss] 传统css 全局作用域: 一旦生效&#xff0c;应用于全局&#xff0c;造成各种各样的冲突&#xff0c;为了避免冲突&#xff0c;会写复杂的id选择器和类选择器依赖问题&#xff1a;引入多个css样式文件&#xff0c;引入的css文件会对后面的css文…

企业数字化转型:打造数字资产开启创新与可持续发展之路

在当今数字经济时代&#xff0c;企业面临激烈竞争与变化的客户需求。传统信息化已不足以支撑发展&#xff0c;需将其提升到数字化高度&#xff0c;以打造数字资产为目标进行转型。 信息化主要是对业务流程进行优化和管理&#xff0c;关注数据采集、存储与处理及业务流程自动化。…

源之东方受邀出席第三届通证经济发展论坛暨绿色消费生态高质量发展大会

2024 年 9 月 27 日&#xff0c;在美丽的博鳌&#xff0c;由中国国际经济技术合作促进会主办&#xff0c;中国国际经济技术合作促进会通证经济工作委员会承办的 2024&#xff08;第三届&#xff09;通证经济发展论坛暨绿色消费生态高质量发展大会隆重召开。本次大会主题是“聚焦…

一键脚本部署单机redis

这里写目录标题 背景步骤总结 背景 现在有要求&#xff0c;将所有安装步骤可复用化 。sh脚本即可完成如上要求&#xff0c;减少人安装带来的不确定性因素。 需要安装包的可以加我微信。 步骤 在/root 目录下创建一个文件我们给他命名为 autoRedis.sh vi autoRedis.sh然后…

ruoyi若依平台——部门管理部分源码分析

来都来了给我点个赞和收藏关注一下在走呗~~~~&#x1f339;&#x1f339;&#x1f339; 目录 数据库结构&#xff1a; 一、部门查询 二、部门新增 三、后端 Controller——SysDeptController部门CRUD&#xff1a; 1.获取部门列表信息&#xff1a; 2.排除特定节点的部门列…

C++ 算法学习——1.8 单调栈算法

单调栈&#xff08;Monotonic Stack&#xff09;是一种在解决一些数组或者链表相关问题时非常有用的数据结构和算法。在C中&#xff0c;单调栈通常用于解决一些需要快速找到元素左右第一个比当前元素大或小的问题。 定义&#xff1a; 单调栈实际上是一个栈&#xff0c;但是与普…

《大规模语言模型从理论到实践》第一轮学习--强化学习(RLHF、PPO)

个人学习笔记,如有错误欢迎指出。 一、强化学习的意义 RLHF(Reinforcement Learning from Human Feedback):强化学习(Reinforcement Learning)结合人类反馈(Human Feedback)来微调大语言模型。 大语言模型的训练步骤包括:预训练、指令微调(SFT)、对齐。 对齐(a…

NVM 安装步骤

NVM 安装步骤 文章目录 NVM 安装步骤一、NVM 是什么二、用途三、安装步骤详解1. 下载与安装2. 验证安装3. 安装Node.js4. 使用安装的Node.js版本5. 验证Node.js安装 四、NVM 常用命令1. 查看已安装的Node.js版本2. 安装指定版本的Node.js3. 卸载指定版本的Node.js4. 切换到已安…

Redis面试题——第四篇

1. Redis主从复制的常见拓扑结构有哪些 一主多从&#xff1a;这是最基本的拓扑结构&#xff0c;包含一个主节点和多个从节点&#xff0c;所有写操作都在主节点上执行&#xff0c;而读操作可以在从节点上进行&#xff0c;以提高读取速度和负载均衡。 树状主从结构&#xff1a;从…

小米澎湃工具箱,一键获取权限

Hyper工具箱已初步支持魅族设备一键获取权限&#xff0c;配置扫描与ROM包索引均已适配Flyme。 支持小米、魅族手机 功能不止刷机、获取权限更多功能下载体验&#xff01; 下载&#xff1a;https://pan.quark.cn/s/4e78f870813f

试着了解YOLOx

在特征提取上来说&#xff0c;主干部分使用了focus网络结构&#xff0c;对特征点进行了划分&#xff0c;将特征点信息堆叠到通道上。 同时采用CSPnet结构&#xff0c;在残差网络堆叠的同时&#xff0c;构建大的残差边&#xff0c;经过少量处理直接连接到最后。 过去的YOLO将分…

数据库系统概论之关系数据库标准语言SQL(一)【超详细】

教材&#xff1a; 数据库系统概论&#xff08;第6版&#xff09;王珊,杜小勇,陈红编著 目录 一、SQL概述 1.1 SQL 的产生与发展 1.2 SQL的特点 1.3 SQL的基本概念 二、数据定义 2.1 数据库的定义 2.2 数据表的定义 2.3 模式的定义 一、SQL概述 1974年IBM为关系DBMS设…

组合式二值编码

论文名称&#xff1a;《A Practical Approach to 3D Scanning in the Presence ofInterreflections, Subsurface Scattering and Defocus》 简介&#xff1a;组合式二值编码&#xff08;包含传统格雷码&#xff0c;XOR-02&#xff0c;XOR-04&#xff0c;minSW&#xff09;&…

Java学习Day25:基础篇15:反射

Java 反射&#xff08;Reflection&#xff09; 1.前置反应 是 Java 编程语言的一个强大特性&#xff0c;它允许程序在运行时检查或修改类的行为。这包括获取类的信息&#xff08;如字段、方法、构造函数等&#xff09;&#xff0c;以及动态地创建对象、调用方法、访问和修改字…

linux的学习第二天

1.vmware的功能&#xff1a; 快照 创建快照&#xff1a; 拍摄此虚拟机的快照&#xff1a;记录保存虚拟机的当前状态&#xff0c;如果系统出现故障&#xff0c;可以通过快照还原&#xff08;错删系统时可以找到快照的系统状态&#xff0c;然后恢复系统&#xff09; 恢复快照…

java项目之精品在线试题库系统设计与实现源码(springboot+vue+mysql)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的精品在线试题库系统设计与实现。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 精品在线试…

sentinel dashboard分布式改造落地设计实现解释(二)-分布式discovery组件

discovery discovery负责维护app/机器资料库&#xff0c;transport健康检测&#xff0c; transport上下线处理。discovery关键是分布式存储&#xff0c;后续研究一下raft&#xff0c;其复制&#xff0c;状态机&#xff0c;快照技术&#xff0c;但个人觉得&#xff0c;discover…

软件分享 | 截图工具 Snipaste

今天分享&#xff1a; 今日分享的是一款截图界的神器——Snipaste&#xff01; 特点&#xff1a; &#x1f3a8; 超清截图&#xff1a; Snipaste的截图功能&#xff0c;清晰度超乎你的想象。无论是工作文档还是游戏画面&#xff0c;都能一键捕捉&#xff0c;细节尽在掌握。 …