如何进行逆墨卡托投影

时间:2012-05-14 08:54:15

标签: c# math geospatial latitude-longitude mercator

以下是我开始编写的一些代码,Mercator投影基于this answer

using System;
using System.Drawing;

namespace CoordinatesTool
{
    public class GeoPoint
    {
        public double Longitude { get; set; }
        public double Latitude { get; set; }

        public string ToString()
        {
            return Latitude + "," + Longitude;
        }

        public PointF ToMercator(int width, int height)
        {
            var x = (float)((Longitude + 180) * width / 360);

            var latRadians = Latitude * Math.PI / 180;
            var yTransformed = Math.Log(Math.Tan((latRadians / 2) + (Math.PI / 4)));
            var yScaled = (float)((height / 2.0) - (width * yTransformed / (2 * Math.PI)));

            return new PointF(x, yScaled);
        }

        public static GeoPoint FromMercator(PointF point, int width, int height)
        {
            return FromMercator(point.X, point.Y, width, height);
        }

        public static GeoPoint FromMercator(double x, double y, int width, int height)
        {
            // No clue what to do here
        }
    }
}

我的目标是在WinForms应用程序中使用此实用程序类。我在这张地图上使用它: http://en.wikipedia.org/wiki/File:Mercator-projection.jpg(宽度:2048,身高:1588)。

墨卡托反演工作得很好(但我怀疑它在北极/南极地区不太准确)。

但逆墨卡托投影确实让我感到困惑。我玩了another question中提出的解决方案,但无法到达任何地方。特别是我不理解Gudermannian(和逆)函数,DEGREES_PER_RADIAN和RADIANS_PER_DEGREE常量,以及如何将y值转换为纬度以调用GudermannianInv()函数。

编辑:以下是我尝试如何进行反投影的方法:

从yScaled开始(FromMercator函数中的参数y):

var yTransformed = 2 * Math.PI * (height / 2.0 - yScaled) / width;
var latRadians = Math.Arctan(Math.Pow(Math.E, yTransformed) - Math.PI / 4) / 2;
// ...

1 个答案:

答案 0 :(得分:1)

以下是您所寻求的一些内容:

  1. radians * degrees/radians == degrees:degrees_per_radian只是一种在英语'中表达degrees/radians的方式。而不是数学'。 radians_per_degree留给读者练习。因此,这两个常量表示在以弧度表示角度和角度之间转换时使用的数字。

  2. 查看您发布的代码,您可以将latRadians转换为y。实现代码以反转这些操作看起来很简单。您需要'取消'取消' -transform' yScaled'。例如,处理线(部分):

    yScaled = ((height / 2.0) - (width * yTransformed / (2 * Math.PI)))

    作为一个数学方程式,您需要根据yTransformed求解yScaled

  3. 至于Gudermannian,你提到的问题在一行代码和3行反Gudermannian中实现。 Gudermannian只是一种将圆形测量(例如度数或弧度测量)转换为线性测量的方法(例如图表上的一厘米,将在纸上发布)。特别是在这里,Gudermannian将纬度转换为0的线性距离。

  4. 修改

    好的,所以看得更近一点,在原始代码中,您将纬度从角度测量转换为线性测量:

    yTransformed = Math.Log(Math.Tan((latRadians / 2) + (Math.PI / 4)))
    

    我认为您可能应该用对Gudermannian逆的调用来替换它,如您链接到的问题的答案中所示。我怀疑你的家庭酿造转型在tan / arctan功能的极端点上磕磕绊绊。然后,您将使用直接的Gudermannian进行非转换。