【问题标题】:How to calculate total volume of multiple overlapping cuboids如何计算多个重叠长方体的总体积
【发布时间】:2012-10-07 13:49:56
【问题描述】:

我有一个长方体列表,由它们的左下角和右上角的坐标定义,边缘平行于轴。坐标是双精度值。这些长方体密集排列,会与一个或多个其他方体重叠,甚至完全包含其他方体。

我需要计算所有给定长方体所包含的总体积。重叠(甚至多次)的区域应该只计算一次。

例如,卷:

  1. ((0,0,0) (3,3,3))
  2. ((0,1,0) (2,2,4))
  3. ((1,0,1) (2,5,2))
  4. ((6,6,6) (8,8,8))

总音量为 27 + 1 + 2 + 8 = 38。 有没有一种简单的方法可以做到这一点(在 O(n^3) 时间或更好的时间内?)?

【问题讨论】:

  • 尝试分而治之的方法。根据它们属于垂直线的哪一侧,将长方体列表分成两组,并将与直线相交的长方体分成两部分。这可能会导致运行时间看起来像 T(n) = 2T(n/2) + cn。
  • @krjampani: 我猜你的意思是飞机
  • 是的!感谢您指出了这一点。但我现在认为扫描平面方法更适合这个问题。

标签: algorithm


【解决方案1】:

在处理每个不相交的长方体时如何维护一组不相交的长方体?

这个集合开始是空的。

第一个长方体将被添加到集合中——它将是唯一的元素,因此保证不会与其他任何元素相交。

第二个和后续的长方体将根据集合中的元素进行检查。对于每个新的长方体 N,对于集合中已经存在的每个元素 E

  • 如果 N 完全被 E 包含,则丢弃 N 并在下一个新长方体处继续处理。
  • 如果 N 完全包含 E,则从集合中删除 E 并继续针对其他元素测试 N在集合中。
  • 如果 NE 相交,则将 N 分成最多五个(见下面的注释)较小的长方体(取决于它们相交的方式)代表不相交的体积,并继续针对集合中的其他元素测试这些较小的长方体。

如果我们对具有一个或多个从 N 生成的长方体(表示由 N 贡献的体积)的非相交元素的测试结束,则t 在任何先前的长方体中)然后将它们全部添加到集合中并处理下一个长方体。

处理完所有长方体后,总体积将是已构建的非相交长方体集合中的体积总和。

【讨论】:

  • 最终我采用了这个解决方案(根据 E 的位置将 N 分成最多 26 个较小的长方体),因为这个功能已经内置到系统中了。
  • 谢谢,最终使用了这个逻辑。但是需要注意的是,拆分 N 最多可以生成 5 个新长方体,而不是 3 个。想象一个立方体与另一个 1x1x2 长方体相交于其中一个面的中间。
  • 谢谢@Patrick。我已更新答案文本以包含此内容。
【解决方案2】:

这可以使用平面扫描算法有效地解决,这是对建议here 的直线扫描算法的直接扩展,用于查找重叠矩形的总面积。

对于每个长方体,将其左右 x 坐标添加到事件队列中并对队列进行排序。现在扫过长方体的 yz 平面(具有恒定的 x 值)并记录事件队列中任意两个连续事件之间的体积。我们通过维护在任何阶段与平面相交的矩形列表来做到这一点

当我们扫过飞机时,我们会遇到两种类型的事件:

(1) 我们看到新长方体开始与扫掠平面相交。在这种情况下,一个新的矩形与平面相交,我们更新与扫描平面相交的矩形的面积。

(2) 与平面相交的现有长方体的末端。在这种情况下,我们必须从当前与平面相交的矩形列表中删除相应的矩形,并更新生成的矩形的新区域。

任意两个连续事件qi和qi+1之间的长方体体积等于两个事件之间的水平距离 在 qi 处与扫描线相交的矩形面积。

通过使用 O(nlogn) algorithm 作为计算矩形面积的子程序,我们可以得到一个 O(n2logn) 算法来计算长方体的总体积。但是可能有更好的方法来维护矩形(因为我们只在任何阶段添加或删除一个矩形)更有效。

【讨论】:

    【解决方案3】:

    我最近遇到了同样的问题,发现以下方法易于实施并且适用于 n 个维度。

    首先建立一个网格,然后检查网格中的每个单元格是否与长方体重叠。重叠长方体的体积是包含在一个或多个长方体中的那些单元的体积之和。

    • 用每个维度的最小值/最大值来描述您的长方体。
    • 对于每个维度,将每个立方体的最小/最大值存储在一个数组中。对该数组进行排序并删除重复项。
    • 现在您有了非等距网格的网格点。网格的每个单元格要么完全在一个或多个长方体内,要么不在。
    • 遍历网格单元并计算与一个或多个长方体重叠的单元的体积。

    您可以使用Cartesian Product获取所有网格单元格。

    【讨论】:

      【解决方案4】:

      我尝试了@ccssmnn 建议的蜂窝方法;它起作用了,但是太慢了。问题是用于“对于每个维度存储数组中每个长方体的最小/最大值”的数组大小。是O(n),因此单元数(因此,执行时间)是n^d,例如,三个维度的n^3

      接下来,按照@krjampani 的建议,我尝试了嵌套扫描线算法;快得多,但仍然太慢。我相信复杂度是n^2*log^3(n)

      所以现在,我想知道是否有任何追索权。我读过几篇提到使用interval treesaugmented interval trees 的帖子;这种方法是否可能具有更好的复杂性,例如n*log^3(n)

      另外,我想弄清楚在这种情况下增加的价值是多少?在点或范围查询的情况下,我可以看到按它们的(xlo,ylo,zlo) 对长方体进行排序,并为每个子树使用max(xhi,yhi,zhi) 作为增广值,但无法弄清楚如何扩展它以跟踪联合长方体及其体积。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-29
        • 1970-01-01
        • 2021-05-25
        • 2013-08-09
        • 1970-01-01
        • 2012-04-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多