ポイントと2つの緯度/経度の仮想線の間の距離の計算


14

例と対応する画像を参照してください。

私は次のことを達成したいと思います:2つの場所(lat / lng)を提供します。これらは以下にAおよびBとして示されています。これから、仮想線が描画され、この線とCの間の距離が計算されます(任意の測定で)。

お絵かき

現在、Google Maps API v3でこれを達成していますが、選択した言語で舞台裏でこれを実行できるようにしたいと考えています。どんなヒント/アイデアも大歓迎です!



@カーク、いいえ、ABは単なる直線です
囚人

@Michael、それは興味深い点です。私はそれを見なければなりません!
囚人

@Prisoner @Kirk文字通り、「真っ直ぐな線」が地表の下を通ります。一般に、表面への放射状の投影は、実際には大円のセグメントになります(球体地球モデルを使用)。
whuber

1
@Prisonerそれは非常に有用な追加情報です!はい。それで合っています。(lat、lon)を使用すると、南北と比較して東西距離が差動的に歪むという事実を補正する必要があります。@Joseがアドバイスするように、座標を投影します。これは、経度に平均緯度のコサインをあらかじめ掛けてから、ユークリッド平面にいるふりをするのと同じくらい簡単です。
whuber

回答:


6
def get_perp( X1, Y1, X2, Y2, X3, Y3):
    """************************************************************************************************ 
    Purpose - X1,Y1,X2,Y2 = Two points representing the ends of the line segment
              X3,Y3 = The offset point 
    'Returns - X4,Y4 = Returns the Point on the line perpendicular to the offset or None if no such
                        point exists
    '************************************************************************************************ """
    XX = X2 - X1 
    YY = Y2 - Y1 
    ShortestLength = ((XX * (X3 - X1)) + (YY * (Y3 - Y1))) / ((XX * XX) + (YY * YY)) 
    X4 = X1 + XX * ShortestLength 
    Y4 = Y1 + YY * ShortestLength
    if X4 < X2 and X4 > X1 and Y4 < Y2 and Y4 > Y1:
        return X4,Y4
    return None

最短の長さは、私が間違えない限り、必要な距離ですか?


はい、Cから線分までの最短距離を探しています。これはこの数学が計算するものですか?
囚人

1
本当にうまくいきました。次の3つのポイント(A、B、C)に合格しました。i.imgur.com / bK9oB.jpgとXの緯度/ 経度で戻ってきました。すばらしい仕事です!
囚人

1
@Hairy、最後に、これを変更して、ラインだけでなく最も近いポイントに移動するにはどうすればよいですか?それで、ラインをジョインするポイントを過ぎて配置した場合、どのようにそれを取得して距離を確認できますか?ポイント?
囚人

1
@Hairy良いスタートですがNone、合法的なソリューションが存在する場合にこのコードが返されることが多すぎるようです。問題は、最後の条件がX1 <X2およびY1 <Y2を想定していることであり、常に保証できるとは限りません。中間性のより良いテストが必要です。
whuber

1
@Hairyあなたと@prisonerとのこのやり取りは生産的だったようです。投票やポイントの変化とは何の関係もありません(または、制御することさえできません)。私のコメントは、返信を改善することのみを目的としています。
whuber

11

たぶん私はそれをあまりにも複雑にしていますが、あなたが望むのはポイントからラインまでの距離です。これは、ABとCをABに直交する線で結ぶABに沿った点からの距離です。ABに垂直なこのベクトルは、

v=[x2-x1, -(y2-y1)] # Point A is [x1,y1] Point B is [x2,y2]

(角括弧を使用して、ベクトルまたは2要素配列を定義しました)。C [xp、yp]とポイントAの間の距離は

u=[x1-xp, y1-xp]

線とCの間の距離は、vに対するuの投影です。mod(v)= 1(それを正規化するだけ)と仮定すると、

distance = u*v = abs( (x2-x1)*(y1-yp) - (x1-xp)*(y2-y1) )

唯一の問題は、座標がWGS84の緯度/ログのペアではなく、投影されていることを確認したい(または測地座標を使用したい)ことです。これにはOGRまたはProj4を使用できます。


3
ちなみに、三角関数を使用しないための数百万の疑似ポイント。あまりにも多くの人が、ArcTanを参照する必要があるときにこれを引き出します:en.wikipedia.org/wiki/Dot_product
ハーブ

@Jose、返信ありがとう!GoogleマップAPIのlat / longを使用しています。数学の部分は私にとって非常に新しいので、試してみて、何が思いつくか見てみましょう。数学のヒントはありますか?例えば、[x2-x1、-(y2-y1)]、それは何に変換されますか?
囚人

このために短い編集を追加しました。基本的には、配列表記ですが、座標を変数x1、x2、y1、y2およびxp、ypに格納する場合、最後に提供した式の右辺のみを記述する必要があります。これはかなり有効なC、Java、JS、Pythonなどのコードです:)
ホセ

1
@Jose Cからライン AB までの距離を計算しています。この図に基づいて、OPはCから線分 AB までの距離を望んでいると思います。これには、線ABへのCの射影がAとBの間にあるかどうかを確認するための追加の作業が必要です。後者の場合、2つの長さCAとCBのうち短い方を使用します。
whuber

1
@Prisoner主な違いは、線が永遠に延びることです(方向ベクトルと点、または2点でのみ定義されます)が、AとBの間のセグメントはAとBの間を結ぶ無限線のビットですB(有限の長さ)
ホセ

4

この数学のすべてにも少し嫌悪感を抱いているので、私は別の角度からそれを考えます。仮想回線ではなく「実際の」回線にしてから、既存のツールを使用します。

AとBが属性を共有している場合、線を引くことでそれらを接続できます(Kosmo GISには、ポイントから線を作成するツールがあり、このためのQGISプラグインもあると思います)。線を作成したら、「C」ポイントレイヤーの「ニア」機能を使用して、線までの距離を確認できます。ソフトウェアに数学を処理させてください!


コメントありがとうございますが、ヘアリーはこれについて切り札を見つけました!
囚人

1
(+1)あなたは素晴らしい点を挙げています。計算幾何学アルゴリズムは、実際に完全に正しく動作することで有名です(これまでに提供されたすべてのコードからわかるように、これは有用かつ例示的ですが、まだ完全には機能しません)。高レベルのGIS手順を使用することは、多くの場合、期待する答えが得られ、正しいことを保証するための良い方法です(GISを信頼している場合は;-)。
whuber

1

AndroidでJavaを使用していた場合、ライブラリ関数を含む1行のみ

import static com.google.maps.android.PolyUtil.distanceToLine;

distanceToLine:

public static double distanceToLine(LatLng p, LatLng start,LatLng end)

ポイントpとラインセグメントの開始から終了までの球体上の距離を計算します。

パラメータ:p-測定するポイント

start-線分の始まり

end-線分の終わり

戻り値:メートル単位の距離(球体を想定)

ライブラリを追加するだけです

dependencies {
    compile 'com.google.maps.android:android-maps-utils:0.5+'
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.