1. Overview
1.概述
When implementing applications that use maps, we will typically run into the problem of coordinate conversion. Most of the time, we need to convert latitude and longitude to a 2D point to display. Fortunately, to solve this problem, we can utilize the formulas of the Mercator projection.
在实现使用地图的应用程序时,我们通常会遇到坐标转换的问题。大多数时候,我们需要将经纬度转换为一个二维点来显示。幸运的是,为了解决这个问题,我们可以利用墨卡托投影的公式。
In this tutorial, we’ll cover the Mercator Projection and will learn how to implement its two variants.
在本教程中,我们将介绍墨卡托投影,并将学习如何实现其两个变体。
2. Mercator Projection
2.墨卡托投影法
The Mercator projection is a map projection introduced by the Flemish cartographer Gerardus Mercator in 1569. A map projection converts latitude and longitude coordinates on the Earth to a point on a flat surface. In other words, it translates a point on the surface of the earth to a point on a flat map.
墨卡托投影是由佛兰德制图师Gerardus Mercator在1569年推出的一种地图投影。地图投影将地球上的经纬度坐标转换为平面上的一个点。换句话说,它将地球表面的一个点转换为平面地图上的一个点。
There are two ways of implementing the Mercator projection. The pseudo Mercator projection treats the Earth as a sphere. The true Mercator projection models the Earth as an ellipsoid. We will implement both versions.
有两种实现墨卡托投影的方法。伪墨卡托投影将地球视为一个球体。真正的墨卡托投影把地球当作一个椭圆体。我们将实现这两个版本。
Let’s start with a base class for both Mercator projection implementations:
让我们从两个墨卡托投影实现的基类开始。
abstract class Mercator {
final static double RADIUS_MAJOR = 6378137.0;
final static double RADIUS_MINOR = 6356752.3142;
abstract double yAxisProjection(double input);
abstract double xAxisProjection(double input);
}
This class also provides the major and the minor radius of Earth measured in meters. It is well known that Earth is not exactly a sphere. For that reason, we need two radiuses. Firstly, the major radius is the distance from the center of the earth to the equator. Secondly, the minor radius is the distance from the center of the earth to the north and south poles.
本课还提供了地球的大半径和小半径,单位是米。众所周知,地球不完全是一个球体。由于这个原因,我们需要两个半径。首先,大半径是指从地球中心到赤道的距离。其次,小半径是指从地球中心到南北两极的距离。
2.1. Spherical Mercator Projection
2.1.球形墨卡托投影
The pseudo-projection model treats the earth as a sphere. In contrast to the elliptical projection where the Earth would be projected on a more accurate shape. This approach allows us a quick estimation to the more precise, but computational heavier elliptical projection. As a result of that, the direct measurements of distances in this projection will be approximate.
伪投射模型将地球视为一个球体。与椭圆投影相反,地球将被投影在一个更精确的形状上。这种方法允许我们对更精确的、但计算量更大的椭圆形的投影。因此,在这个投影中对距离的直接测量将是近似的。
Furthermore, the proportions of the shapes on the map will marginally alter. As a result of that latitude and ratios of shapes of objects on the map like countries, lakes, rivers, etc. are not precisely preserved.
此外,地图上的形状比例也会略有改变。作为一个结果,纬度和地图上的物体形状比例,如国家、湖泊、河流等,都没有精确地保留。
This is also called the Web Mercator projection – commonly used in web applications including Google Maps.
这也被称为网络墨卡托投影 – 常用于包括谷歌地图在内的网络应用。
Let’s implement this approach:
让我们来实施这种方法。
public class SphericalMercator extends Mercator {
@Override
double xAxisProjection(double input) {
return Math.toRadians(input) * RADIUS_MAJOR;
}
@Override
double yAxisProjection(double input) {
return Math.log(Math.tan(Math.PI / 4 + Math.toRadians(input) / 2)) * RADIUS_MAJOR;
}
}
The first thing to note on this approach is the fact that this approach represents the radius of the earth by one constant and not two as it really is. Secondly, we can see that we have implemented two functions to use for converting to x-axis projection and y-axis projection. In the class above we have used Math library provided by java to help us make our code simpler.
关于这种方法,首先要注意的是,这种方法用一个常数来表示地球的半径,而不是真正的两个。 其次,我们可以看到,我们已经实现了两个函数,用于转换为x轴投影和y轴投影。在上面的类中,我们使用了java提供的Math库来帮助我们使代码更简单。
Let’s test a simple conversion:
让我们来测试一个简单的转换。
Assert.assertEquals(2449028.7974520186, sphericalMercator.xAxisProjection(22));
Assert.assertEquals(5465442.183322753, sphericalMercator.yAxisProjection(44));
It is worth noting that this projection will map points into a bounding box (left, bottom, right, top) of (-20037508.34, -23810769.32, 20037508.34, 23810769.32).
值得注意的是,这个投影将把点映射到一个(左、下、右、上)的边界框中(-20037508.34, -23810769.32, 20037508.34, 23810769.32)。
2.2. Elliptical Mercator Projection
2.2.椭圆墨卡托投影
The true projection models the earth as an ellipsoid. This projection gives accurate ratios for objects anywhere on Earth. Certainly, it respects objects on the map but not 100% accurate. However, this approach is not the most frequently used because it is computationally complex.
真正的投影是将地球模拟成一个椭圆体。这种投影给出了精确的比率对于地球上任何地方的物体。当然,它尊重地图上的物体,但不是100%准确。然而,这种方法不是最经常使用的,因为它在计算上很复杂。
Let’s implement this approach:
让我们来实施这种方法。
class EllipticalMercator extends Mercator {
@Override
double yAxisProjection(double input) {
input = Math.min(Math.max(input, -89.5), 89.5);
double earthDimensionalRateNormalized = 1.0 - Math.pow(RADIUS_MINOR / RADIUS_MAJOR, 2);
double inputOnEarthProj = Math.sqrt(earthDimensionalRateNormalized) *
Math.sin( Math.toRadians(input));
inputOnEarthProj = Math.pow(((1.0 - inputOnEarthProj) / (1.0+inputOnEarthProj)),
0.5 * Math.sqrt(earthDimensionalRateNormalized));
double inputOnEarthProjNormalized =
Math.tan(0.5 * ((Math.PI * 0.5) - Math.toRadians(input))) / inputOnEarthProj;
return (-1) * RADIUS_MAJOR * Math.log(inputOnEarthProjNormalized);
}
@Override
double xAxisProjection(double input) {
return RADIUS_MAJOR * Math.toRadians(input);
}
}
Above we can see how complex this approach is regarding the projection on the y-axis. This is because it should take into consideration the non-round earth shape. Although the true Mercator approach seems complex, is more accurate than the spherical approach as it uses to radius for representing earth one minor and one major.
上面我们可以看到,这种方法在Y轴上的投影是多么复杂。这是因为它应该考虑到非圆形的地球形状。虽然真正的墨卡托方法看起来很复杂,但它比球面方法更准确,因为它使用半径来代表地球,一个小半径和一个大半径。
Let’s test a simple conversion:
让我们来测试一个简单的转换。
Assert.assertEquals(2449028.7974520186, ellipticalMercator.xAxisProjection(22));
Assert.assertEquals(5435749.887511954, ellipticalMercator.yAxisProjection(44));
This projection will map points into a bounding box of (-20037508.34, -34619289.37, 20037508.34, 34619289.37).
这个投影将把点映射到一个(-20037508.34, -34619289.37, 20037508.34, 34619289.37)的边界框内。
3. Conclusion
3.结论
If we need to convert latitude and longitude coordinates onto a 2D surface, we can use the Mercator projection. Depending on the accuracy we need for our implementation, we can use the spherical or elliptical approach.
如果我们需要将经纬度坐标转换到一个二维平面上,我们可以使用墨卡托投影法。根据我们的实现所需要的精度,我们可以使用球面或椭圆的方法。
As always, we can find the code of this article over on GitHub.
一如既往,我们可以在GitHub上找到本文的代码over。