標準のNMEA形式で緯度または経度の読み取り値がある場合、その読み取り値をメートルに変換する簡単な方法/数式はありますか。それをJava(J9)で実装できますか?
編集:Okは私がやりたいことは不可能だと思われる簡単に、しかし私が本当にやりたいことは:
緯度と経度の中間地点があり、緯度と経度のユーザーがあるとすると、それらを比較して、ユーザーに彼らが合理的に近い距離にいることを伝えるタイミングを決定する簡単な方法があるとしましょうウェイポイント?私は合理的であることが主題であると理解していますが、これは簡単にできるのですか、それとも過度に数学的ですか?
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)ポイント間の最短距離については、大圏距離に関する このWikipediaの記事 を参照してください。
これを容易にする多くのツールがあります。関係するものの詳細については、 monjardin's answer を参照してください。
ただし、これを行うことは必ずしも難しくありません。 Javaを使用しているようですが、 GDAL のようなものを調べることをお勧めします。ルーチンにJavaラッパーを提供し、Lat/Lon(地理座標)からUTM(投影座標系)またはその他の妥当な地図投影に変換するために必要なすべてのツールを備えています。
UTMは、メーターであるため操作が簡単なので、素晴らしいです。ただし、適切な処理を行うには、適切な TMゾーン を取得する必要があります。緯度/経度のペアに適切なゾーンを見つけるために、グーグル経由で利用できるいくつかの簡単なコードがあります。
念のため、Rバージョンの b-h-の関数 を示します。
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
}
地球の退行の平均距離に基づいています。
1°= 111km;
これをラジアンに変換し、メートルに分割すると、RADのマジックナンバーがメートルで表示されます。0.000008998719243599958;
その後:
const RAD = 0.000008998719243599958;
Math.sqrt(Math.pow(lat1 - lat2, 2) + Math.pow(long1 - long2, 2)) / RAD;
これを計算する方法はかなりあります。それらのすべては、半径が地球のものである球面三角法の近似を使用します。
http://www.movable-type.co.uk/scripts/latlong.html を試して、さまざまな言語のメソッドとコードを少し見つけてください。
1海里(1852メートル)は、赤道で1 arcminute 経度として定義されます。ただし、変換が実際に意味をなすように作業している mapprojection ( UTM も参照)を定義する必要があります。
'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でも)。
十分に近い場合、それらを平面上の座標として扱うことで逃げることができます。これは、完全な精度が要求されず、任意の制限と比較するために必要な距離の大まかな推測だけである場合、たとえば、通りまたは都市レベルで機能します。