边界框布尔减法?

时间:2010-10-25 00:11:37

标签: boolean subtraction bounding

从另一个边界框中减去边界框的最佳或有效方法是什么(即从边界框布尔减法创建n个边界框)?

理想情况下,生成的边界框尽可能是正方形,因此存在有限的“碎片”(即1宽度,1高度,100深度)。

1 个答案:

答案 0 :(得分:0)

这个问题很老了,但是既然我做了,我就会回答它。

首先将两个范围(边界框)视为同心正方形。我们从外部减去内部的那个。

A----------------------------------B
|                                  |
|     A----------------------B     |
|     |                      |     |
|     |                      |     |
|     D----------------------C     |
|                                  |
D----------------------------------C

然后你最终会得到8个盒子。

A----------------------------------B
|  1  |           2          |  3  |
|----------------------------------|
|     |                      |  4  |
|  8  |                      |     |
|----------------------------------|
|  7  |           6          |  5  |
D----------------------------------C

所以,诀窍是制作正方形。大多数图形库都有代码来处理范围'。我将在Javascript中使用OpenLayers作为示例。这个想法是你通过从每对点绘制一个对角线并获得它的边界框来制作范围(边界框),然后使用一些先前制作的边界框的点向下级联。下面的代码应该是自我解释的。我们从范围e1减去范围e2,其被描绘为内部范围,其被描绘为外部范围:

  var b1 = ol.extent.boundingExtent([ol.extent.getTopLeft(e1), ol.extent.getTopLeft(e2)]);
  var b2 = ol.extent.boundingExtent([ol.extent.getBottomLeft(b1), ol.extent.getBottomLeft(e2)]);
  var b3 = ol.extent.boundingExtent([ol.extent.getBottomLeft(e1), ol.extent.getBottomLeft(e2)]);
  var b4 = ol.extent.boundingExtent([ol.extent.getBottomLeft(b3), ol.extent.getBottomRight(e2)]);
  var b5 = ol.extent.boundingExtent([ol.extent.getBottomRight(e1), ol.extent.getBottomRight(e2)]);
  var b6 = ol.extent.boundingExtent([ol.extent.getBottomRight(b5), ol.extent.getTopRight(e2)]);
  var b7 = ol.extent.boundingExtent([ol.extent.getTopRight(e1), ol.extent.getTopRight(e2)]);
  var b8 = ol.extent.boundingExtent([ol.extent.getTopLeft(e1), ol.extent.getTopLeft(b7)]);

例如,请注意我们如何使用边界框b1中的坐标来生成b2,b3来生成b4等。

现在我们知道范围可能不是同心的。有些方框可能不在我们的答案范围内。然而,需要注意的一个很酷的条件是,如果减去范围(e2)的一个角落在基础范围(e1)内,那么我们需要三个连接的框。因此,如果e2的左上角是e1,那么我们需要b1,b2和b8。同样,如果e2的左下角在e1中,那么我们需要b6,b7和b8。您可能会注意到某些重复项,例如b8,但我们稍后会对其进行过滤。所以,让我们收集我们的结果。

  var results = [];
  if (ol.extent.containsCoordinate(e1, ol.extent.getTopLeft(e2))) {
    results.push(b1, b2, b3);
  }
  if (ol.extent.containsCoordinate(e1, ol.extent.getTopRight(e2))) {
    results.push(b8, b7, b6);
  }
  if (ol.extent.containsCoordinate(e1, ol.extent.getBottomRight(e2))) {
    results.push(b6, b5, b4);
  }
  if (ol.extent.containsCoordinate(e1, ol.extent.getBottomLeft(e2))) {
    results.push(b2, b3, b4);
  }

消除重复,但也要注意这样一个事实,特别是在范围共享边界的情况下,其中一些框将是空的"。通常,您可以使用与范围相关的getArea()函数来解决这个问题。下面是一个聪明的javascript方法来过滤掉数组中的重复对象,因为Array.indexOf使用' ==='并仅返回其第一场比赛。而且,我们只收集实际上有一个区域的盒子。

results = results.filter(function(a,i,arr) {
             return arr.indexOf(a) === i && ol.extent.getArea(a) > 0;
          });

使用注意事项:

请注意,如果两个初始边界框不相交,则会产生一个空列表。因此,此方法仅适用于相交的范围。图形库通常具有两个范围交叉的布尔函数。

例如,如果您要加载潜在范围(e1)减去已经加载的(e2)并且它们不相交,您可能只想直接加载e1。取决于您的申请。

希望这个答案对某人有用!