class TestQuadMethods(unittest.TestCase): def setUp(self): self.quad = QuadTree(Region(0,0, 256, 256)) def tearDown(self): self.quad = None def test_basic(self): self.assertTrue(self.quad.add((10, 20))) self.assertFalse(self.quad.add((10, 20))) self.assertTrue(self.quad.find((10,20))) self.assertFalse(self.quad.find((5, 5))) def expand(self, region): """When Full Sub-trees returned as nodes traverse to expand nodes.""" result = [p for p in self.quad.range(region)] expanded = [] for pair in result: if pair[1]: for d in pair[0].preorder(): if d.points != None: expanded = expanded + d.points else: expanded.append(pair[0][0]) return expanded def test_adding(self): for _ in range(500): self.quad.add((random.randint(25,225), random.randint(25,225))) # make sure not to overlap! q_ne = self.expand(Region(128, 128, 256, 256)) q_nw = self.expand(Region(0, 128, 128, 256)) q_sw = self.expand(Region(0, 0, 128, 128)) q_se = self.expand(Region(128, 0, 256, 128)) q_all = self.expand(Region(0,0, 256, 256)) # quick check to see if any were missing combined = q_ne + q_nw + q_sw + q_se for q in q_all: if q not in combined: print (q, " missing ") # check duplicates for i in range(len(combined)): for j in range(len(combined)): if j <= i: pass else: if combined[i] == combined[j]: print ("Duplicate:", combined[i]) self.assertEquals(len(q_all), len(combined))
class TestQuadMethods(unittest.TestCase): def setUp(self): self.quad = QuadTree(Region(0, 0, 256, 256)) def tearDown(self): self.quad = None def test_basic(self): self.assertTrue(self.quad.add((10, 20))) self.assertFalse(self.quad.add((10, 20))) self.assertTrue(self.quad.find((10, 20))) self.assertFalse(self.quad.find((5, 5))) def expand(self, region): """When Full Sub-trees returned as nodes traverse to expand nodes.""" result = [p for p in self.quad.range(region)] expanded = [] for pair in result: if pair[1]: for d in pair[0].preorder(): if d.points != None: expanded = expanded + d.points else: expanded.append(pair[0][0]) return expanded def test_adding(self): for _ in range(500): self.quad.add((random.randint(25, 225), random.randint(25, 225))) # make sure not to overlap! q_ne = self.expand(Region(128, 128, 256, 256)) q_nw = self.expand(Region(0, 128, 128, 256)) q_sw = self.expand(Region(0, 0, 128, 128)) q_se = self.expand(Region(128, 0, 256, 128)) q_all = self.expand(Region(0, 0, 256, 256)) # quick check to see if any were missing combined = q_ne + q_nw + q_sw + q_se for q in q_all: if q not in combined: print(q, " missing ") # check duplicates for i in range(len(combined)): for j in range(len(combined)): if j <= i: pass else: if combined[i] == combined[j]: print("Duplicate:", combined[i]) self.assertEquals(len(q_all), len(combined))
def __init__(self): """App for creating Quad tree dynamically with moving squares that detect collisions.""" self.tree = QuadTree(Region(0, 0, 512, 512)) self.match = None # for range query self.selectedRegion = None self.queryRect = None self.master = tkinter.Tk() self.master.title('Quad Tree Collision Detection') self.w = tkinter.Frame(self.master, width=512, height=512) self.canvas = tkinter.Canvas(self.w, width=512, height=512) self.paint() self.master.after(frameDelay, self.updateSquares) self.canvas.bind("<Button-1>", self.click) self.w.pack()
def __init__(self): """App for creating Quad tree dynamically and executing range queries.""" self.tree = QuadTree(Region(0,0,W,H)) self.match = None # for range query self.selectedRegion = None self.queryRect = None self.master = tkinter.Tk() self.master.title('Quad Tree Range Application') self.w = tkinter.Frame(self.master, width=W, height=H) self.canvas = tkinter.Canvas(self.w, width=W, height=H) self.paint() self.canvas.bind("<Button-1>", self.click) self.canvas.bind("<Button-3>", self.range) # when right mouse clicked self.canvas.bind("<ButtonRelease-3>", self.clear) self.canvas.bind("<B3-Motion>", self.range) # only when right mouse dragged self.w.pack()
def __init__(self): """App for creating Quad tree dynamically with moving squares that detect collisions.""" self.tree = QuadTree(Region(0,0,512,512)) self.match = None # for range query self.selectedRegion = None self.queryRect = None self.master = tkinter.Tk() self.master.title('Quad Tree Collision Detection') self.w = tkinter.Frame(self.master, width=512, height=512) self.canvas = tkinter.Canvas(self.w, width=512, height=512) self.paint() self.master.after(frameDelay, self.updateSquares) self.canvas.bind("<Button-1>", self.click) self.w.pack()
class QuadTreeApp: def __init__(self): """App for creating Quad tree dynamically and executing range queries.""" self.tree = QuadTree(Region(0,0,W,H)) self.match = None # for range query self.selectedRegion = None self.queryRect = None self.master = tkinter.Tk() self.master.title('Quad Tree Range Application') self.w = tkinter.Frame(self.master, width=W, height=H) self.canvas = tkinter.Canvas(self.w, width=W, height=H) self.paint() self.canvas.bind("<Button-1>", self.click) self.canvas.bind("<Button-3>", self.range) # when right mouse clicked self.canvas.bind("<ButtonRelease-3>", self.clear) self.canvas.bind("<B3-Motion>", self.range) # only when right mouse dragged self.w.pack() def toCartesian(self, y): """Convert tkinter point into Cartesian""" return self.w.winfo_height() - y def toTk(self,y): """Convert Cartesian into tkinter point.""" if y == maxValue: return 0 tk_y = self.w.winfo_height() if y != minValue: tk_y -= y return tk_y def clear(self, event): """End of range search.""" self.selectedRegion = None self.paint() def range(self, event): """Initiate a range search using a selected rectangular region.""" p = (event.x, self.toCartesian(event.y)) if self.selectedRegion is None: self.selectedStart = Region(p[X],p[Y], p[X],p[Y]) self.selectedRegion = self.selectedStart.unionPoint(p) self.paint() # return (node,status) where status is True if draining entire tree rooted at node. Draw these # all in Yellow using another inorder traversal for pair in self.tree.range(self.selectedRegion): if pair[1]: self.canvas.create_rectangle(pair[0].region.x_min, self.toTk(pair[0].region.y_min), pair[0].region.x_max, self.toTk(pair[0].region.y_max), fill='Red', stipple='gray12') else: p = pair[0][0] # ignore data and grab point self.canvas.create_rectangle(p[X] - RectangleSize, self.toTk(p[Y]) - RectangleSize, p[X] + RectangleSize, self.toTk(p[Y]) + RectangleSize, fill='Red') self.queryRect = self.canvas.create_rectangle(self.selectedRegion.x_min, self.toTk(self.selectedRegion.y_min), self.selectedRegion.x_max, self.toTk(self.selectedRegion.y_max), outline='Red', dash=(2, 4)) def click(self, event): """Add point to QuadTree.""" p = (event.x, self.toCartesian(event.y)) self.tree.add(p) self.paint() def visit (self, node): """ Visit node to paint properly.""" if node == None: return if node.points is None: r = node.region self.canvas.create_rectangle(r.x_min, self.toTk(r.y_min), r.x_max, self.toTk(r.y_max)) self.canvas.create_line(r.x_min, self.toTk(node.origin[Y]), r.x_max, self.toTk(node.origin[Y]), fill='black', dash=(2, 4)) self.canvas.create_line(node.origin[X], self.toTk(r.y_min), node.origin[X], self.toTk(r.y_max), fill='black', dash=(2, 4)) for n in node.children: self.visit(n) else: for p in node.points: self.canvas.create_rectangle(p[X] - RectangleSize, self.toTk(p[Y]) - RectangleSize, p[X] + RectangleSize, self.toTk(p[Y]) + RectangleSize, fill='Black') def prepare(self, event): """prepare to add points.""" if self.label: self.label.destroy() self.label = None self.canvas.pack() def paint(self): """Paint Quad tree by visiting all nodes, or show introductory message.""" if self.tree.root: self.canvas.delete(tkinter.ALL) self.visit(self.tree.root) else: self.label = tkinter.Label(self.w, width=100, height = 40, text="Click To Add Points") self.label.bind("<Button-1>", self.prepare) self.label.pack()
class QuadTreeApp: def __init__(self): """App for creating Quad tree dynamically with moving squares that detect collisions.""" self.tree = QuadTree(Region(0, 0, 512, 512)) self.match = None # for range query self.selectedRegion = None self.queryRect = None self.master = tkinter.Tk() self.master.title('Quad Tree Collision Detection') self.w = tkinter.Frame(self.master, width=512, height=512) self.canvas = tkinter.Canvas(self.w, width=512, height=512) self.paint() self.master.after(frameDelay, self.updateSquares) self.canvas.bind("<Button-1>", self.click) self.w.pack() def toCartesian(self, y): """Convert tkinter point into Cartesian""" return self.w.winfo_height() - y def toTk(self, y): """Convert Cartesian into tkinter point.""" if y == maxValue: return 0 tk_y = self.w.winfo_height() if y != minValue: tk_y -= y return tk_y def click(self, event): """Add point to QuadTree with random motion in place. Let animation paint as appropriate.""" p = (event.x, self.toCartesian(event.y)) dx = random.randint(1, 4) * (2 * random.randint(0, 1) - 1) dy = random.randint(1, 4) * (2 * random.randint(0, 1) - 1) self.tree.add(p, [dx, dy, 0]) def visit(self, node): """ Visit node to paint properly.""" if node == None: return if node.points is None: r = node.region self.canvas.create_rectangle(r.x_min, self.toTk(r.y_min), r.x_max, self.toTk(r.y_max)) self.canvas.create_line(r.x_min, self.toTk(node.origin[Y]), r.x_max, self.toTk(node.origin[Y]), fill='black', dash=(2, 4)) self.canvas.create_line(node.origin[X], self.toTk(r.y_min), node.origin[X], self.toTk(r.y_max), fill='black', dash=(2, 4)) for n in node.children: self.visit(n) else: for (p, d) in zip(node.points, node.data): markColor = 'Black' if d[HIT]: markColor = 'Red' self.canvas.create_rectangle(p[X] - RectangleSize, self.toTk(p[Y]) - RectangleSize, p[X] + RectangleSize, self.toTk(p[Y]) + RectangleSize, fill=markColor) def prepare(self, event): """prepare to add points""" if self.label: self.label.destroy() self.label = None self.canvas.pack() def updateSquares(self): """Move all shapes and repaint.""" self.master.after(frameDelay, self.updateSquares) if self.tree.root: for n in self.tree.root.preorder(): if n.points is None: continue pts = list(n.points) datas = list(n.data) for idx in range(len(pts)): pt = pts[idx] data = datas[idx] n.remove(pt) p = [pt[X], pt[Y]] d = [data[X], data[Y], max(0, data[HIT] - 1)] if pt[X] + d[X] <= self.tree.region.x_min: d[X] = -d[X] elif p[X] + d[X] >= self.tree.region.x_max: d[X] = -d[X] else: p[X] = pt[X] + d[X] if p[Y] + d[Y] <= self.tree.region.y_min: d[Y] = -d[Y] elif p[Y] + d[Y] >= self.tree.region.y_max: d[Y] = -d[Y] else: p[Y] = pt[Y] + d[Y] # Update hit status for all colliding points for (_, data) in self.tree.collide((p[X], p[Y]), RectangleSize): data[HIT] = MaxHit d[HIT] = MaxHit self.tree.add((p[X], p[Y]), [d[X], d[Y], d[HIT]]) self.canvas.delete(tkinter.ALL) self.visit(self.tree.root) def paint(self): """Paint Quad tree by visiting all nodes, or show introductory message.""" if self.tree.root: self.canvas.delete(tkinter.ALL) self.visit(self.tree.root) else: self.label = tkinter.Label(self.w, width=100, height=40, text="Click To Add Moving Squares") self.label.bind("<Button-1>", self.prepare) self.label.pack()
class QuadTreeApp: def __init__(self): """App for creating Quad tree dynamically with moving squares that detect collisions.""" self.tree = QuadTree(Region(0,0,512,512)) self.match = None # for range query self.selectedRegion = None self.queryRect = None self.master = tkinter.Tk() self.master.title('Quad Tree Collision Detection') self.w = tkinter.Frame(self.master, width=512, height=512) self.canvas = tkinter.Canvas(self.w, width=512, height=512) self.paint() self.master.after(frameDelay, self.updateSquares) self.canvas.bind("<Button-1>", self.click) self.w.pack() def toCartesian(self, y): """Convert tkinter point into Cartesian""" return self.w.winfo_height() - y def toTk(self,y): """Convert Cartesian into tkinter point.""" if y == maxValue: return 0 tk_y = self.w.winfo_height() if y != minValue: tk_y -= y return tk_y def click(self, event): """Add point to QuadTree with random motion in place. Let animation paint as appropriate.""" p = (event.x, self.toCartesian(event.y)) dx = random.randint(1,4)*(2*random.randint(0,1)-1) dy = random.randint(1,4)*(2*random.randint(0,1)-1) self.tree.add(p, [dx,dy,0]) def visit (self, node): """ Visit node to paint properly.""" if node == None: return if node.points is None: r = node.region self.canvas.create_rectangle(r.x_min, self.toTk(r.y_min), r.x_max, self.toTk(r.y_max)) self.canvas.create_line(r.x_min, self.toTk(node.origin[Y]), r.x_max, self.toTk(node.origin[Y]), fill='black', dash=(2, 4)) self.canvas.create_line(node.origin[X], self.toTk(r.y_min), node.origin[X], self.toTk(r.y_max), fill='black', dash=(2, 4)) for n in node.children: self.visit(n) else: for (p,d) in zip(node.points,node.data): markColor = 'Black' if d[HIT]: markColor = 'Red' self.canvas.create_rectangle(p[X] - RectangleSize, self.toTk(p[Y]) - RectangleSize, p[X] + RectangleSize, self.toTk(p[Y]) + RectangleSize, fill=markColor) def prepare(self, event): """prepare to add points""" if self.label: self.label.destroy() self.label = None self.canvas.pack() def updateSquares(self): """Move all shapes and repaint.""" self.master.after(frameDelay, self.updateSquares) if self.tree.root: for n in self.tree.root.preorder(): if n.points is None: continue pts = list(n.points) datas = list(n.data) for idx in range(len(pts)): pt = pts[idx] data = datas[idx] n.remove(pt) p = [pt[X], pt[Y]] d = [data[X], data[Y], max(0,data[HIT]-1)] if pt[X] + d[X] <= self.tree.region.x_min: d[X] = -d[X] elif p[X] + d[X] >= self.tree.region.x_max: d[X] = -d[X] else: p[X] = pt[X] + d[X] if p[Y] + d[Y] <= self.tree.region.y_min: d[Y] = -d[Y] elif p[Y] + d[Y] >= self.tree.region.y_max: d[Y] = -d[Y] else: p[Y] = pt[Y] + d[Y] # Update hit status for all colliding points for (_,data) in self.tree.collide((p[X],p[Y]), RectangleSize): data[HIT] = MaxHit d[HIT] = MaxHit self.tree.add((p[X],p[Y]),[d[X],d[Y],d[HIT]]) self.canvas.delete(tkinter.ALL) self.visit(self.tree.root) def paint(self): """Paint Quad tree by visiting all nodes, or show introductory message.""" if self.tree.root: self.canvas.delete(tkinter.ALL) self.visit(self.tree.root) else: self.label = tkinter.Label(self.w, width=100, height = 40, text="Click To Add Moving Squares") self.label.bind("<Button-1>", self.prepare) self.label.pack()
def setUp(self): self.quad = QuadTree(Region(0,0, 256, 256))