我正在编写一个基于整数的四叉树结构,它从节点构建而不是向下构建。为此,我需要发现包含所有元素的下一个最大节点。如果我定义了一个预先存在的节点,那么尝试在该节点的边界之外添加一个项目,它需要创建一个更大的节点来包含它们。我有(我认为是聪明的)代码,用于查找单个点周围的边界框:
public static Rectangle BoundingRectangle(Point p, int magnitude)
{
Rectangle bounds = new Rectangle()
{
X = (p.X & ~((1 << magnitude) - 1)),
Y = (p.Y & ~((1 << magnitude) - 1)),
Width = (1 << magnitude),
Height = (1 << magnitude)
};
return bounds;
}
[注意,点(0,0)周围的方框是位置(0,0)的大小(1,1),不位置(-.5, - .5) ),因为它都是基于整数的]
这将始终(从我所知道的)返回一个适合作为节点的四叉树的框。例如,new Rectangle(0,0,2,2)
是可以接受的,new Rectangle(2,2,2,2)
也是如此,但new Rectangle(1,1,2,2)
不会。
我的问题是我无法弄清楚如何为矩形而不是一个点完成此操作。我能想到的唯一解决方案是循环增加数量级的方框,但我确信必须有一些我无法想到的O(1)解决方案。
示例:
Rectangle(X,Y,1,1) -> Rectangle(X,Y,1,1)
Rectangle(0,0,2,2) -> Rectangle(0,0,2,2)
Rectangle(1,1,2,2) -> Rectangle(0,0,4,4)
Rectangle(1,1,3,3) -> Rectangle(0,0,4,4)
Rectangle(0,5,2,2) -> Rectangle(0,4,4,4)
Rectangle(3,3,2,2) -> Rectangle(0,0,8,8)
实施
private static int BitScanReverse(int mask)
{
int index = 0;
while (mask > 1)
{
mask >>= 1;
index++;
}
return index;
}
public static Rectangle BoundingRectangle(Point p, int magnitude)
{
Rectangle bounds = new Rectangle()
{
X = (p.X & ~((1 << magnitude) - 1)),
Y = (p.Y & ~((1 << magnitude) - 1)),
Width = (1 << magnitude),
Height = (1 << magnitude)
};
return bounds;
}
public static Rectangle BoundingRectangle(Rectangle r, int magnitude)
{
int msb = BitScanReverse((r.X ^ (r.X + r.Width - 1)) | (r.Y ^ (r.Y + r.Height - 1)));
return BoundingRectangle(r.Location, Math.Max(msb + 1, magnitude));
}
答案 0 :(得分:3)
让我们先考虑一维的一维版本。我们有一个偏移和长度,而不是一个矩形。
边界矩形的“幅度”告诉你要忽略多少位。
假设offset = 1234且length = 56.我们要忽略足够的位,以便'offset'(1234)和'offset + length-1'(1289)映射到相同的数字。
1234 = 10011010010
1289 = 10100001001
显然,我们需要忽略除前两位之外的所有位(忽略9位)。
我们可以通过1234 XOR 1289(475)
以编程方式找到它1234 = 10011010010
1289 = 10100001001
475 = 00111011011
然后找到最重要的设置位475.大多数处理器都有此指令(在Windows上,它是_BitScanReverse)。
现在,对于2D情况,我们需要获得X轴和Y轴的XOR。然后,我们将这两个结果合并在一起。最后,找到最重要的设置位。
所以,在伪代码中:
magnitude = MSBof( ( X ^ (X+width-1) ) | ( Y ^ (Y+height-1) ) )
要获取实际的矩形,只需使用帖子中的功能即可。传入新的点(X,Y)。