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))
Exemplo n.º 2
0
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))
Exemplo n.º 3
0
    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()
Exemplo n.º 4
0
    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()
Exemplo n.º 6
0
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()
Exemplo n.º 7
0
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()
Exemplo n.º 9
0
 def setUp(self):
     self.quad = QuadTree(Region(0,0, 256, 256))
Exemplo n.º 10
0
 def setUp(self):
     self.quad = QuadTree(Region(0,0, 256, 256))