teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

3

GitHubリンク追記

2018/09/30 21:45

投稿

opyon
opyon

スコア1009

answer CHANGED
@@ -7,6 +7,7 @@
7
7
  @tiitoiさんの回答にある論文はさっぱり分かりませんが、引用したコードの条件式を手探りで発見し要件を満たす結果が得られたことはとても満足しています。
8
8
  @tiitoiさんの描画部分のコードのおかげで試行錯誤とテストが捗りとても感謝しています。
9
9
 
10
+
10
11
  変更した判定条件式
11
12
  ```
12
13
  chk = a * p.x + b * p.y + c
@@ -121,4 +122,5 @@
121
122
  ax.add_line(Line2D([s.x, e.x], [s.y, e.y], color='g'))
122
123
  show_image(ax, img)
123
124
  # plt.savefig('test.png')
124
- ```
125
+ ```
126
+ [GitHub](https://github.com/opyon/public/blob/master/Python3/qa149396.ipynb)

2

条件式改修+描画部分引用

2018/09/30 21:45

投稿

opyon
opyon

スコア1009

answer CHANGED
@@ -1,30 +1,43 @@
1
1
  [線分の上に点が載っているか判定する](https://www.pandanoir.info/entry/2016/11/08/130504)
2
2
 
3
- ~~検証していませんが、上記サンプルコードに線分と判定する座標を与えれば判定出来そうですね。~~
4
- ~~実装頑張ってみてください。~~
5
-
6
- 判定部分のみ実装てみました。
3
+ 判定部分は上記から引用改修しました。
4
+ 描画部分は@tiitoiさんコードから引用し改修しました。
7
5
  上記参考コードをそのまま移植するだけでは判定出来ませんでした。
8
- 試行錯誤したところ、判定条件式 `a * p.x + b * p.y + c == 0` 変更することで欲しい結果が得られました。
6
+ 試行錯誤したところ、判定条件式 `a * p.x + b * p.y + c == 0` から下記のように変更することで欲しい結果が得られました。
7
+ @tiitoiさんの回答にある論文はさっぱり分かりませんが、引用したコードの条件式を手探りで発見し要件を満たす結果が得られたことはとても満足しています。
8
+ @tiitoiさんの描画部分のコードのおかげで試行錯誤とテストが捗りとても感謝しています。
9
9
 
10
10
  変更した判定条件式
11
11
  ```
12
- chk = a * p.x + b * p.y + c
12
+ chk = a * p.x + b * p.y + c
13
+
14
+ len_x = e.x - s.x
15
+ len_y = e.y - s.y
16
+ if len_x == len_y:
17
+ v = 0
18
+ else:
19
+ v = len_x // 2 + len_y // 2
20
+
13
- if chk >= -2 and chk <= 2:
21
+ if chk >= v * -1 and chk <= v:
22
+ return True
23
+ else:
24
+ return False
14
25
  ```
26
+ ![イメージ説明](756cd83de567cf71865d4fcdbab735a3.png)
15
27
 
16
- 但し計算根拠に基づいた式を作ったわけではなく手探りで見つけただけなので正しいアルゴリズムかどうかは分かりません。
17
- 検証範囲も始点固定(0,0)で、終点(1,3)終点(2,3)終点(3,3)だけです。
28
+ ```Python3
29
+ import sys
18
- この範囲なら要件通りの判定出来ています。
30
+ import numpy as np
31
+ print(sys.version)
19
32
 
20
- ```Python3
21
33
  class Point_():
22
34
 
23
35
  def __init__(self, x_init, y_init):
24
36
  self.x = x_init
25
37
  self.y = y_init
26
38
 
39
+
27
- def chk(s,e,p):
40
+ def chk(s, e, p):
28
41
  if s.x <= p.x and p.x <= e.x:
29
42
  if s.y <= e.y \
30
43
  and (s.y <= p.y and p.y <= e.y) \
@@ -36,43 +49,76 @@
36
49
  b = s.x - e.x
37
50
  c = s.x * (s.y - e.y) - s.y * (s.x - e.x)
38
51
 
52
+ #以下判定条件式を追加改修
39
53
  chk = a * p.x + b * p.y + c
54
+
55
+ len_x = e.x - s.x
56
+ len_y = e.y - s.y
57
+ if len_x == len_y:
58
+ v = 0
59
+ else:
60
+ v = len_x // 2 + len_y // 2
61
+
40
- if chk >= -2 and chk <= 2:
62
+ if chk >= v * -1 and chk <= v:
41
63
  return True
42
64
  else:
43
- pass
44
65
  return False
66
+ #追加改修以上
45
67
 
46
- s_x = 0
68
+ # 描画部分は@tiitoiさんコードから引用しコードに合わせて改修
47
- s_y = 0
69
+ import matplotlib.pyplot as plt
48
- e_x = 2
70
+ from matplotlib.lines import Line2D
49
- e_y = 3
50
71
 
51
- s = Point_(s_x, s_y)
72
+ def show_image(ax, img):
73
+ ax.imshow(img, interpolation='none')
74
+ ax.grid(which='minor', color='b', linestyle='-', linewidth=1)
75
+ # Major ticks
76
+ ax.set_xticks(np.arange(0, 10, 1))
77
+ ax.set_yticks(np.arange(0, 10, 1))
52
- e = Point_(e_x, e_y)
78
+ # Labels for major ticks
79
+ ax.set_xticklabels(np.arange(10))
80
+ ax.set_yticklabels(np.arange(10))
81
+ # Minor ticks
82
+ ax.set_xticks(np.arange(-.5, 10, 1), minor=True)
83
+ ax.set_yticks(np.arange(-.5, 10, 1), minor=True)
53
84
 
85
+ def draw_line(img, p1, p2, color=[255, 0, 0]):
86
+ x1, y1 = p1
87
+ x2, y2 = p2
88
+
89
+ slope = (y2 - y1) / (x2 - x1)
90
+
91
+ xs = np.arange(x1, x2 + 1, 0.01)
92
+ ys = y1 + slope * (xs - x1)
93
+ pts = np.vstack([xs, ys]).T
94
+ print(pts.shape)
95
+
96
+ pts = np.ceil(pts).astype(int) # 離散化する。
97
+ pts = np.unique(pts, axis=0) # 重複する点を削除
98
+
99
+ # 座標入力
100
+ s = Point_(1, 2)
101
+ e = Point_(8, 7)
102
+
54
- print(f'直線({s_x},{s_y})-({e_x},{e_y})')
103
+ print(f'直線({s.x},{s.y})-({e.x},{e.y})')
104
+ points = []
55
- for p_x in range(e_x+1):
105
+ for p_x in range(s.x,e.x+1,1):
56
- for p_y in range(e_y+1):
106
+ for p_y in range(s.y,e.y+1,1):
57
107
  p = Point_(p_x, p_y)
108
+ ret = chk(s,e,p)
109
+ if ret:
58
- print(f'点({p_x},{p_y}) {chk(s,e,p)} ')
110
+ points.append([p_x,p_y])
59
111
 
60
- ```
112
+ points = np.array(points)
61
113
 
62
- 出力例
114
+ # 白紙の画像を作成する。
115
+ img = np.full((10, 10, 3), 255, dtype=np.uint8)
116
+
63
- ```
117
+ for x, y in points:
118
+ img[y, x] = [255, 0, 0] # 赤
119
+
120
+ fig, ax = plt.subplots(figsize=(8, 8), facecolor='w')
64
- 3.7.0 (default, Jun 28 2018, 08:04:48) [MSC v.1912 64 bit (AMD64)]
121
+ ax.add_line(Line2D([s.x, e.x], [s.y, e.y], color='g'))
65
- 直線(0,0)-(2,3)
122
+ show_image(ax, img)
66
- 点(0,0) True
67
- 点(0,1) True
68
- (0,2) False
123
+ # plt.savefig('test.png')
69
- 点(0,3) False
70
- 点(1,0) False
71
- 点(1,1) True
72
- 点(1,2) True
73
- 点(1,3) False
74
- 点(2,0) False
75
- 点(2,1) False
76
- 点(2,2) True
77
- 点(2,3) True
78
124
  ```

1

実装してみた

2018/09/30 21:33

投稿

opyon
opyon

スコア1009

answer CHANGED
@@ -1,4 +1,78 @@
1
1
  [線分の上に点が載っているか判定する](https://www.pandanoir.info/entry/2016/11/08/130504)
2
2
 
3
- 検証していませんが、上記サンプルコードに線分と判定する座標を与えれば判定出来そうですね。
3
+ ~~検証していませんが、上記サンプルコードに線分と判定する座標を与えれば判定出来そうですね。~~
4
- 実装頑張ってみてください。
4
+ ~~実装頑張ってみてください。~~
5
+
6
+ 判定部分のみ実装してみました。
7
+ 上記参考コードをそのまま移植するだけでは判定出来ませんでした。
8
+ 試行錯誤したところ、判定条件式 `a * p.x + b * p.y + c == 0` を変更することで欲しい結果が得られました。
9
+
10
+ 変更した判定条件式
11
+ ```
12
+ chk = a * p.x + b * p.y + c
13
+ if chk >= -2 and chk <= 2:
14
+ ```
15
+
16
+ 但し計算根拠に基づいた式を作ったわけではなく手探りで見つけただけなので正しいアルゴリズムかどうかは分かりません。
17
+ 検証範囲も始点固定(0,0)で、終点(1,3)終点(2,3)終点(3,3)だけです。
18
+ この範囲なら要件通りの判定出来ています。
19
+
20
+ ```Python3
21
+ class Point_():
22
+
23
+ def __init__(self, x_init, y_init):
24
+ self.x = x_init
25
+ self.y = y_init
26
+
27
+ def chk(s,e,p):
28
+ if s.x <= p.x and p.x <= e.x:
29
+ if s.y <= e.y \
30
+ and (s.y <= p.y and p.y <= e.y) \
31
+ or s.y >= e.y \
32
+ and (s.y >= p.y \
33
+ and p.y >= e.y) \
34
+ :
35
+ a = e.y - s.y
36
+ b = s.x - e.x
37
+ c = s.x * (s.y - e.y) - s.y * (s.x - e.x)
38
+
39
+ chk = a * p.x + b * p.y + c
40
+ if chk >= -2 and chk <= 2:
41
+ return True
42
+ else:
43
+ pass
44
+ return False
45
+
46
+ s_x = 0
47
+ s_y = 0
48
+ e_x = 2
49
+ e_y = 3
50
+
51
+ s = Point_(s_x, s_y)
52
+ e = Point_(e_x, e_y)
53
+
54
+ print(f'直線({s_x},{s_y})-({e_x},{e_y})')
55
+ for p_x in range(e_x+1):
56
+ for p_y in range(e_y+1):
57
+ p = Point_(p_x, p_y)
58
+ print(f'点({p_x},{p_y}) {chk(s,e,p)} ')
59
+
60
+ ```
61
+
62
+ 出力例
63
+ ```
64
+ 3.7.0 (default, Jun 28 2018, 08:04:48) [MSC v.1912 64 bit (AMD64)]
65
+ 直線(0,0)-(2,3)
66
+ 点(0,0) True
67
+ 点(0,1) True
68
+ 点(0,2) False
69
+ 点(0,3) False
70
+ 点(1,0) False
71
+ 点(1,1) True
72
+ 点(1,2) True
73
+ 点(1,3) False
74
+ 点(2,0) False
75
+ 点(2,1) False
76
+ 点(2,2) True
77
+ 点(2,3) True
78
+ ```