質問
標準のNMEA形式で緯度または経度の読み取り値がある場合、その読み取り値をメートルに変換する簡単な方法/数式はありますか?それをJava(J9)で実装できますか?
編集: 私がやりたいことは簡単にできませんが、本当にやりたいことは
緯度と経度の中間地点があり、緯度と経度のユーザーがそれらを比較して、ユーザーに合理的に近い範囲内にいることを伝えるタイミングを決定する簡単な方法があるとしましょうウェイポイントの距離?私は合理的であることが主題であると理解していますが、これは簡単に実行できるのですか、それともまだ過度に数学ですか?
解決
これはjavascript関数です:
function measure(lat1, lon1, lat2, lon2){ // generally used geo measurement function
var R = 6378.137; // Radius of earth in KM
var dLat = lat2 * Math.PI / 180 - lat1 * Math.PI / 180;
var dLon = lon2 * Math.PI / 180 - lon1 * Math.PI / 180;
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
Math.sin(dLon/2) * Math.sin(dLon/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
return d * 1000; // meters
}
説明: https://en.wikipedia.org/wiki/Haversine_formula
haversineの式は、経度と緯度を指定して、球上の2点間の大圏距離を決定します。
他のヒント
単純な式を探しているのであれば、これはおそらく地球が周囲40075 kmの球体であると仮定した場合の最も簡単な方法です。
緯度1°のメートル単位の長さ=常に111.32 km
経度1°のメートル単位の長さ= 40075 km * cos(緯度)/ 360
2つの座標間の短い距離を近似するために、次の式を使用しました http://en.wikipedia.org/wiki/Lat-lon :
m_per_deg_lat = 111132.954 - 559.822 * cos( 2 * latMid ) + 1.175 * cos( 4 * latMid);
m_per_deg_lon = 111132.954 * cos ( latMid );
。
以下のコードでは、ウィキペディアの式との関係を示すために生の数値を残しています。
double latMid, m_per_deg_lat, m_per_deg_lon, deltaLat, deltaLon,dist_m;
latMid = (Lat1+Lat2 )/2.0; // or just use Lat1 for slightly less accurate estimate
m_per_deg_lat = 111132.954 - 559.822 * cos( 2.0 * latMid ) + 1.175 * cos( 4.0 * latMid);
m_per_deg_lon = (3.14159265359/180 ) * 6367449 * cos ( latMid );
deltaLat = fabs(Lat1 - Lat2);
deltaLon = fabs(Lon1 - Lon2);
dist_m = sqrt ( pow( deltaLat * m_per_deg_lat,2) + pow( deltaLon * m_per_deg_lon , 2) );
ウィキペディアのエントリには、距離計算が縦方向に100kmで0.6m以内、縦方向に100kmで1cm以内であると記載されていますが、その精度は私の使用には問題ないことを確認していません。
緯度と経度は距離ではなくポイントを指定するため、質問は無意味です。 2つの(lat、lon)ポイント間の最短距離については、このウィキペディアの記事大圏距離。
これを簡単にするツールはたくさんあります。内容の詳細については、 monjardinの回答をご覧ください。
ただし、これを行うことは必ずしも難しくありません。 Javaを使用しているようですので、 GDAL のようなものを調べることをお勧めします。ルーチンのJavaラッパーを提供し、Lat / Lon(地理座標)からUTM(投影座標系)またはその他の妥当な地図投影に変換するために必要なすべてのツールを備えています。
UTMは、メーターであるため、操作が簡単なので便利です。ただし、適切に機能するには、適切な UTMゾーンを取得する必要があります。緯度/経度のペアに適したゾーンを見つけるために、グーグル経由で利用できるいくつかの簡単なコードがあります。
念のため、 b-h-の関数のRバージョンを以下に示します。
measure <- function(lon1,lat1,lon2,lat2) {
R <- 6378.137 # radius of earth in Km
dLat <- (lat2-lat1)*pi/180
dLon <- (lon2-lon1)*pi/180
a <- sin((dLat/2))^2 + cos(lat1*pi/180)*cos(lat2*pi/180)*(sin(dLon/2))^2
c <- 2 * atan2(sqrt(a), sqrt(1-a))
d <- R * c
return (d * 1000) # distance in meters
}
これを計算する方法はかなりあります。いずれも半径が地球のものである球面三角法の近似を使用します。
http://www.movable-type.co.uk/を試すscripts / latlong.html を使用して、さまざまな言語のメソッドとコードを少し。
地球の退行の平均距離に基づいています。
1&#176; = 111km;
これをラジアンに変換し、メートルに分割するには、RADのマジックナンバー(メートル単位)を使用します:0.000008998719243599958;
then:
const RAD = 0.000008998719243599958;
Math.sqrt(Math.pow(lat1 - lat2, 2) + Math.pow(long1 - long2, 2)) / RAD;
'below is from
'http://www.zipcodeworld.com/samples/distance.vbnet.html
Public Function distance(ByVal lat1 As Double, ByVal lon1 As Double, _
ByVal lat2 As Double, ByVal lon2 As Double, _
Optional ByVal unit As Char = "M"c) As Double
Dim theta As Double = lon1 - lon2
Dim dist As Double = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) + _
Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * _
Math.Cos(deg2rad(theta))
dist = Math.Acos(dist)
dist = rad2deg(dist)
dist = dist * 60 * 1.1515
If unit = "K" Then
dist = dist * 1.609344
ElseIf unit = "N" Then
dist = dist * 0.8684
End If
Return dist
End Function
Public Function Haversine(ByVal lat1 As Double, ByVal lon1 As Double, _
ByVal lat2 As Double, ByVal lon2 As Double, _
Optional ByVal unit As Char = "M"c) As Double
Dim R As Double = 6371 'earth radius in km
Dim dLat As Double
Dim dLon As Double
Dim a As Double
Dim c As Double
Dim d As Double
dLat = deg2rad(lat2 - lat1)
dLon = deg2rad((lon2 - lon1))
a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Cos(deg2rad(lat1)) * _
Math.Cos(deg2rad(lat2)) * Math.Sin(dLon / 2) * Math.Sin(dLon / 2)
c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a))
d = R * c
Select Case unit.ToString.ToUpper
Case "M"c
d = d * 0.62137119
Case "N"c
d = d * 0.5399568
End Select
Return d
End Function
Private Function deg2rad(ByVal deg As Double) As Double
Return (deg * Math.PI / 180.0)
End Function
Private Function rad2deg(ByVal rad As Double) As Double
Return rad / Math.PI * 180.0
End Function
緯度と経度をxおよびy表現に変換するには、使用するマップ投影のタイプを決定する必要があります。私にとっては、楕円形メルカトル図法は非常によく見えます。 こちら(Javaでも)実装を見つけることができます。
十分に近い場合、それらを平面上の座標として扱うことで逃げることができます。これは、完全な精度が要求されず、任意の制限と比較するために必要な距離の大まかな推測だけである場合、たとえば通りや都市レベルで機能します。
簡単な解決策が必要な場合は、他のコメントで概説されているように、 Haversine式を使用します。精度に敏感なアプリケーションを使用している場合、Haversineの式は、地球が円であると仮定しているため、0.5%を超える精度を保証しません。 Earthが偏球体であることを考慮するには、 Vincentyの式の使用を検討してください。 さらに、Haversineの式で使用する半径がわかりません:{赤道:6,378.137 km、極:6,356.752 km、体積:6,371.0088 km}。
球面ジオメトリを作成するには、座標をラジアンに変換する必要があります。変換したら、2点間の距離を計算できます。その後、距離を任意のメジャーに変換できます。