如何将纬度或经度转换为米?

发布于 2024-07-14 18:40:39 字数 237 浏览 8 评论 0原文

如果我有标准 NMEA 格式的纬度或经度读数,是否有一种简单的方法/公式将该读数转换为米,然后我可以在 Java (J9) 中实现?

编辑: 好吧,看来我想做的事情不可能容易,但是我真正想做的是:

假设我有一个航路点的纬度和经度,并且用户的纬度和经度是否存在有什么简单的方法可以比较它们来决定何时告诉用户他们距离路点相当近? 我意识到合理是主题,但这容易做到还是仍然过于数学化?

If I have a latitude or longitude reading in standard NMEA format is there an easy way / formula to convert that reading to meters, which I can then implement in Java (J9)?

Edit:
Ok seems what I want to do is not possible easily, however what I really want to do is:

Say I have a lat and long of a way point and a lat and long of a user is there an easy way to compare them to decide when to tell the user they are within a reasonably close distance of the way point? I realise reasonable is subject but is this easily do-able or still overly maths-y?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(19

恋竹姑娘 2024-07-21 18:40:39

这是一个 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

半正矢公式确定给定经度和纬度的球体上两点之间的大圆距离。

Here is a javascript function:

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
}

Explanation: https://en.wikipedia.org/wiki/Haversine_formula

The haversine formula determines the great-circle distance between two points on a sphere given their longitudes and latitudes.

你在看孤独的风景 2024-07-21 18:40:39

如果您正在寻找一个简单的公式,这可能是最简单的方法,假设地球是一个周长为 40075 公里的球体。

1° 纬度的长度(以公里为单位) = 始终 111.32 km

1° 经度的长度(以公里为单位) = 40075 km * cos( 纬度 ) / 360

Given you're looking for a simple formula, this is probably the simplest way to do it, assuming that the Earth is a sphere with a circumference of 40075 km.

Length in km of 1° of latitude = always 111.32 km

Length in km of 1° of longitude = 40075 km * cos( latitude ) / 360

未蓝澄海的烟 2024-07-21 18:40:39

为了近似两个坐标之间的短距离,我使用了以下公式
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 m 以内,纬向 100 公里的距离计算在 1 cm 以内,但我尚未验证这一点,因为任何接近该精度的地方都适合我使用。

For approximating short distances between two coordinates I used formulas from
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 );

.

In the code below I've left the raw numbers to show their relation to the formula from wikipedia.

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) );

The wikipedia entry states that the distance calcs are within 0.6m for 100km longitudinally and 1cm for 100km latitudinally but I have not verified this as anywhere near that accuracy is fine for my use.

弄潮 2024-07-21 18:40:39

这是 bh- 函数 的 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
}

Here is the R version of b-h-'s function, just in case:

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
}
霊感 2024-07-21 18:40:39

地球是一个令人烦恼的不规则表面,因此没有简单的公式可以准确地做到这一点。 你必须使用地球的近似模型,并将你的坐标投影到它上面。 我通常看到的用于此目的的模型是 WGS 84。 GPS 设备通常使用这种方法来解决完全相同的问题。

NOAA 有一些软件,您可以在其网站上下载这些软件来帮助解决此问题。

The earth is an annoyingly irregular surface, so there is no simple formula to do this exactly. You have to live with an approximate model of the earth, and project your coordinates onto it. The model I typically see used for this is WGS 84. This is what GPS devices usually use to solve the exact same problem.

NOAA has some software you can download to help with this on their website.

心凉 2024-07-21 18:40:39

有很多工具可以让这一切变得简单。 有关内容的更多详细信息,请参阅 monjardin 的回答涉及。

然而,做到这一点并不一定困难。 听起来您正在使用 Java,所以我建议您研究一下 GDAL 之类的内容。 它为他们的例程提供了java包装器,并且他们拥有从Lat/Lon(地理坐标)转换为UTM(投影坐标系)或其他一些合理的地图投影所需的所有工具。

UTM 很好,因为它是米,所以很容易使用。 但是,您需要获得适当的 UTM 区域才能让它做好工作。 通过谷歌搜索可以找到一些简单的代码来为纬度/经度对找到合适的区域。

There are many tools that will make this easy. See monjardin's answer for more details about what's involved.

However, doing this isn't necessarily difficult. It sounds like you're using Java, so I would recommend looking into something like GDAL. It provides java wrappers for their routines, and they have all the tools required to convert from Lat/Lon (geographic coordinates) to UTM (projected coordinate system) or some other reasonable map projection.

UTM is nice, because it's meters, so easy to work with. However, you will need to get the appropriate UTM zone for it to do a good job. There are some simple codes available via googling to find an appropriate zone for a lat/long pair.

对你而言 2024-07-21 18:40:39

有很多方法可以计算这个。 它们都使用球面三角学的近似值,其中半径是地球的半径。

尝试 http://www.movable-type.co.uk/scripts/latlong .html 了解一些不同语言的方法和代码。

There are quite a few ways to calculate this. All of them use aproximations of spherical trigonometry where the radius is the one of the earth.

try http://www.movable-type.co.uk/scripts/latlong.html for a bit of methods and code in different languages.

蓝海似她心 2024-07-21 18:40:39

一海里(1852 米)定义为赤道经度一弧分。 但是,您需要定义地图投影(另请参阅UTM),您正在其中努力使转换真正有意义。

One nautical mile (1852 meters) is defined as one arcminute of longitude at the equator. However, you need to define a map projection (see also UTM) in which you are working for the conversion to really make sense.

瑕疵 2024-07-21 18:40:39
    '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
    '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
oО清风挽发oО 2024-07-21 18:40:39

要将纬度和经度转换为 x 和 y 表示形式,您需要决定使用哪种类型的地图投影。 对我来说,椭圆墨卡托似乎非常好。 在这里您可以找到一个实现(也可以用 Java 实现)。

To convert latitude and longitude in x and y representation you need to decide what type of map projection to use. As for me, Elliptical Mercator seems very well. Here you can find an implementation (in Java too).

暖风昔人 2024-07-21 18:40:39

这是一个 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 ;

Here is a MySQL function:

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 ;
绝影如岚 2024-07-21 18:40:39

原贴问
“如果我有标准 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;
\\=======

为了将其应用于您的问题类型,我将弥补
您的一个数据点位于

[Latitude, Longitude]=[+30, 30]

,另一个数据点位于

[Latitude, Longitude]=[+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
? 

500 米/1 英寸的误差仅为 1/20000 左右,
对于大多数图表来说已经足够了,
但人们可能想减少 1 英寸的误差。
对于完全通用的转换方式
纬度、经度到正交 x、y 坐标
对于地球上的任何一点,我都会选择放弃
将坐标线与东西向对齐
和南北,除了仍然保持中心
y 轴指向正北。 例如你可以
围绕两极旋转地球(围绕 3-D Z 轴)
所以地图的中心点位于经度零。
然后倾斜地球仪(围绕 3-D y 轴)
将中心点设置为 lat,long = [0,0]。
在地球上点 lat,long = [0,0] 是
距离两极最远并且有经纬度
它们周围最正交的网格
所以你可以使用这些新的“南北”、“东西”
线作为坐标 x,y 线而不会引起
会发生的拉伸
在将中心点旋转远离极点之前。
显示一个明确的例子将需要更多的空间。

Original poster asked
"If I have a latitude or longitude reading in standard NMEA format is there an easy way / formula to convert that reading to meters"

I haven't used Java in a while so I did the solution here in "PARI".
Just plug your point's latitude and longitudes
into the equations below to get
the exact arc lengths and scales
in meters per (second of Longitude)
and meters per (second of Latitude).
I wrote these equations for
the free-open-source-mac-pc math program "PARI".
You can just paste the following into it
and the I will show how to apply them to two made up points:

\\=======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;
\\=======

To apply that to your type of problem I will make up
that one of your data points was at

[Latitude, Longitude]=[+30, 30]

and the other at

[Latitude, Longitude]=[+30:00:16.237796,30:00:18.655502].

To convert those points to meters in two coordinates:

I can setup a system of coordinates in meters
with the first point being at the origin: [0,0] meters.
Then I can define the coordinate x-axis as due East-West,
and the y-axis as due North-South.

Then the second point's coordinates are:

? [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]

Warning on precision:
Note however:
Since the surface of the Earth is curved,
2-dimensional coordinates obtained on it can't follow
the same rules as cartesian coordinates
such as the Pythagorean Theorem perfectly.
Also lines pointing due North-South
converge in the Northern Hemisphere.
At the North Pole it becomes obvious
that North-South lines won't serve well for
lines parallel to the y-axis on a map.

At 30 degrees Latitude with 500 meter lengths,
the x-coordinate changes by 1.0228 inches if the scale is set from [0,+500] instead of [0,0]:

? [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
? 

The error there of 500meters/1inch is only about 1/20000,
good enough for most diagrams,
but one might want to reduce the 1 inch error.
For a completely general way to convert
lat,long to orthogonal x,y coordinates
for any point on the globe, I would chose to abandon
aligning coordinate lines with East-West
and North-South, except still keeping the center
y-axis pointing due North. For example you could
rotate the globe around the poles (around the 3-D Z-axis)
so the center point in your map is at longitude zero.
Then tilt the globe (around the 3-D y-axis) to
bring your center point to lat,long = [0,0].
On the globe points at lat,long = [0,0] are
farthest from the poles and have a lat,long
grid around them that is most orthogonal
so you can use these new "North-South", "East-West"
lines as coordinate x,y lines without incurring
the stretching that would have occurred doing
that before rotating the center point away from the pole.
Showing an explicit example of that would take a lot more space.

折戟 2024-07-21 18:40:39

为什么要限制在一级呢?

该公式基于比例:

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]

请注意,deg 和 deg 简化了,剩下的就是两侧的米)。

对于经度最大周长与纬度的余弦成正比(正如你可以想象的那样,绕北极跑比绕赤道绕圈短),所以它是2 * pi * R * cos(latitude[rad])
因此

longitude distance[m] = ( 2 * pi * R[m] * cos(latitude[rad]) * longitude[deg] ) / 360[deg]

请注意,在计算 cos 之前,您必须将纬度从 deg 转换为 rad。


省略谁只是寻找公式的详细信息:

lat_in_m = 111132.954 * lat_in_degree / 360
lon_in_m = 111132.954 * cos(lat_in_radians) * lon_in_deg ) / 360

Why limiting to one degree?

The formula is based on the proportion:

distance[m] : distance[deg] = max circumference[m] : 360[deg]

Lets say you are given an angle for a latitude and one for longitude both in degrees: (longitude[deg], latitude[deg])

For the latitude, the max circumference is always the one passing for the poles. In a spherical model, with radius R (in meters) the max circumference is 2 * pi * R and the proportions resolves to:

latitude[m] = ( 2 * pi * R[m] * latitude[deg] ) / 360[deg]

(note that deg and deg simplifies, and what remains is meters on both sides).

For the longitude the max circumference is proportional to the cosine of the latitude (as you can imagine running in circle the north pole is shorter than running in circle around the equator), so it is 2 * pi * R * cos(latitude[rad]).
Therefore

longitude distance[m] = ( 2 * pi * R[m] * cos(latitude[rad]) * longitude[deg] ) / 360[deg]

Note that you will have to convert the latitude from deg to rad before computing the cos.


Omitting details for who is just looking for the formula:

lat_in_m = 111132.954 * lat_in_degree / 360
lon_in_m = 111132.954 * cos(lat_in_radians) * lon_in_deg ) / 360
(り薆情海 2024-07-21 18:40:39

如果它足够近,您可以将它们视为平面上的坐标。 如果不需要完美的精度,并且您所需要的只是粗略地猜测所涉及的距离以与任意限制进行比较,那么这适用于街道或城市级别。

If its sufficiently close you can get away with treating them as coordinates on a flat plane. This works on say, street or city level if perfect accuracy isnt required and all you need is a rough guess on the distance involved to compare with an arbitrary limit.

花海 2024-07-21 18:40:39

这是 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
  }

Here is a version in 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
  }
污味仙女 2024-07-21 18:40:39

要将两个纬度/经度之间的距离直接转换为它们之间的 xy 米,您可以使用维基百科中的地球半径方程。 在 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 得到这些半径的周长。

To directly convert the distance between two latitudes/longitudes to the x y meters between them, you could use the Earth Radius equations from Wikipedia. In C, these are:

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;

Where a is the radius of the Earth at the equator and e2 is the Earth's eccentricity squared. The equations get the radii between the two points and PI/180 gets the circumferences of those radii.

云巢 2024-07-21 18:40:39

如果您想要一个简单的解决方案,请使用其他评论中概述的 Haversine 公式。 如果您的应用程序对精度敏感,请记住半正弦公式不能保证精度优于 0.5%,因为它假设地球是一个球体。 要认为地球是扁球体,请考虑使用文森蒂公式
此外,我不确定我们应该使用半正弦公式的半径:{赤道:6,378.137公里,极地:6,356.752公里,体积:6,371.0088公里}。

If you want a simple solution then use the Haversine formula as outlined by the other comments. If you have an accuracy sensitive application keep in mind the Haversine formula does not guarantee an accuracy better then 0.5% as it is assuming the earth is a sphere. To consider that Earth is a oblate spheroid consider using Vincenty's formulae.
Additionally, I'm not sure what radius we should use with the Haversine formula: {Equator: 6,378.137 km, Polar: 6,356.752 km, Volumetric: 6,371.0088 km}.

寄居人 2024-07-21 18:40:39

您需要将坐标转换为弧度才能进行球面几何。 转换后,您可以计算两点之间的距离。 然后可以将距离转换为您想要的任何度量。

You need to convert the coordinates to radians to do the spherical geometry. Once converted, then you can calculate a distance between the two points. The distance then can be converted to any measure you want.

楠木可依 2024-07-21 18:40:39

基于地球上的平均距离。

1°=111公里;

将其转换为弧度并除以米,得到 RAD 的一个神奇数字,以米为单位:0.000008998719243599958;

然后:

const RAD = 0.000008998719243599958;
Math.sqrt(Math.pow(lat1 - lat2, 2) + Math.pow(long1 - long2, 2)) / RAD;

Based on average distance for degress in the Earth.

1° = 111km;

Converting this for radians and dividing for meters, take's a magic number for the RAD, in meters: 0.000008998719243599958;

then:

const RAD = 0.000008998719243599958;
Math.sqrt(Math.pow(lat1 - lat2, 2) + Math.pow(long1 - long2, 2)) / RAD;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文