#pragma section-numbers off <> = Points & Rectangles = A pair of classes to provide points and rectangles. Surprisingly, I haven't been able to find a single Python module providing such primitive support. WxPython supports wxPoint and wxRect, but it lacks many basic functions (such as, say, adding two points together to produce a third point..!) (See: [[http://wiki.wxpython.org/index.cgi/wx_2eRect|wxPyWiki:wx.Rect]]) This code is lacking a zillion essential features (but interpoint distance can now be calculated). I only put in the ones I needed immediately. Please add, refactor, optimize, rename stuff to be more standard, etc., as you see fit..! ''If there's an actual, accessible, easy-to-include Python module, not tied to a graphics library, that does this stuff already, please write about it here! No sense in reinventing the wheel. I've looked, but haven't found one. Hence this.'' {{{ #!python """Point and Rectangle classes. This code is in the public domain. Point -- point with (x,y) coordinates Rect -- two points, forming a rectangle """ import math class Point: """A point identified by (x,y) coordinates. supports: +, -, *, /, str, repr length -- calculate length of vector to point from origin distance_to -- calculate distance between two points as_tuple -- construct tuple (x,y) clone -- construct a duplicate integerize -- convert x & y to integers floatize -- convert x & y to floats move_to -- reset x & y slide -- move (in place) +dx, +dy, as spec'd by point slide_xy -- move (in place) +dx, +dy rotate -- rotate around the origin rotate_about -- rotate around another point """ def __init__(self, x=0.0, y=0.0): self.x = x self.y = y def __add__(self, p): """Point(x1+x2, y1+y2)""" return Point(self.x+p.x, self.y+p.y) def __sub__(self, p): """Point(x1-x2, y1-y2)""" return Point(self.x-p.x, self.y-p.y) def __mul__( self, scalar ): """Point(x1*x2, y1*y2)""" return Point(self.x*scalar, self.y*scalar) def __div__(self, scalar): """Point(x1/x2, y1/y2)""" return Point(self.x/scalar, self.y/scalar) def __str__(self): return "(%s, %s)" % (self.x, self.y) def __repr__(self): return "%s(%r, %r)" % (self.__class__.__name__, self.x, self.y) def length(self): return math.sqrt(self.x**2 + self.y**2) def distance_to(self, p): """Calculate the distance between two points.""" return (self - p).length() def as_tuple(self): """(x, y)""" return (self.x, self.y) def clone(self): """Return a full copy of this point.""" return Point(self.x, self.y) def integerize(self): """Convert co-ordinate values to integers.""" self.x = int(self.x) self.y = int(self.y) def floatize(self): """Convert co-ordinate values to floats.""" self.x = float(self.x) self.y = float(self.y) def move_to(self, x, y): """Reset x & y coordinates.""" self.x = x self.y = y def slide(self, p): '''Move to new (x+dx,y+dy). Can anyone think up a better name for this function? slide? shift? delta? move_by? ''' self.x = self.x + p.x self.y = self.y + p.y def slide_xy(self, dx, dy): '''Move to new (x+dx,y+dy). Can anyone think up a better name for this function? slide? shift? delta? move_by? ''' self.x = self.x + dx self.y = self.y + dy def rotate(self, rad): """Rotate counter-clockwise by rad radians. Positive y goes *up,* as in traditional mathematics. Interestingly, you can use this in y-down computer graphics, if you just remember that it turns clockwise, rather than counter-clockwise. The new position is returned as a new Point. """ s, c = [f(rad) for f in (math.sin, math.cos)] x, y = (c*self.x - s*self.y, s*self.x + c*self.y) return Point(x,y) def rotate_about(self, p, theta): """Rotate counter-clockwise around a point, by theta degrees. Positive y goes *up,* as in traditional mathematics. The new position is returned as a new Point. """ result = self.clone() result.slide(-p.x, -p.y) result.rotate(theta) result.slide(p.x, p.y) return result class Rect: """A rectangle identified by two points. The rectangle stores left, top, right, and bottom values. Coordinates are based on screen coordinates. origin top +-----> x increases | | left -+- right v | y increases bottom set_points -- reset rectangle coordinates contains -- is a point inside? overlaps -- does a rectangle overlap? top_left -- get top-left corner bottom_right -- get bottom-right corner expanded_by -- grow (or shrink) """ def __init__(self, pt1, pt2): """Initialize a rectangle from two points.""" self.set_points(pt1, pt2) def set_points(self, pt1, pt2): """Reset the rectangle coordinates.""" (x1, y1) = pt1.as_tuple() (x2, y2) = pt2.as_tuple() self.left = min(x1, x2) self.top = min(y1, y2) self.right = max(x1, x2) self.bottom = max(y1, y2) def contains(self, pt): """Return true if a point is inside the rectangle.""" x,y = pt.as_tuple() return (self.left <= x <= self.right and self.top <= y <= self.bottom) def overlaps(self, other): """Return true if a rectangle overlaps this rectangle.""" return (self.right > other.left and self.left < other.right and self.top < other.bottom and self.bottom > other.top) def top_left(self): """Return the top-left corner as a Point.""" return Point(self.left, self.top) def bottom_right(self): """Return the bottom-right corner as a Point.""" return Point(self.right, self.bottom) def expanded_by(self, n): """Return a rectangle with extended borders. Create a new rectangle that is wider and taller than the immediate one. All sides are extended by "n" points. """ p1 = Point(self.left-n, self.top-n) p2 = Point(self.right+n, self.bottom+n) return Rect(p1, p2) def __str__( self ): return "" % (self.left,self.top, self.right,self.bottom) def __repr__(self): return "%s(%r, %r)" % (self.__class__.__name__, Point(self.left, self.top), Point(self.right, self.bottom)) }}} == Historical Note == It seems that [[http://www.informatik.hu-berlin.de/Themen/manuals/python/python-texinfo/top.html|Python version 1.0.2]] had [[http://www.informatik.hu-berlin.de/Themen/manuals/python/python-texinfo/module_index.html|standard module]] [[http://www.informatik.hu-berlin.de/Themen/manuals/python/python-texinfo/rect.html|rect!]] == See Also == * [[http://en.wikipedia.org/wiki/Cartesian_coordinate_system|Wikipedia:Cartesian coordinate system]] * [[http://en.wikipedia.org/wiki/Vector_%28spatial%29|Wikipedia:Vector]]