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

huangapple go评论103阅读模式
英文:

how convert easting northing coordinates to latitude longitude?

问题

我需要使用Go将EastingsNorthings OSGB36坐标转换为纬度和经度坐标。因此,我想知道是否有任何可以完成这个任务的包。从头开始编写一个似乎并不容易。我在一个沙盒虚拟机中运行代码,所以代码必须是纯Go的。

输入:

  • Northing - 相对于国家网格原点向北的距离(以米为单位)。
  • Easting - 相对于国家网格原点向东的距离(以米为单位)。

示例:

 348356,862582

输出(十进制度数 -DDD):

  • 纬度
  • 经度

示例:

41.40338, 2.17403
英文:

I need to convert Eastings and Northings OSGB36 coordinates into latitude and longitude coordinates using Go. Therefore I'm wondering if there is any package that do just this. Writing one from scratch doesn't seem trivial. I'm running the code in a sandboxed VM so the code must be pure Go.

Input:

  • Northing - Distance in metres north of National Grid origin.
  • Easting - Distance in metres east of National Grid origin.

Example:

 348356,862582

Output (Decimal degrees -DDD):

  • Latitude
  • Longitude

Example:

41.40338, 2.17403

答案1

得分: 3

你可以尝试使用go-proj-4库,它是一个对全面的PROJ.4 - 地图投影库进行封装的工具。

我没有尝试过这两个库,但看起来它们应该能完成工作。

另外,你也可以将这个页面上的代码进行移植。

英文:

You could try the go-proj-4 library which is a wrapper to the comprehensive PROJ.4 - Cartographic Projections Library.

I haven't tried either but it looks like it should do the job.

Alternatively you could port the code on this page

答案2

得分: 2

下面的代码是从Chris Veness的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)
}

输出结果为:

Latitude: 52.833026N
Longitude: 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之间进行转换

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

这段代码没有经过充分测试(它产生与原始javascript代码相同的输出,但这并不能保证正确性),可能存在严重的错误,但它应该能指导你朝正确的方向前进(无意冒犯)。

英文:

The code below is very naively ported from the javascript (© 2005-2014 Chris Veness) at the link Nick Craig-Wood provided. I've only ported the OsGridToLatLong() function, but the others shouldn't be too difficult. Also, this treats all values as float64. You may want to treat northing and easting as int.

package main
import (
&quot;fmt&quot;
&quot;math&quot;
)
const (
radToDeg = 180 / math.Pi
degToRad = math.Pi / 180
a    = 6377563.396
b    = 6356256.909  // Airy 1830 major &amp; 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 &amp; 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 &gt;= 1e-5 { // until &lt; 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(&quot;Latitude: %fN\nLongitude: %fE\n&quot;, lat, lon)
}

Produces:
>Latitude: 52.833026N
Longitude: 4.871525E

These are OSGB-36 coordinates.

From Chris Veness's original post:
>"The Ordnance Survey uses ‘OSGB-36’, based on an elliptical model of the earth’s surface which is a good fit to the UK. GPS systems generally use the world-wide ‘WGS-84’, based on an elliptical model which is a best approximation to the entire earth. At Greenwich, these differ by about 126m (they coincide somewhere in the Atlantic ocean; there’s more on Wikipedia)"

I have no idea if this is where the OSGB-36 coords for Northing: 348356, Easting: 862582 are meant to be, but the code above, and the javascript code (JSFiddle), put it somewhere in the northern Netherlands. (Although the coords shown on the map are WGS-84, and not OSGB-36. See converting between OSGB-36 & WGS-84 for more details.)

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

This code hasn't been properly tested (It produces the same output as the original javascript code, but that's no guarantee of correctness), and may have hideous bugs, but it should point you in the right direction (no pun intended).

Playground

答案3

得分: 1

你好,我遇到了同样的问题。
我正在将我们的代码库从Python移植过来。我们使用了Tobias Bieniek的这个库-(UTM Python版本)。它在GitHub上是公开的。

我没有找到什么好的轻量级库。我只是将这个库移植到了Go语言上- UTM Go语言库。它是纯Go语言编写的,只包含两个方法。你可以在代码库中找到指向godoc的徽章链接。我在生产环境中使用它。

为了提高速度,可以使用以下命令:

go get github.com/im7mortal/UTM

英文:

Hi I had the same problem.
I was porting our codebase from python. We used this library - (UTM python version) by Tobias Bieniek. It is public on github.

I didn't find something good and lightweight. I just ported this library on golang - UTM golang library. It's pure go which contain only two methods. You can find badge-link to godoc in repository. I use it in a production.

For speed use:
>go get github.com/im7mortal/UTM

huangapple
  • 本文由 发表于 2014年3月8日 02:34:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/22258012.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定