如何计算多个重叠长方体的总体积

时间:2012-10-07 13:49:57

标签: algorithm

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

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

例如,卷:

  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))
  5. 总音量为27 + 1 + 2 + 8 = 38。 有没有一种简单的方法(在O(n ^ 3)时间或更好?)?

4 个答案:

答案 0 :(得分:2)

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

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

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

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

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

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

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

答案 1 :(得分:2)

在处理每个长方体时,如何保持一组非相交的长方体?

此系列将开始为空。

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

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

  • 如果 N 完全包含在 E 中,请丢弃 N 并在下一个新的长方体处继续处理。
  • 如果 N 完全包含 E ,请从集合中删除 E 并继续针对其他元素测试 N 在集合中。
  • 如果 N E 相交,则将 N 分成一个,两个或三个较小的长方体(取决于它们如何相交),表示该体积不相交并继续测试这些较小的长方体与集合中的其他元素。

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

一旦处理了所有长方体,总体积将是已建立的非相交长方体集合中体积的总和。

答案 2 :(得分:0)

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

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

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

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

答案 3 :(得分:0)

我尝试了@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)作为增值,但无法弄清楚如何对其进行扩展以保持跟踪长方体的结合及其体积。