forked from tmr232/Ink2Impress
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmatutil.py
119 lines (90 loc) · 2.86 KB
/
matutil.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
"""
Decompose rotate&scale only (no shear) 2d matrices
"""
import math
import matrix
from matrix import Matrix, eye
def e_vec(size, dim):
if dim >= size:
raise ValueError("Dimension %d is larger than or equal to size %d" % (dim, size))
vec = matrix.column_vector([0 for x in range(size)])
vec[(dim, 0)] = 1
return vec
E_X = e_vec(2, 0)
E_Y = e_vec(2, 1)
def decompose_scale(mat):
"""Decompose the scale factors from a transformation matrix without shear.
"""
if not mat.is_square():
raise ValueError("Can't decompose a non-square matrix.")
dims = mat.rows()
scales = []
for dim in range(dims):
vec = e_vec(dims, dim)
vec_tag = mat * vec
scale = math.sqrt(vec_tag.transpose().matrix_multiply(vec_tag))
scales.append(scale)
return scales
def scale_matrix(*scale):
scale_vec = matrix.row_vector(list(scale))
scale_mat = matrix.eye(len(scale))
mat = matrix.Matrix(
[
[
(scale[col] if col == row else 0) for
col in range(len(scale))
] for
row in range(len(scale))
]
)
return mat
def translation_matrix(*translation):
mat = eye(len(translation) + 1)
for i, t in enumerate(translation):
mat[(i, len(translation))] = t
return mat
def rotation_matrix(size, d1, d2, angle):
if d1 == d2:
raise ValueError("d1 and d2 are equal!")
if d1 >= size or d2 >= size:
raise ValueError("Rotation dimensions are larger than matrix size!")
cos = math.cos(angle)
sin = math.sin(angle)
rotation_mat = matrix.eye(size)
rotation_mat[(d1, d1)] = cos
rotation_mat[(d1, d2)] = -sin
rotation_mat[(d2, d2)] = cos
rotation_mat[(d2, d1)] = sin
return rotation_mat
def rotation_matrix2(rotation):
cos = math.cos(rotation)
sin = math.sin(rotation)
return matrix.Matrix([
[cos, -sin],
[sin, cos]
])
def get_rotation_matrix(mat):
scale = decompose_scale(mat)
unscale_matrix = scale_matrix(*[1./s for s in scale])
return mat * unscale_matrix
#return rotation_matrix2(decompose_rotation2(mat))
def get_scale_matrix(mat):
return scale_matrix(decompose_scale(mat))
def decompose_rotation2(mat):
"""Decompose the rotation angles from a transformation matrix without shear.
"""
if not mat.is_square():
raise ValueError("Can't decompose a non-square matrix.")
if not mat.rows() == 2:
raise ValueError("Matrix is not 2x2")
rotation_mat = get_rotation_matrix(mat)
return math.atan2(rotation_mat[(1,0)], rotation_mat[(0,0)])
#vec = E_X
#vec_tag = mat * vec
#x = vec_tag[(0, 0)]
#y = vec_tag[(1, 0)]
#return math.atan2(y, x)
def main():
pass
if __name__ == "__main__":
main()