2008-01-09 14:40:04 +00:00
|
|
|
#!/usr/bin/env python
|
|
|
|
import sys
|
|
|
|
INF = sys.maxint
|
|
|
|
|
|
|
|
|
|
|
|
## Rect
|
|
|
|
##
|
|
|
|
class Rect:
|
|
|
|
|
2008-05-06 10:57:41 +00:00
|
|
|
def __init__(self, x=-INF, y=-INF, width=None, height=None):
|
|
|
|
self.x0 = x
|
|
|
|
self.y0 = y
|
|
|
|
if width == None:
|
2008-01-09 14:40:04 +00:00
|
|
|
self.x1 = INF
|
|
|
|
else:
|
2008-05-06 10:57:41 +00:00
|
|
|
self.x1 = x+width
|
|
|
|
if height == None:
|
2008-01-09 14:40:04 +00:00
|
|
|
self.y1 = INF
|
|
|
|
else:
|
2008-05-06 10:57:41 +00:00
|
|
|
self.y1 = y+height
|
2008-01-09 14:40:04 +00:00
|
|
|
return
|
|
|
|
|
2008-04-26 06:47:56 +00:00
|
|
|
def __repr__(self):
|
2008-05-06 10:57:41 +00:00
|
|
|
return '<Rect: (%d,%d) (%dx%d)>' % (self.x0, self.y0, self.x1-self.x0, self.y1-self.y0)
|
2008-04-26 06:47:56 +00:00
|
|
|
|
2008-01-09 14:40:04 +00:00
|
|
|
def overlap(self, rect):
|
|
|
|
return not (rect.x1 <= self.x0 or self.x1 <= rect.x0 or
|
|
|
|
rect.y1 <= self.y0 or self.y1 <= rect.y0)
|
|
|
|
|
|
|
|
|
2008-05-06 10:57:41 +00:00
|
|
|
## ExtGrid
|
2008-01-09 14:40:04 +00:00
|
|
|
##
|
2008-05-06 10:57:41 +00:00
|
|
|
class ExtGrid:
|
2008-01-09 14:40:04 +00:00
|
|
|
|
|
|
|
def __init__(self, gridsize):
|
|
|
|
self.gridsize = gridsize
|
2008-05-06 10:57:41 +00:00
|
|
|
self.gridy = {}
|
2008-01-09 14:40:04 +00:00
|
|
|
return
|
2008-05-06 10:57:41 +00:00
|
|
|
|
|
|
|
def __repr__(self):
|
|
|
|
return '<ExtGrid(size=%d): %r>' % (self.gridsize, self.gridy)
|
2008-01-09 14:40:04 +00:00
|
|
|
|
|
|
|
def cells(self, x0, x1):
|
|
|
|
i = int(x0 / self.gridsize)
|
|
|
|
x = i * self.gridsize
|
|
|
|
while x < x1:
|
|
|
|
yield i
|
|
|
|
x += self.gridsize
|
|
|
|
i += 1
|
|
|
|
return
|
|
|
|
|
2008-05-06 10:57:41 +00:00
|
|
|
def add(self, rect, obj):
|
|
|
|
if isinstance(rect, tuple): rect = Rect(*rect)
|
|
|
|
xcells = list(self.cells(rect.x0, rect.x1))
|
|
|
|
for y in self.cells(rect.y0, rect.y1):
|
|
|
|
if y not in self.gridy:
|
|
|
|
gridx = {}
|
|
|
|
self.gridy[y] = gridx
|
2008-04-26 06:47:56 +00:00
|
|
|
else:
|
2008-05-06 10:57:41 +00:00
|
|
|
gridx = self.gridy[y]
|
|
|
|
for x in xcells:
|
|
|
|
assert isinstance(gridx, dict), gridx
|
|
|
|
if x not in gridx:
|
|
|
|
objs = []
|
|
|
|
gridx[x] = objs
|
|
|
|
else:
|
|
|
|
objs = gridx[x]
|
|
|
|
objs.append((rect, obj))
|
|
|
|
assert isinstance(gridx, dict), gridx
|
2008-01-09 14:40:04 +00:00
|
|
|
return
|
|
|
|
|
2008-05-06 10:57:41 +00:00
|
|
|
def get(self, rect):
|
|
|
|
if isinstance(rect, tuple): rect = Rect(*rect)
|
2008-01-09 14:40:04 +00:00
|
|
|
objs = set()
|
2008-05-06 10:57:41 +00:00
|
|
|
xcells = list(self.cells(rect.x0, rect.x1))
|
|
|
|
for y in self.cells(rect.y0, rect.y1):
|
|
|
|
if y not in self.gridy: continue
|
|
|
|
gridx = self.gridy[y]
|
|
|
|
for x in xcells:
|
|
|
|
if x not in gridx: continue
|
|
|
|
objs.update( obj for (r,obj) in gridx[x] if rect.overlap(r) )
|
2008-01-09 14:40:04 +00:00
|
|
|
return objs
|
|
|
|
|
2008-05-06 10:57:41 +00:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
e = ExtGrid(10)
|
2008-01-09 14:40:04 +00:00
|
|
|
assert list(e.cells(-1, 1)) == [-1,0]
|
|
|
|
assert list(e.cells(0, 1)) == [0]
|
|
|
|
assert list(e.cells(0, 10)) == [0]
|
|
|
|
assert list(e.cells(0, 11)) == [0,1]
|
|
|
|
assert list(e.cells(1, 11)) == [0,1]
|
|
|
|
assert list(e.cells(10, 11)) == [1]
|
|
|
|
assert list(e.cells(0, 20)) == [0,1]
|
|
|
|
assert list(e.cells(10, 20)) == [1]
|
|
|
|
assert list(e.cells(1,21)) == [0,1,2]
|
|
|
|
assert list(e.cells(11,21)) == [1,2]
|
2008-05-06 10:57:41 +00:00
|
|
|
e.add((0,0,10,10), 'a')
|
|
|
|
e.add((10,10,10,10), 'b')
|
|
|
|
e.add((5,5,5,10), 'c')
|
|
|
|
assert sorted(e.get((0,0,1,1))) == ['a']
|
|
|
|
assert sorted(e.get((10,10,1,1))) == ['b']
|
|
|
|
assert sorted(e.get((5,10,10,10))) == ['b','c']
|
|
|
|
assert sorted(e.get((5,5,10,10))) == ['a','b','c']
|