1from typing import Union
2from math import sin, cos, radians
3
4
[docs]
5class AffineMap:
6
7 # 平面のアフィン変換クラス
8 #
9 # 使い方:
10 # mat = AffineMap.new()
11
12 @classmethod
13 def _matmul3(
14 cls, a: list[list[Union[int, float]]], b: list[list[Union[int, float]]]
15 ) -> list[list[Union[int, float]]]:
16 res: list[list[Union[int, float]]] = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
17 for i in range(3):
18 for k in range(3):
19 for j in range(3):
20 res[i][j] += b[k][j] * a[i][k]
21 return res
22
[docs]
23 @classmethod
24 def new(cls) -> list[list[Union[int, float]]]:
25 return [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
26
[docs]
27 @classmethod
28 def shift(
29 cls,
30 a: list[list[Union[int, float]]],
31 shift_x: Union[int, float] = 0,
32 shift_y: Union[int, float] = 0,
33 ) -> list[list[Union[int, float]]]:
34 b = [[1, 0, shift_x], [0, 1, shift_y], [0, 0, 1]]
35 return cls._matmul3(b, a)
36
[docs]
37 @classmethod
38 def expand(
39 cls,
40 a: list[list[Union[int, float]]],
41 ratio_x: Union[int, float] = 1,
42 ratio_y: Union[int, float] = 1,
43 ) -> list[list[Union[int, float]]]:
44 b = [[ratio_x, 0, 0], [0, ratio_y, 0], [0, 0, 1]]
45 return cls._matmul3(b, a)
46
[docs]
47 @classmethod
48 def rotate(
49 cls, a: list[list[Union[int, float]]], theta: Union[int, float] = 0
50 ) -> list[list[Union[int, float]]]:
51 if theta == 90:
52 b = [[0, -1, 0], [1, 0, 0], [0, 0, 1]]
53 elif theta == -90:
54 b = [[0, 1, 0], [-1, 0, 0], [0, 0, 1]]
55 else:
56 theta = radians(theta)
57 b: list[list[Union[int, float]]] = [
58 [cos(theta), -sin(theta), 0],
59 [sin(theta), cos(theta), 0],
60 [0, 0, 1],
61 ]
62 return cls._matmul3(b, a)
63
[docs]
64 @classmethod
65 def x_symmetrical_move(
66 cls, a: list[list[Union[int, float]]], p: Union[int, float]
67 ) -> list[list[Union[int, float]]]:
68 b = [[-1, 0, 2 * p], [0, 1, 0], [0, 0, 1]]
69 return cls._matmul3(b, a)
70
[docs]
71 @classmethod
72 def y_symmetrical_move(
73 cls, a: list[list[Union[int, float]]], p: Union[int, float]
74 ) -> list[list[Union[int, float]]]:
75 b = [[1, 0, 0], [0, -1, 2 * p], [0, 0, 1]]
76 return cls._matmul3(b, a)
77
[docs]
78 @staticmethod
79 def get(
80 a: list[list[Union[int, float]]], x: float, y: float
81 ) -> tuple[float, float]:
82 a0, a1, _ = a
83 x, y = a0[0] * x + a0[1] * y + a0[2], a1[0] * x + a1[1] * y + a1[2]
84 return x, y