Files
OmniLottie/lottie/nvector.py
T
2026-03-01 21:36:54 +08:00

149 lines
3.5 KiB
Python

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 "<NVector %s>" % 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))