質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

1回答

3250閲覧

Pythonで点と線の距離を計算したい

okmokm

総合スコア10

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2018/10/29 01:24

編集2018/10/29 02:10

Pythonを使用して点と線の距離を計算したいのですが、方法がわかりません。

こちらのサイトを拝見し、距離を計算するための公式を知ることはできました。

私は現在、地図上に目標とする座標を打ち、その点々でできた線を実際に歩いてみてGPSの座標を取得しています。
ですので、目標とする座標でできた線と、実際に歩いてできた座標のデータがあります。

上でリンクを貼ったサイトの図を流用して説明すると、点aと点bが目標とする座標で、それらの間に実際の座標の点cがたくさんあるような感じです。

また、目標の線も実際の座標も一方向だけに向かって進んでいるのではなく、途中で折り返す部分があったりして、どうやって処理すればいいか思い浮かびません。

今のところ、目標地点の座標が入っているリストをforループで回して、その中でさらに実際の座標が入っているリストをforループで回してます。二つ目のforループの中で、リンク先の公式を使い距離を求めています。
ですが、思っているような動きになりませんでした。

Python3

1 2import numpy as np 3 4target_list = [(,), ..., (,)] # 座標のタプルのリストになっている 5actual_list = [(,),....,(,)] # 座標のタプルのリストになっている 6block = 0 7length = 0 8 9for a in range(len(target_list) - 1): 10 for point in actual_list:     11 u = np.array([target_list[block+1][0] - target_list[block][0], target_list[block+1][1] - target_list[block][1]]) 12 v = np.array([point[0] - target_list[block][0], point[1] - target_list[block][1]]) 13 14 distance = abs(np.cross(u, v) / np.linalg.norm(u)) 15 if length < distance: 16 length = distance 17 # if文で条件分岐してblockをインクリメントする?

以上のような流れになるように思ったのですが、blockを進めていくためのインクリメントの方法もよくわかりません。
ループの回し方がおかしいのだと思うのですが、どのように考えればいいのでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2018/10/29 01:39

思っていたような動きにならないとはどうなるんでしょうか。ソースコードもなし、その結果も省略されてるでは回答しようがありませんが。
okmokm

2018/10/29 01:46 編集

目標の線は点からできているので、二つの点(a,b)で線分をとり、その線分の範囲の中にある実際の点との距離を計算していき、実際の点が線分の範囲を超えたら次の線分に移って同様に計算していく、というような動きを考えていました。ですが、結果としては、実際の点の一点目だけで処理が回っていき、終わっているような状態です。
tiitoi

2018/10/29 04:34

ある点からある直線への距離というならわかりますが、複数の線分がある場合、ある点から線分の距離といった場合、どのように定義するのでしょうか?質問の目的が2つの軌道がどれくらいかけ離れているかを示す指標を計算したいという動機であれば、他の方法もあるかと思います。
okmokm

2018/10/29 04:51

計算の目的は仰っているように、二つの軌道がどれくらい離れているかを計算したいということです。しかし、これ以外に方法が思いつきませんでした。ほかにどのような方法が考えられるのでしょうか?
tiitoi

2018/10/31 02:18 編集

2つの軌道の差を計算するというのは SLAM という分野で出てくる話なので「Trajectory similarity」等で検索すると、計測方法について記載がある論文が出てきます。「点と線分の距離の差の合計」という計測方法ではどの線分との距離を計算するのかなど問題があり、軌道の誤差を計算するあまりいい指標にはならない気がします。
okmokm

2018/10/31 06:39

SLAMという分野があるんですね、ありがとうございます。Trajectory Simiralityも調べたいと思います。「点と線分の距離の差の合計」というよりも、それぞれの実際の点と線分の距離を求め、それらの中で最も大きい値を最大の誤差とするような処理を考えていました。どちらにしても点と線分の距離を求めるのは難しいということですね。
tiitoi

2018/10/31 07:10

点と線分の距離自体を求めるのは難しくないです。https://teratail.com/questions/155180 の回答にやり方を書いてあります。 ただ、そのやり方で目的である軌道のずれの計算につかえるかはわからないので、軌道の類似性を計測する他の手段も探してみてはという意味で書きました。
okmokm

2018/10/31 07:55 編集

もちろんtiitoiさんのコメントのご主旨は理解しています。言葉足らずですみませんでした。「軌道の類似性を計測する」という考え方が今まで思い浮かびませんでした。単純な計算ではできなさそうな感じですね…。ありがとうございます。
guest

回答1

0

端的に云えば

if length < distance:

が、やりたいこととは逆の判定になっていると思われます。またblock変数については特にいじる必要はありません。
できるだけ提示されたコードを維持しつつ変数名の修正、コメント追加したコード例を示します。

Python

1import numpy as np 2import sys 3 4target_list = [(0,0),(1,1),(2,4)] # 歩いた点群 5actual_list = [(0.1,0.2),(1.1,1.2),(2.1,4,1)] # 目標座標を結ぶ各線分を構成する点群 6min_lens = sys.float_info.max # 最近線分から最も近い歩いた点の距離。最大値をセット 7max_lens =-sys.float_info.max # 〃 遠い〃 距離。最小値をセット 8for actual_pt in actual_list: # 各歩いた点について 9 10 print('歩いた座標:{:.2f},{:.2f}'.format(actual_pt[0],actual_pt[1])) 11 12 # まず、最も距離の近い線分を特定する 13 min_len = sys.float_info.max # 距離。最大値をセット 14 15 for cur_idx in range(len(target_list) - 1): # 各線分について 16 u = np.array([target_list[cur_idx+1][0] - target_list[cur_idx][0], target_list[cur_idx+1][1] - target_list[cur_idx][1]]) 17 v = np.array([actual_pt[0] - target_list[cur_idx][0], actual_pt[1] - target_list[cur_idx][1]]) 18 cur_len = abs(np.cross(u, v) / np.linalg.norm(u)) 19 20 # 現在の距離の方が小さい→最小値を更新 21 if cur_len <= min_len: 22 min_len = cur_len 23 24 # 最近線分からの最も近い点、遠い点の距離を記憶する 25 print('最近線分までの距離:{:.2f}'.format(min_len)) 26 if min_len <= min_lens: 27 min_lens = min_len 28 elif min_len >= max_lens: 29 max_lens = min_len 30 31print('最近線分からの最近距離:{:.2f}, 最遠距離:{:.2f}'.format(min_lens,max_lens))

投稿2018/10/29 05:21

編集2018/10/29 06:42
can110

総合スコア38352

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

okmokm

2018/10/29 06:20

詳細な例までお示しいただきありがとうございます。 こちらのコードは折り返し地点でも関係なく計算可能なのでしょうか? また、最も離れている座標、つまりどの実際の点が最も誤差があったのかを取得したい場合は、min_lenをどのように変更するのでしょうか?
can110

2018/10/29 06:44

まずは最も近い線分を求めるので ・折り返し地点でも問題ありません。 > また、最も離れている座標、つまりどの実際の点が最も誤差があったのか 最近と最遠の点の距離を最後に出力するように回答修正しました。
okmokm

2018/10/29 06:52

sys.float_info.maxで最も近い線分を求めることができている、ということでしょうか?なぜこれだけのコードで最も近い線分を求めることができるのか、まだ理解できていないので、可能でしたらご説明いただきたいです。 また、このコードをリストの中身が千個以上あるようなデータで実行してみたところ、2分ほど時間がかかるのですが、どのようにすれば処理の時間を短くすることができるのでしょうか?
can110

2018/10/29 08:35

最近(小)値を求めるための初期値として、とても大きな数値を初期値としてセットしています。 この初期値をセットすることによって、必ず走査先頭のデータで最小値がセットされることが保証されます。 なお、根本的な考えは、コードコメントおよび簡単なデータ例値で動作を確認しつつ理解してみてください。 さらに処理時間を短くするにはforループではなくNumPyだけで行列演算すると可能ですが、まずは現在のコードの動きを理解をするのが先決かと思います。
okmokm

2018/10/30 00:05

二つ目のforでの処理が、実際の点と最も近い線分を求める処理ということになると理解しています。 また、何度も恐縮なんですが、まれに明らかに最も誤差が大きい点を取れない場合があるのですが、どのような原因が考えられますか?
can110

2018/10/30 08:20

その誤差とはGPSの計測誤差ではありませんか? であれば処理側では異常値を弾く必要があります。
okmokm

2018/10/31 00:34

言葉が不足していてすみません。誤差とは実際の点と目標の軌道とが最も離れているときの実際の点のことです。 データ自体に異常値がある可能性があるということですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問