import operator import math def vop(op, a, b): return list(map(op, a, b)) class NVector(): def __init__(self, *components): self.components = list(components) def __str__(self): return str(self.components) def __repr__(self): return "" % self def __len__(self): return len(self.components) def to_list(self): return list(self.components) def __add__(self, other): return type(self)(*vop(operator.add, self.components, other.components)) def __sub__(self, other): return type(self)(*vop(operator.sub, self.components, other.components)) def __mul__(self, scalar): if isinstance(scalar, NVector): return type(self)(*vop(operator.mul, self.components, scalar.components)) return type(self)(*(c * scalar for c in self.components)) def __truediv__(self, scalar): return type(self)(*(c / scalar for c in self.components)) def __iadd__(self, other): self.components = vop(operator.add, self.components, other.components) return self def __isub__(self, other): self.components = vop(operator.sub, self.components, other.components) return self def __imul__(self, scalar): if isinstance(scalar, NVector): self.components = vop(operator.mul, self.components, scalar.components) else: self.components = [c * scalar for c in self.components] return self def __itruediv__(self, scalar): self.components = [c / scalar for c in self.components] return self def __neg__(self): return type(self)(*(-c for c in self.components)) def __getitem__(self, key): if isinstance(key, slice): return NVector(*self.components[key]) return self.components[key] def __setitem__(self, key, value): self.components[key] = value def __eq__(self, other): return self.components == other.components def __abs__(self): return type(self)(*(abs(c) for c in self.components)) @property def length(self): return math.sqrt(sum(map(lambda x: x**2, self.components))) def dot(self, other): return sum(map(operator.mul, self.components, other.components)) def clone(self): return NVector(*self.components) def lerp(self, other, t): return self * (1-t) + other * t @property def x(self): return self.components[0] @x.setter def x(self, v): self.components[0] = v @property def y(self): return self.components[1] @y.setter def y(self, v): self.components[1] = v @property def z(self): return self.components[2] @z.setter def z(self, v): self.components[2] = v def element_scaled(self, other): return type(self)(*vop(operator.mul, self.components, other.components)) def cross(self, other): """ @pre len(self) == len(other) == 3 """ a = self b = other return type(self)( a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0], ) @property def polar_angle(self): """ @pre len(self) == 2 """ return math.atan2(self.y, self.x) def Point(x, y): return NVector(x, y) def Size(x, y): return NVector(x, y) def Point3D(x, y, z): return NVector(x, y, z) def PolarVector(length, theta): return NVector(length * math.cos(theta), length * math.sin(theta))