2009-07-22 9 views
8

У меня есть проекционная карта Меркатора как JPEG, и я хотел бы знать, как связать заданную координату x, y с ее широтой и долготой. Я посмотрел на функцию Гудерманна, но я, честно говоря, не понимаю, как принять эту функцию и применить ее. А именно, какой вклад он ожидает? Реализация, которую я нашел (JavaScript), кажется, занимает диапазон между -PI и PI, но какова корреляция между моим значением y в пикселях и этим диапазоном?Как я могу получить широту, долготу от x, y на карте Меркатора (JPEG)?

Кроме того, я нашел эту функцию, которая занимает широту и возвращает плитку для Карт Google, в которой также используется Mercator. Казалось бы, если бы я знал, как отменить эту функцию, я был бы очень близок к тому, чтобы ответить.

/*<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

Если я правильно помню, Google использует эквидистантную проекцию, а не Меркатора. –

+0

Как Virtual Earth, так и Google используют Mercator. –

+1

Кроме того, максимальная полезная широта при использовании Меркатора не составляет + -90 градусов - это примерно + -85.05112878 градусов. Величина - бесконечность на полюсах, поэтому вам нужно закрыть ее и игнорировать полюса. –

ответ

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

Спасибо! Попробуйте это прямо сейчас. –

+1

Итак, если у меня есть изображение карты меркатора размером 1588 пикселей, и я хочу знать широту, где y = 677, я бы вычислил 677 с точки зрения + PI -PI и назвал Gudermannian (y_in_terms_of_pi)? Я понимаю, что это неправильно, но вы можете видеть, где я мысленно здесь ... –

+0

Например, на карте мерцатора размером 1588 пикселов 30,0N составляет 615 пикселей сверху. Но если я выражаю 615 в терминах линейного диапазона от PI (0) до -PI (1588), я получаю 615 -> 0,70824318. И назовение вышеупомянутого Гудерманна (0.70824318) дает 37.5587, а не 30.0. –

2

Google и т.д., используйте «сферический Меркатор», проекция Меркатора с использованием сферической модели Земли, а не медленнее и более сложных эллиптических уравнений.

Преобразования доступны как часть кода OpenLayers:

http://docs.openlayers.org/library/spherical_mercator.html

0

Важное замечание при выполнении обратного является то, что не существует такого понятия, как «на Меркатор карты», как в случае с большинством других картографических проекций. Каждая карта меркатора существует в зависимости от входного значения phi. Согласно wikipedia google использует 85.051129, а другие поставщики карт используют 85.05113. Поэтому входные значения для гудерманна должны быть масштабированы на основе, например, 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 
    ); 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^