Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

hw19 posted

  • Loading branch information...
commit a82df2899e9c93ecd2131745745a6e4f0be03e6c 1 parent 8b17fc1
Alec Goebel alecgoebel authored
90 hw19/README.md
Source Rendered
... ... @@ -0,0 +1,90 @@
  1 +Homework 19
  2 +=========================
  3 +Recursion and QuadTrees
  4 +-------------------------
  5 +
  6 +In this assignment, you will be fleshing out a [Quadtree](http://en.wikipedia.org/wiki/Quadtree). Quadtrees are traditionally used in graphics programming to quickly eliminate large groups of points.
  7 +
  8 +QuadTreeNode is already mostly a quadtree. However, in order to actually use it in a program, there should be easier ways to access the data inside the QuadTree. Specifically, we need a way to get a list of all the points in the quadtree and a way to get every rectangle (quadrents).
  9 +
  10 +As you add the methods in this homework, run `test_quad.py` to run the normal battery of unit tests to see if it works. Once you are completely done, you can use `./rundemo` to run a graphical demo to see your quadtree in action.
  11 +
  12 +> `rundemo` is a python file so can just be opened in IDLE on Windows.
  13 +
  14 +
  15 +Getting the Points (get_points)
  16 +--------------------------------
  17 +
  18 +Add a method `get_points` to QuadTreeNode. This method will fetch a list of every point stored in a QuadTreeNode and it's children. Since each
  19 +
  20 +**Requirements:**
  21 +
  22 + * if there are no points, return an empty list
  23 + * if there is only one point, return a list with only that point in it
  24 + * if there is more than one point, return a list with every point
  25 + * the order the points are output doesn't matter
  26 +
  27 +**Example:**
  28 +
  29 +```python
  30 +>>> qtree = QuadTreeNode(Rect(0, 0, 100, 100))
  31 +>>> # no points
  32 +>>> qtree.get_points()
  33 +[]
  34 +>>> # one point
  35 +>>> qtree.add_point((25, 25))
  36 +>>> qtree.get_points()
  37 +[ (25,25) ]
  38 +>>> # many points
  39 +>>> qtree.add_point((75, 75))
  40 +>>> qtree.add_point((22, 22))
  41 +[ (25,25), (75, 75), (22, 22) ]
  42 +```
  43 +
  44 +
  45 +
  46 +Getting Rects (quadrents)
  47 +--------------------------------
  48 +
  49 +Add a method `get_rects` which fetches every rectangle out of a QuadTree. This includes the root node and its children if it has any and so on. This should be a flat list of rectangles (not lists in lists).
  50 +
  51 +**Requirements:**
  52 +
  53 + * if there are zero/one points, return just the root rect
  54 + * if there is more than one point, return the root rect and all it's children
  55 + * if there is more than one level of nesting, return nested child.
  56 + * order of rects doesn't matter
  57 +
  58 +> **HINT:** You can use an optional `rects` parameter to keep track of all the rects as you add them. Since arrays are a reference, adding a rect to an array as you recurse is a good way to track all the values
  59 +
  60 +**Example:**
  61 +
  62 +```python
  63 +>>> qtree = QuadTreeNode(Rect(0, 0, 100, 100))
  64 +>>> # no points
  65 +>>> qtree.get_rects()
  66 +[<rect(0, 0, 100, 100)>]
  67 +>>> # one point
  68 +>>> qtree.add_point((10, 10))
  69 +>>> qtree.get_rects()
  70 +[<rect(0, 0, 100, 100)>]
  71 +>>> # two points in different quadrents
  72 +>>> qtree.add_point((75, 75))
  73 +>>> qtree.get_rects()
  74 +[<rect(0, 0, 100, 100)>, <rect(0, 0, 50, 50)>, <rect(50, 0, 50, 50)>, <rect(0, 50, 50, 50)>, <rect(50, 50, 50, 50)>]
  75 +>>> # two points in the same quadrent
  76 +>>> qtree.add_point((40, 40))
  77 +>>> qtree.get_rects()
  78 +[<rect(0, 0, 100, 100)>, <rect(0, 0, 50, 50)>, <rect(0, 0, 25, 25)>, <rect(25, 0, 25, 25)>, <rect(0, 25, 25, 25)>, <rect(25, 25, 25, 25)>, <rect(25, 0, 25, 25)>, <rect(0, 25, 25, 25)>, <rect(25, 25, 25, 25)>]
  79 +```
  80 +
  81 +[Advanced] Collide Point with QuadTree (collidepoint)
  82 +--------------------------------------------------------
  83 +
  84 +Add a method `collidepoint` which returns the smallest QuadTreeNode which collides with a given point.
  85 +
  86 +**Requirements:**
  87 + * if the point is not within the QuadTreeNode, return None
  88 + * if the QuadTreeNode is not split and the point collides, return itself
  89 + * if the QuadTreeNode is split, return collidepoint for the child
  90 +
162 hw19/quad.py
... ... @@ -0,0 +1,162 @@
  1 +"""
  2 +quad.py
  3 +
  4 +=========================
  5 +Homework 19
  6 +=========================
  7 +Recursion and QuadTrees
  8 +-------------------------
  9 +
  10 +In this assignment, you will be fleshing out a Quadtree (http://en.wikipedia.org/wiki/Quadtree). Quadtrees are traditionally used
  11 +in graphics programming to quickly eliminate large groups of points.
  12 +
  13 +QuadTreeNode is already mostly a quadtree. However, in order to actually use it in a program, there should be easier ways to access the
  14 +data inside the QuadTree. Specifically, we need a way to get a list of all the points in the quadtree and a way to get every rectangle (quadrents).
  15 +
  16 +As you add the methods in this homework, run `test_quad.py` to run the normal battery of unit tests to see if it works. Once you are completely done, you can use `./rundemo` to run a graphical demo to see your quadtree in action.
  17 +
  18 +> `rundemo` is a python file so can just be opened in IDLE on Windows.
  19 +
  20 +
  21 +Getting the Points (get_points)
  22 +--------------------------------
  23 +
  24 +Add a method `get_points` to QuadTreeNode. This method will fetch a list of every point stored in
  25 +a QuadTreeNode and it's children. Since each
  26 +
  27 +Requirements:
  28 + * if there are no points, return an empty list
  29 + * if there is only one point, return a list with only that point in it
  30 + * if there is more than one point, return a list with every point
  31 + * the order the points are output doesn't matter
  32 +
  33 +Example:
  34 + >>> qtree = QuadTreeNode(Rect(0, 0, 100, 100))
  35 + >>> # no points
  36 + >>> qtree.get_points()
  37 + []
  38 + >>> # one point
  39 + >>> qtree.add_point((25, 25))
  40 + >>> qtree.get_points()
  41 + [ (25,25) ]
  42 + >>> # many points
  43 + >>> qtree.add_point((75, 75))
  44 + >>> qtree.add_point((22, 22))
  45 + [ (25,25), (75, 75), (22, 22) ]
  46 +
  47 +
  48 +
  49 +Getting Rects (quadrents)
  50 +--------------------------------
  51 +
  52 +Add a method `get_rects` which fetches every rectangle out of a QuadTree. This includes the root node and its children if it has any and so on. This should be a flat list of rectangles (not lists in lists).
  53 +
  54 +Requirements:
  55 + * if there are zero/one points, return just the root rect
  56 + * if there is more than one point, return the root rect and all it's children
  57 + * if there is more than one level of nesting, return nested child.
  58 + * order of rects doesn't matter
  59 +
  60 +> HINT: You can use an optional `rects` parameter to keep track of all the rects as you add them. Since arrays are a reference, adding a rect to an array as you recurse is a good way to track all the values
  61 +
  62 +Example:
  63 + >>> qtree = QuadTreeNode(Rect(0, 0, 100, 100))
  64 + >>> # no points
  65 + >>> qtree.get_rects()
  66 + [<rect(0, 0, 100, 100)>]
  67 + >>> # one point
  68 + >>> qtree.add_point((10, 10))
  69 + >>> qtree.get_rects()
  70 + [<rect(0, 0, 100, 100)>]
  71 + >>> # two points in different quadrents
  72 + >>> qtree.add_point((75, 75))
  73 + >>> qtree.get_rects()
  74 + [<rect(0, 0, 100, 100)>, <rect(0, 0, 50, 50)>, <rect(50, 0, 50, 50)>, <rect(0, 50, 50, 50)>, <rect(50, 50, 50, 50)>]
  75 + >>> # two points in the same quadrent
  76 + >>> qtree.add_point((40, 40))
  77 + >>> qtree.get_rects()
  78 + [<rect(0, 0, 100, 100)>, <rect(0, 0, 50, 50)>, <rect(0, 0, 25, 25)>, <rect(25, 0, 25, 25)>, <rect(0, 25, 25, 25)>, <rect(25, 25, 25, 25)>, <rect(25, 0, 25, 25)>, <rect(0, 25, 25, 25)>, <rect(25, 25, 25, 25)>]
  79 +
  80 +
  81 +[Advanced] Collide Point with QuadTree (collidepoint)
  82 +--------------------------------------------------------
  83 +
  84 +Add a method `collidepoint` which returns the smallest QuadTreeNode which collides with a given point.
  85 +
  86 +Requirements:
  87 + * if the point is not within the QuadTreeNode, return None
  88 + * if the QuadTreeNode is not split and the point collides, return itself
  89 + * if the QuadTreeNode is split, return collidepoint for the child
  90 +
  91 +
  92 +"""
  93 +
  94 +from math import ceil, floor
  95 +
  96 +import pygame
  97 +from pygame.locals import *
  98 +
  99 +from pygame import Rect
  100 +
  101 +MAX_DEPTH = 10
  102 +class QuadTreeNode(object):
  103 +
  104 + def __init__(self, rect, depth = 0):
  105 + self.rect = rect
  106 + self.data = None
  107 + self.is_split = False
  108 +
  109 + self.ne = None
  110 + self.nw = None
  111 + self.se = None
  112 + self.sw = None
  113 +
  114 + self.depth = depth
  115 +
  116 + def add_point(self, point):
  117 + # if we don't have data, just add it
  118 + if self.data is None and not self.is_split:
  119 + self.data = point
  120 + return
  121 + elif self.depth == MAX_DEPTH:
  122 + self.data = point
  123 + return
  124 +
  125 + # if already haven't split, do that now
  126 + if not self.is_split:
  127 + prev_point = self.data
  128 + self.is_split = True
  129 +
  130 + r = self.rect
  131 + w = self.rect.width / 2.0
  132 + h = self.rect.height / 2.0
  133 + d = self.depth + 1
  134 +
  135 + self.nw = QuadTreeNode( Rect(r.left, r.top, floor(w), floor(h) ), d )
  136 + self.ne = QuadTreeNode( Rect(r.centerx, r.top, ceil(w), floor(h) ), d )
  137 + self.sw = QuadTreeNode( Rect(r.left, r.centery, floor(w), ceil(h) ), d )
  138 + self.se = QuadTreeNode( Rect(r.centerx, r.centery, ceil(w), ceil(h) ), d )
  139 +
  140 + # re add the point
  141 + self.add_point(prev_point)
  142 +
  143 + # add the point to the split
  144 + if self.nw.rect.collidepoint(point):
  145 + self.nw.add_point(point)
  146 + elif self.ne.rect.collidepoint(point):
  147 + self.ne.add_point(point)
  148 + elif self.sw.rect.collidepoint(point):
  149 + self.sw.add_point(point)
  150 + else:
  151 + self.se.add_point(point)
  152 +
  153 + # def get_points(self):
  154 +
  155 +
  156 + # def get_rects(node, rects=None):
  157 + # if rects is None:
  158 + # rects = []
  159 +
  160 +
  161 + # Advanced
  162 + # def collidepoint(self, point):
44 hw19/rundemo
... ... @@ -0,0 +1,44 @@
  1 +#!/usr/bin/env python
  2 +
  3 +from math import ceil, floor
  4 +
  5 +import pygame
  6 +from pygame.locals import *
  7 +
  8 +from pygame import Rect
  9 +
  10 +from quad import QuadTreeNode
  11 +
  12 +
  13 +pygame.init()
  14 +screen = pygame.display.set_mode((800, 800))
  15 +root = QuadTreeNode(screen.get_rect())
  16 +
  17 +done = False
  18 +clock = pygame.time.Clock()
  19 +while not done:
  20 + for event in pygame.event.get():
  21 + if event.type == QUIT:
  22 + done = True
  23 + elif event.type == KEYDOWN and event.key == K_ESCAPE:
  24 + done = True
  25 + elif event.type == MOUSEBUTTONDOWN:
  26 + root.add_point(pygame.mouse.get_pos())
  27 +
  28 + screen.fill(0)
  29 +
  30 + # draw quadtree
  31 + if hasattr(root, "collidepoint"):
  32 + active = root.collidepoint(pygame.mouse.get_pos())
  33 + screen.fill((80,80,80), active.rect)
  34 +
  35 + if hasattr(root, "get_rects"):
  36 + for rect in root.get_rects():
  37 + pygame.draw.rect(screen, (170, 170, 170), rect, 1)
  38 +
  39 + if hasattr(root, "get_points"):
  40 + for point in root.get_points():
  41 + pygame.draw.circle(screen, (255,255,255), point, 3)
  42 +
  43 + pygame.display.flip()
  44 + clock.tick(30)
129 hw19/test_quad.py
... ... @@ -0,0 +1,129 @@
  1 +#!/usr/bin/env python
  2 +
  3 +import math
  4 +
  5 +from pygame import Rect
  6 +
  7 +try:
  8 + import unittest2 as unittest
  9 +except:
  10 + import unittest
  11 +
  12 +from quad import QuadTreeNode
  13 +
  14 +class QuadTreeTest(unittest.TestCase):
  15 +
  16 + def setUp(self):
  17 + self.qtree = QuadTreeNode(Rect(0,0,100, 100))
  18 +
  19 + # get_points tests
  20 + @unittest.skipIf(not hasattr(QuadTreeNode, "get_points"), "missing get_points")
  21 + def test_get_points_empty(self):
  22 + "if no points have been added, get_points should return an empty list"
  23 + self.assertItemsEqual(self.qtree.get_points(), [], "No points have been added to the quadtree, should return an empty list")
  24 +
  25 + @unittest.skipIf(not hasattr(QuadTreeNode, "get_points"), "missing get_points")
  26 + def test_get_points_one(self):
  27 + "if only one point is added, a list containing that one point should be returned"
  28 + self.qtree.add_point((25, 25))
  29 + self.assertItemsEqual(self.qtree.get_points(), [(25,25)], "One point has been added, only one point should be returned")
  30 +
  31 + @unittest.skipIf(not hasattr(QuadTreeNode, "get_points"), "missing get_points")
  32 + def test_get_points_many(self):
  33 + "get_points should return all points added"
  34 +
  35 + self.qtree.add_point((25, 25))
  36 + self.qtree.add_point((75, 75))
  37 + self.qtree.add_point((22, 22))
  38 + self.assertItemsEqual(self.qtree.get_points(), [(22,22), (75,75), (25,25)], "Incorrect points returned")
  39 +
  40 + # get_rects tests
  41 + @unittest.skipIf(not hasattr(QuadTreeNode, "get_rects"), "missing get_rects")
  42 + def test_get_rects_simple(self):
  43 + "if zero or one points have been added, get_rects should just return a list with the root's rect"
  44 + self.assertIn(self.qtree.rect, self.qtree.get_rects(), "root rect missing, no points")
  45 + self.assertEqual(1, len(self.qtree.get_rects()), "too many rects returned, no points")
  46 +
  47 + self.qtree.add_point((30,30))
  48 + self.assertIn(self.qtree.rect, self.qtree.get_rects(), "root rect missing, one point")
  49 + self.assertEqual(1, len(self.qtree.get_rects()), "too many rects returned, one point")
  50 +
  51 + @unittest.skipIf(not hasattr(QuadTreeNode, "get_rects"), "missing get_rects")
  52 + def test_get_rects_split(self):
  53 + "if only one split has happened, the root and it's children should be returned"
  54 +
  55 + self.qtree.add_point((25,25))
  56 + self.qtree.add_point((75,75))
  57 + rects = self.qtree.get_rects()
  58 +
  59 + self.assertEqual(5, len(rects), "expected 5 rects (root and children)")
  60 + self.assertIn(self.qtree.rect, rects, "root rect missing")
  61 + self.assertIn(self.qtree.nw.rect, rects, "root.nw rect missing")
  62 + self.assertIn(self.qtree.ne.rect, rects, "root.ne rect missing")
  63 + self.assertIn(self.qtree.sw.rect, rects, "root.sw rect missing")
  64 + self.assertIn(self.qtree.se.rect, rects, "root.se rect missing")
  65 +
  66 + @unittest.skipIf(not hasattr(QuadTreeNode, "get_rects"), "missing get_rects")
  67 + def test_get_rects_complex(self):
  68 + "if many splits have occured, all rects should be returned"
  69 +
  70 + self.qtree.add_point((10,10))
  71 + self.qtree.add_point((40,40))
  72 + self.qtree.add_point((75,75))
  73 + rects = self.qtree.get_rects()
  74 +
  75 + self.assertEqual(9, len(rects), "expected 5 rects (root and children)")
  76 + self.assertIn(self.qtree.rect, rects, "root rect missing")
  77 + self.assertIn(self.qtree.nw.rect, rects, "root.nw rect missing")
  78 + self.assertIn(self.qtree.ne.rect, rects, "root.ne rect missing")
  79 + self.assertIn(self.qtree.sw.rect, rects, "root.sw rect missing")
  80 + self.assertIn(self.qtree.se.rect, rects, "root.se rect missing")
  81 + self.assertIn(self.qtree.nw.nw.rect, rects, "root.nw.nw rect missing")
  82 + self.assertIn(self.qtree.nw.ne.rect, rects, "root.nw.ne rect missing")
  83 + self.assertIn(self.qtree.nw.sw.rect, rects, "root.nw.sw rect missing")
  84 + self.assertIn(self.qtree.nw.se.rect, rects, "root.nw.se rect missing")
  85 +
  86 +
  87 + # collidepoint tests
  88 + @unittest.skipIf(not hasattr(QuadTreeNode, "collidepoint"), "missing collidepoints")
  89 + def test_collidepoint_out_of_bounds(self):
  90 + "if point is out of bounds, collidepoint should return None"
  91 + self.assertIsNone(self.qtree.collidepoint((101,101)), "point is out of bounds, should return None")
  92 +
  93 + @unittest.skipIf(not hasattr(QuadTreeNode, "collidepoint"), "missing collidepoints")
  94 + def test_collidepoint_simple(self):
  95 + "if there are zero or one points, collidepoint just needs to return the node"
  96 + self.assertEqual(self.qtree, self.qtree.collidepoint((50,50)), "no points, expected root node")
  97 + self.qtree.add_point((50,50))
  98 + self.assertEqual(self.qtree, self.qtree.collidepoint((50,50)), "one points, expected root node")
  99 +
  100 +
  101 + @unittest.skipIf(not hasattr(QuadTreeNode, "collidepoint"), "missing collidepoints")
  102 + def test_collidepoint_split(self):
  103 + "if there is one split, collidepoint needs to return the correct quadrent"
  104 + self.qtree.add_point((75,75))
  105 + self.qtree.add_point((25,25))
  106 +
  107 + self.assertEqual(self.qtree.nw, self.qtree.collidepoint((25,25)), "expected nw")
  108 + self.assertEqual(self.qtree.ne, self.qtree.collidepoint((75,25)), "expected ne")
  109 + self.assertEqual(self.qtree.sw, self.qtree.collidepoint((25,75)), "expected sw")
  110 + self.assertEqual(self.qtree.se, self.qtree.collidepoint((75,75)), "expected se")
  111 +
  112 + @unittest.skipIf(not hasattr(QuadTreeNode, "collidepoint"), "missing collidepoints")
  113 + def test_collidepoint_complex(self):
  114 + "if there is one split, collidepoint needs to return the correct quadrent"
  115 + self.qtree.add_point((75,75))
  116 + self.qtree.add_point((10,10))
  117 + self.qtree.add_point((40,40))
  118 +
  119 + self.assertEqual(self.qtree.ne, self.qtree.collidepoint((75,25)), "expected ne")
  120 + self.assertEqual(self.qtree.sw, self.qtree.collidepoint((25,75)), "expected sw")
  121 + self.assertEqual(self.qtree.se, self.qtree.collidepoint((75,75)), "expected se")
  122 +
  123 + self.assertEqual(self.qtree.nw.nw, self.qtree.collidepoint((10,10)), "expected nw.nw")
  124 + self.assertEqual(self.qtree.nw.ne, self.qtree.collidepoint((40,10)), "expected nw.ne")
  125 + self.assertEqual(self.qtree.nw.sw, self.qtree.collidepoint((10,40)), "expected nw.sw")
  126 + self.assertEqual(self.qtree.nw.se, self.qtree.collidepoint((40,40)), "expected nw.se")
  127 +
  128 +if __name__ == "__main__":
  129 + unittest.main()
6 hw23/README.md
Source Rendered
... ... @@ -0,0 +1,6 @@
  1 +Homework 24
  2 +=====================
  3 +Final Games Due
  4 +---------------------
  5 +
  6 +Make sure your game is playable and turned in without bugs. This is a *release candidate* for your final game. Make sure to get some sleep so you can show off and check out all the games made by this class.
14 hw24/README.md
Source Rendered
... ... @@ -1,6 +1,10 @@
1   -Homework 24
2   -=====================
3   -Final Games Due
4   ----------------------
  1 +Homework 25
  2 +================================
  3 +Final writeup and Release Game
  4 +--------------------------------
5 5
6   -Make sure your game is playable and turned in without bugs. This is a *release candidate* for your final game. Make sure to get some sleep so you can show off and check out all the games made by this class.
  6 +Sit down with your group and write a short postmortem on your project wiki about how the project went. This should include what went right, what went wrong, and what the next step for the project would be if you continued.
  7 +
  8 +Then, release your game. Feel free to fix any minor bugs that you discovered on Monday in class.
  9 +
  10 +Finally, send us an email (cs112 at hampshire.edu) with a short evaluation of yourself and your partner. Tell us who did what, how it went, and if you'd work with them again.
10 hw25/README.md
Source Rendered
... ... @@ -1,10 +0,0 @@
1   -Homework 25
2   -================================
3   -Final writeup and Release Game
4   ---------------------------------
5   -
6   -Sit down with your group and write a short postmortem on your project wiki about how the project went. This should include what went right, what went wrong, and what the next step for the project would be if you continued.
7   -
8   -Then, release your game. Feel free to fix any minor bugs that you discovered on Monday in class.
9   -
10   -Finally, send us an email (cs112 at hampshire.edu) with a short evaluation of yourself and your partner. Tell us who did what, how it went, and if you'd work with them again.

0 comments on commit a82df28

Please sign in to comment.
Something went wrong with that request. Please try again.