如果我有一个标准NMEA格式的纬度或经度读数,是否有一种简单的方式/公式将该读数转换为米,并且我可以在Java(J9)中实现?
编辑: 好吧,似乎我想做的事情不是很容易,但我真正想做的是:
假设我有一个航点的纬度和经度以及一个用户的纬度和经度,是否有一种简单的方法来比较它们,以决定何时告诉用户他们已经接近航点的合理距离?我知道“合理”是主观的,但这很容易实现还是过于数学化了?
如果我有一个标准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
哈弗赛公式用于计算两个点在球面上的经纬度间的大圆距离。
alt1
和alt2
,而dm
是以米为单位的距离(上面的measure
函数的结果)。 您可以使用JS的hypothenuse函数Math.hypot(x, y)
,其中x
是dm
,y
是max(alt1, alt2) - min(alt1, alt2)
。 - Marco Aurélio da Silva如果你正在寻找一个简单的公式,那么这可能是最简单的方法,假设地球是一个周长为40075公里的球体。
1°纬度线对应的长度 = 总是111.32公里
1°经度线对应的长度 = 40075公里 * cos( 纬度 ) / 360
我使用从 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厘米以内,但我并未验证这一精度是否足够满足我的使用需求。
这里是 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
}
原帖问道:“如果我有一个标准NMEA格式的纬度或经度读数,是否有一种简单的方法/公式将该读数转换为米?”
我已经有一段时间没有使用Java了,所以我在“PARI”中提供了解决方案。只需将您的点的纬度和经度插入以下方程式中,即可获得每秒经度和每秒纬度的精确弧长和比例尺(以米为单位)。我为自由开源的Mac-PC数学程序“PARI”编写了这些方程式。您只需将以下内容粘贴到其中,然后我将展示如何将它们应用于两个虚构的点:
\\=======Arc lengths along Latitude and Longitude and the respective scales:
\p300
default(format,"g.42")
dms(u)=[truncate(u),truncate((u-truncate(u))*60),((u-truncate(u))*60-truncate((u-truncate(u))*60))*60];
SpinEarthRadiansPerSec=7.292115e-5;\
GMearth=3986005e8;\
J2earth=108263e-8;\
re=6378137;\
ecc=solve(ecc=.0001,.9999,eccp=ecc/sqrt(1-ecc^2);qecc=(1+3/eccp^2)*atan(eccp)-3/eccp;ecc^2-(3*J2earth+4/15*SpinEarthRadiansPerSec^2*re^3/GMearth*ecc^3/qecc));\
e2=ecc^2;\
b2=1-e2;\
b=sqrt(b2);\
fl=1-b;\
rfl=1/fl;\
U0=GMearth/ecc/re*atan(eccp)+1/3*SpinEarthRadiansPerSec^2*re^2;\
HeightAboveEllipsoid=0;\
reh=re+HeightAboveEllipsoid;\
longscale(lat)=reh*Pi/648000/sqrt(1+b2*(tan(lat))^2);
latscale(lat)=reh*b*Pi/648000/(1-e2*(sin(lat))^2)^(3/2);
longarc(lat,long1,long2)=longscale(lat)*648000/Pi*(long2-long1);
latarc(lat1,lat2)=(intnum(th=lat1,lat2,sqrt(1-e2*(sin(th))^2))+e2/2*sin(2*lat1)/sqrt(1-e2*(sin(lat1))^2)-e2/2*sin(2*lat2)/sqrt(1-e2*(sin(lat2))^2))*reh;
\\=======
为了将这个应用到您的问题类型上,我会假设您的一个数据点位于
[纬度,经度]=[+30, 30]
而另一个数据点位于
[纬度,经度]=[+30:00:16.237796,30:00:18.655502]。
为了将这些点转换为两个坐标系中的米:
我可以建立一个以第一个点为原点的米制坐标系:[0,0] 米。 然后我可以定义 x 轴坐标为东西方向,y 轴坐标为南北方向。
那么第二个点的坐标就是:
? [longarc(30*Pi/180,30*Pi/180,((18.655502/60+0)/60+30)*Pi/180),latarc(30*Pi/180,((16.237796/60+0)/60+30)*Pi/180)]
%9 = [499.999998389040060103621525561027349597207, 499.999990137812119668486524932382720606325]
精度警告: 需要注意的是: 由于地球表面是弯曲的, 在其上获得的二维坐标不能遵循 与笛卡尔坐标系完全相同的规则, 例如勾股定理。 此外,指向正北-正南的线条 在北半球会汇聚。 在北极,显然 南北线不适用于 地图上平行于y轴的线。
在30度纬度和500米长度下, 如果比例尺从[0,+500]而不是[0,0]设置, x坐标将变化1.0228英寸:
? [longarc(((18.655502/60+0)/60+30)*Pi/180,30*Pi/180,((18.655502/60+0)/60+30)*Pi/180),latarc(30*Pi/180,((16.237796/60+0)/60+30)*Pi/180)]
%10 = [499.974018595036400823218815901067566617826, 499.999990137812119668486524932382720606325]
? (%10[1]-%9[1])*1000/25.4
%12 = -1.02282653557713702372872677007019603860352
?
为什么要局限于一个学位?
这个公式是基于比例计算的:
distance[m] : distance[deg] = max circumference[m] : 360[deg]
(longitude[deg], latitude[deg])
对于纬度来说,最大周长
总是经过两极的那一条。在球形模型中,半径为R(以米为单位),最大周长为2 * pi * R
,比例可表示为:latitude[m] = ( 2 * pi * R[m] * latitude[deg] ) / 360[deg]
最大周长
与纬度的余弦成比例(想象一下在北极圈内循环比在赤道附近循环要短),因此它是2 * pi * R * cos(latitude[rad])
。因此,longitude distance[m] = ( 2 * pi * R[m] * cos(latitude[rad]) * longitude[deg] ) / 360[deg]
lat_in_m = 111132.954 * lat_in_degree / 360
lon_in_m = 111132.954 * cos(lat_in_radians) * lon_in_deg ) / 360