回答編集履歴

2

d

2019/03/05 05:53

投稿

tiitoi
tiitoi

スコア21956

test CHANGED
@@ -1,8 +1,6 @@
1
- 仕様明確ないのでアイデアだけ
1
+ fana さん回答してくださった方法実装してみました。
2
2
 
3
3
 
4
-
5
- 行列の各要素を4点で構成される正方形と考え、回転している x 軸に垂直な直線が交わる正方形を求めて、その値の平均をとる。
6
4
 
7
5
 
8
6
 
@@ -13,6 +11,10 @@
13
11
 
14
12
 
15
13
  ```python
14
+
15
+ import matplotlib.pyplot as plt
16
+
17
+ from matplotlib.patches import Rectangle
16
18
 
17
19
  import numpy as np
18
20
 
@@ -30,11 +32,21 @@
30
32
 
31
33
  [7, 2, 1, 6, 2, 8]], dtype=float)
32
34
 
35
+ angle = 10 # x 軸の回転角度 (degree)
36
+
33
- assert mat.shape[0] % 2 == 0 and mat.shape[1] % 2 == 0
37
+ radius = np.array(mat.shape) // 2 # 半径
34
38
 
35
39
 
36
40
 
41
+ def create_rotation_matrix(angle):
42
+
37
- theta = 10
43
+ t = np.deg2rad(angle)
44
+
45
+ return np.array([[np.cos(t), -np.sin(t)],
46
+
47
+ [np.sin(t), np.cos(t)]])
48
+
49
+ R = create_rotation_matrix(-angle) # x 軸の回転方向とは逆の方向に回転する回転行列
38
50
 
39
51
  ```
40
52
 
@@ -42,21 +54,105 @@
42
54
 
43
55
  ```
44
56
 
57
+ # 各セルの4点の座標を作成する。
58
+
45
59
  cells = []
60
+
61
+ id_ = 0 # あとでどのセルが含まれているのか確認するための識別子 (デバッグ用)
46
62
 
47
63
  for (i, j), value in np.ndenumerate(mat):
48
64
 
49
- # 行列 (i, j) 成分を行列中心を原とする標準座標系の点 (x, y) に変換する
65
+ # セル左下の点 (x, y) を定義する
50
66
 
51
- # (x, y) = j - rows // 2, i - cols // 2
67
+ x, y = j - radius[1], radius[0] - i - 1
52
68
 
53
- x, y = j - mat.shape[1] // 2, i - mat.shape[0] // 2
54
-
55
- # セルを構成する点
69
+ # セルを構成する4を作成する。
56
70
 
57
71
  rect = np.array([[x, y], [x + 1, y], [x + 1, y + 1], [x, y + 1], [x, y]])
58
72
 
73
+ # セルを構成する4点を回転させる。
74
+
75
+ rect = rect.dot(R.T)
76
+
77
+
78
+
59
- cells.append([rect, value])
79
+ cells.append((id_, rect, value))
80
+
81
+ id_ += 1
82
+
83
+ ```
84
+
85
+
86
+
87
+ 各区別 [x_i, x_{i + 1}] に含まれるセルを見つけて、その値の平均を計算する。
88
+
89
+
90
+
91
+ ```
92
+
93
+ edges = np.arange(-radius[1], radius[1] + 1)
94
+
95
+
96
+
97
+ for left, right in zip(edges, edges[1:]):
98
+
99
+ values = []
100
+
101
+ for id_, rect, value in cells:
102
+
103
+ if np.any((left <= rect[:, 0]) & (rect[:, 0] <= right)):
104
+
105
+ values.append((id_, value)) # セルの4隅の1点でも [left, right] に含まれる場合
106
+
107
+ values = sorted(values, key=lambda x: x[0]) # 見やすいように id でソートする。
108
+
109
+ mean = np.mean([x[1] for x in values]) # 平均
110
+
111
+ print('{} <= x <= {}:\n value: {}\n mean: {}'.format(
112
+
113
+ left, right, values, mean))
114
+
115
+ ```
116
+
117
+
118
+
119
+ ```
120
+
121
+ -3 <= x <= -2:
122
+
123
+ value: [(0, 3.0), (6, 2.0), (12, 4.0), (18, 0.0), (19, 4.0), (24, 4.0), (25, 2.0), (30, 7.0), (31, 2.0)]
124
+
125
+ mean: 3.111111111111111
126
+
127
+ -2 <= x <= -1:
128
+
129
+ value: [(0, 3.0), (1, 4.0), (6, 2.0), (7, 8.0), (12, 4.0), (13, 8.0), (18, 0.0), (19, 4.0), (20, 3.0), (25, 2.0), (26, 6.0), (31, 2.0), (32, 1.0)]
130
+
131
+ mean: 3.6153846153846154
132
+
133
+ -1 <= x <= 0:
134
+
135
+ value: [(1, 4.0), (2, 6.0), (7, 8.0), (8, 5.0), (13, 8.0), (14, 1.0), (15, 0.0), (19, 4.0), (20, 3.0), (21, 7.0), (26, 6.0), (27, 1.0), (32, 1.0), (33, 6.0)]
136
+
137
+ mean: 4.285714285714286
138
+
139
+ 0 <= x <= 1:
140
+
141
+ value: [(2, 6.0), (3, 9.0), (8, 5.0), (9, 0.0), (14, 1.0), (15, 0.0), (16, 3.0), (20, 3.0), (21, 7.0), (22, 1.0), (27, 1.0), (28, 0.0), (33, 6.0), (34, 2.0)]
142
+
143
+ mean: 3.142857142857143
144
+
145
+ 1 <= x <= 2:
146
+
147
+ value: [(3, 9.0), (4, 0.0), (9, 0.0), (10, 3.0), (15, 0.0), (16, 3.0), (17, 1.0), (22, 1.0), (23, 2.0), (28, 0.0), (29, 9.0), (34, 2.0), (35, 8.0)]
148
+
149
+ mean: 2.923076923076923
150
+
151
+ 2 <= x <= 3:
152
+
153
+ value: [(4, 0.0), (5, 8.0), (10, 3.0), (11, 5.0), (16, 3.0), (17, 1.0), (23, 2.0), (29, 9.0), (35, 8.0)]
154
+
155
+ mean: 4.333333333333333
60
156
 
61
157
  ```
62
158
 
@@ -68,66 +164,34 @@
68
164
 
69
165
  ###################################################################
70
166
 
71
- from matplotlib.patches import Rectangle
72
-
73
- import matplotlib.pyplot as plt
74
-
75
167
  fig, ax = plt.subplots(figsize=(6, 6))
76
168
 
77
169
 
78
170
 
79
171
  # 各セルを描画する。
80
172
 
81
- for rect, value in cells:
173
+ for id_, rect, value in cells:
82
174
 
83
175
  ax.plot(rect[:, 0], rect[:, 1], c='gray', alpha=0.5) # セルの枠線
84
176
 
85
177
  cx, cy = (rect[0] + rect[2]) / 2 # セルの中心
86
178
 
179
+ s = '{}:{}'.format(id_, value)
180
+
87
- ax.text(cx, cy, value, ha='center', va='center') # 値
181
+ ax.text(cx, cy, s, ha='center', va='center', rotation=-angle) # 値
88
182
 
89
183
  ax.autoscale(False)
90
184
 
185
+ # x 軸、y 軸を引く。
91
186
 
187
+ ax.axhline(), ax.axvline()
92
188
 
93
- # x 軸に垂直な直線を描画する。
189
+ # 垂直線を引く
94
190
 
95
- # theta だけ回転させた場合、x 軸の傾きは tan(theta), y 軸の傾きは tan(theta + 90) となることに注意すると
96
-
97
- for j in range(mat.shape[1]):
98
-
99
- x = j - mat.shape[1] // 2 + 0.5
100
-
101
- # (x', y') を通り、傾き m の直線 ===> (y - y') = m (x - x')
102
-
103
- xs = np.linspace(*ax.get_xlim(), 100)
191
+ ax.vlines(edges, *ax.get_xlim(), alpha=0.5)
104
-
105
- ys = (xs - x) * np.tan(np.radians(theta + 90))
106
-
107
- ax.plot(xs, ys, c='b', lw=1)
108
-
109
-
110
-
111
- # 回転後の x 軸、y 軸を描画する。
112
-
113
- xs = np.linspace(*ax.get_xlim(), 100)
114
-
115
- ys = xs * np.tan(np.radians(theta))
116
-
117
- ax.plot(xs, ys, c='k', lw=3)
118
-
119
-
120
-
121
- ys = xs * np.tan(np.radians(theta + 90))
122
-
123
- ax.plot(xs, ys, c='k', lw=3)
124
192
 
125
193
  ```
126
194
 
127
195
 
128
196
 
129
- ![イメージ説明](e52a938e4633f9fea57ff1dc413a6e33.png)
197
+ ![イメージ説明](45ac21cb6f1209e2647976c8bc85f0ae.png)
130
-
131
-
132
-
133
- 青い直線が通るセルを調べてその値の平均をとる。

1

d

2019/03/05 05:53

投稿

tiitoi
tiitoi

スコア21956

test CHANGED
@@ -34,7 +34,7 @@
34
34
 
35
35
 
36
36
 
37
- theta = 30
37
+ theta = 10
38
38
 
39
39
  ```
40
40
 
@@ -44,9 +44,9 @@
44
44
 
45
45
  cells = []
46
46
 
47
- for (i, j), v in np.ndenumerate(mat):
47
+ for (i, j), value in np.ndenumerate(mat):
48
48
 
49
- # 行列の (i, j) 成分を行列の中心を原点とする標準座標系の点 (x, y) に変換する式 ===>
49
+ # 行列の (i, j) 成分を行列の中心を原点とする標準座標系の点 (x, y) に変換する式
50
50
 
51
51
  # (x, y) = j - rows // 2, i - cols // 2
52
52
 
@@ -54,9 +54,9 @@
54
54
 
55
55
  # セルを構成する点
56
56
 
57
- r = np.array([[x, y], [x + 1, y], [x + 1, y + 1], [x, y + 1], [x, y]])
57
+ rect = np.array([[x, y], [x + 1, y], [x + 1, y + 1], [x, y + 1], [x, y]])
58
58
 
59
- cells.append([r, v])
59
+ cells.append([rect, value])
60
60
 
61
61
  ```
62
62
 
@@ -78,13 +78,13 @@
78
78
 
79
79
  # 各セルを描画する。
80
80
 
81
- for r, v in cells:
81
+ for rect, value in cells:
82
82
 
83
- ax.plot(r[:, 0], r[:, 1], c='gray', alpha=0.5) # セルの枠線
83
+ ax.plot(rect[:, 0], rect[:, 1], c='gray', alpha=0.5) # セルの枠線
84
84
 
85
- cx, cy = (r[0] + r[2]) / 2 # セルの中心
85
+ cx, cy = (rect[0] + rect[2]) / 2 # セルの中心
86
86
 
87
- ax.text(cx, cy, v, ha='center', va='center') # 値
87
+ ax.text(cx, cy, value, ha='center', va='center') # 値
88
88
 
89
89
  ax.autoscale(False)
90
90
 
@@ -94,11 +94,11 @@
94
94
 
95
95
  # theta だけ回転させた場合、x 軸の傾きは tan(theta), y 軸の傾きは tan(theta + 90) となることに注意すると
96
96
 
97
- for j in range(mat.shape[1] + 1):
97
+ for j in range(mat.shape[1]):
98
+
99
+ x = j - mat.shape[1] // 2 + 0.5
98
100
 
99
101
  # (x', y') を通り、傾き m の直線 ===> (y - y') = m (x - x')
100
-
101
- x = j - mat.shape[1] // 2
102
102
 
103
103
  xs = np.linspace(*ax.get_xlim(), 100)
104
104
 
@@ -126,7 +126,7 @@
126
126
 
127
127
 
128
128
 
129
- ![イメージ説明](e84dc4262a832cd4515f21df8dbb7ca9.png)
129
+ ![イメージ説明](e52a938e4633f9fea57ff1dc413a6e33.png)
130
130
 
131
131
 
132
132