Welcome, guest | Sign In | My Account | Store | Cart
```from math import *
from functools import wraps

################################################################################

def autocast(method): # Optional method decorator
@wraps(method)
def wrapper(self, obj):
try:
return method(self, self.__class__(*obj))
except TypeError:
return method(self, obj)
return wrapper

################################################################################

def Polar2(magnitude, degrees):
return Vector2(x, y)

################################################################################

class Vector2:

__slots__ = 'x', 'y'

def __init__(self, x, y):
self.x = x
self.y = y

def __repr__(self):
return 'Vector2({!r}, {!r})'.format(self.x, self.y)

def polar_repr(self):
x, y = self.x, self.y
magnitude = hypot(x, y)
angle = degrees(atan2(x, y)) % 360
return 'Polar2({!r}, {!r})'.format(magnitude, angle)

# Rich Comparison Methods

def __lt__(self, obj):
if isinstance(obj, Vector2):
x1, y1, x2, y2 = self.x, self.y, obj.x, obj.y
return x1 * x1 + y1 * y1 < x2 * x2 + y2 * y2
return hypot(self.x, self.y) < obj

def __le__(self, obj):
if isinstance(obj, Vector2):
x1, y1, x2, y2 = self.x, self.y, obj.x, obj.y
return x1 * x1 + y1 * y1 <= x2 * x2 + y2 * y2
return hypot(self.x, self.y) <= obj

def __eq__(self, obj):
if isinstance(obj, Vector2):
return self.x == obj.x and self.y == obj.y
return hypot(self.x, self.y) == obj

def __ne__(self, obj):
if isinstance(obj, Vector2):
return self.x != obj.x or self.y != obj.y
return hypot(self.x, self.y) != obj

def __gt__(self, obj):
if isinstance(obj, Vector2):
x1, y1, x2, y2 = self.x, self.y, obj.x, obj.y
return x1 * x1 + y1 * y1 > x2 * x2 + y2 * y2
return hypot(self.x, self.y) > obj

def __ge__(self, obj):
if isinstance(obj, Vector2):
x1, y1, x2, y2 = self.x, self.y, obj.x, obj.y
return x1 * x1 + y1 * y1 >= x2 * x2 + y2 * y2
return hypot(self.x, self.y) >= obj

# Boolean Operation

def __bool__(self):
return self.x != 0 or self.y != 0

# Container Methods

def __len__(self):
return 2

def __getitem__(self, index):
return (self.x, self.y)[index]

def __setitem__(self, index, value):
temp = [self.x, self.y]
temp[index] = value
self.x, self.y = temp

def __iter__(self):
yield self.x
yield self.y

def __reversed__(self):
yield self.y
yield self.x

def __contains__(self, obj):
return obj in (self.x, self.y)

# Binary Arithmetic Operations

if isinstance(obj, Vector2):
return Vector2(self.x + obj.x, self.y + obj.y)
return Vector2(self.x + obj, self.y + obj)

def __sub__(self, obj):
if isinstance(obj, Vector2):
return Vector2(self.x - obj.x, self.y - obj.y)
return Vector2(self.x - obj, self.y - obj)

def __mul__(self, obj):
if isinstance(obj, Vector2):
return Vector2(self.x * obj.x, self.y * obj.y)
return Vector2(self.x * obj, self.y * obj)

def __truediv__(self, obj):
if isinstance(obj, Vector2):
return Vector2(self.x / obj.x, self.y / obj.y)
return Vector2(self.x / obj, self.y / obj)

def __floordiv__(self, obj):
if isinstance(obj, Vector2):
return Vector2(self.x // obj.x, self.y // obj.y)
return Vector2(self.x // obj, self.y // obj)

def __mod__(self, obj):
if isinstance(obj, Vector2):
return Vector2(self.x % obj.x, self.y % obj.y)
return Vector2(self.x % obj, self.y % obj)

def __divmod__(self, obj):
if isinstance(obj, Vector2):
return (Vector2(self.x // obj.x, self.y // obj.y),
Vector2(self.x % obj.x, self.y % obj.y))
return (Vector2(self.x // obj, self.y // obj),
Vector2(self.x % obj, self.y % obj))

def __pow__(self, obj):
if isinstance(obj, Vector2):
return Vector2(self.x ** obj.x, self.y ** obj.y)
return Vector2(self.x ** obj, self.y ** obj)

def __lshift__(self, obj):
if isinstance(obj, Vector2):
return Vector2(self.x << obj.x, self.y << obj.y)
return Vector2(self.x << obj, self.y << obj)

def __rshift__(self, obj):
if isinstance(obj, Vector2):
return Vector2(self.x >> obj.x, self.y >> obj.y)
return Vector2(self.x >> obj, self.y >> obj)

def __and__(self, obj):
if isinstance(obj, Vector2):
return Vector2(self.x & obj.x, self.y & obj.y)
return Vector2(self.x & obj, self.y & obj)

def __xor__(self, obj):
if isinstance(obj, Vector2):
return Vector2(self.x ^ obj.x, self.y ^ obj.y)
return Vector2(self.x ^ obj, self.y ^ obj)

def __or__(self, obj):
if isinstance(obj, Vector2):
return Vector2(self.x | obj.x, self.y | obj.y)
return Vector2(self.x | obj, self.y | obj)

# Binary Arithmetic Operations (with reflected operands)

return Vector2(obj + self.x, obj + self.y)

def __rsub__(self, obj):
return Vector2(obj - self.x, obj - self.y)

def __rmul__(self, obj):
return Vector2(obj * self.x, obj * self.y)

def __rtruediv__(self, obj):
return Vector2(obj / self.x, obj / self.y)

def __rfloordiv__(self, obj):
return Vector2(obj // self.x, obj // self.y)

def __rmod__(self, obj):
return Vector2(obj % self.x, obj % self.y)

def __rdivmod__(self, obj):
return (Vector2(obj // self.x, obj // self.y),
Vector2(obj % self.x, obj % self.y))

def __rpow__(self, obj):
return Vector2(obj ** self.x, obj ** self.y)

def __rlshift__(self, obj):
return Vector2(obj << self.x, obj << self.y)

def __rrshift__(self, obj):
return Vector2(obj >> self.x, obj >> self.y)

def __rand__(self, obj):
return Vector2(obj & self.x, obj & self.y)

def __rxor__(self, obj):
return Vector2(obj ^ self.x, obj ^ self.y)

def __ror__(self, obj):
return Vector2(obj | self.x, obj | self.y)

# Augmented Arithmetic Assignments

if isinstance(obj, Vector2):
self.x += obj.x
self.y += obj.y
else:
self.x += obj
self.y += obj
return self

def __isub__(self, obj):
if isinstance(obj, Vector2):
self.x -= obj.x
self.y -= obj.y
else:
self.x -= obj
self.y -= obj
return self

def __imul__(self, obj):
if isinstance(obj, Vector2):
self.x *= obj.x
self.y *= obj.y
else:
self.x *= obj
self.y *= obj
return self

def __itruediv__(self, obj):
if isinstance(obj, Vector2):
self.x /= obj.x
self.y /= obj.y
else:
self.x /= obj
self.y /= obj
return self

def __ifloordiv__(self, obj):
if isinstance(obj, Vector2):
self.x //= obj.x
self.y //= obj.y
else:
self.x //= obj
self.y //= obj
return self

def __imod__(self, obj):
if isinstance(obj, Vector2):
self.x %= obj.x
self.y %= obj.y
else:
self.x %= obj
self.y %= obj
return self

def __ipow__(self, obj):
if isinstance(obj, Vector2):
self.x **= obj.x
self.y **= obj.y
else:
self.x **= obj
self.y **= obj
return self

def __ilshift__(self, obj):
if isinstance(obj, Vector2):
self.x <<= obj.x
self.y <<= obj.y
else:
self.x <<= obj
self.y <<= obj
return self

def __irshift__(self, obj):
if isinstance(obj, Vector2):
self.x >>= obj.x
self.y >>= obj.y
else:
self.x >>= obj
self.y >>= obj
return self

def __iand__(self, obj):
if isinstance(obj, Vector2):
self.x &= obj.x
self.y &= obj.y
else:
self.x &= obj
self.y &= obj
return self

def __ixor__(self, obj):
if isinstance(obj, Vector2):
self.x ^= obj.x
self.y ^= obj.y
else:
self.x ^= obj
self.y ^= obj
return self

def __ior__(self, obj):
if isinstance(obj, Vector2):
self.x |= obj.x
self.y |= obj.y
else:
self.x |= obj
self.y |= obj
return self

# Unary Arithmetic Operations

def __pos__(self):
return Vector2(+self.x, +self.y)

def __neg__(self):
return Vector2(-self.x, -self.y)

def __invert__(self):
return Vector2(~self.x, ~self.y)

def __abs__(self):
return Vector2(abs(self.x), abs(self.y))

# Virtual "magnitude" Attribute

def __fg_ma(self):
return hypot(self.x, self.y)

def __fs_ma(self, value):
x, y = self.x, self.y
temp = value / hypot(x, y)
self.x, self.y = x * temp, y * temp

magnitude = property(__fg_ma, __fs_ma, doc='Virtual "magnitude" Attribute')

# Virtual "direction" Attribute

def __fg_di(self):
return atan2(self.y, self.x)

def __fs_di(self, value):
temp = hypot(self.x, self.y)
self.x, self.y = cos(value) * temp, sin(value) * temp

direction = property(__fg_di, __fs_di, doc='Virtual "direction" Attribute')

# Virtual "degrees" Attribute

def __fg_de(self):
return degrees(atan2(self.x, self.y)) % 360

def __fs_de(self, value):
value, temp = radians(value), hypot(self.x, self.y)
self.x, self.y = sin(value) * temp, cos(value) * temp

degrees = property(__fg_de, __fs_de, doc='Virtual "degrees" Attribute')

# Virtual "xy" Attribute

def __fg_xy(self):
return self.x, self.y

def __fs_xy(self, value):
self.x, self.y = value

xy = property(__fg_xy, __fs_xy, doc='Virtual "xy" Attribute')

# Virtual "yx" Attribute

def __fg_yx(self):
return self.y, self.x

def __fs_yx(self, value):
self.y, self.x = value

yx = property(__fg_yx, __fs_yx, doc='Virtual "yx" Attribute')

# Unit Vector Operations

def unit_vector(self):
x, y = self.x, self.y
temp = hypot(x, y)
return Vector2(x / temp, y / temp)

def normalize(self):
x, y = self.x, self.y
temp = hypot(x, y)
self.x, self.y = x / temp, y / temp
return self

# Vector Multiplication Operations

def dot_product(self, vec):
return self.x * vec.x + self.y * vec.y

def cross_product(self, vec):
return self.x * vec.y - self.y * vec.x

# Geometric And Physical Reflections

def reflect(self, vec):
x1, y1, x2, y2 = self.x, self.y, vec.x, vec.y
temp = 2 * (x1 * x2 + y1 * y2) / (x2 * x2 + y2 * y2)
return Vector2(x2 * temp - x1, y2 * temp - y1)

def bounce(self, vec):
x1, y1, x2, y2 = self.x, self.y, +vec.y, -vec.x
temp = 2 * (x1 * x2 + y1 * y2) / (x2 * x2 + y2 * y2)
return Vector2(x2 * temp - x1, y2 * temp - y1)

# Standard Vector Operations

def project(self, vec):
x, y = vec.x, vec.y
temp = (self.x * x + self.y * y) / (x * x + y * y)
return Vector2(x * temp, y * temp)

def rotate(self, vec):
x1, y1, x2, y2 = self.x, self.y, vec.x, vec.y
return Vector2(x1 * x2 + y1 * y2, y1 * x2 - x1 * y2)

def interpolate(self, vec, bias):
a = 1 - bias
return Vector2(self.x * a + vec.x * bias, self.y * a + vec.y * bias)

# Other Useful Methods

def near(self, vec, dist):
x, y = self.x - vec.x, self.y - vec.y
return x * x + y * y <= dist * dist

def perpendicular(self):
return Vector2(+self.y, -self.x)

def subset(self, vec1, vec2):
x1, x2 = vec1.x, vec2.x
if x1 <= x2:
if x1 <= self.x <= x2:
y1, y2 = vec1.y, vec2.y
if y1 <= y2:
return y1 <= self.y <= y2
return y2 <= self.y <= y1
else:
if x2 <= self.x <= x1:
y1, y2 = vec1.y, vec2.y
if y1 <= y2:
return y1 <= self.y <= y2
return y2 <= self.y <= y1
return False

def distance(self, vec):
return hypot(self.x - vec.x, self.y - vec.y)

def limit(self, dist):
x, y = self.x, self.y
magnitude = hypot(x, y)
if magnitude > dist:
temp = dist / magnitude
self.x, self.y = x * temp, y * temp
return self

def direction_between(self, vec):
return atan2(self.y, self.x) - atan2(vec.y, vec.x)

def degrees_between(self, vec):
diff = degrees(atan2(self.y, self.x) - atan2(vec.y, vec.x)) % 360
return 360 - diff if diff > 180 else diff

# Synonymous Definitions

copy = __pos__

inverse = __neg__

unit = unit_vector

dot = dot_product

cross = cross_product

lerp = interpolate

perp = perpendicular

dist = distance

dir_diff = direction_between

deg_diff = degrees_between

################################################################################

import recipe576904; recipe576904.bind_all(globals())
```