十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

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

【计算几何】布尔运算交并补异或 本文涉及知识点数学 几何求PathD及PathsD的面积数学规则逆时针为外边界面积为正顺时针为内边界孔洞面积为负数。两个完全相同的矩形一个逆时针一个顺时针usingSystem;usingSystem.Collections.Generic;usingSystem.ComponentModel;usingSystem.Data;usingSystem.Drawing;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;usingSystem.Windows.Forms;usingClipper2Lib;PathDpath1newPathD(newPointD[]{newPointD(0,0),newPointD(100,0),newPointD(100,100),newPointD(0,100)});PathDpath2newPathD();path2.AddRange(path1);path2.Reverse();doublearea1Clipper.Area(path1);doublearea2Clipper.Area(path2);Console.WriteLine(面积一area1);Console.WriteLine(面积二area2);运行结果符合预期。面积一10000面积二-10000PathsDpsnewPathsD();ps.Add(path1);ps.Add(path2);doublearea3Clipper.Area(ps);Console.WriteLine(面积三area3);运行结果符合预期 面积三0两个逆时针矩形不重叠PathDpath1CreatePath(100,100,10);PathDpath2CreatePath(200,100,10);doublearea1Clipper.Area(path1);doublearea2Clipper.Area(path2);Console.WriteLine(面积一area1);Console.WriteLine(面积二area2);PathsDpsnewPathsD();ps.Add(path1);ps.Add(path2);doublearea3Clipper.Area(ps);Console.WriteLine(面积三area3);结果是两者之和面积一400面积二400面积三800两个完全相同的矩形端点重合方向相同PathDpath1CreatePath(100,100,10);PathDpath2CreatePath(100,100,10);doublearea1Clipper.Area(path1);doublearea2Clipper.Area(path2);Console.WriteLine(面积一area1);Console.WriteLine(面积二area2);PathsDpsnewPathsD();ps.Add(path1);ps.Add(path2);doublearea3Clipper.Area(ps);Console.WriteLine(面积三area3);重叠部分重复计算面积一400面积二400面积三800不重叠矩形一个顺时针一个逆时针PathDpath1CreatePath(100,100,10);PathDpath2CreatePath(200,100,10);path2.Reverse();doublearea1Clipper.Area(path1);doublearea2Clipper.Area(path2);Console.WriteLine(面积一area1);Console.WriteLine(面积二area2);PathsDpsnewPathsD();ps.Add(path1);ps.Add(path2);doublearea3Clipper.Area(ps);Console.WriteLine(面积三area3);面积一400面积二-400面积三0结论Paths面积就是各Path面积之和。缠绕数Winding Number以区域子区域内任意一点为起点任意方向做射线。边界线从右向左穿过射线缠绕数 1边界线从左向右穿过射线缠绕数 -1缠绕数 所有穿越的代数和。为了实现方便一般用水平向右的射线。逆势针矩形任意边界方向都在对应射线的的逆时针平面故WN1。顺时针矩形任何边界方向都在对应射线的顺时针平面故WN-1。凹多边形向左的射线和一条边界相交边界在射线的逆时针半平面。故WN1。向右的射线和五条边界相交3条边界在射线的逆时针半平面2条在射线的顺时针半平面故WN3-21。向右水平的射线令射线方向 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​如果v2在v1的逆时针半平面则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{EvenOdd0,NonZero1,Positive2,Negative3}EvenOdd (奇偶):WN为奇数是内部。和Path是逆时针还是顺时针无关。假定将某个Path改变方向x个交点由-1变成1y个交点由1变成-1。则WN变化为2x-2y是偶数故WN的奇偶性不变。NonZero(非0WN不是0是内部。和Path的方向有关。逆时针矩形内部有另外一个逆时针矩形内部矩形WN2。如果将任何一个矩形反向则内部矩形的WN为0。Positive(正数):WN0时是内部。Negative(负数):WN0时是内部。运算类型决定最终保留哪些区域。例如Intersection交集保留 WC 2 的区域。Union并集保留 WC 0 的区域。Difference差集保留 WC 1 的区域。XOR异或保留 WC1 的区域。交集并集异或都内部WC都是1外包都是0。差集被减数内部是1,减数内部是-1被减数减数外部是0。一个正方形的并path1逆时针path2 顺时针。Paths哪些块是内部由FillType和WN决定。奇偶publicForm1(){InitializeComponent();PathDpath1CreatePath(0,0,100);PathDpath2CreatePath(0,0,10);path2.Reverse();FillRulefrFillRule.EvenOdd;varps1Clipper.Union(newPathsD(newPathD[]{path1}),fr);varps2Clipper.Union(newPathsD(newPathD[]{path2}),fr);doublearea3Clipper.Area(ps1);doublearea4Clipper.Area(ps2);Console.WriteLine(FillRule:fr);Console.WriteLine(面积三area3);Console.WriteLine(面积四area4);}//创建正方形,点集合逆时针顺序PathDCreatePath(doublexCenter,doubleyCenter,doublehalfLen){PointD[]pts{newPointD(xCenter-halfLen,yCenter-halfLen),newPointD(xCenterhalfLen,yCenter-halfLen),newPointD(xCenterhalfLen,yCenterhalfLen),newPointD(xCenter-halfLen,yCenterhalfLen)};returnnewPathD(pts);}运行结果FillRule:EvenOdd面积三40000面积四400path1的WN1,path2的WN-1都是奇数故都是内部。非0只修改一行代码FillRulefrFillRule.NonZero;FillRule:NonZero面积三40000面积四400± 1 \pm 1±1都非0故都是内部。正数FillRulefrFillRule.Positive;FillRule:Positive面积三40000面积四0负数FillRulefrFillRule.Negative;FillRule:Negative面积三0面积四4001个paths 2个path的并path1逆时针矩形path2逆时针矩形path2完全在path1内部。path2反转后形成path3即path3顺时针。path2内部WN2path3内部WN0;path1内部非空洞WN1。奇偶publicForm1(){InitializeComponent();PathDpath1CreatePath(0,0,100);PathDpath2CreatePath(0,0,10);PathDpath3CreatePath(0,0,10);path3.Reverse();Console.WriteLine(面积一Clipper.Area(path1));Console.WriteLine(面积二Clipper.Area(path2));Console.WriteLine(面积三Clipper.Area(path3));FillRulefrFillRule.EvenOdd;varps12Clipper.Union(newPathsD(newPathsD(){path1,path2}),fr);varps13Clipper.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(xCenterhalfLen,yCenter-halfLen),newPointD(xCenterhalfLen,yCenterhalfLen),newPointD(xCenter-halfLen,yCenterhalfLen)};returnnewPathD(pts);}面积一40000面积二400面积三-400EvenOdd面积一二39600面积一三39600非零只修改一行。FillRulefrFillRule.NonZero;面积一40000面积二400面积三-400NonZero面积一二40000面积一三39600正数FillRulefrFillRule.Positive;面积一40000面积二400面积三-400Positive面积一二40000面积一三39600负数FillRulefrFillRule.Negative;面积一40000面积二400面积三-400Negative面积一二0面积一三0两个paths的交集path1,path2的WN1path3的WN-1奇偶PathDpath1CreatePath(0,0,100);PathDpath2CreatePath(0,0,10);PathDpath3CreatePath(0,0,10);path3.Reverse();Console.WriteLine(面积一Clipper.Area(path1));Console.WriteLine(面积二Clipper.Area(path2));Console.WriteLine(面积三Clipper.Area(path3));FillRulefrFillRule.EvenOdd;varps12Clipper.Intersect(newPathsD(newPathsD(){path1}),newPathsD(newPathsD(){path2}),fr);varps13Clipper.Intersect(newPathsD(newPathsD(){path1}),newPathsD(newPathsD(){path3}),fr);Console.WriteLine(fr);Console.WriteLine(面积一二Clipper.Area(ps12));Console.WriteLine(面积一三Clipper.Area(ps13));面积一40000面积二400面积三-400EvenOdd面积一二400面积一三400非0FillRulefrFillRule.NonZero;面积一40000面积二400面积三-400NonZero面积一二400面积一三400正数面积一40000面积二400面积三-400Positive面积一二400面积一三0负数面积一40000面积二400面积三-400Negative面积一二0面积一三0两个paths的差集奇偶面积一40000面积二400面积三-400EvenOdd面积一二39600面积一三39600非0面积一40000面积二400面积三-400NonZero面积一二39600面积一三39600正数面积一40000面积二400面积三-400Positive面积一二39600负数面积一40000面积二400面积三-400Negative面积一二0面积一三0两个paths的交集 异或奇偶面积一40000面积二400面积三-400EvenOdd面积一二39600面积一三39600非0面积一40000面积二400面积三-400NonZero面积一二39600面积一三39600正数面积一40000面积二400面积三-400Positive面积一二39600面积一三40000负数面积一40000面积二400面积三-400Negative面积一二0面积一三400返回值Clipper的返回值可以认为是Even-Odd或者Non-Zero中任意一种即兼容这两种填充方式。演示工具演示工具基于Cad支持Cad2013及更高版本。亲士库版本2026.9.4Cliper库版本2.0.0.0点击下载亲士数学演示工具箱如果不会操作请看视频https://edu.csdn.net/course/detail/41418建议用工具尝试以下情况四种填充方式部分多边形相离部分多边形相切部分多边形相离。部分多边形是凸多边形部分是凹多边形。由于布尔运算容易理解故工具只演示一个Path的并。如果不想可视频或操作可直接看图片。奇偶模式的并集01模式的并集正数并集负数并集并集也可能为空。上图红色三角形WN是1。黄色三角形是0穿过三角形是-1,穿过矩形是1。红色矩形是1。全部不是负数。扩展阅读计算几何为骨排样优化为魂作品亲士CAD工具箱经典文章推荐二维排样万物皆数学查阅鄙人的博文请点击博文下载学院导航活到老学到老。明朝中后期大约50%的进士能当上堂官(副部及更高)能当上堂官的举人只有十余人。子墨子言之事无终始无务多业。也就是我们常说的专业的人做专业的事。测试环境操作系统win7 开发环境 VS2019C17或者 操作系统win10 开发环境 VS2022C17如无特殊说明本算法用**C**实现。
返回列表