[transform] Add Transform.toDecomposed()
This commit is contained in:
parent
a1907cfd4d
commit
cf9dece8f2
@ -349,6 +349,44 @@ class Transform(NamedTuple):
|
|||||||
"""
|
"""
|
||||||
return "[%s %s %s %s %s %s]" % self
|
return "[%s %s %s %s %s %s]" % self
|
||||||
|
|
||||||
|
def toDecomposed(self) -> "DecomposedTransform":
|
||||||
|
"""Decompose into a DecomposedTransform."""
|
||||||
|
# Adapted from an answer on
|
||||||
|
# https://math.stackexchange.com/questions/13150/extracting-rotation-scale-values-from-2d-transformation-matrix
|
||||||
|
a, b, c, d, x, y = self
|
||||||
|
delta = a * d - b * c
|
||||||
|
|
||||||
|
rotation = 0
|
||||||
|
scaleX = scaleY = 0
|
||||||
|
skewX = skewY = 0
|
||||||
|
|
||||||
|
# Apply the QR-like decomposition.
|
||||||
|
if a != 0 or b != 0:
|
||||||
|
r = math.sqrt(a * a + b * b)
|
||||||
|
rotation = math.acos(a / r) if b > 0 else -math.acos(a / r)
|
||||||
|
scaleX, scaleY = (r, delta / r)
|
||||||
|
skewX, skewY = (math.atan((a * c + b * d) / (r * r)), 0)
|
||||||
|
elif c != 0 or d != 0:
|
||||||
|
s = math.sqrt(c * c + d * d)
|
||||||
|
rotation = math.pi / 2 - (math.acos(-c / s) if d > 0 else -math.acos(c / s))
|
||||||
|
scaleX, scaleY = (delta / s, s)
|
||||||
|
skewX, skewY = (0, math.atan((a * c + b * d) / (s * s)))
|
||||||
|
else:
|
||||||
|
# a = b = c = d = 0
|
||||||
|
pass
|
||||||
|
|
||||||
|
return DecomposedTransform(
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
math.degrees(rotation),
|
||||||
|
scaleX,
|
||||||
|
scaleY,
|
||||||
|
-math.degrees(skewX),
|
||||||
|
math.degrees(skewY),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
|
||||||
def __bool__(self):
|
def __bool__(self):
|
||||||
"""Returns True if transform is not identity, False otherwise.
|
"""Returns True if transform is not identity, False otherwise.
|
||||||
|
|
||||||
|
@ -115,6 +115,14 @@ class TransformTest(object):
|
|||||||
assert Scale(2) == Transform(2, 0, 0, 2, 0, 0)
|
assert Scale(2) == Transform(2, 0, 0, 2, 0, 0)
|
||||||
assert Scale(1, 2) == Transform(1, 0, 0, 2, 0, 0)
|
assert Scale(1, 2) == Transform(1, 0, 0, 2, 0, 0)
|
||||||
|
|
||||||
|
def test_decompose(self):
|
||||||
|
t = Transform(2, 0, 0, 3, 5, 7)
|
||||||
|
d = t.toDecomposed()
|
||||||
|
assert d.scaleX == 2
|
||||||
|
assert d.scaleY == 3
|
||||||
|
assert d.translateX == 5
|
||||||
|
assert d.translateY == 7
|
||||||
|
|
||||||
|
|
||||||
class DecomposedTransformTest(object):
|
class DecomposedTransformTest(object):
|
||||||
def test_identity(self):
|
def test_identity(self):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user