news 2026/10/30 2:16:09

【计算几何】clipper库之扫描线、活动边、输出区域

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【计算几何】clipper库之扫描线、活动边、输出区域

本文涉及知识点

数学 几何

裁剪算法

Sutherland-Hodgman (1974):这是最经典的算法之一。它的核心限制是裁剪多边形必须是凸多边形,因此它非常适合矩形窗口裁剪这类简单场景。
Weiler-Atherton (1977):这是第一个能够处理任意多边形(包括凹多边形、带孔多边形) 的通用算法。它通过构建多边形间的图结构来追踪边界,功能强大,但数据结构和实现都比较复杂。
Vatti (1992):Vatti算法同样面向任意多边形,并且是首个能够处理自相交多边形的算法之一。它基于扫描线(Scanline)思想,功能非常全面,但算法本身也相当复杂。
Greiner-Hormann (1998):这个算法可以被看作是Weiler-Atherton的简化版本。它的目标是提供一种更简单、更快速的方式来处理任意(包括自相交)多边形。其核心数据结构是双向链表,比Weiler的图结构和Vatti的复杂状态机要轻量得多。
Clipper使用的是Vatti clipping算法,和计算几何讲的略有区别。

ClipperBase成员变量

actives_ 是 AEL(活动边表) 的头指针;
sel_ 是 SEL(排序边表) 的头指针;
intersect_nodes_ 记录交点。
horz_seg_list_:水平段候选列表
horz_join_list_:水平连接配对列表
std::priority_queue<int64_t> scanline_list_: 扫描线的纵坐标。默认是大根堆,故扫描线的y是从大到小。
minima_list_: 记录局部最小值,数学的局部最大值。本文不采用数学的说法。
outrec_list_:记录最终的结果,区域。

扫描线

观察结论:一,交点没扫描线。二,顶点全部有扫描线。
红色扫描线是初始化扫描线,两个多边形局部最小值。
黄色扫描线是新的局部最小值。当处理新的局部最小值时,如果左右边界非水平,则左右边界的的top.y是新的扫描线。InsertLocalMinimaIntoAEL函数处理。
绿色扫描线是更新边,添加的扫描线。DoTopOfScanbeam,扫描线和线段bottom相同时,将线段t加到扫描线。
红色圆圈处是局部最大点,所有扫描线加了两次,InsertLocalMinimaIntoAEL和DoTopOfScanbeam各加一次。


活动边y大的是bom,y小的是bot。当扫描线是bom时,将top放到扫描线队列。局部最小点的纵坐标大于相邻点的纵坐标,故无法通过此法增加到扫描线队列,故必须提前放到扫描线队列。

非局部最小点p一定可以被枚举到

性质一:p到两个(或一个)临接点p1,p2。p到p1和p2不会都下降,否则p就是局部最小点。不失一般性,令p到p1上升。
性质二:从p到p1方向移动,一定会遇到局部最小点,令遇到的第一个局部最小点是q。比如y最大的点。
性质三:p到q一定全部是上升路径,否则p到q之间有其它局部最小点,与假设矛盾。即q直接或间接能找到p。

活动边图例:扫描线

选中的是当前扫描线,蓝色的是当前活动边。
扫描线207处理完毕


处理完164

处理完119

处理完81
处理完46

处理完44

44 处理完局部最小点

处理完23

处理完21

处理完1

处理完-40

处理完-47

观察结论:当扫描线经过局部最小点时增加一组活动边。
观察结论:当扫描线经过局部最大点时,一组活动边消失。

显然交点也会影响活动边


交点会交换活动边的顺序。

并集的输出区

更改扫描线之前,扫描线处于被选中状态,蓝线、紫色是输出区域。填充规则非0FillRule::NonZero.
扫描线纵坐标207。


扫描线164

扫描线119

扫描线81

扫描线46

扫描线44:两个区域,第二个区域只有一个点

扫描线23

扫描线21

扫描线1

扫描线-40


扫描线-47

扫描线-64

异或输出区

扫描线23

扫描线21

扫描线1

扫描线-40

扫描线-47

交集的输出区域

扫描线23之前,全部为空。
扫描线23

扫描线

扫描线1
扫描线-40

差集的输出区域

扫描线44

扫描线23

扫描线21

扫描线1

扫描线-40

扫描线-47

扩展阅读

计算几何为骨,排样优化为魂
作品:亲士CAD工具箱
经典文章推荐:二维排样
万物皆数学
查阅鄙人的博文,请点击博文下载学院导航
活到老,学到老。明朝中后期,大约50%的进士能当上堂官(副部及更高);能当上堂官的举人只有十余人。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。

测试环境

操作系统:win7 开发环境: VS2019C++17
或者 操作系统:win10 开发环境: VS2022C++17
如无特殊说明,本算法用**C++**实现。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/30 2:11:07

Ruffle 桌面版:3 分钟打开 SWF 文件完整指南

Ruffle 桌面版&#xff1a;3 分钟打开 SWF 文件完整指南 【免费下载链接】ruffle A Flash Player emulator written in Rust 项目地址: https://gitcode.com/GitHub_Trending/ru/ruffle 从双击 Ruffle 到第一帧画面出现&#xff0c;通常 30 秒就够。它是一个用 Rust 写成…

作者头像 李华
网站建设 2026/10/30 2:10:26

【技术思考】Token经济下的通信技术发展(二)

继续前面的思考&#xff0c;继续聊聊关于沉浸式通信的技术的可能发展。 Q:针对沉浸式通信&#xff0c;业界有提出“网业端协同业务体验增强技术&#xff0c;实现端边云协同渲染计算&#xff0c;提升沉浸式体验”&#xff0c;请解读一下这个技术方向的具体研究内容&#xff0c…

作者头像 李华
网站建设 2026/10/30 2:07:11

深度拆解 Blueprint:数据密集型 React UI 工具包如何支撑万行表格

深度拆解 Blueprint&#xff1a;数据密集型 React UI 工具包如何支撑万行表格 【免费下载链接】blueprint A React-based UI toolkit for the web 项目地址: https://gitcode.com/gh_mirrors/bl/blueprint 给内部数据平台做管理台&#xff0c;表格行数一旦过十万&#x…

作者头像 李华
网站建设 2026/10/30 2:00:46

英集芯移动电源IC开发避坑指南:I2C 时序、寄存器操作容易踩的雷

前言在移动电源领域&#xff0c;英集芯的电源管理IC市场占有率还是蛮高的&#xff0c;基本上这个行业领域里面的&#xff0c;或多或少都用过英集芯的电源管理IC&#xff0c;他们家的IC有一个好处就是集成了DC-DC和快充协议&#xff0c;开发起来相对简单&#xff0c;不需要考虑协…

作者头像 李华
网站建设 2026/10/30 2:00:46

HeidiSQL 9.2.0.4947 安装配置与连接排错指南

简介&#xff1a;HeidiSQL 9.2.0.4947 安装包面向需要管理 MySQL、MariaDB、SQL Server、PostgreSQL 与 Oracle 等数据库的开发者、数据库管理员及初学者&#xff0c;提供图形化操作入口&#xff0c;减少直接编写 SQL 命令的负担。压缩包共 2 个文件&#xff0c;以 exe 安装程序…

作者头像 李华