如果我有一个标准NMEA格式的纬度或经度读数,是否有一种简单的方式/公式将该读数转换为米,并且我可以在Java(J9)中实现?
编辑: 好吧,似乎我想做的事情不是很容易,但我真正想做的是:
假设我有一个航点的纬度和经度以及一个用户的纬度和经度,是否有一种简单的方法来比较它们,以决定何时告诉用户他们已经接近航点的合理距离?我知道“合理”是主观的,但这很容易实现还是过于数学化了?
如果我有一个标准NMEA格式的纬度或经度读数,是否有一种简单的方式/公式将该读数转换为米,并且我可以在Java(J9)中实现?
编辑: 好吧,似乎我想做的事情不是很容易,但我真正想做的是:
假设我有一个航点的纬度和经度以及一个用户的纬度和经度,是否有一种简单的方法来比较它们,以决定何时告诉用户他们已经接近航点的合理距离?我知道“合理”是主观的,但这很容易实现还是过于数学化了?
'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
这里是一个 MySQL 函数:
SET @radius_of_earth = 6378.137; -- In kilometers
DROP FUNCTION IF EXISTS Measure;
DELIMITER //
CREATE FUNCTION Measure (lat1 REAL, lon1 REAL, lat2 REAL, lon2 REAL) RETURNS REAL
BEGIN
-- Multiply by 1000 to convert millimeters to meters
RETURN 2 * @radius_of_earth * 1000 * ASIN(SQRT(
POW(SIN((lat2 - lat1) / 2 * PI() / 180), 2) +
COS(lat1 * PI() / 180) *
COS(lat2 * PI() / 180) *
POW(SIN((lon2 - lon1) / 2 * PI() / 180), 2)
));
END; //
DELIMITER ;
这里是用 Swift
的一个版本:
func toDegreeAt(point: CLLocationCoordinate2D) -> CLLocationDegrees {
let latitude = point.latitude
let earthRadiusInMetersAtSeaLevel = 6378137.0
let earthRadiusInMetersAtPole = 6356752.314
let r1 = earthRadiusInMetersAtSeaLevel
let r2 = earthRadiusInMetersAtPole
let beta = latitude
let earthRadiuseAtGivenLatitude = (
( pow(pow(r1, 2) * cos(beta), 2) + pow(pow(r2, 2) * sin(beta), 2) ) /
( pow(r1 * cos(beta), 2) + pow(r2 * sin(beta), 2) )
)
.squareRoot()
let metersInOneDegree = (2 * Double.pi * earthRadiuseAtGivenLatitude * 1.0) / 360.0
let value: CLLocationDegrees = self / metersInOneDegree
return value
}
要直接将两个纬度/经度之间的距离转换为它们之间的x y米,您可以使用维基百科上的地球半径方程。在C语言中,这些方程式如下:
N = a/sqrt(1-e2)*(sin(Lat1)*sin(Lat1))));
latlen = ((1-e2)/(a*a))*N*N*N*(Lat1-Lat2)*PI/180;
lonlen = (N*cos(Lat1))*(Lon1-Lon2)*PI/180;
其中,a是赤道上地球半径,e2是地球离心率的平方。这些方程式可以得到两点之间的半径,而PI/180则可以得到这些半径的周长。
基于地球上每度的平均距离。
1° = 111公里;
将其转换为弧度并除以米数,需要一个魔术数字RAD,单位为米:0.000008998719243599958;
然后:
const RAD = 0.000008998719243599958;
Math.sqrt(Math.pow(lat1 - lat2, 2) + Math.pow(long1 - long2, 2)) / RAD;