Created
June 16, 2016 13:48
-
-
Save tfeldmann/4c4b56807f4447266bc6f722bf63705b to your computer and use it in GitHub Desktop.
A fast, feature-rich and easy-to-use python 2D vector class based on complex numbers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" A python 2D vector class based on complex numbers | |
""" | |
import cmath | |
class Vector(complex): | |
@classmethod | |
def fromPolar(cls, r, phi): | |
return cls(cmath.rect(r, phi)) | |
@classmethod | |
def fromQPoint(cls, qpoint): | |
return cls(qpoint.x(), qpoint.y()) | |
@property | |
def x(self): | |
return self.real | |
@property | |
def y(self): | |
return self.imag | |
@property | |
def xy(self): | |
return (self.x, self.y) | |
@property | |
def r(self): | |
return abs(self) | |
@property | |
def phi(self): | |
return self.normalizeAngle(cmath.phase(self)) | |
@property | |
def rphi(self): | |
return (self.r, self.phi) | |
@property | |
def qpoint(self): | |
from PySide import QtCore | |
return QtCore.QPointF(self.x, self.y) | |
@staticmethod | |
def normalizeAngle(phi): | |
return phi % (2 * cmath.pi) | |
@property | |
def unitVector(self, *, suppressZeroDivisionError=True): | |
length = abs(self) | |
if length == 0 and suppressZeroDivisionError: | |
return Vector(1, 0) | |
else: | |
return self / length | |
unitV = unitVector | |
@property | |
def normalVector(self): | |
return Vector(self.y, -self.x) | |
normal = normalVector | |
def isBetweenAngles(self, startAngle, stopAngle): | |
phi = self.normalizeAngle(cmath.phase(self)) | |
fromPhi = self.normalizeAngle(startAngle) | |
toPhi = self.normalizeAngle(stopAngle) | |
if fromPhi <= toPhi: | |
return fromPhi <= phi <= toPhi | |
return fromPhi <= phi or phi <= toPhi | |
def translate(self, dx, dy): | |
return self + Vector(dx, dy) | |
def rotate(self, phi, center=None): | |
if not center: | |
return self * cmath.exp(1j * phi) | |
else: | |
vec = center.vectorTo(self) | |
return center + vec * cmath.exp(1j * phi) | |
def scale(self, factorX, factorY): | |
return Vector(self.x * factorX, self.y * factorY) | |
def vectorTo(self, point): | |
return point - self | |
to = vectorTo | |
def __add__(self, other): | |
return Vector(super().__add__(other)) | |
def __pos__(self): | |
return Vector(super().__pos__()) | |
def __neg__(self): | |
return Vector(super().__neg__()) | |
def __sub__(self, other): | |
return Vector(super().__sub__(other)) | |
def __mul__(self, other): | |
return Vector(super().__mul__(other)) | |
def __truediv__(self, other): | |
return Vector(super().__truediv__(other)) | |
def __round__(self): | |
return Vector(round(self.x), round(self.y)) | |
def __repr__(self): | |
return '<Vector(x=%.3f, y=%.3f)>' % self.xy | |
def __str__(self): | |
return '(%.3f, %.3f)' % self.xy |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment