回答編集履歴
2
d
answer
CHANGED
@@ -1,11 +1,12 @@
|
|
1
|
-
|
1
|
+
fana さんが回答してくださった方法で実装してみました。
|
2
2
|
|
3
|
-
行列の各要素を4点で構成される正方形と考え、回転している x 軸に垂直な直線が交わる正方形を求めて、その値の平均をとる。
|
4
3
|
|
5
4
|
----
|
6
5
|
|
7
6
|
|
8
7
|
```python
|
8
|
+
import matplotlib.pyplot as plt
|
9
|
+
from matplotlib.patches import Rectangle
|
9
10
|
import numpy as np
|
10
11
|
|
11
12
|
mat = np.array([[3, 4, 6, 9, 0, 8],
|
@@ -14,54 +15,85 @@
|
|
14
15
|
[0, 4, 3, 7, 1, 2],
|
15
16
|
[4, 2, 6, 1, 0, 9],
|
16
17
|
[7, 2, 1, 6, 2, 8]], dtype=float)
|
18
|
+
angle = 10 # x 軸の回転角度 (degree)
|
17
|
-
|
19
|
+
radius = np.array(mat.shape) // 2 # 半径
|
18
20
|
|
21
|
+
def create_rotation_matrix(angle):
|
19
|
-
|
22
|
+
t = np.deg2rad(angle)
|
23
|
+
return np.array([[np.cos(t), -np.sin(t)],
|
24
|
+
[np.sin(t), np.cos(t)]])
|
25
|
+
R = create_rotation_matrix(-angle) # x 軸の回転方向とは逆の方向に回転する回転行列
|
20
26
|
```
|
21
27
|
|
22
28
|
```
|
29
|
+
# 各セルの4点の座標を作成する。
|
23
30
|
cells = []
|
31
|
+
id_ = 0 # あとでどのセルが含まれているのか確認するための識別子 (デバッグ用)
|
24
32
|
for (i, j), value in np.ndenumerate(mat):
|
25
|
-
#
|
33
|
+
# セルの左下の点 (x, y) を定義する。
|
26
|
-
|
34
|
+
x, y = j - radius[1], radius[0] - i - 1
|
27
|
-
x, y = j - mat.shape[1] // 2, i - mat.shape[0] // 2
|
28
|
-
# セルを構成する点
|
35
|
+
# セルを構成する4点を作成する。
|
29
36
|
rect = np.array([[x, y], [x + 1, y], [x + 1, y + 1], [x, y + 1], [x, y]])
|
37
|
+
# セルを構成する4点を回転させる。
|
38
|
+
rect = rect.dot(R.T)
|
39
|
+
|
30
|
-
cells.append(
|
40
|
+
cells.append((id_, rect, value))
|
41
|
+
id_ += 1
|
31
42
|
```
|
32
43
|
|
44
|
+
各区別 [x_i, x_{i + 1}] に含まれるセルを見つけて、その値の平均を計算する。
|
45
|
+
|
46
|
+
```
|
47
|
+
edges = np.arange(-radius[1], radius[1] + 1)
|
48
|
+
|
49
|
+
for left, right in zip(edges, edges[1:]):
|
50
|
+
values = []
|
51
|
+
for id_, rect, value in cells:
|
52
|
+
if np.any((left <= rect[:, 0]) & (rect[:, 0] <= right)):
|
53
|
+
values.append((id_, value)) # セルの4隅の1点でも [left, right] に含まれる場合
|
54
|
+
values = sorted(values, key=lambda x: x[0]) # 見やすいように id でソートする。
|
55
|
+
mean = np.mean([x[1] for x in values]) # 平均
|
56
|
+
print('{} <= x <= {}:\n value: {}\n mean: {}'.format(
|
57
|
+
left, right, values, mean))
|
58
|
+
```
|
59
|
+
|
60
|
+
```
|
61
|
+
-3 <= x <= -2:
|
62
|
+
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)]
|
63
|
+
mean: 3.111111111111111
|
64
|
+
-2 <= x <= -1:
|
65
|
+
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)]
|
66
|
+
mean: 3.6153846153846154
|
67
|
+
-1 <= x <= 0:
|
68
|
+
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)]
|
69
|
+
mean: 4.285714285714286
|
70
|
+
0 <= x <= 1:
|
71
|
+
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)]
|
72
|
+
mean: 3.142857142857143
|
73
|
+
1 <= x <= 2:
|
74
|
+
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)]
|
75
|
+
mean: 2.923076923076923
|
76
|
+
2 <= x <= 3:
|
77
|
+
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)]
|
78
|
+
mean: 4.333333333333333
|
79
|
+
```
|
80
|
+
|
33
81
|
```python
|
34
82
|
# デバッグ用
|
35
83
|
###################################################################
|
36
|
-
from matplotlib.patches import Rectangle
|
37
|
-
import matplotlib.pyplot as plt
|
38
84
|
fig, ax = plt.subplots(figsize=(6, 6))
|
39
85
|
|
40
86
|
# 各セルを描画する。
|
41
|
-
for rect, value in cells:
|
87
|
+
for id_, rect, value in cells:
|
42
88
|
ax.plot(rect[:, 0], rect[:, 1], c='gray', alpha=0.5) # セルの枠線
|
43
89
|
cx, cy = (rect[0] + rect[2]) / 2 # セルの中心
|
90
|
+
s = '{}:{}'.format(id_, value)
|
44
|
-
ax.text(cx, cy,
|
91
|
+
ax.text(cx, cy, s, ha='center', va='center', rotation=-angle) # 値
|
45
92
|
ax.autoscale(False)
|
46
|
-
|
47
|
-
# x 軸に垂直な直線を描画する。
|
48
|
-
# theta だけ回転させた場合、x 軸の傾きは tan(theta), y 軸の傾きは tan(theta + 90) となることに注意すると
|
49
|
-
for j in range(mat.shape[1]):
|
50
|
-
x = j - mat.shape[1] // 2 + 0.5
|
51
|
-
# (x', y') を通り、傾き m の直線 ===> (y - y') = m (x - x')
|
52
|
-
xs = np.linspace(*ax.get_xlim(), 100)
|
53
|
-
ys = (xs - x) * np.tan(np.radians(theta + 90))
|
54
|
-
ax.plot(xs, ys, c='b', lw=1)
|
55
|
-
|
56
|
-
#
|
93
|
+
# x 軸、y 軸を引く。
|
94
|
+
ax.axhline(), ax.axvline()
|
95
|
+
# 垂直線を引く
|
57
|
-
|
96
|
+
ax.vlines(edges, *ax.get_xlim(), alpha=0.5)
|
58
|
-
ys = xs * np.tan(np.radians(theta))
|
59
|
-
ax.plot(xs, ys, c='k', lw=3)
|
60
|
-
|
61
|
-
ys = xs * np.tan(np.radians(theta + 90))
|
62
|
-
ax.plot(xs, ys, c='k', lw=3)
|
63
97
|
```
|
64
98
|
|
65
|
-

|
66
|
-
|
67
|
-
青い直線が通るセルを調べてその値の平均をとる。
|
1
d
answer
CHANGED
@@ -16,18 +16,18 @@
|
|
16
16
|
[7, 2, 1, 6, 2, 8]], dtype=float)
|
17
17
|
assert mat.shape[0] % 2 == 0 and mat.shape[1] % 2 == 0
|
18
18
|
|
19
|
-
theta =
|
19
|
+
theta = 10
|
20
20
|
```
|
21
21
|
|
22
22
|
```
|
23
23
|
cells = []
|
24
|
-
for (i, j),
|
24
|
+
for (i, j), value in np.ndenumerate(mat):
|
25
|
-
# 行列の (i, j) 成分を行列の中心を原点とする標準座標系の点 (x, y) に変換する式
|
25
|
+
# 行列の (i, j) 成分を行列の中心を原点とする標準座標系の点 (x, y) に変換する式
|
26
26
|
# (x, y) = j - rows // 2, i - cols // 2
|
27
27
|
x, y = j - mat.shape[1] // 2, i - mat.shape[0] // 2
|
28
28
|
# セルを構成する点
|
29
|
-
|
29
|
+
rect = np.array([[x, y], [x + 1, y], [x + 1, y + 1], [x, y + 1], [x, y]])
|
30
|
-
cells.append([
|
30
|
+
cells.append([rect, value])
|
31
31
|
```
|
32
32
|
|
33
33
|
```python
|
@@ -38,17 +38,17 @@
|
|
38
38
|
fig, ax = plt.subplots(figsize=(6, 6))
|
39
39
|
|
40
40
|
# 各セルを描画する。
|
41
|
-
for
|
41
|
+
for rect, value in cells:
|
42
|
-
ax.plot(
|
42
|
+
ax.plot(rect[:, 0], rect[:, 1], c='gray', alpha=0.5) # セルの枠線
|
43
|
-
cx, cy = (
|
43
|
+
cx, cy = (rect[0] + rect[2]) / 2 # セルの中心
|
44
|
-
ax.text(cx, cy,
|
44
|
+
ax.text(cx, cy, value, ha='center', va='center') # 値
|
45
45
|
ax.autoscale(False)
|
46
46
|
|
47
47
|
# x 軸に垂直な直線を描画する。
|
48
48
|
# theta だけ回転させた場合、x 軸の傾きは tan(theta), y 軸の傾きは tan(theta + 90) となることに注意すると
|
49
|
-
for j in range(mat.shape[1]
|
49
|
+
for j in range(mat.shape[1]):
|
50
|
+
x = j - mat.shape[1] // 2 + 0.5
|
50
51
|
# (x', y') を通り、傾き m の直線 ===> (y - y') = m (x - x')
|
51
|
-
x = j - mat.shape[1] // 2
|
52
52
|
xs = np.linspace(*ax.get_xlim(), 100)
|
53
53
|
ys = (xs - x) * np.tan(np.radians(theta + 90))
|
54
54
|
ax.plot(xs, ys, c='b', lw=1)
|
@@ -62,6 +62,6 @@
|
|
62
62
|
ax.plot(xs, ys, c='k', lw=3)
|
63
63
|
```
|
64
64
|
|
65
|
-

|
66
66
|
|
67
67
|
青い直線が通るセルを調べてその値の平均をとる。
|