Расчёт плоской проекции из широты и долготы (EPSG:3857)
Получаю данные широты и долготы с OSM, решил нарисовать на плоскости, предварительно возводя в 3 степень, возле себя всё хорошо, за сотни километров - карта начинает искажаться. Далее я начал искать формулы для проекции на плоскость и обратно, вот что нашёл и подстроил под свой проект:
const float POS_CONST = 20037508.34f; // Эта константа в итоге должна перевести градусы в метры
const float ZOOM_CONST = 0.005f; // Этой константой я масштабирую точки, чтобы "сжать" плоскую карту до нужного мне размера
public static float GetUnityPointX(float lon) // Получение пространственной координаты по широте
{
return (lon * POS_CONST * ZOOM_CONST / 180f);
}
public static float GetUnityPointY(float lat) // Получение пространственной координаты по долготе
{
var y = Mathf.Log(Mathf.Tan((90 + lat) * Mathf.PI / 360)) / (Mathf.PI / 180);
return (y * POS_CONST * ZOOM_CONST / 180f);
}
public static float GetOsmPointX(float x) // Получение OSM широты по мировой координате
{
return x / (Mathf.PI / 180.0f) / POS_CONST / ZOOM_CONST;
}
public static float GetOsmPointY(float y) // Получение OSM долготы по мировой координате
{
return (2f * Mathf.Atan(Mathf.Exp(y / POS_CONST / ZOOM_CONST)) - Mathf.PI / 2f) / (Mathf.PI / 180f);
}
Формулы взял отсюда: https://gist.github.com/springmeyer/871897
В итоге, картинка выравнилась по X (ну, потому что избавились от степенной зависимости), и немного выравнилась по Y, но, искажения остались.
Что происходит теперь - я делю мир по высоте на равные части (делю градусы на константу), далее перевожу градусы этих точек в мировые координаты. (деля мир на константу по X и на константу по Y я получаю сетку из прямоугольников одинаковой длины - такой прямоугольник существует в градусах, так же, такой прямоугольник я рассчитываю в координатах мира в виде плоской проекции).
Возьмём за размер прямоугольника некий 1 градус. Это значит что в любой точке земли может быть прямоугольник размера 1x1 виртуальный градус. Вот я нарисую прямоугольник и его проекцию на плоскость:

Справа этот прямоугольник в градусах, слева после того как я спроецировал его на плоскость по формулам.
Далее, я начинаю двигать прямоугольник в градусах ближе к полюсу, вот что в итоге получается:

Обращу внимание ещё раз - размер прямоугольников одинаков в градусах, но отличается после того как я выполняю проекцию.
Вот проекция Меркатора:
Здесь так же видно что у экватора прямоугольники более менее одинаковы, но чем ближе к полюсам, тем они сильнее вытягиваются, ровно то что происходит у меня.
- Правильно ли я вообще понимаю концепцию широты, долготы?
- Есть ли алгоритмы проекции на плоскость, которые бы гарантировали мне что взятый интервал в градусах по широте будет всегда одинаков, так же как и получаемый в расчётах интервал между точками в мире? И что в моём алгоритме неправильно?
Ответы (1 шт):
В общем перенесу итоги обсуждений здесь в ответе. Начну с ссылок списков проекций, где надо было искать в первую очередь. То есть, все проекции уже давно спроектированы, изобретать свою формулу надо после изучения всех существующих:
- Список проекций из документации
Proj4(на английском языке). - Список проекций на Википедии (на русском языке).
Из обсуждений выяснилось что автор изначально искал Равновеликую цилиндрическую проекцию Ламберта.
Но, как я предполагал изначально, автору не нужны были все эти проекции, если хорошо подумать. В общем, конкретно в данной ситуации, нужный функционал полностью реализуется библиотекой коммерческого проекта mapbox.com. У mapbox есть множество опенсурсных проектов. Некоторые из проектов задевают какие-то проприетарные сервисы.


