【问题标题】:Compute union of two arbitrary shapes计算两个任意形状的并集
【发布时间】:2010-01-26 14:43:19
【问题描述】:

我正在开发一个应用程序,我需要能够组合用户绘制的两个重叠的任意形状。这将是对两个形状的联合操作。生成的形状将是两个重叠形状的轮廓。

形状按顺时针方向存储为一系列点。

理想情况下,我想要一个算法,它将采用两个点数组 (x,y) 并返回一个结果形状的数组。

我一直在阅读 Boolean operations on polygons 上的 Wikipedia,其中提到了 Sweep line algorithm,但我无法将这与我的目标联系起来,可惜我不是数学家。

我正在使用 ActionScript 3 开发应用程序,但我熟悉 C#、Java,并且我可以通过 C 和 C++ 选择自己的方式。

【问题讨论】:

    标签: math geometry boolean-operations


    【解决方案1】:

    正确实现布尔运算并非易事;幸运的是,已经有一些库实现了这个功能。

    您使用什么语言?如果是 C++,请查看 CGAL,计算几何算法库。

    【讨论】:

    • 谢谢,我在 AS3 中实现,但熟悉 C#、Java
    • 啊...好吧,我不确定 CGAL 源代码是否有那么有趣的分离和移植,因为它以非常通用的方式表达它的算法,模仿 STL ( IIRC,已经有一段时间了)。您最好移植链接到 Wikipedia 页面底部的更具体的库之一。或者,您可以简单地将两个多边形渲染为位图,然后对其执行布尔运算吗?
    • 我发现了支持 UNION 操作的 GPC code.google.com/p/gpcas 的 Java 端口的这个(部分)AS3 端口。感谢您的意见。
    • 很好的发现——看起来这正是您所需要的!
    【解决方案2】:

    给定两个点列表(A 和 B)
    - [ 1 ] 对于 A 中的每一行,它是否与 B 中的一条线相交
    -.- [2] 如果没有(更多)线相交,则没有重叠
    -.- [3] 如果 (A) 中的一条线与 B 中的一条线相交,则
    -.-.- [4] 将交点添加到输出中
    -.-.- [5] A 的下一行与 B 相交
    -.-.-.- [6] 如果没有,请将其添加到输出(在 B 内)转到 5
    -.-.-.- [7] 如果是,则将相交添加到输出并切换列表 A 和 B 转到 2

    另见Intersection Point Of Two Lines。对不起,我不会写代码:)

    【讨论】:

    • 感谢 Jon... 也应该说“添加逻辑以避免无限循环”
    • 当心——这个问题并不像你想象的那么简单。值得深思的是:A 中的一条线(或“边”)可能与 B 中的多条边相交。两个原始多边形可能不相交;或 A 可能完全位于 B 内;或 B 可能完全位于 A 内(尽管如果您仅查看线之间的交叉点,这三种情况看起来相同)。多边形不必是凸的,两个非凸多边形的并集可以有孔。等等……计算几何因有各种你一开始没有想到的特殊情况而臭名昭著。
    • 是的 Martin - A 组中的一条线可能与 B 组中的多条线交叉。因此,您需要从起点选择最近的交叉点。我正在尝试一种“填充缠绕”算法方法。
    • 感谢您的想法,伊恩。我正在我面前的垫子上查看一个非常相似的算法。它开始思考 Martin B 的一些观点,这让我开始寻找图书馆来为我做这件事。
    【解决方案3】:

    另见GPC

    【讨论】:

      【解决方案4】:

      this algorithm 适合你吗?

      【讨论】:

      • 这个算法计算交集; Greg B 正在寻找工会。此外,该算法仅在两个多边形及其交集都是凸的情况下才有效; Greg B 谈到“任意形状”,所以我认为他也希望能够处理非凸多边形。
      • 公平点马丁。我曾假设它们是凸形,并建议使用该算法作为找到两个交点的起点。
      • 此链接已失效
      【解决方案5】:

      怎么样:

      1. 选择两个形状中最左边的点。将该形状称为 A 并将其设为当前形状。
      2. 沿当前形状顺时针旋转到下一个点,并检查是否有一条或多条线相交。
        • 如果有任何线相交,请找到第一个交点并将其添加到您的新形状中。切换到沿其他形状缠绕。
        • 如果没有线相交,则移动到形状 A 中的下一个点,并将其添加为新形状中的点。继续沿当前形状缠绕。
      3. 重复第 2 步。

      我认为,如果您继续沿着当前的任何形状蜿蜒曲折,寻找交叉点,那应该可以满足您的需求。我认为这也应该处理凹形......

      我相信,一旦你掌握了基础知识,你可以添加很多优化。

      【讨论】:

        【解决方案6】:

        好像还有个javascript api:

        https://github.com/bjornharrtell/jsts/

        这似乎实现了 jts 标准并且有几个不同的实现:

        http://tsusiatsoftware.net/jts/jts-links.html#ports

        他们都应该能够执行联合等:

        http://tsusiatsoftware.net/jts/JTSUser/contents.html

        但 csg.js 是 IMO 最令人印象深刻的项目

        https://github.com/evanw/csg.js

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-12-13
          • 2015-11-04
          • 2018-03-30
          • 2021-10-21
          • 1970-01-01
          • 2018-03-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多