mirror of
https://github.com/OpenVGLab/OmniLottie.git
synced 2026-09-17 07:36:27 +00:00
Initial Commit
This commit is contained in:
@@ -0,0 +1,205 @@
|
||||
import math
|
||||
from ..nvector import NVector
|
||||
|
||||
|
||||
def _sign(x):
|
||||
if x < 0:
|
||||
return -1
|
||||
return 1
|
||||
|
||||
|
||||
class TransformMatrix:
|
||||
scalar = float
|
||||
|
||||
def __init__(self):
|
||||
""" Creates an Identity matrix """
|
||||
self.to_identity()
|
||||
|
||||
def clone(self):
|
||||
m = TransformMatrix()
|
||||
m._mat = list(self._mat)
|
||||
return m
|
||||
|
||||
return self
|
||||
|
||||
def __getitem__(self, key):
|
||||
row, col = key
|
||||
return self._mat[row*4+col]
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
row, col = key
|
||||
self._mat[row*4+col] = self.scalar(value)
|
||||
|
||||
@property
|
||||
def a(self):
|
||||
return self[0, 0]
|
||||
|
||||
@a.setter
|
||||
def a(self, v):
|
||||
self[0, 0] = self.scalar(v)
|
||||
|
||||
@property
|
||||
def b(self):
|
||||
return self[0, 1]
|
||||
|
||||
@b.setter
|
||||
def b(self, v):
|
||||
self[0, 1] = self.scalar(v)
|
||||
|
||||
@property
|
||||
def c(self):
|
||||
return self[1, 0]
|
||||
|
||||
@c.setter
|
||||
def c(self, v):
|
||||
self[1, 0] = self.scalar(v)
|
||||
|
||||
@property
|
||||
def d(self):
|
||||
return self[1, 1]
|
||||
|
||||
@d.setter
|
||||
def d(self, v):
|
||||
self[1, 1] = self.scalar(v)
|
||||
|
||||
@property
|
||||
def tx(self):
|
||||
return self[3, 0]
|
||||
|
||||
@tx.setter
|
||||
def tx(self, v):
|
||||
self[3, 0] = self.scalar(v)
|
||||
|
||||
@property
|
||||
def ty(self):
|
||||
return self[3, 1]
|
||||
|
||||
@ty.setter
|
||||
def ty(self, v):
|
||||
self[3, 1] = self.scalar(v)
|
||||
|
||||
def __str__(self):
|
||||
return str(self._mat)
|
||||
|
||||
def scale(self, x, y=None):
|
||||
if y is None:
|
||||
y = x
|
||||
|
||||
m = TransformMatrix()
|
||||
m.a = x
|
||||
m.d = y
|
||||
self *= m
|
||||
return self
|
||||
|
||||
def translate(self, x, y=None):
|
||||
if y is None:
|
||||
x, y = x
|
||||
m = TransformMatrix()
|
||||
m.tx = x
|
||||
m.ty = y
|
||||
self *= m
|
||||
return self
|
||||
|
||||
def skew(self, x_rad, y_rad):
|
||||
m = TransformMatrix()
|
||||
m.c = math.tan(x_rad)
|
||||
m.b = math.tan(y_rad)
|
||||
self *= m
|
||||
return self
|
||||
|
||||
def skew_from_axis(self, skew, axis):
|
||||
self.rotate(axis)
|
||||
m = TransformMatrix()
|
||||
m.c = math.tan(skew)
|
||||
self *= m
|
||||
self.rotate(-axis)
|
||||
return self
|
||||
|
||||
def row(self, i):
|
||||
return NVector(self[i, 0], self[i, 1], self[i, 2], self[i, 3])
|
||||
|
||||
def column(self, i):
|
||||
return NVector(self[0, i], self[1, i], self[2, i], self[3, i])
|
||||
|
||||
def to_identity(self):
|
||||
self._mat = [
|
||||
1., 0., 0., 0.,
|
||||
0., 1., 0., 0.,
|
||||
0., 0., 1., 0.,
|
||||
0., 0., 0., 1.,
|
||||
]
|
||||
|
||||
def apply(self, vector):
|
||||
vector3 = NVector(vector.x, vector.y, 0, 1)
|
||||
return NVector(
|
||||
self.column(0).dot(vector3),
|
||||
self.column(1).dot(vector3),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def rotation(cls, radians):
|
||||
m = cls()
|
||||
m.a = math.cos(radians)
|
||||
m.b = -math.sin(radians)
|
||||
m.c = math.sin(radians)
|
||||
m.d = math.cos(radians)
|
||||
|
||||
return m
|
||||
|
||||
def __mul__(self, other):
|
||||
m = TransformMatrix()
|
||||
for row in range(4):
|
||||
for col in range(4):
|
||||
m[row, col] = self.row(row).dot(other.column(col))
|
||||
return m
|
||||
|
||||
def __imul__(self, other):
|
||||
m = self * other
|
||||
self._mat = m._mat
|
||||
return self
|
||||
|
||||
def rotate(self, radians):
|
||||
self *= TransformMatrix.rotation(radians)
|
||||
return self
|
||||
|
||||
def extract_transform(self):
|
||||
a = self.a
|
||||
b = self.b
|
||||
c = self.c
|
||||
d = self.d
|
||||
tx = self.tx
|
||||
ty = self.ty
|
||||
|
||||
dest_trans = {
|
||||
"translation": NVector(tx, ty),
|
||||
"angle": 0,
|
||||
"scale": NVector(1, 1),
|
||||
"skew_axis": 0,
|
||||
"skew_angle": 0,
|
||||
}
|
||||
|
||||
delta = a * d - b * c
|
||||
if a != 0 or b != 0:
|
||||
r = math.hypot(a, b)
|
||||
dest_trans["angle"] = - _sign(b) * math.acos(a/r)
|
||||
sx = r
|
||||
sy = delta / r
|
||||
dest_trans["skew_axis"] = 0
|
||||
else:
|
||||
r = math.hypot(c, d)
|
||||
dest_trans["angle"] = math.pi / 2 + _sign(d) * math.acos(c / r)
|
||||
sx = delta / r
|
||||
sy = r
|
||||
dest_trans["skew_axis"] = math.pi / 2
|
||||
|
||||
dest_trans["scale"] = NVector(sx, sy)
|
||||
|
||||
skew = math.atan2((a * c + b * d), r * r)
|
||||
dest_trans["skew_angle"] = skew
|
||||
|
||||
return dest_trans
|
||||
|
||||
def to_css_2d(self):
|
||||
return "matrix(%s, %s, %s, %s, %s, %s)" % (
|
||||
self.a, self.b, self.c, self.d, self.tx, self.ty
|
||||
)
|
||||
Reference in New Issue
Block a user