news 2026/9/15 7:59:48

【计算几何】布尔运算交并补异或

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【计算几何】布尔运算交并补异或

本文涉及知识点

数学 几何

求PathD及PathsD的面积

数学规则逆时针为外边界,面积为正;顺时针为内边界(孔洞),面积为负数。

两个完全相同的矩形,一个逆时针一个顺时针

usingSystem;usingSystem.Collections.Generic;usingSystem.ComponentModel;usingSystem.Data;usingSystem.Drawing;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;usingSystem.Windows.Forms;usingClipper2Lib;
PathDpath1=newPathD(newPointD[]{newPointD(0,0),newPointD(100,0),newPointD(100,100),newPointD(0,100)});PathDpath2=newPathD();path2.AddRange(path1);path2.Reverse();doublearea1=Clipper.Area(path1);doublearea2=Clipper.Area(path2);Console.WriteLine("面积一:"+area1);Console.WriteLine("面积二:"+area2);

运行结果符合预期。
面积一:10000
面积二:-10000

PathsDps=newPathsD();ps.Add(path1);ps.Add(path2);doublearea3=Clipper.Area(ps);Console.WriteLine("面积三:"+area3);
运行结果符合预期: 面积三:0

两个逆时针矩形不重叠

PathDpath1=CreatePath(100,100,10);PathDpath2=CreatePath(200,100,10);doublearea1=Clipper.Area(path1);doublearea2=Clipper.Area(path2);Console.WriteLine("面积一:"+area1);Console.WriteLine("面积二:"+area2);PathsDps=newPathsD();ps.Add(path1);ps.Add(path2);doublearea3=Clipper.Area(ps);Console.WriteLine("面积三:"+area3);

结果是两者之和:
面积一:400
面积二:400
面积三:800

两个完全相同的矩形(端点重合,方向相同)

PathDpath1=CreatePath(100,100,10);PathDpath2=CreatePath(100,100,10);doublearea1=Clipper.Area(path1);doublearea2=Clipper.Area(path2);Console.WriteLine("面积一:"+area1);Console.WriteLine("面积二:"+area2);PathsDps=newPathsD();ps.Add(path1);ps.Add(path2);doublearea3=Clipper.Area(ps);Console.WriteLine("面积三:"+area3);

重叠部分重复计算:
面积一:400
面积二:400
面积三:800

不重叠矩形,一个顺时针一个逆时针

PathDpath1=CreatePath(100,100,10);PathDpath2=CreatePath(200,100,10);path2.Reverse();doublearea1=Clipper.Area(path1);doublearea2=Clipper.Area(path2);Console.WriteLine("面积一:"+area1);Console.WriteLine("面积二:"+area2);PathsDps=newPathsD();ps.Add(path1);ps.Add(path2);doublearea3=Clipper.Area(ps);Console.WriteLine("面积三:"+area3);

面积一:400
面积二:-400
面积三:0

结论

Paths面积就是各Path面积之和。

缠绕数(Winding Number)

以区域(子区域)内任意一点为起点,任意方向做射线。边界线从右向左穿过射线:缠绕数 +1,边界线从左向右穿过射线:缠绕数 -1,缠绕数 = 所有穿越的代数和。为了实现方便,一般用水平向右的射线。

逆势针矩形

任意边界方向都在对应射线的的逆时针平面,故WN+1。

顺时针矩形

任何边界方向都在对应射线的顺时针平面,故WN-1。

凹多边形

向左的射线和一条边界相交,边界在射线的逆时针半平面。故WN+1。
向右的射线和五条边界相交,3条边界在射线的逆时针半平面,2条在射线的顺时针半平面,故WN+3-2=1。

向右水平的射线

令射线方向 v 1 , 边界方向 v 2 ,如果 v 2 在 v 1 的逆时针半平面,则 v 1 × v 2 > 0 令射线方向v_1,边界方向v_2,如果v2在v1的逆时针半平面,则v_1 \times v_2 > 0令射线方向v1,边界方向v2,如果v2v1的逆时针半平面,则v1×v2>0,假定射线水平向右,及v 1 = ( 1 , 0 ) ,则 v 1 × v 2 = v 2 . y v_1=(1,0),则v_1 \times v_2 = v_2.yv1=(1,0),则v1×v2=v2.y

FillType 与布尔运算

publicenumFillRule{EvenOdd=0,NonZero=1,Positive=2,Negative=3}

EvenOdd (奇偶):WN为奇数是内部。和Path是逆时针还是顺时针无关。假定将某个Path改变方向,x个交点由-1变成1,y个交点由1变成-1。则WN变化为:2x-2y,是偶数,故WN的奇偶性不变。
NonZero(非0):WN不是0是内部。和Path的方向有关。逆时针矩形内部有另外一个逆时针矩形,内部矩形WN=2。如果将任何一个矩形反向,则内部矩形的WN为0。
Positive(正数):WN>0时,是内部。
Negative(负数):WN<0时,是内部。
运算类型决定最终保留哪些区域。例如:
Intersection(交集):保留 WC = +2 的区域。
Union(并集):保留 WC > 0 的区域。
Difference(差集):保留 WC = +1 的区域。
XOR(异或):保留 WC=1 的区域。
交集并集异或都内部WC都是1,外包都是0。
差集,被减数内部是1,减数内部是-1,被减数减数外部是0。

一个正方形的并

path1逆时针,path2 顺时针。Paths哪些块是内部,由FillType和WN决定。

奇偶

publicForm1(){InitializeComponent();PathDpath1=CreatePath(0,0,100);PathDpath2=CreatePath(0,0,10);path2.Reverse();FillRulefr=FillRule.EvenOdd;varps1=Clipper.Union(newPathsD(newPathD[]{path1}),fr);varps2=Clipper.Union(newPathsD(newPathD[]{path2}),fr);doublearea3=Clipper.Area(ps1);doublearea4=Clipper.Area(ps2);Console.WriteLine("FillRule:"+fr);Console.WriteLine("面积三:"+area3);Console.WriteLine("面积四:"+area4);}//创建正方形,点集合逆时针顺序PathDCreatePath(doublexCenter,doubleyCenter,doublehalfLen){PointD[]pts={newPointD(xCenter-halfLen,yCenter-halfLen),newPointD(xCenter+halfLen,yCenter-halfLen),newPointD(xCenter+halfLen,yCenter+halfLen),newPointD(xCenter-halfLen,yCenter+halfLen)};returnnewPathD(pts);}

运行结果:
FillRule:EvenOdd
面积三:40000
面积四:400
path1的WN=1,path2的WN=-1,都是奇数,故都是内部。

非0

只修改一行代码

FillRulefr=FillRule.NonZero;

FillRule:NonZero
面积三:40000
面积四:400
± 1 \pm 1±1都非0,故都是内部。

正数

FillRulefr=FillRule.Positive;

FillRule:Positive
面积三:40000
面积四:0

负数

FillRulefr=FillRule.Negative;

FillRule:Negative
面积三:0
面积四:400

1个paths 2个path的并

path1逆时针矩形,path2逆时针矩形,path2完全在path1内部。path2反转后形成path3,即path3顺时针。
path2内部:WN=2,path3内部:WN=0;path1内部非空洞,WN=1。

奇偶

publicForm1(){InitializeComponent();PathDpath1=CreatePath(0,0,100);PathDpath2=CreatePath(0,0,10);PathDpath3=CreatePath(0,0,10);path3.Reverse();Console.WriteLine("面积一:"+Clipper.Area(path1));Console.WriteLine("面积二:"+Clipper.Area(path2));Console.WriteLine("面积三:"+Clipper.Area(path3));FillRulefr=FillRule.EvenOdd;varps12=Clipper.Union(newPathsD(newPathsD(){path1,path2}),fr);varps13=Clipper.Union(newPathsD(newPathsD(){path1,path3}),fr);Console.WriteLine(""+fr);Console.WriteLine("面积一二:"+Clipper.Area(ps12));Console.WriteLine("面积一三:"+Clipper.Area(ps13));}//创建正方形,点集合逆时针顺序PathDCreatePath(doublexCenter,doubleyCenter,doublehalfLen){PointD[]pts={newPointD(xCenter-halfLen,yCenter-halfLen),newPointD(xCenter+halfLen,yCenter-halfLen),newPointD(xCenter+halfLen,yCenter+halfLen),newPointD(xCenter-halfLen,yCenter+halfLen)};returnnewPathD(pts);}

面积一:40000
面积二:400
面积三:-400
EvenOdd
面积一二:39600
面积一三:39600

非零

只修改一行。

FillRulefr=FillRule.NonZero;

面积一:40000
面积二:400
面积三:-400
NonZero
面积一二:40000
面积一三:39600

正数

FillRulefr=FillRule.Positive;

面积一:40000
面积二:400
面积三:-400
Positive
面积一二:40000
面积一三:39600

负数

FillRulefr=FillRule.Negative;

面积一:40000
面积二:400
面积三:-400
Negative
面积一二:0
面积一三:0

两个paths的交集

path1,path2的WN=1,path3的WN=-1

奇偶

PathDpath1=CreatePath(0,0,100);PathDpath2=CreatePath(0,0,10);PathDpath3=CreatePath(0,0,10);path3.Reverse();Console.WriteLine("面积一:"+Clipper.Area(path1));Console.WriteLine("面积二:"+Clipper.Area(path2));Console.WriteLine("面积三:"+Clipper.Area(path3));FillRulefr=FillRule.EvenOdd;varps12=Clipper.Intersect(newPathsD(newPathsD(){path1}),newPathsD(newPathsD(){path2}),fr);varps13=Clipper.Intersect(newPathsD(newPathsD(){path1}),newPathsD(newPathsD(){path3}),fr);Console.WriteLine(""+fr);Console.WriteLine("面积一二:"+Clipper.Area(ps12));Console.WriteLine("面积一三:"+Clipper.Area(ps13));

面积一:40000
面积二:400
面积三:-400
EvenOdd
面积一二:400
面积一三:400

非0

FillRulefr=FillRule.NonZero;

面积一:40000
面积二:400
面积三:-400
NonZero
面积一二:400
面积一三:400

正数

面积一:40000
面积二:400
面积三:-400
Positive
面积一二:400
面积一三:0

负数

面积一:40000
面积二:400
面积三:-400
Negative
面积一二:0
面积一三:0

两个paths的差集

奇偶

面积一:40000
面积二:400
面积三:-400
EvenOdd
面积一二:39600
面积一三:39600

非0

面积一:40000
面积二:400
面积三:-400
NonZero
面积一二:39600
面积一三:39600

正数

面积一:40000
面积二:400
面积三:-400
Positive
面积一二:39600

负数

面积一:40000
面积二:400
面积三:-400
Negative
面积一二:0
面积一三:0

两个paths的交集 异或

奇偶

面积一:40000
面积二:400
面积三:-400
EvenOdd
面积一二:39600
面积一三:39600

非0

面积一:40000
面积二:400
面积三:-400
NonZero
面积一二:39600
面积一三:39600

正数

面积一:40000
面积二:400
面积三:-400
Positive
面积一二:39600
面积一三:40000

负数

面积一:40000
面积二:400
面积三:-400
Negative
面积一二:0
面积一三:400

返回值

Clipper的返回值,可以认为是Even-Odd或者Non-Zero中任意一种,即兼容这两种填充方式。

演示工具

演示工具基于Cad,支持Cad2013及更高版本。
亲士库版本:2026.9.4
Cliper库版本:2.0.0.0
点击下载亲士数学演示工具箱
如果不会操作,请看视频:https://edu.csdn.net/course/detail/41418
建议用工具尝试以下情况:
四种填充方式
部分多边形相离,部分多边形相切,部分多边形相离。
部分多边形是凸多边形,部分是凹多边形。
由于布尔运算容易理解,故工具只演示一个Path的并。
如果不想可视频或操作,可直接看图片。

奇偶模式的并集


01模式的并集


正数并集


负数并集

并集也可能为空。


上图红色三角形WN是1。黄色三角形是0,穿过三角形是-1,穿过矩形是1。红色矩形是1。全部不是负数。

扩展阅读

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

测试环境

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

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

世界模型到底是什么?李飞飞、朱军等如何解读?

从渲染器、模拟器、规划器&#xff0c;到理解、想象、行动的闭环&#xff0c;中美顶尖 AI Lab正在补全世界模型走向 AGI 的两种坐标。 2026 年&#xff0c;「世界模型」是 AI 圈最没有共识的词之一。 一段能够连续生成的视频&#xff0c;被叫作世界模型&#xff1b;一个随键鼠…

作者头像 李华
网站建设 2026/9/15 7:59:07

奥特曼说人类进入AGI时代!黄仁勋更是一锤定音:“AGI 已经到来“!| 让我们畅聊人工智能的发展

过去几年&#xff0c;AI 的进化速度已经快到让很多人产生一种明显的感觉&#xff1a;我们可能正在接近一个新的临界点。 从大语言模型、推理模型&#xff0c;到 Agent、世界模型和具身智能&#xff0c;AI 正从“会聊天、会生成内容”&#xff0c;一步步走向“会推理、会规划、会…

作者头像 李华
网站建设 2026/9/15 7:58:19

MoE架构解密:稀疏激活如何让大模型本地部署成为可能

上个月帮一个朋友折腾本地大模型&#xff0c;他从网上找了各种“7B、13B模型随便跑”的教程&#xff0c;结果自己一张4090 跑 70B 参数级别的模型时直接 OOM&#xff0c;整个人都懵了。后来我给他推荐了 MoE 架构的模型&#xff0c;问题才真正解决。这件事让我想认真聊聊最近非…

作者头像 李华
网站建设 2026/9/15 7:58:01

如何选择优质人力咨询公司及评估投资回报

1. 为什么选择人力咨询公司如此关键&#xff1f;在当今竞争激烈的商业环境中&#xff0c;人力资源已经成为企业最核心的竞争力之一。根据我的从业经验&#xff0c;超过70%的企业在人力资源管理方面都存在不同程度的痛点&#xff0c;而这些问题往往不是靠内部调整就能解决的。这…

作者头像 李华
网站建设 2026/9/15 7:57:20

OpenCV与视觉大模型融合实战:多模态图像检索与LoRA微调指南

1. 从传统OpenCV到视觉大模型&#xff1a;开发者的坐标系变了1.1 为什么说2026年是视觉开发者绕不开的一个节点我在OpenCV这个生态里泡了快十年&#xff0c;从早年的车牌识别、人脸检测、边缘检测&#xff0c;到后来的YOLO系列目标检测&#xff0c;再到今天的CLIP、LLaVA、Qwen…

作者头像 李华