从另一个边界框中减去一个边界框的最佳或有效方法是什么(即从边界框布尔减法创建 n 个边界框)?
理想情况下,生成的边界框尽可能是方形的,因此存在有限的“碎片”(即 1 宽度、1 高度、100 深度)。
从另一个边界框中减去一个边界框的最佳或有效方法是什么(即从边界框布尔减法创建 n 个边界框)?
理想情况下,生成的边界框尽可能是方形的,因此存在有限的“碎片”(即 1 宽度、1 高度、100 深度)。
这个问题很老了,但是既然我做到了,我会回答它。
首先将两个范围(边界框)视为同心正方形。我们从外部减去内部。
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。取决于您的应用程序。
希望这个答案对某人有用!