pymunk.transform 源代码
import math
from typing import NamedTuple, Tuple, Union, cast, overload
from .vec2d import Vec2d
[文档]
class Transform(NamedTuple):
"""Type used for 2x3 affine transforms.
See wikipedia for details:
http://en.wikipedia.org/wiki/Affine_transformation
The properties map to the matrix in this way:
= = ==
a c tx
b d ty
0 0 1
= = ==
An instance can be created in this way:
>>> Transform(1,2,3,4,5,6)
Transform(a=1, b=2, c=3, d=4, tx=5, ty=6)
Or overriding only some of the values (on a identity matrix):
>>> Transform(b=3,ty=5)
Transform(a=1, b=3, c=0, d=1, tx=0, ty=5)
Or using one of the static methods like identity or translation (see each
method for details).
The Transform supports the matrix multiplicaiton operator (@) with a
Transform, Vec2d or tuple as second operand, which produces a transformed
Transform or Vec2d as result:
>>> Transform.scaling(2) @ Transform.scaling(3)
Transform(a=6, b=0, c=0, d=6, tx=0, ty=0)
>>> Transform.scaling(2) @ Vec2d(1, 2)
Vec2d(2, 4)
"""
a: float = 1
b: float = 0
c: float = 0
d: float = 1
tx: float = 0
ty: float = 0
@overload
def __matmul__(self, other: Tuple[float, float]) -> Vec2d:
...
@overload
def __matmul__(
self, other: Tuple[float, float, float, float, float, float]
) -> "Transform":
...
[文档]
def __matmul__(
self,
other: Union[
Tuple[float, float], Tuple[float, float, float, float, float, float]
],
) -> Union[Vec2d, "Transform"]:
"""Multiply this transform with a Transform, Vec2d or Tuple of size 2
or 6.
Examples (Transform @ Transform):
>>> Transform() @ Transform() == Transform.identity()
True
>>> Transform.translation(2,3) @ Transform.translation(4,5)
Transform(a=1, b=0, c=0, d=1, tx=6, ty=8)
>>> Transform.scaling(2) @ Transform.scaling(3)
Transform(a=6, b=0, c=0, d=6, tx=0, ty=0)
>>> Transform.scaling(2) @ Transform.translation(3,4)
Transform(a=2, b=0, c=0, d=2, tx=6, ty=8)
>>> Transform.translation(3,4) @ Transform.scaling(2)
Transform(a=2, b=0, c=0, d=2, tx=3, ty=4)
Examples (Transform @ Vec2d):
>>> Transform.identity() @ Vec2d(1, 2)
Vec2d(1, 2)
>>> Transform.scaling(2) @ Vec2d(1, 2)
Vec2d(2, 4)
>>> Transform.translation(3,5) @ Vec2d(1, 2)
Vec2d(4, 7)
>>> Transform.rotation(1) @ Vec2d(1, 2) == Vec2d(1, 2).rotated(1)
True
"""
assert (
len(other) == 2 or len(other) == 6
), f"{other} not supported. Only Vec2d, Transform and Sequence of length 2 or 6 are supported."
if len(other) == 2:
assert len(other) == 2
x, y = cast(Tuple[float, float], other)
return Vec2d(
self.a * x + self.c * y + self.tx, self.b * x + self.d * y + self.ty
)
else:
a, b, c, d, tx, ty = cast(Tuple[float, float, float, float, float, float], other)
return Transform(
a=self.a * a + self.c * b + self.tx * 0,
b=self.b * a + self.d * b + self.ty * 0,
c=self.a * c + self.c * d + self.tx * 0,
d=self.b * c + self.d * d + self.ty * 0,
tx=self.a * tx + self.c * ty + self.tx * 1,
ty=self.b * tx + self.d * ty + self.ty * 1,
)
[文档]
@staticmethod
def identity() -> "Transform":
"""The identity transform
Example:
>>> Transform.identity()
Transform(a=1, b=0, c=0, d=1, tx=0, ty=0)
Returns a Transform with this matrix:
= = =
1 0 0
0 1 0
0 0 1
= = =
"""
return Transform(1, 0, 0, 1, 0, 0)
[文档]
def translated(self, x: float, y: float) -> "Transform":
"""Translate this Transform and return the result.
Example:
>>> Transform.scaling(2).translated(3,4)
Transform(a=2, b=0, c=0, d=2, tx=6, ty=8)
"""
return self @ Transform.translation(x, y)
[文档]
def scaled(self, s: float) -> "Transform":
"""Scale this Transform and return the result.
Example:
>>> Transform.translation(3,4).scaled(2)
Transform(a=2, b=0, c=0, d=2, tx=3, ty=4)
"""
return self @ Transform.scaling(s)
[文档]
def rotated(self, t: float) -> "Transform":
"""Rotate this Transform and return the result.
>>> '%.2f, %.2f, %.2f, %.2f, %.2f, %.2f' % Transform.rotation(1).rotated(0.5)
'0.07, 1.00, -1.00, 0.07, 0.00, 0.00'
>>> '%.2f, %.2f, %.2f, %.2f, %.2f, %.2f' % Transform.rotation(1.5)
'0.07, 1.00, -1.00, 0.07, 0.00, 0.00'
"""
return self @ Transform.rotation(t)
[文档]
@staticmethod
def translation(x: float, y: float) -> "Transform":
"""A translation transform
Example to translate (move) by 3 on x and 5 in y axis:
>>> Transform.translation(3, 5)
Transform(a=1, b=0, c=0, d=1, tx=3, ty=5)
Returns a Transform with this matrix:
= = =
1 0 x
0 1 y
0 0 1
= = =
"""
return Transform(tx=x, ty=y)
# split into scale and scale_non-uniform
[文档]
@staticmethod
def scaling(s: float) -> "Transform":
"""A scaling transform
Example to scale 4x:
>>> Transform.scaling(4)
Transform(a=4, b=0, c=0, d=4, tx=0, ty=0)
Returns a Transform with this matrix:
= = =
s 0 0
0 s 0
0 0 1
= = =
"""
return Transform(a=s, d=s)
[文档]
@staticmethod
def rotation(t: float) -> "Transform":
"""A rotation transform
Example to rotate by 1 rad:
>>> '%.2f, %.2f, %.2f, %.2f, %.2f, %.2f' % Transform.rotation(1)
'0.54, 0.84, -0.84, 0.54, 0.00, 0.00'
Returns a Transform with this matrix:
====== ======= =
cos(t) -sin(t) 0
sin(t) cos(t) 0
0 0 1
====== ======= =
"""
c = math.cos(t)
s = math.sin(t)
return Transform(a=c, b=s, c=-s, d=c)