def setup_class(self): self.qt = Node(0, 0, 90, 90) # put a 9x9 tile on every 3 horizontal and vertical units [ self.qt.insert(Rectangle(x, y, x + 9, y + 9)) for x in range(0, 80, 3) for y in range(0, 80, 3) ] assert len(self.qt.get_children()) == 27 * 27
def setup_class(self): self.qt = Node(0, 0, 1000, 1000) # fill with 10x10 squares [ self.qt.insert(Rectangle(x, y, x + 10, y + 10)) for x in range(0, 1000, 10) for y in range(0, 1000, 10) ] assert len(self.qt.get_children()) == 10000
def test_item_crossing_border(self, max_depth, coords): # adding item that cross borders shouldn't trigger nested subdivisions qt = Node(0, 0, 1024, 1024, max_depth) assert qt._get_depth() == 0 assert qt._get_number_of_nodes() == 1 rect = Rectangle(*coords) qt.insert(rect) assert qt.get_children() == [rect] assert qt._get_depth() == 1 assert qt._get_number_of_nodes() == 5
def test_insert_and_reinsert(self, quadtree_bounds, max_depth): params = quadtree_bounds + (max_depth, ) qt = Node(*params) rect = random_rectangle(quadtree_bounds) print 'Testing with {0}, {1}'.format(qt, rect) # shown if test fails assert qt.direct_children == [] assert qt.get_children() == [] qt.insert(rect) assert qt.get_children() == [rect] qt.reinsert(rect) assert qt.get_children() == [rect]
def test_clear(self): qt = Node(0, 0, 1000, 1000) [qt.insert(random_rectangle(qt.bounds)) for _ in range(300)] assert len(qt.get_children()) == 300 assert qt._get_depth() in [3, 4] # can't know for sure qt.clear() assert qt.get_children() == [] assert qt.direct_children == []
class Test_tiled_overlapping_tiles: def setup_class(self): self.qt = Node(0, 0, 90, 90) # put a 9x9 tile on every 3 horizontal and vertical units [ self.qt.insert(Rectangle(x, y, x + 9, y + 9)) for x in range(0, 80, 3) for y in range(0, 80, 3) ] assert len(self.qt.get_children()) == 27 * 27 ### enclose ### def enclose(self, x1, y1, x2, y2): return self.qt.get_enclosed_children((x1, y1, x2, y2)) def test_enclose_all(self): assert len(self.enclose(-1, -1, 91, 91)) == 27 * 27 assert len(self.enclose(0, 0, 90, 90)) == 27 * 27 def test_enclose_each_30x30(self): for x in range(0, 51, 3): # some couldn't fit near the end bounds for y in range(0, 51, 3): # so skip looking for them assert len(self.enclose(x, y, x + 30, y + 30)) == 64 ### overlap ### def overlap(self, x1, y1, x2, y2): return self.qt.get_overlapped_children((x1, y1, x2, y2)) def test_overlap_all(self): assert len(self.overlap(-1, -1, 91, 91)) == 27 * 27 assert len(self.overlap(0, 0, 91, 91)) == 27 * 27 assert len(self.overlap(2, 2, 88, 98)) == 27 * 27 ### under_point ### # this implicitly tests get_overlapped_children, skipped testing that # explicitly since it'd be too verbose def under(self, x, y): return self.qt.get_children_under_point(x, y) def test_under_point_each(self): # for these values it must be 9 rectangles under point, however for # some other values it might be up to 16 (at boundaries, e.g. at 9x9) for x in range(7, 80, 9): for y in range(7, 80, 9): assert len(self.under(x, y)) == 9 assert len(self.under(9, 9)) == 16
def setup_class(self): self.qt = Node(0, 0, 90, 90) # put a 9x9 tile on every 3 horizontal and vertical units [self.qt.insert(Rectangle(x, y, x + 9, y + 9)) for x in range(0, 80, 3) for y in range(0, 80, 3)] assert len(self.qt.get_children()) == 27 * 27
def setup_class(self): self.qt = Node(0, 0, 1000, 1000) # fill with 10x10 squares [self.qt.insert(Rectangle(x, y, x + 10, y + 10)) for x in range(0, 1000, 10) for y in range(0, 1000, 10)] assert len(self.qt.get_children()) == 10000
class Test_tiled_overlapping_tiles: def setup_class(self): self.qt = Node(0, 0, 90, 90) # put a 9x9 tile on every 3 horizontal and vertical units [self.qt.insert(Rectangle(x, y, x + 9, y + 9)) for x in range(0, 80, 3) for y in range(0, 80, 3)] assert len(self.qt.get_children()) == 27 * 27 ### enclose ### def enclose(self, x1, y1, x2, y2): return self.qt.get_enclosed_children((x1, y1, x2, y2)) def test_enclose_all(self): assert len(self.enclose(-1, -1, 91, 91)) == 27 * 27 assert len(self.enclose(0, 0, 90, 90)) == 27 * 27 def test_enclose_each_30x30(self): for x in range(0, 51, 3): # some couldn't fit near the end bounds for y in range(0, 51, 3): # so skip looking for them assert len(self.enclose(x, y, x + 30, y + 30)) == 64 ### overlap ### def overlap(self, x1, y1, x2, y2): return self.qt.get_overlapped_children((x1, y1, x2, y2)) def test_overlap_all(self): assert len(self.overlap(-1, -1, 91, 91)) == 27 * 27 assert len(self.overlap(0, 0, 91, 91)) == 27 * 27 assert len(self.overlap(2, 2, 88, 98)) == 27 * 27 ### under_point ### # this implicitly tests get_overlapped_children, skipped testing that # explicitly since it'd be too verbose def under(self, x, y): return self.qt.get_children_under_point(x, y) def test_under_point_each(self): # for these values it must be 9 rectangles under point, however for # some other values it might be up to 16 (at boundaries, e.g. at 9x9) for x in range(7, 80, 9): for y in range(7, 80, 9): assert len(self.under(x, y)) == 9 assert len(self.under(9, 9)) == 16
def test_insert_and_reinsert(self, quadtree_bounds, max_depth): params = quadtree_bounds + (max_depth,) qt = Node(*params) rect = random_rectangle(quadtree_bounds) print 'Testing with {0}, {1}'.format(qt, rect) # shown if test fails assert qt.direct_children == [] assert qt.get_children() == [] qt.insert(rect) assert qt.get_children() == [rect] qt.reinsert(rect) assert qt.get_children() == [rect]
def test(self, n_elems, quadtree_bounds, max_depth, change_bounds): rects = [random_rectangle(quadtree_bounds) for _ in range(n_elems)] params = quadtree_bounds + (max_depth, ) qt = Node(*params) [qt.insert(r) for r in rects] key = lambda r: r.bounds assert sorted(qt.get_children(), key=key) == sorted(rects, key=key) assert len(qt.get_children()) == n_elems shuffle(rects) for r in rects: if change_bounds: new_bounds = random_rectangle(quadtree_bounds).bounds r.bounds = new_bounds qt.reinsert(r) assert sorted(qt.get_children(), key=key) == sorted(rects, key=key)
def test(self, n_elems, quadtree_bounds, max_depth, removal_order): rects = [random_rectangle(quadtree_bounds) for _ in range(n_elems)] params = quadtree_bounds + (max_depth, ) qt = Node(*params) [qt.insert(r) for r in rects] key = lambda r: r.bounds assert sorted(qt.get_children(), key=key) == sorted(rects, key=key) assert len(qt.get_children()) == n_elems pop_element = [ lambda: rects.pop(0), lambda: rects.pop(), lambda: rects.pop(randint(0, len(rects) - 1)), ][removal_order] while rects: rect = pop_element() qt.remove(rect) assert sorted(qt.get_children(), key=key) == sorted(rects, key=key) assert qt.get_children() == []
def test(self, n_elems, quadtree_bounds, max_depth, change_bounds): rects = [random_rectangle(quadtree_bounds) for _ in range(n_elems)] params = quadtree_bounds + (max_depth,) qt = Node(*params) [qt.insert(r) for r in rects] key = lambda r: r.bounds assert sorted(qt.get_children(), key=key) == sorted(rects, key=key) assert len(qt.get_children()) == n_elems shuffle(rects) for r in rects: if change_bounds: new_bounds = random_rectangle(quadtree_bounds).bounds r.bounds = new_bounds qt.reinsert(r) assert sorted(qt.get_children(), key=key) == sorted(rects, key=key)
class Test_insert_and_remove_single_item_once: def setup_class(self): self.qt = Node(0, 0, 1000, 1000) self.rect = Rectangle(20, 20, 40, 40) def test_is_empty_after_initialization(self): assert self.qt.direct_children == [] assert self.qt.get_children() == [] def test_contains_rect_after_insert(self): self.qt.insert(self.rect) assert self.qt.get_children() == [self.rect] def test_is_empty_after_removing(self): self.qt.remove(self.rect) assert self.qt.direct_children == [] assert self.qt.get_children() == []
def test(self, n_elems, quadtree_bounds, max_depth, removal_order): rects = [random_rectangle(quadtree_bounds) for _ in range(n_elems)] params = quadtree_bounds + (max_depth,) qt = Node(*params) [qt.insert(r) for r in rects] key = lambda r: r.bounds assert sorted(qt.get_children(), key=key) == sorted(rects, key=key) assert len(qt.get_children()) == n_elems pop_element = [ lambda: rects.pop(0), lambda: rects.pop(), lambda: rects.pop(randint(0, len(rects) - 1)), ][removal_order] while rects: rect = pop_element() qt.remove(rect) assert sorted(qt.get_children(), key=key) == sorted(rects, key=key) assert qt.get_children() == []
class Test_tiled: def setup_class(self): self.qt = Node(0, 0, 1000, 1000) # fill with 10x10 squares [self.qt.insert(Rectangle(x, y, x + 10, y + 10)) for x in range(0, 1000, 10) for y in range(0, 1000, 10)] assert len(self.qt.get_children()) == 10000 ### enclose ### def enclose(self, x1, y1, x2, y2): return self.qt.get_enclosed_children((x1, y1, x2, y2)) def test_enclose_all(self): assert len(self.enclose(-1, -1, 1001, 1001)) == 10000 assert len(self.enclose(0, 0, 1000, 1000)) == 10000 def test_enclose_each(self): for x in range(0, 1000, 10): for y in range(0, 1000, 10): exp = Rectangle(x, y, x + 10, y + 10) assert self.enclose(x - 1, y - 1, x + 11, y + 11) == [exp] def test_enclose_some(self): got = sorted(self.enclose(377, 499, 401, 601), key=key) exp = sorted([ Rectangle(380, 500, 390, 510), Rectangle(390, 500, 400, 510), Rectangle(380, 510, 390, 520), Rectangle(390, 510, 400, 520), Rectangle(380, 520, 390, 530), Rectangle(390, 520, 400, 530), Rectangle(380, 530, 390, 540), Rectangle(390, 530, 400, 540), Rectangle(380, 540, 390, 550), Rectangle(390, 540, 400, 550), Rectangle(380, 550, 390, 560), Rectangle(390, 550, 400, 560), Rectangle(380, 560, 390, 570), Rectangle(390, 560, 400, 570), Rectangle(380, 570, 390, 580), Rectangle(390, 570, 400, 580), Rectangle(380, 580, 390, 590), Rectangle(390, 580, 400, 590), Rectangle(380, 590, 390, 600), Rectangle(390, 590, 400, 600), ], key=key) assert got == exp ### overlap ### def overlap(self, x1, y1, x2, y2): return self.qt.get_overlapped_children((x1, y1, x2, y2)) def test_overlap_all(self): assert len(self.overlap(-1, -1, 1001, 1001)) == 10000 assert len(self.overlap(0, 0, 1000, 1000)) == 10000 assert len(self.overlap(8, 8, 992, 992)) == 10000 def test_overlap_each(self): # overlap at the corner where 4 rectangles meet for x in range(10, 1000, 10): for y in range(10, 1000, 10): exp = sorted([ Rectangle(x - 10, y - 10, x, y), Rectangle(x - 10, y, x, y + 10), Rectangle(x, y, x + 10, y + 10), Rectangle(x, y - 10, x + 10, y), ], key=key) got = sorted(self.overlap(x - 1, y - 1, x + 1, y + 1), key=key) assert got == exp def test_overlap_some(self): got = sorted(self.overlap(387, 501, 391, 591), key=key) exp = sorted([ Rectangle(380, 500, 390, 510), Rectangle(390, 500, 400, 510), Rectangle(380, 510, 390, 520), Rectangle(390, 510, 400, 520), Rectangle(380, 520, 390, 530), Rectangle(390, 520, 400, 530), Rectangle(380, 530, 390, 540), Rectangle(390, 530, 400, 540), Rectangle(380, 540, 390, 550), Rectangle(390, 540, 400, 550), Rectangle(380, 550, 390, 560), Rectangle(390, 550, 400, 560), Rectangle(380, 560, 390, 570), Rectangle(390, 560, 400, 570), Rectangle(380, 570, 390, 580), Rectangle(390, 570, 400, 580), Rectangle(380, 580, 390, 590), Rectangle(390, 580, 400, 590), Rectangle(380, 590, 390, 600), Rectangle(390, 590, 400, 600), ], key=key) assert got == exp ### under_point ### def under(self, x, y): return self.qt.get_children_under_point(x, y) def test_under_point_each(self): for x in range(10, 1000, 10): for y in range(10, 1000, 10): exp = [Rectangle(x, y, x + 10, y + 10)] got = self.under(x + randint(1, 9), y + randint(1, 9)) assert got == exp
def test_reinsert_into_same_quadrant(self, max_depth): bounds = (0.001, 0.001, 0.002, 0.002) qt = Node(0, 0, 1024, 1024, max_depth) assert qt._get_depth() == 0 assert qt._get_number_of_nodes() == 1 rect = Rectangle(*bounds) qt.insert(rect) assert qt._get_depth() == max_depth assert qt._get_number_of_nodes() == 1 + max_depth * 4 # make sure that top-left quadrant is the only one subdivided depths = [qt.quadrants[i]._get_depth() for i in range(4)] assert depths == [max_depth - 1, 0, 0, 0] # change coords and reinsert into same place qt.reinsert(rect) assert qt._get_depth() == max_depth assert qt._get_number_of_nodes() == 1 + max_depth * 4 depths = [qt.quadrants[i]._get_depth() for i in range(4)] assert depths == [max_depth - 1, 0, 0, 0]
def test_reinsert_into_another_quadrant(self, max_depth): bounds_1 = (0.01, 0.01, 0.02, 0.02) bounds_2 = (1023.998, 1023.998, 1023.999, 1023.999) qt = Node(0, 0, 1024, 1024, max_depth) assert qt._get_depth() == 0 assert qt._get_number_of_nodes() == 1 rect = Rectangle(*bounds_1) qt.insert(rect) assert qt._get_depth() == max_depth assert qt._get_number_of_nodes() == 1 + max_depth * 4 # make sure that top-left quadrant is the only one subdivided depths = [qt.quadrants[i]._get_depth() for i in range(4)] assert depths == [max_depth - 1, 0, 0, 0] # change coords and reinsert rect.bounds = bounds_2 qt.reinsert(rect) assert qt._get_depth() == max_depth assert qt._get_number_of_nodes() == 1 + max_depth * 4 # make sure that bottom-right quadrant is the only one subdivided depths = [qt.quadrants[i]._get_depth() for i in range(4)] assert depths == [0, 0, 0, max_depth - 1]
def test_insert_two_at_different_locations(self): qt = Node(0, 0, 1000, 1000) rect1 = Rectangle(10, 10, 20, 20) rect2 = Rectangle(800, 800, 900, 900) qt.insert(rect1) qt.insert(rect2) assert qt.get_children() == [rect1, rect2] qt.remove(rect1) assert qt.get_children() == [rect2] qt.insert(rect1) assert qt.get_children() == [rect1, rect2] qt.remove(rect2) assert qt.get_children() == [rect1] qt.remove(rect1) assert qt.get_children() == [] assert qt.direct_children == []
def setup_class(self): self.qt = Node(0, 0, 1000, 1000) self.rect = Rectangle(20, 20, 40, 40)
def test_insert_small_rect_in_corner(self, max_depth, coords): # inserting small rectangle in top left corner should make the # quadtree perform maximum number of subdivisions qt = Node(0, 0, 1024, 1024, max_depth) assert qt._get_depth() == 0 assert qt._get_number_of_nodes() == 1 rect = Rectangle(*coords) qt.insert(rect) assert qt._get_depth() == max_depth assert qt._get_number_of_nodes() == 1 + max_depth * 4 qt.remove(rect) assert qt._get_depth() == 0 assert qt._get_number_of_nodes() == 1
class Test_tiled: def setup_class(self): self.qt = Node(0, 0, 1000, 1000) # fill with 10x10 squares [ self.qt.insert(Rectangle(x, y, x + 10, y + 10)) for x in range(0, 1000, 10) for y in range(0, 1000, 10) ] assert len(self.qt.get_children()) == 10000 ### enclose ### def enclose(self, x1, y1, x2, y2): return self.qt.get_enclosed_children((x1, y1, x2, y2)) def test_enclose_all(self): assert len(self.enclose(-1, -1, 1001, 1001)) == 10000 assert len(self.enclose(0, 0, 1000, 1000)) == 10000 def test_enclose_each(self): for x in range(0, 1000, 10): for y in range(0, 1000, 10): exp = Rectangle(x, y, x + 10, y + 10) assert self.enclose(x - 1, y - 1, x + 11, y + 11) == [exp] def test_enclose_some(self): got = sorted(self.enclose(377, 499, 401, 601), key=key) exp = sorted([ Rectangle(380, 500, 390, 510), Rectangle(390, 500, 400, 510), Rectangle(380, 510, 390, 520), Rectangle(390, 510, 400, 520), Rectangle(380, 520, 390, 530), Rectangle(390, 520, 400, 530), Rectangle(380, 530, 390, 540), Rectangle(390, 530, 400, 540), Rectangle(380, 540, 390, 550), Rectangle(390, 540, 400, 550), Rectangle(380, 550, 390, 560), Rectangle(390, 550, 400, 560), Rectangle(380, 560, 390, 570), Rectangle(390, 560, 400, 570), Rectangle(380, 570, 390, 580), Rectangle(390, 570, 400, 580), Rectangle(380, 580, 390, 590), Rectangle(390, 580, 400, 590), Rectangle(380, 590, 390, 600), Rectangle(390, 590, 400, 600), ], key=key) assert got == exp ### overlap ### def overlap(self, x1, y1, x2, y2): return self.qt.get_overlapped_children((x1, y1, x2, y2)) def test_overlap_all(self): assert len(self.overlap(-1, -1, 1001, 1001)) == 10000 assert len(self.overlap(0, 0, 1000, 1000)) == 10000 assert len(self.overlap(8, 8, 992, 992)) == 10000 def test_overlap_each(self): # overlap at the corner where 4 rectangles meet for x in range(10, 1000, 10): for y in range(10, 1000, 10): exp = sorted([ Rectangle(x - 10, y - 10, x, y), Rectangle(x - 10, y, x, y + 10), Rectangle(x, y, x + 10, y + 10), Rectangle(x, y - 10, x + 10, y), ], key=key) got = sorted(self.overlap(x - 1, y - 1, x + 1, y + 1), key=key) assert got == exp def test_overlap_some(self): got = sorted(self.overlap(387, 501, 391, 591), key=key) exp = sorted([ Rectangle(380, 500, 390, 510), Rectangle(390, 500, 400, 510), Rectangle(380, 510, 390, 520), Rectangle(390, 510, 400, 520), Rectangle(380, 520, 390, 530), Rectangle(390, 520, 400, 530), Rectangle(380, 530, 390, 540), Rectangle(390, 530, 400, 540), Rectangle(380, 540, 390, 550), Rectangle(390, 540, 400, 550), Rectangle(380, 550, 390, 560), Rectangle(390, 550, 400, 560), Rectangle(380, 560, 390, 570), Rectangle(390, 560, 400, 570), Rectangle(380, 570, 390, 580), Rectangle(390, 570, 400, 580), Rectangle(380, 580, 390, 590), Rectangle(390, 580, 400, 590), Rectangle(380, 590, 390, 600), Rectangle(390, 590, 400, 600), ], key=key) assert got == exp ### under_point ### def under(self, x, y): return self.qt.get_children_under_point(x, y) def test_under_point_each(self): for x in range(10, 1000, 10): for y in range(10, 1000, 10): exp = [Rectangle(x, y, x + 10, y + 10)] got = self.under(x + randint(1, 9), y + randint(1, 9)) assert got == exp