# Copyright 2008 by Peter Moxhay and Wade Brainerd. # This file is part of Math. # # Math is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Math is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Math. If not, see . import math class Vector: def __init__(self, x=0, y=0): self.x = x self.y = y # Binary operators. def __add__(self, v): return Vector(self.x + v.x, self.y + v.y) def __sub__(self, v): return Vector(self.x - v.x, self.y - v.y) def __mul__(self, n): return Vector(self.x * n, self.y * n) def __div__(self, n): return Vector(self.x / n, self.y / n) # In-place operators. def __iadd__(self, v): self.x += v.x self.y += v.y return self def __isub__(self, v): self.x -= v.x self.y -= v.y return self def __imul__(self, n): self.x *= n self.y *= n return self def __idiv__(self, n): self.x /= n self.y /= n return self # Unary operators def __neg__(self): return Vector(-self.x, -self.y) def __abs__(self): return Vector(abs(self.x), abs(self.y)) def __repr__(self): return "x=%f y=%f" % (self.x, self.y) # Methods def dot(self, v): """Returns the dot product with v as a scalar.""" return self.x*v.x + self.y*v.y def length(self): """Returns the vector length.""" return math.sqrt(self.x*self.x + self.y*self.y) def scaled(self, factor): """Returns the vector scaled by a given factor.""" return Vector(self.x * factor, self.y * factor) def theta(self): """Returns the vector's angle with respect to the x-axis.""" return math.atan2(self.y, self.x) def normalize(self): """Returns the vector normalized, or else a zero vector if the vector has zero length.""" l = self.length() if l > 0: return self / l else: return Vector(0, 0) def max(self, v): """Returns the componentwise maximum of the vector with v.""" return Vector(max(self.x, v.x), max(self.y, v.y)) def min(self, v): """Returns the componentwise minimum of the vector with v.""" return Vector(min(self.x, v.x), min(self.y, v.y)) def clamp(self, mn, mx): """Returns the vector clamped componentwise between mn and mx.""" return self.max(mx).min(mn) def rotate(self, a): """Returns the vector rotated about the origin by a radians.""" sa, ca, = math.sin(a), math.cos(a) return Vector(self.x*ca - self.y*sa, self.x*sa + self.y*ca) def approx_equal(self, a, tolerance=5): """Returns True if the vector is within tolerance of equaling a.""" return (self - a).length() < tolerance