下面的代码是从javascript(©2005-2014
Chris Veness)在
链接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
f0 = 0.9996012717
lat0 = 49 * degToRad
lon0 = -2 * degToRad
n0 = -100000.0
e0 = 400000.0
e2 = 1 - (b*b)/(a*a)
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 {
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)
}
cosLat := math.Cos(lat)
sinLat := math.Sin(lat)
nu := a * f0 / math.Sqrt(1-e2*sinLat*sinLat)
rho := a * f0 * (1 - e2) / math.Pow(1-e2*sinLat*sinLat, 1.5)
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坐标。
来自Chris Veness的原始帖子:
“Ordnance Survey使用'OSGB-36',基于一个椭圆形地球表面模型,这个模型非常适合英国。GPS系统通常使用全球性的'WGS-84',基于一个椭圆形模型,这是对整个地球的最佳近似。在格林威治,它们相差约126米(它们在大西洋的某个地方重合;维基百科上有更多信息)”
我不确定这个
Northing: 348356, Easting: 862582
的 OSGB-36 坐标是否应该在这里,但是上面的代码和
JavaScript 代码 (JSFiddle) 把它放在了
荷兰北部的某个地方。(尽管地图上显示的坐标是 WGS-84,而不是 OSGB-36。有关 OSGB-36 和 WGS-84 之间的转换,请参见
这里。)
![Probably completely wrong](https://i.imgur.com/fRhP1Z3.png?1)
这段代码尚未经过充分测试(它产生的输出与原始JavaScript代码相同,但这并不能保证其正确性),可能存在可怕的错误,但它应该能指出正确的方向(无意双关)。
游乐场