(这种方法遵循与@GarethRees 类似的想法:首先,廉价地发现哪些多边形对不需要检查是否包含。一旦仍然需要检查的对数是可以接受的,就做精确的(昂贵的)几何查看。)
很容易计算每个多边形 p 的边界矩形,即左、右、上和下,所以让我们先这样做。例如左侧:p.L = min { x : (x,y) is a vertex of p }
时间与点数成线性关系。
为避免将每个多边形相互比较,您可以将该区域划分为 2x2 网格。假设区域的宽度和高度分别由Dx
和给出Dy
,那么您可以创建九个集合top,bottom,left,right,topright,topleft,bottomright,bottomleft,rest
并执行以下操作:
for p in polygons:
in_top = p.B > Dy/2
in_bottom = p.T < Dy/2
in_left = p.R < Dx/2
in_right = p.L > Dx/2
if in_top:
if in_left:
add p to topleft
elsif in_right:
add p to topright
else:
add p to top
elsif in_bottom:
if in_left:
add p to bottomleft
elsif in_right:
add p to bottomright
else:
add p to bottom
if in_right and not (in_top or in_bottom):
add p to right
elsif in_left and not (in_top or in_bottom):
add p to left
if not (in_top or in_bottom or in_left or in_right):
add p to rest
这又是线性时间。每个多边形都被分箱到其最“紧密”的包含扇区中。你从中得到了什么?好吧,例如,您知道对于其中的任何多边形p
,left
都不可能与 set 存在任何包含关系right
,因此您无需比较它们。bottomleft
与right
、bottomleft
和之间topleft
也是如此,依此类推。这是您的示例中的样子:
Dx/2
+----------------------|---------------------+
| | |
| +----------------+ | +--------+ |
| | | | / | |
| | +--------+ | | / | |
|___|___|________|___|_|____ /__+===d(2)=+___|_ Dy/2
| | | | | | / | |
| | +---b(3)-+ | | / | +---+ |
| | | | +-----+ | | |
| +-----------c(2)-+ | e(2)+ |
| | |
+----------------------|----------------a(1)-+
所以rest = {a}, top = {}, bottom = {}, left = {b,c}, right = {d}
topleft = {}, topright = {}, bottomleft = {}, bottomright = {e}
所以基本上现在你最多需要比较(用昂贵的精确支票)b
to c
,d
toe
和a
所有其他人——事实上,如果你以聪明的方式订购支票,你就不需要与a
所有其他人比较,因为包含是传递性的,所以如果你注意到c
包含b
和a
包含c
,那么你不需要检查是否a
包含b
。
另一点是您可以递归地应用上述推理。比如说套装topright
太大了,不适合你的口味;然后,您可以通过进一步划分该子区域来应用相同的技术(只需要正确记账)。