2009-07-22 94 views
8

我有一個墨卡託投影映射爲JPEG,我想知道如何將給定的x,y座標與其經度和緯度關聯。我看過Gudermannian函數,但我真的不明白如何使用該函數並應用它。也就是說,它期望什麼輸入?我發現的實現(JavaScript)似乎需要-PI和PI之間的範圍,但是我的y值(以像素爲單位)和該範圍之間的相關性如何?如何在墨卡托地圖(JPEG)上從x,y獲取緯度和經度?

此外,我發現這個函數需要一個緯度並返回谷歌地圖,也使用墨卡託瓷磚。似乎如果我知道如何反轉這個功能,我會非常接近我的答案。

/*<summary>Get the vertical tile number from a latitude 
using Mercator projection formula</summary>*/ 

    private int getMercatorLatitude(double lati) 
    { 
     double maxlat = Math.PI; 

     double lat = lati; 

     if (lat > 90) lat = lat - 180; 
     if (lat < -90) lat = lat + 180; 

     // conversion degre=>radians 
     double phi = Math.PI * lat/180; 

     double res; 
     //double temp = Math.Tan(Math.PI/4 - phi/2); 
     //res = Math.Log(temp); 
     res = 0.5 * Math.Log((1 + Math.Sin(phi))/(1 - Math.Sin(phi))); 
     double maxTileY = Math.Pow(2, zoom); 
     int result = (int)(((1 - res/maxlat)/2) * (maxTileY)); 

     return (result); 
    } 
+0

如果我沒有記錯,谷歌採用的是方形投影,而不是墨卡託。 – 2009-07-22 15:23:41

+0

Virtual Earth和Google都使用墨卡託。 – 2009-07-22 15:28:14

回答

7

這裏有一些代碼給你...讓我知道如果你需要更多的解釋。

/// <summary> 
    /// Calculates the Y-value (inverse Gudermannian function) for a latitude. 
    /// <para><see cref="http://en.wikipedia.org/wiki/Gudermannian_function"/></para> 
    /// </summary> 
    /// <param name="latitude">The latitude in degrees to use for calculating the Y-value.</param> 
    /// <returns>The Y-value for the given latitude.</returns> 
    public static double GudermannianInv(double latitude) 
    { 
     double sign = Math.Sign(latitude); 
     double sin = Math.Sin(latitude * RADIANS_PER_DEGREE * sign); 
     return sign * (Math.Log((1.0 + sin)/(1.0 - sin))/2.0); 
    } 

    /// <summary> 
    /// Returns the Latitude in degrees for a given Y. 
    /// </summary> 
    /// <param name="y">Y is in the range of +PI to -PI.</param> 
    /// <returns>Latitude in degrees.</returns> 
    public static double Gudermannian(double y) 
    { 
     return Math.Atan(Math.Sinh(y)) * DEGREES_PER_RADIAN; 
    } 
0

進行逆時一個重要的注意的是,有作爲「墨卡托地圖」沒有這樣的事情是與其他大多數地圖投影的情況。存在的每個墨卡托地圖根據輸入的phi值而不同。根據維基百科,谷歌使用85.051129,其他地圖提供商使用85.05113。因此,Gudermannian的輸入值必須根據例如GudermannianInv(85.05113)。

1

Erich Mirabal's answer是完全正確的(如果不是完全的話)。

我剛剛使用'理論上的256x256墨卡託瓷磚'(谷歌單一瓷磚版本的世界地圖)對它進行了測試。

tile0

這裏有一個小更多的代碼(JavaScript的,但易於遵循)澄清。

我住在澳大利亞,緯度約爲-33°。

convertRange(
    GudermannianInv(-33), 
    [Math.PI, - Math.PI], 
    [0, 256] 
); 

152.88327883810192

如果算上152個像素從瓦的頂部向下,你會發現澳大利亞。 我也通過將結果與已知的良好函數進行比較來驗證此答案是正確的。

可以肯定的,我們可以扭轉計算:

Gudermannian(
    convertRange(
     152.88, 
     [0, 256], 
     [Math.PI, - Math.PI] 
)); 

現在我們又回到-32.99613291758226

棘手的部分不處於古德曼函數,但在兩個尺度之間的轉換。

幸運的是,是相當懶了,恨這些類型的結垢問題,我已經有了一個小功能來做到這一點凌亂的轉換我。

/** 
    * convert number from _n_ of r1[0] .. r1[1] to _n_ of r2[0] .. r2[1] 
    * @example `convertRange(5, [0, 10], [0, 100]) === 50` 
    * 
    * @param {number} value 
    * @param {array<number>} r1 old range 
    * @param {array<number>} r2 new range 
    * @returns {number} value adjusted for new range 
    */ 
    function convertRange(value, r1, r2) { 
     return (value - r1[0]) 
      * (r2[1] - r2[0]) 
      /(r1[1] - r1[0]) 
      + r2[0]; 
    } 

和JavaScript版本的原有功能自然是:

function Gudermannian(y) { 
    return Math.atan(Math.sinh(y)) * (180/Math.PI) 
} 

function GudermannianInv(latitude) 
{ 
    var sign = Math.sign(latitude); 
    var sin = Math.sin(
          latitude 
         * (Math.PI/180) 
         * sign 
    ); 
    return sign * (
     Math.log(
      (1 + sin)/(1 - sin) 
     )/2 
    ); 
}