65.9K
CodeProject 正在变化。 阅读更多。
Home

在 C# 中将纬度和经度转换为英国国家网格

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.87/5 (18投票s)

2015 年 7 月 6 日

CPOL

10分钟阅读

viewsIcon

34306

介绍了坐标系转换的解释,并附有 C# 示例。

引言

本文旨在揭开从一个坐标系转换到另一个坐标系的概念的神秘面纱。本文将介绍一些 C# 示例,包括如何将 GPS 坐标转换为英国国家网格以及如何反向转换。这些示例使用了免费的 GeoUK NuGet 包。GeoUK 是一个可移植类库项目(配置文件 78),因此可以添加到 Visual Studio 或 Xamarin 中,并支持 .Net 4.5+、Windows Phone 8+、Xamarin.IOS/Android、Windows 8 应用商店应用等。

我应该提到的一点是,本文是对一个复杂主题的极大简化讨论。英国地形测量局提供了与英国使用的坐标系相关的详细文档。

纬度和经度

地球近似球形。如果您拿一个充气的沙滩球,将脚放在上面并轻轻按压,您将得到一个被压扁的球体,称为椭球体。地球是椭球形的,尽管有一些凸起和凹陷。

纬度和经度坐标系可以描述地球上的任何一点,但是,只有当我们首先定义了地球的详细信息(例如纬度和经度系统的原点以及所用椭球体的大小和形状)时,它才能做到这一点。这些定义被称为基准面。问题是,根据您在世界上的位置,通常会使用不同的椭球体,因此也会使用不同的基准面。在某些情况下,根据具体要求,同一位置可以使用多个基准面。这意味着纬度和经度只有在我们知道正在使用哪个基准面时才能描述地球上的一个点。可以证明,如果将基于 OSGB36 基准面的纬度和经度输入到使用 WGS84 基准面的 GPS 中,它将指向不同的位置。因此,能够在不同基准面之间转换坐标至关重要,本文后面所示的示例将展示如何在 C# 中使用 GeoUK 包来完成此操作。

为什么有这么多基准面

在继续讨论坐标系之前,值得解释一下为什么我们使用不同的椭球体,因此也使用不同的基准面。WGS84 是大多数 GPS 系统中默认使用的标准基准面,那么为什么不简单地使用它呢?下图显示了地球及其所有凸起和凹陷的粗略图像。大椭球体虽然不能完美拟合,但为我们提供了一个可以在世界各地使用的通用椭球体,可以将其视为 WGS84。然而,可以看到较小的椭球体更适合地球的一小部分。因此,如果您恰好在地球的这一小部分上,使用这个较小的椭球体将提供更高的精度。因此,需要多个椭球体以及在它们之间进行转换。如果您在英国,这个较小的椭球体将是艾里椭球体,是 OSGB36 基准面的一部分。该椭球体最初由乔治·艾里爵士于 1830 年定义。

 

还需要考虑的另一件事是,由于各种效应,其中最重要的是构造运动,地球表面任何特定点的 WGS84 位置都在不断变化。因此,WGS84 本身不适合测绘,因为地面会不断地在任何基于 WGS84 的测绘网格表面上滑动。对于覆盖小区域的系统来说,情况并非如此,因为测绘网格也可以移动。因此,世界各地都有一些基准面,它们在某个时间点(历元)基于 WGS84 基准面,但为了考虑地块运动而略有偏离。欧洲的一个这样的基准面称为 ETRS89。稍后将详细介绍。

不同的坐标系

经纬度系统可能是最著名的坐标系。然而,在英国,地形测量局地图通常使用东距和北距(地图参考)作为坐标系。笛卡尔坐标(X、Y 和 Z)也可能非常有用。本文无意在此描述笛卡尔坐标,但是,下面详细介绍的代码将在中间步骤中使用它们。

重要的是要理解,坐标之间的转换发生在同一基准面内。将 OSGB36 东距和北距转换为经纬度,会返回基于相同 OSGB36 基准面的经纬度。要将这些坐标转换为用于使用 WGS84 的 GPS 的经纬度,还需要进行基准面转换。下面所示的示例将展示如何在 C# 中使用 GeoUK 包来完成此操作。

目前没有精确的方法用于基准面转换,但是,只要所需的精度不低于 5 米,就可以使用赫尔默特变换。对于厘米精度,需要采用完全不同的方法。这在“获取更高精度”一节中有所描述。

地图投影

Map showing Easting and Northing Coordinates

在我们进入实际代码之前,快速讨论一下投影是值得的。

投影可以看作是将椭球体上的点传输到平面(如地图)上的任何函数。就我们的目的而言,我们可以认为这意味着将经纬度转换为东距和北距。这意味着任何与东距/北距坐标的转换都需要指定一个投影。

入门

GeoUK 包是一个 PCL78 程序集,可与 .NET 和 Mono 一起使用。使用 NuGet 包管理器提示将该包添加到 Xamarin 或 Visual Studio。

> Install-Package GeoUK

第一个示例获取地形测量局地图的东距/北距,并将其转换为 GPS (WGS84) 经纬度。因此,需要进行坐标转换(东距/北距到经纬度),还需要进行基准面转换(OSGB36 到 WGS84)。如前所述,ETRS89 基准面是 WGS84 的欧洲版本。1989 年,这些基准面进行了对齐,此后它们略有偏离,但是,就我们的目的而言,我们可以认为它们是相同的。

首先是坐标转换。东距/北距来自地形测量局地图,因此使用的是 OSGB36 基准面,采用艾里椭球体和英国国家网格投影 (BNG)。

步骤 1:转换为笛卡尔坐标

using GeoUK;
using GeoUK.Projections;
using GeoUK.Coordinates;
using GeoUK.Ellipsoids;
...

// Given an easting and northing in metres (see text)
const double easting = 651409.903;
const double northing = 313177.270;

// Convert to Cartesian
var cartesian = Convert.ToCartesian (new Airy1830 (),
        new BritishNationalGrid (),
        new EastingNorthing (
            easting, 
            northing));

这些新的笛卡尔坐标仍然参考 OSGB 基准面。一旦我们有了笛卡尔坐标,我们就可以进行到 ETRS89 (WGS84) 的转换。

步骤 2:从 OSBB36 基准面转换到 ETRS89 基准面(参见文章文本)

var wgsCartesian = Transform.OSBB36ToEtrs89 (cartesian); //ETRS89 is effectively WGS84   

现在我们有了参考 WGS84 基准面(使用 WGS84 椭球体)的笛卡尔结果,可以简单地将它们转换为经纬度。

步骤 3:转换回经纬度

var wgsLatLong = Convert.ToLatitudeLongitude (new Wgs84 (), 
                                                wgsCartesian);

总而言之,对于从基准面 A 到基准面 B 的东距北距坐标的基准面变化,首先使用基准面 A 的椭球体转换为笛卡尔坐标。然后,在转换回使用基准面 B 的椭球体的经纬度之前,应用从基准面 A 到基准面 B 的转换。反向操作也使用相同的过程。

英国国家网格示例

转换

下面的代码以上述方式从 WGS84/ETRS89 经纬度转换为 OSGB36 东距/北距。

var latLong = new LatitudeLongitude(52.6579785974266, 1.71605194571289);

var cartesian = Convert.ToCartesian (new Wgs84 (), latLong);
var bngCartesian = Transform.Etrs89ToOsgb36 (cartesian);
var bngEN = Convert.ToEastingNorthing (new Airy1830 (), new BritishNationalGrid (), bngCartesian);

OS 地图参考

地形测量局地图中使用的地图参考(东距/北距)分为 500 公里网格,这些网格又细分为 100 公里网格。这些网格有一个两位字母代码。第一个字母代表 500 公里网格,第二个字母代表其中的 100 公里网格。一个六位数的地图参考看起来像 TL123456,其中前两个字符代表地图上指示的 100 公里网格,六位数中的前三位代表东距,后三位代表北距。使用此系统意味着地图参考被引用为从网格原点的东距/北距(以米为单位)。一个 EastingNorthing 坐标对象,如上述转换返回的那样,可以使用 Osgb36 类转换为 OS 地图参考,如下所示

// Convert to Osgb36 coordinates by creating a new object passing  
// in the EastingNorthing object to the constructor.
var osgb36EN = new Osgb36(bngEN);
var mapReference = osgb36EN.MapReference;

高度

高度是一个复杂的话题,有很多测量方法。术语“海平面”经常在对话中使用,但海平面一直在变化,大块陆地对重力有影响,这会影响海洋。还要考虑一些地球最高的山脉可以在海底找到。正如我所说,这一切很快就变得非常棘手。

正如我们上面所看到的,我们在转换中使用椭球体来表示地球,这意味着当在 LatitudeLongitude 坐标对象中表示高度时,通常是椭球体高度。椭球体高度不是很有用,因为点 A 的椭球体高度可能大于点 B,而 A 却在 B 的下坡处。这是因为椭球体不是一个水平表面,因为它没有考虑地球表面存在的非规则性。

Image showing Geoid model compared to the ellipsoid.

水平面是一个在所有点都垂直于重力的表面。这意味着它必须考虑影响重力的各种凸起和凹陷。大地水准面是一个水平面,可用于测量高度。以这种方式测量的高度称为正高。大地水准面可以是全球性的(通常用大写“G”表示),也可以是特定国家或地区的局部大地水准面(通常用小写“g”表示)。

英国大陆的测绘局测绘使用新林测绘基准面 (ODN) 垂直坐标系。ODN 对应于 1915 年至 1921 年间在康沃尔纽林潮汐测量站测量的平均海平面。将此特定“平均海平面”作为零高度点的高度称为 ODN 高度。因此,ODN 是如上所述的局部大地水准面定义。ODN 高度用于所有英国大陆测绘局等高线、点高和基准点高。英国周围的许多岛屿都有自己的基于当地潮汐测量站的“平均海平面”(局部大地水准面)。

就此处详细介绍的从 WGS84 到 OSGB36 的转换示例而言,WGS 椭球体高度转换为类似 ODN 高度,精度在所有方向上约为 5 米。

获取更高精度

为了在将 ETRS89 (WGS84) 坐标转换为英国国家网格时获得更高的精度,需要使用地形测量局大地水准面模型 (OSGM02)。OSGM02 可以被认为是一张覆盖大不列颠、北爱尔兰和爱尔兰共和国的大橡胶片。对 OSGM02 中的数据应用特殊的转换,以从 ETRS89 和 OSGB36 进行转换。对于大不列颠,该转换称为 OSTN02。OSTN02 转换与活跃 GPS 网络站的 ETRS89 位置相结合,代表了 OSGB36 的官方定义,可以提供非常精确的转换。

这种“橡胶片”大地水准面实际上是一个查找表,可用于确定正高(大地水准面)高度,并通过 OSTN 转换,确定精确的东距和北距坐标。值得注意的是,北爱尔兰和爱尔兰共和国使用相同的大地水准面模型,但使用不同的转换 (OSi/OSNI),这至少目前不在本文的讨论范围之内。

GeoUK.OSTN NuGet 包扩展了 GeoUK 包,以包含 OSGM02/OSTN0 和 OSTN15 功能,并提供了一种简单的方法,可以精确地从 ETRS89 到 BNG 进行单向转换。可以使用以下包管理器命令将该包添加到项目中。该包依赖于 GeoUK 包,并将根据需要添加它。

> Install-Package GeoUK.OSTN

需要注意的是,GeoUK.OSTN 包包含 OSGM02 大地水准面和 OSTN02 OSTN15 转换,因此相当大,此外,转换速度将比使用上面示例中使用的赫尔默特转换慢。

下面的示例将 ETRS89 经纬度/椭球体高度转换为 BNG 东距和北距以及 ODN 高度,精度在 10 厘米左右。

var latLong = new LatitudeLongitude(52.658007833, 1.716073973, 108.05);
var bng = GeoUK.OSTN.Transform.Etrs89ToOsgb (latLong);  

摘要

本文讨论了将 GPS 坐标转换为英国国家网格时需要考虑的各种元素。演示了赫尔默特转换,其精度在所有方向上约为 5 米,还展示了一种更精确的方法,该方法遵循地形测量局推荐的方法,使用 OSGM02 大地水准面模型。

该库通过 NuGet 免费提供,主要目的是简化一个复杂的难题。

尽情享用!

© . All rights reserved.