Commits

Andrew Peterson committed 6ba43a1

Added documentation to primitives module. Minor fix to Circle width/height calculation.

Comments (0)

Files changed (1)

djlib/primitives.py

+""" Primitives Module
+
+Module containing basic primitives for use with graphics, physics, and other
+maths calculations. Each primitive has methods to aid in interactions between
+them, as well as instance methods for generating objects based on numerous
+construction data.
+
+Support Primitives:
+    Vector - Standard geometric vector, the heart of all game calculations.
+    Point - Alias for `Vector` representing position data.
+    Size - Alias for `Vector` representing dimension.
+    Entity - Base class for any object containing positional data.
+    Rect - Bounding Rectangle containing position and size.
+    Circle - Bounding Circle containing position and radius.
+"""
 
 # IMPORTS
 import math
 from copy import copy
 
 class Vector(list):
+    """ Standard geometric vector, the heart of all game calculations.
+
+    This Vector is designed to handle an arbitrary number of dimensions, though
+    2D and 3D are most likely. Internal components are stored as a `list` for 
+    mutability reasons. Since this class is the base of most game operations,
+    care should be taken to ensure its methods are as efficent
+    as possible.
+
+    Attributes:
+        x,y,z - Direct component access is provided for the first 3 dimensions.
+    """
 
     _ATTR_STRING = "xyz"
 
     def __init__(self, *coords):
         list.__init__(self, list(coords))
 
+    ############
+    # Operators
+    ############
+
     def __add__(self, other_vec):
+        """ Add two Vectors, returning a new Vector. """
         return Vector(*[x+y for x,y in zip(self, other_vec)])
 
     def __iadd__(self, other_vec):
+        """ Add two Vectors together, modifying this instance. """
         for i in xrange(len(self)):
             self[i] += other_vec[i]
         return self
 
     def __sub__(self, other_vec):
+        """ Subtract two Vectors, returning a new Vector. """
         return Vector(*[x-y for x,y in zip(self, other_vec)])
 
     def __isub__(self, other_vec):
+        """ Subtract two Vectors, modifying this instance. """
         for i in xrange(len(self)):
             self[i] -= other_vec[i]
         return self
 
     def __mul__(self, vec_or_scale):
+        """ Scale Vector or calculate Dot Poduct, returning a new Vector
+
+        Result of Vector multiplication changes based on type of `vec_or_scale`.
+        If a Vector is specify, the dot product of the two Vectors are
+        calculate. If a scalar value is used, the Vector is scaled.
+
+        Args:
+            vec_or_scale(Vector) - Second Vector to calculate Dot Product
+            vec_or_scale(scalar) - Any scalar value (int, float, double)
+        """
         if isinstance(vec_or_scale, Vector):
             return self.dot(vec_or_scale)
         return self.scaled(vec_or_scale)
 
     def __imul__(self, scale):
+        """ Scale Vector, modifying this instance. """
         for i in xrange(len(self)):
             self[i] *= scale
         return self
 
     def __neg__(self):
+        """ Reverse Vector, returning a new Vector. """
         return Vector(*[-x for x in self])
 
     def __eq__(self, other_vec):
+        """ Return whether two Vectors are the same. """
         for x,y in zip(self, other_vec):
             if x != y:
                 return False
         return "<"+", ".join(str(x) for x in self)+">"
 
     def __getattr__(self, attr):
-        # print "get",attr
+        """ Access Vector components based on _ATTR_STRING location. """
         return self[self._ATTR_STRING.index(attr)]
 
     def __setattr__(self, attr, value):
-        # print "set",attr,value
+        """ Set Vector components based on _ATTR_STRING location. """
         idx = self._ATTR_STRING.find(attr)
         if idx < 0:
             list.__setattr__(self, attr, value)
         return hash(str(self))
 
     def length(self):
+        """ Return length of Vector. """
         return math.sqrt(sum([x*x for x in self]))
 
     def scaled(self, scale):
+        """ Scale Vector, returning new Vector. """
         return Vector(*[x*scale for x in self])
 
     def normalized(self):
+        """ Normalize Vector, returning a new Vector. """
         length = self.length()
         if length:
             return Vector(*[x/length for x in self])
         return copy(self)
 
     def dot(self, other_vec):
+        """ Calculate the Dot Product of two Vectors. """
         return sum([x*y for x,y in zip(self, other_vec)])
 
     def args(self):
+        """ Return Vector components as a tuple.
+
+        Aids transition to functions expecting Vector data as individual
+        components. 
+        """
         return tuple(self)
     
     def intArgs(self):
+        """ Return Vector components as a tuple, truncated to integers.
+
+        Most pygame graphical operations expect position data as integers.
+        This aids in using Vectors for those operations.
+        """
         return tuple([int(x) for x in self])
 
     def clear(self):
+        """ Set Vector to origin. """
         for i in xrange(len(self)):
             self[i] = 0
 
     def distanceApart(self, other_vec):
+        """ Calculate distance between two Vectors. """
         return (self - other_vec).length()
     
     def interpolate(self, other_vec, d):
+        """ Perform a linear interpolation along this Vector. """
         diff = other_vec - self
         return self + diff.scaled(d)
 
     def copy(self):
+        """ Create a copy of this Vector. """
         return copy(self)
     
 #end Vector
 
 class Point(Vector):
+    """ Alias for `Vector` representing position data.
+
+    Exists only to allow better code comprehension and introspection.
+    """
     pass
 #end Point
 
 class Size(Vector):
+    """ Alias for `Vector` representing dimension.
+
+    Exists only to allow better code comprehension and introspection.
+    Overides `_ATTR_STRING` to allow component access based on 
+    Width, Height, Length.
+    """
     _ATTR_STRING = "whl"
 #end Size
 
 class Entity:
+    """ Base class for any object containing positional data.
+
+    Created to allow for more uniform position access across all
+    Bounding Volumes and more advance physical objects.
+    """
     def __init__(self, position=[0,0]):
         self.pos = position
 
 #end Entity
 
 class BoundingVolume(Entity):
+    """ Base class for various Bounding Volumes. 
+
+    All Volumes should have a position, and therefore are derived from Entity.
+    """
 
     def contains(self, entity):
+        """ Return whether this Volume contains another `Entity`.
+
+        Args:
+            entity(Entity, BoundingVolume) - Arbitrary Entity or BoundingVolume
+                that should be tested for containment. Support types may vary.
+        """
         return self.pos == entity.pos
 
     def center(self):
+        """ Return Point representing the center of this Volume. """
         return self.pos
 
     def offset(self, offset_x, offset_y):
+        """ Return an offset Volume that varies based on type. """
         return self.pos+Vector(offset_x, offset_y)
 
     def width(self):
+        """ Return computed Width of Volume. """
         return 0
 
     def height(self):
+        """ Return computed Height of Volume. """
         return 0
     
 #end BoundingVolume
 
 class Rect(BoundingVolume):
+    """ An axix-aligned bounding Rectangle that has both a position and size. """
 
     # CLASS METHODS
     @classmethod
     def fromPoints(cls, top_left, bottom_right):
+        """ Create Rectangle from top-left and bottom-right points. """
         return Rect(top_left, bottom_right - top_left)
 
     @classmethod
     def fromPointSize(cls, vec_pos, width, height):
+        """ Create Rectangle from top-left Point and Size. """
         return Rect(vec_pos, Vector(width, height))
 
     @classmethod
     def fromSides(cls, left, top, right, bottom):
+        """ Create Rectangle from left, top, right, bottom values. """
         return Rect(Vector(left, top), Vector(right-left, bottom-top))
 
     # INSTANCE METHODS
         self.size = size
 
     def contains(self, entity):
+        """ Return whether this Rect contains another `BoundingVolume`.
+
+        Args:
+            entity (BoundingVolume) - Supports `Vector`, `Rect`, and `Circle`
+
+        Raises:
+            NotImplementedError - Raises on unsupported BoundingVolume type.
+        """
         bottom_right = self.pos + self.size
         
         # Vector
         return self.pos + self.size.scaled(0.5)
 
     def corners(self):
+        """ Return tuple of (top-left, top-right, bottom-left, bottom-right) points. """
         return (self.pos.copy(), self.pos+Vector(self.size[0], 0), self.pos+Vector(0, self.size[1]), self.pos+self.size)
 
     def sides(self):
+        """ Return tuple of (left, top, right, bottom) values. """
         return (self.pos[0], self.pos[1], self.pos[0]+self.size[0], self.pos[1]+self.size[1])
 
     def intersects(self, rect):
+        """ Return whether Rect intersects or contains another Rect. """
+        if not isinstance(rect, Rect):
+            raise NotImplementedError
+
         ours = self.corners()
         for corner in ours:
             if rect.contains(corner):
         return False
 
     def offset(self, offset_x, offset_y):
+        """ Return expanded/contracted Rect based on offsets. """
         o = Vector(offset_x, offset_y)
         return Rect.fromPoints(self.pos-o, self.size+o)
 
 #end Rect
 
 class Circle(BoundingVolume):
+    """ A bounding Circle with both position and size. """
 
     # CLASS METHODS
     @classmethod
     def fromPoints(cls, center, circum):
+        """ Create Circle from a center and tangential `Point`. """
         return Circle(center, (circum - center).length())
 
     @classmethod
     def fromPointSize(cls, position, radius):
+        """ Create Circle from a center position and radius. """
         return Circle(position, radius)
 
     # INSTANCE METHODS
         self.radius = radius
 
     def pointOnCircle(self, rad):
+        """ Return a tangential point on circle at specified radian. """
         ray = Vector(math.cos(rad), math.sin(rad)).scaled(self.radius)
         return self.pos + ray
 
     def contains(self, entity):
+        """ Return whether this Rect contains another `BoundingVolume`.
+
+        Args:
+            entity(BoundingVolume) - Supports `Vector`, `Rect`, and `Circle` types
+
+        Raises:
+            NotImplementedError - Raises on unsupported BoundingVolume type.
+        """
         # Vector
         if isinstance(entity, Vector):
             return (self.pos - entity).length() <= self.radius
         raise NotImplementedError
 
     def offset(self, offset_x, offset_y):
+        """ Return Circle with expanded/contracted radius. """
         return Circle(self.pos, offset_x+offset_y)
 
     def width(self):
-        return self.radius
+        return self.radius*2
 
     def height(self):
-        return self.radius
+        return self.radius*2
         
 #end Circle