2012-05-14 9 views
1

Вот код, который я начал писать, проекция Меркатора основана на 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, но никуда не мог добраться. Особенно я не понимаю гудерманновскую (и обратную) функцию, константы DEGREES_PER_RADIAN и RADIANS_PER_DEGREE, и как я должен преобразовать значение y в широту, чтобы вызвать функцию GudermannianInv().

РЕДАКТИРОВАТЬ: Вот как я пытался, как сделать обратную проекцию:

Запуск с yScaled (параметр у в функции FromMercator):

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

ответ

0

Вот несколько битов, что вы ищете:

  1. radians * degrees/radians == degrees: degrees_per_radian это просто способ выражения degrees/radians в «английском», а не в «математике». radians_per_degree остается как упражнение для читателя. Таким образом, эти две константы представляют собой числа, которые вы используете при преобразовании между углами в градусах и углах в радианах.

  2. Рассматривая код, который вы опубликовали, у вас есть линии для преобразования latRadians в y. Для реализации этих операций просто реализовать код. Вам нужно «un'-scale» и «un'-transform» yScaled. Например, обработка линии (часть):

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

    как математическое уравнение, вам нужно решить для yTransformed с точки зрения yScaled.

  3. Что касается Гудерманна, то вопрос, который вы ссылаетесь, реализует это в одной строке кода и обратном гадерманском в 3 строках. Гудерманн - это просто способ преобразования кругового измерения (например, измерения в градусах или радиан) в линейное измерение (например, один в сантиметрах на диаграмме, которая будет опубликована на бумаге). В частности, и здесь уместно, то Gudermannian преобразует широту в линейное расстояние от 0.

EDIT

ОК, так что выглядит немного ближе, в исходном коде вы превращаете широту от углового измерения в линейную с линией:

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

Я думаю, что вы, вероятно, следует заменить это призыв к обратному Gudermannian, как указано в ответе на вопрос, который вы ссылку. Я подозреваю, что ваша домашняя трансформация натыкается на экстремальные точки в функциях tan/arctan. Тогда вы, конечно, использовали бы прямой гудерманн в процессе не-преобразования.

+0

Так что DEGREES_PER_RADIAN - 360/(2 * Math.PI) и RADIANS_PER_DEGREE (2 * Math.PI)/360? – DavWEB

+0

Ну, я всегда с '180/pi' и' pi/180', но да, у вас есть значения правильно. –

+0

Ваш второй пункт - это именно то, что я пробовал в первую очередь. «Не-масштабная часть не была сложной. Но потом я боролся с частью «un'-transform», я думаю, потому что это не сработало, как ожидалось. Я уточню свой вопрос, что именно я получил. – DavWEB

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