pygame is
Python
Simple DirectMedia Layer
 
 
pygame.org is
Site Swing
Wiki

BoundingBox

      
Search:  
 
 

A BoundingBox is like a 3D pygame.Rect object, and can be used for many of the same things. This code uses PyEuclid.

import euclid
 
XPOS = euclid.Vector3(1., 0, 0)
XNEG = euclid.Vector3(-1., 0, 0)
YPOS = euclid.Vector3(0, 1., 0)
YNEG = euclid.Vector3(0, -1., 0)
ZPOS = euclid.Vector3(0, 0, 1.)
ZNEG = euclid.Vector3(0, 0, -1.)
 
class AABox(object):
    '''Axis-Aligned Box centered on "center" with dimensions x, y, z'''
    def __init__(self, c, dx, dy, dz):
        self.dx, self.dy, self.dz = dx, dy, dz
        self.c = c
 
    @classmethod
    def from_extents(cls, minx, maxx, miny, maxy, minz, maxz):
        '''Return an AABox created from minx, max, miny, maxy, minz and
        maxz dimensions.
        '''
        dx = (maxx - minx) * 0.5
        dy = (maxy - miny) * 0.5
        dz = (maxz - minz) * 0.5
        c = (minx + self.dx, miny + self.dy, minz + self.dz)
        return cls(c, dx, dy, dz)
 
 
    def __add__(self, b):
        '''Adds another bounding box volume, the new box covers both volumes.
        '''
        extents = (min(self.minx, b.minx), max(self.maxx, b.maxx),
          min(self.miny, b.miny), max(self.maxy, b.maxy),
          min(self.minz, b.minz), max(self.maxz, b.maxz))
        return self.from_extents(*extents)
 
    def get_c(self):
        '''Just return the value.'''
        return self.__c
 
    def set_c(self, c):
        '''Set the extents based on the center value and our dimensions.
        '''
        if isinstance(c, euclid.Point3):
            pass
        elif isinstance(c, euclid.Vector3):
            c = euclid.Point3(c.x, c.y, c.z)
        else:
            c = euclid.Point3(*c)
        c = self.__c = c
 
        x = (c.x - self.dx/2, c.x + self.dx/2)
        self.xmin = min(x)
        self.xmax = max(x)
 
        y = (c.y - self.dy/2, c.y + self.dy/2)
        self.ymin = min(y)
        self.ymax = max(y)
 
        z = (c.z - self.dz/2, c.z + self.dz/2)
        self.zmin = min(z)
        self.zmax = max(z)
 
    c = property(get_c, set_c, None)
 
    def __repr__(self):
        a = tuple(self.__c) + (self.dx, self.dy, self.dz)
        return '<aabox c="%s,%s,%s" d="%s,%s,%s">'%a
 
    def is_intersecting(self, other):
        '''Does the other thing (currently just AABox and euclid.Point3)
        intersect this box?
        '''
        if isinstance(other, euclid.Point3):
            return (self.xmin &lt; other.x &lt; self.xmax and
                    self.ymin &lt; other.y &lt; self.ymax and
                    self.zmin &lt; other.z &lt; self.zmax)
        elif isinstance(other, AABox):
            c = other.c
            hdx, hdy, hdz = other.dx/2, other.dy/2, other.dz/2
            return (self.xmin-hdx &lt; c.x &lt; self.xmax+hdx and
                self.ymin-hdy &lt; c.y &lt; self.ymax+hdy and
                self.zmin-hdz &lt; c.z &lt; self.zmax+hdz)
        else:
            raise NotImplementedError
 
    def resolve_collision(self, other):
        '''An AABox has been determined to have collided with this AABox
        by is_intersecting() above. This method is to be called with the
        AABox in its non-intersecting state, and will move it as far as
        it can such that it touches this AABox (which is stationary).
 
        Returns (other AABox new center postion, velocity modifier)
 
        Velocity modifier indicates which axis we modified and thus
        which velocity axis should be zeroed.
        '''
        if not isinstance(other, AABox): raise NotImplementedError
        c = other.c
 
        # test from middle of closest edges
        s = self.__c
        sx = s.x; cx = c.x
        if other.c.x > self.c.x:
            s.x = self.xmax
            c.x = other.xmin
            v = (c - s).normalize()
            x = v.dot(XPOS)
        else:
            s.x = self.xmin
            c.x = other.xmax
            v = (c - s).normalize()
            x = v.dot(XNEG)
        s.x = sx; c.x = cx
        sy = s.y; cy = c.y
        if other.c.y > self.c.y:
            s.y = self.ymax
            c.y = other.ymin
            v = (c - s).normalize()
            y = v.dot(YPOS)
        else:
            s.y = self.ymin
            c.y = other.ymax
            v = (c - s).normalize()
            y = v.dot(YNEG)
        s.y = sy; c.y = cy
        sz = s.z; cz = c.z
 
        if other.c.z &lt; self.c.z:
            s.z = self.zmax
            c.z = other.zmin
            v = (c - s).normalize()
            z = v.dot(ZPOS)
        else:
            s.z = self.zmin
            c.z = other.zmax
            v = (c - s).normalize()
            z = v.dot(ZNEG)
        s.z = sz; c.z = cz
 
        # now see which axis has the dot product closest to 1
        if y > x and y > z:
            c.y = self.ymax + other.dy/2
            vmod = euclid.Vector3(1, 0, 1)
        elif x > z:
            hdx = other.dx/2
            if c.x > self.c.x: c.x = self.xmax + hdx
            else: c.x = self.xmin - hdx
            vmod = euclid.Vector3(0, 1, 1)
        else:
            hdz = other.dz/2
            if c.z > self.c.z: c.z = self.zmax + hdz
            else: c.z = self.zmin - hdz
            vmod = euclid.Vector3(1, 1, 0)
 
        return c, vmod
</aabox>

Watch out for that aabox "tag" at the end there, it's a dag generated

spotlight

 
our projects
pygame.org welcomes all python game, art, music, sound, video and multimedia projects. If they use pygame or not.
 
recent releases
Apr 19, 2014

Apr 16, 2014


Apr 13, 2014

Apr 9, 2014

Mar 18, 2014


Mar 15, 2014


Mar 14, 2014

Mar 13, 2014

Mar 11, 2014

... more!
 
for pygame related questions, comments, and suggestions, please see help (lists, irc)