我需要使用Go将Eastings
和Northings
OSGB36坐标转换为纬度和经度坐标。因此,我想知道是否有任何包这样做。从头开始写一个看起来并不简单。我在沙盒VM中运行代码,因此代码必须是纯粹的Go。
输入:
示例:
348356,862582
输出(十进制度-DDD):
示例:
41.40338, 2.17403
答案 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
。您可能希望将northing
和easting
视为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
来自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。)
此代码未经过正确测试(它产生与原始javascript代码相同的输出,但不能保证正确性),并且可能有 hideous 错误,但它应该指向您正确的方向(没有双关语)。
答案 2 :(得分:1)
嗨我有同样的问题。 我从python移植我们的代码库。我们使用了这个库 - (UTM python version)作者Tobias Bieniek。它在github上是公开的。
我没有找到好的和轻量级的东西。我刚刚在golang上移植了这个库 - UTM golang library。纯粹的只包含两种方法。你可以在存储库中找到godoc链接到godoc。我在制作中使用它。
速度使用:
去获取github.com/im7mortal/UTM