如果我有标准NMEA格式的纬度或经度读数,有一种简单的方法/公式可以将读数转换为米,然后我可以用Java(J9)实现吗?
编辑: 好吧,我想做的事情似乎不太可能轻松,但我真正想做的是:
假设我有一个方向点和一个方向点,一个用户的纬度和长度是一种简单的方法来比较它们以决定何时告诉用户他们在合理地关闭路的距离点?我认为合理是主题,但是这很容易做到还是仍然过于数学?
答案 0 :(得分:138)
这是一个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
根据经度和纬度,半正弦公式确定球体上两点之间的大圆距离。
答案 1 :(得分:32)
鉴于你正在寻找一个简单的公式,这可能是最简单的方法,假设地球是一个40075公里的周长范围。
纬度1°的长度(以米为单位)= 111.32 km
以1°经度为单位的长度= 40075 km * cos(纬度)/ 360
答案 2 :(得分:27)
为了近似两个坐标之间的短距离,我使用了公式 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) );
维基百科条目指出纵向100公里的距离计算在0.6米范围内,纬度100公里的距离计算范围在1厘米范围内,但我没有证实这一点,因为我的使用准确度很高。
答案 3 :(得分:12)
纬度和经度指定点,而不是距离,所以你的问题有点荒谬。如果您询问两个(纬度,经度)点之间的最短距离,请参阅大圆距离上的this Wikipedia article。
答案 4 :(得分:8)
地球是一个令人烦恼的不规则表面,因此没有简单的公式可以做到这一点。你必须使用地球的近似模型,并将坐标投射到它上面。我通常看到用于此的模型是WGS 84。这就是GPS设备通常用来解决完全相同的问题。
NOAA有一些软件可供您下载以帮助解决on their website。
答案 5 :(得分:7)
有很多工具可以让这很容易。有关所涉及的内容的详细信息,请参阅monjardin's answer。
然而,这样做并不一定困难。听起来你正在使用Java,所以我建议你研究GDAL之类的东西。它为它们的例程提供了java包装器,它们具有从Lat / Lon(地理坐标)转换为UTM(投影坐标系)或其他合理的地图投影所需的所有工具。
UTM很好,因为它是米,所以很容易使用。但是,您需要获得适当的UTM zone才能完成这项工作。通过谷歌搜索可以找到一些简单的代码,为纬度/经度对找到合适的区域。
答案 6 :(得分:5)
以下是b-h-'s function的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
}
答案 7 :(得分:2)
有很多方法可以计算出来。所有这些都使用球形三角学的近似,其中半径是地球的一个。
尝试http://www.movable-type.co.uk/scripts/latlong.html获取不同语言的一些方法和代码。
答案 8 :(得分:2)
一海里(1852米)被定义为赤道的一个arcminute经度。但是,您需要定义一个map projection(另请参阅UTM),其中您正在为转换工作做真正有意义。
答案 9 :(得分:1)
'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
答案 10 :(得分:1)
要在x和y表示中转换纬度和经度,您需要确定要使用的地图投影类型。至于我,Elliptical Mercator看起来非常好。 Here你可以找到一个实现(在Java中也是如此)。
答案 11 :(得分:1)
基于地球的平均距离。
1°= 111km;
将此转换为弧度并除以米,取RAD的幻数,以米为单位:0.000008998719243599958;
然后:
const RAD = 0.000008998719243599958;
Math.sqrt(Math.pow(lat1 - lat2, 2) + Math.pow(long1 - long2, 2)) / RAD;
答案 12 :(得分:1)
这是一个 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 ;
答案 13 :(得分:0)
如果距离足够近,你可以将它们视为平面上的坐标。如果不需要完美的准确度,这就可以说是街道或城市级别,您只需要粗略猜测与任意限制进行比较所涉及的距离。
答案 14 :(得分:0)
这是 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
}
答案 15 :(得分:-1)
如果您想要一个简单的解决方案,请使用其他评论中概述的Haversine formula。如果你有一个准确度敏感的应用程序,请记住,Haversine公式不能保证精度优于0.5%,因为假设地球是一个圆。考虑使用Vincenty's formulae来考虑地球是扁球体。 另外,我不确定我们应该使用Haversine公式的半径:{赤道:6,378.137 km,极地:6,356.752 km,体积:6,371.0088 km}。
答案 16 :(得分:-2)
您需要将坐标转换为弧度以执行球面几何。转换后,您可以计算两点之间的距离。然后可以将距离转换为您想要的任何度量。