2010-10-25 71 views
2

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

理想情况下,由此产生的包围盒尽可能地平方,以便有限的“碎片”(即,1宽度,1高度,100深度)。

+0

是否有您喜欢的解决方案的特定语言,或者您刚刚使用算法? – 2010-10-25 00:17:49

+0

我使用c#,但如果有人用另一种语言,我可以很容易地转换它。 – 2010-10-25 00:37:12

+0

有没有这样的运气?你可以在JavaScript中做同样的事情吗? – Baz1nga 2011-04-26 22:02:58

回答

0

这个问题已经很老了,但自从我做到了,我会回答它。

首先想到两个范围(包围盒)作为同心正方形。我们从外部减去内部的一个。

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

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

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

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

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),那么您可能只想直接加载e1。取决于你的申请。

希望这答案对某人有用!