如何将东北坐标转换为纬度经度?

时间:2014-03-07 18:34:36

标签: go gis

我需要使用Go将EastingsNorthings OSGB36坐标转换为纬度和经度坐标。因此,我想知道是否有任何包这样做。从头开始写一个看起来并不简单。我在沙盒VM中运行代码,因此代码必须是纯粹的Go。

输入:

  • Northing - 国家电网原点北面的距离。
  • Easting - 国家电网原产地以东的米距离。

示例:

 348356,862582

输出(十进制度-DDD):

  • 纬度
  • 经度

示例:

41.40338, 2.17403

3 个答案:

答案 0 :(得分:4)

您可以尝试go-proj-4库,它是综合PROJ.4 - Cartographic Projections Library的包装。

我也没试过,但它看起来应该可以胜任。

或者,您可以移植代码on this page

答案 1 :(得分:2)

以下代码是非常天真地移植到Chris Veness the link提供的javascript(©2005-2014 Nick Craig-Wood)。我只移植了OsGridToLatLong()函数,但其​​他函数不应该太难。此外,这会将所有值视为float64。您可能希望将northingeasting视为int

package main

import (
    "fmt"
    "math"
)

const (
    radToDeg = 180 / math.Pi
    degToRad = math.Pi / 180

    a    = 6377563.396
    b    = 6356256.909  // Airy 1830 major & minor semi-axes
    f0   = 0.9996012717 // NatGrid scale factor on central meridian
    lat0 = 49 * degToRad
    lon0 = -2 * degToRad // NatGrid true origin
    n0   = -100000.0
    e0   = 400000.0        // northing & easting of true origin, metres
    e2   = 1 - (b*b)/(a*a) // eccentricity squared
    n    = (a - b) / (a + b)
    n2   = n * n
    n3   = n * n * n
)

func OsGridToLatLong(northing, easting float64) (float64, float64) {
    lat := lat0
    m := 0.0
    for northing-n0-m >= 1e-5 { // until < 0.01mm
        lat = (northing-n0-m)/(a*f0) + lat
        ma := (1 + n + (5/4)*n2 + (5/4)*n3) * (lat - lat0)
        mb := (3*n + 3*n*n + (21/8)*n3) * math.Sin(lat-lat0) * math.Cos(lat+lat0)
        mc := ((15/8)*n2 + (15/8)*n3) * math.Sin(2*(lat-lat0)) * math.Cos(2*(lat+lat0))
        md := (35 / 24) * n3 * math.Sin(3*(lat-lat0)) * math.Cos(3*(lat+lat0))
        m = b * f0 * (ma - mb + mc - md) // meridional arc
    }
    cosLat := math.Cos(lat)
    sinLat := math.Sin(lat)
    nu := a * f0 / math.Sqrt(1-e2*sinLat*sinLat)                 // transverse radius of curvature
    rho := a * f0 * (1 - e2) / math.Pow(1-e2*sinLat*sinLat, 1.5) // meridional radius of curvature
    eta2 := nu/rho - 1
    tanLat := math.Tan(lat)
    tan2lat := tanLat * tanLat
    tan4lat := tan2lat * tan2lat
    tan6lat := tan4lat * tan2lat
    secLat := 1 / cosLat
    nu3 := nu * nu * nu
    nu5 := nu3 * nu * nu
    nu7 := nu5 * nu * nu
    vii := tanLat / (2 * rho * nu)
    viii := tanLat / (24 * rho * nu3) * (5 + 3*tan2lat + eta2 - 9*tan2lat*eta2)
    ix := tanLat / (720 * rho * nu5) * (61 + 90*tan2lat + 45*tan4lat)
    x := secLat / nu
    xi := secLat / (6 * nu3) * (nu/rho + 2*tan2lat)
    xii := secLat / (120 * nu5) * (5 + 28*tan2lat + 24*tan4lat)
    xiia := secLat / (5040 * nu7) * (61 + 662*tan2lat + 1320*tan4lat + 720*tan6lat)
    de := easting - e0
    de2 := de * de
    de3 := de2 * de
    de4 := de2 * de2
    de5 := de3 * de2
    de6 := de4 * de2
    de7 := de5 * de2
    lat = lat - vii*de2 + viii*de4 - ix*de6
    lon := lon0 + x*de - xi*de3 + xii*de5 - xiia*de7
    return lat * radToDeg, lon * radToDeg
}

func main() {
    lat, lon := OsGridToLatLong(348356.0, 862582.0)
    fmt.Printf("Latitude: %fN\nLongitude: %fE\n", lat, lon)
}

产地:

  

纬度:52.833026N
  经度:4.871525E

这些是OSGB-36 coordinates

来自Chris Veness's原帖:

  

“军械测量使用'OSGB-36',基于地球表面的椭圆模型,非常适合英国.GPS系统通常使用全球'WGS-84',基于椭圆机这是一个最接近整个地球的模型。在格林威治,它们差别大约126米(它们在大西洋的某个地方重合;在维基百科上有更多)“

我不知道这是否是Northing: 348356, Easting: 862582的OSGB-36坐标的位置,但上面的代码和javascript code (JSFiddle)将其置于somewhere in the northern Netherlands。 (虽然地图上显示的坐标是WGS-84,而不是OSGB-36。有关详细信息,请参阅converting between OSGB-36 & WGS-84。)

Probably completely wrong

此代码未经过正确测试(它产生与原始javascript代码相同的输出,但不能保证正确性),并且可能有 hideous 错误,但它应该指向您正确的方向(没有双关语)。

Playground

答案 2 :(得分:1)

嗨我有同样的问题。 我从python移植我们的代码库。我们使用了这个库 - (UTM python version)作者Tobias Bieniek。它在github上是公开的。

我没有找到好的和轻量级的东西。我刚刚在golang上移植了这个库 - UTM golang library。纯粹的只包含两种方法。你可以在存储库中找到godoc链接到godoc。我在制作中使用它。

速度使用:

  

去获取github.com/im7mortal/UTM