Як я можу зробити полілінійну обгортання по всьому світу?


14

Я використовую картки з листівками, щоб створити подання навколосвітнього виклику. Я хотів би додати полілінію, яка прямує на схід від Токіо, а потім з’являється на карті на захід від Південної Америки, але натомість я отримую лінію, яка перетинає карту у зворотному напрямку (див. Жовту лінію).

введіть тут опис зображення

Я думаю, це, мабуть, пов’язано з дателінами та / або системами координат, але я трохи ескізний у деталях. Хтось може пояснити теорію, що потрібно зробити, щоб це працювало? Я використовую прискіпливу проекцію Nasa:

var bluemarble = new L.TileLayer.WMS("http://demo.opengeo.org/geoserver/wms", {
layers: 'bluemarble',
attribution: "Data © NASA Blue Marble, image service by OpenGeo",
minZoom: 2,
maxZoom: 5
});

2
Вам потрібно розбити полілінію на меридіані + -180 градусів. Для цього потрібно знайти широту, на якій поліліній перетинає меридіан. У вашому ГІС, ймовірно, є методи, які дозволяють зробити пробивні. Якщо ні, то просте рішення може бути отримане з коду, показаного у пов'язаній нитці . Чи можете ви виконати такий код на своїй платформі?
whuber

Я погоджуюся з whuber. Мені довелося виконати подібне завдання при перетині багатокутників + - 180. Вам потрібно розбиватися на кілька поліліній / багатокутників щоразу, коли перетинаєте + -180.
Стів

Відповіді:


13

Вам потрібно розбити полілінію на меридіані + -180 градусів. Для цього потрібно знайти широту, на якій поліліній перетинає меридіан. У вашому ГІС, ймовірно, є методи, які дозволяють зробити злам. Якщо ні, то просте рішення може бути отримане з коду, показаного у пов'язаній нитці . Ось кілька деталей.

  • Полілінія представлена ​​у вигляді послідовності вершин , кожна з яких дається у (лат., Лон) формі, з -180 <= lon <= 180. Потрібно перевірити кожну послідовну пару, щоб побачити, чи перетинає він меридіан + -180. Існує швидкий тест: якщо абсолютне значення різниці довжин становить 180 або більше, відбувається перетин.

  • У межах кожного відрізка (lat0, lon0) -> (lat1, lon1), який перетинає меридіан + -180, потрібно розбити полілінію на дві частини, де вона перетинається.

Ключовим є знаходження широти точки перелому з розумною точністю. Це найпростіше зробити за допомогою сферичної моделі землі: похибка (порівняно з більш точною еліпсоїдальною моделлю) буде занадто малою, щоб помітити.

Нехай розглянутий відрізок переходить від точки 0 у (lat0, lon0) до точки 1 у (lat1, lon1). Точку розриву можна знайти, провівши відрізок прямої в 3D між двома точками, представленими на декартових координатах, і знайти, де координата y дорівнює нулю. У декартові координати є

(x0, y0, z0) = (cos(lon0)*sin(lat0), sin(lon0)*sin(lat0), cos(lat0))

і подібний вираз, що дає (x1, y1, z1) для точки 1. Розв’яжіть рівняння

t * y0 + (1-t) * y1 = 0

для т; тобто,

t = y1 / (y1 - y0).

Отже, координати перетину є

(x, y, z) = (t * x0 + (1-t) * x1, 0, t * z0 + (1-t) * z1)

Ця точка (що лежить під земною поверхнею десь під меридіаном + -180) має широту, рівну

lat2 = ATan(z/x).

Точка розриву повинна бути представлена ​​двома способами. Приєднавши його після (lat0, lon0), щоб закінчити першу частину розбитої полілінії, використовуйте (lat2, -180), якщо lon0 є негативною, а іншим чином використовуйте (lat2, 180). Приєднуючи її раніше (lat1, lon1), щоб розпочати другу частину розбитої полілінії, дотримуйтесь аналогічного правила.

У виняткових випадках одна або обидві точки 0 і точки 1 можуть знаходитись на меридіані + -180. Дотримуючись цієї процедури, ви змусите розмістити відрізок нульової довжини на одній із створених вами поліліній. Якщо це може спричинити проблеми з ГІС, протестуйте цей стан.

Зауважте, що полілінія може перетинати цей меридіан не один раз. Тому, знайшовши перший розрив і розбивши поліліній на дві частини, потрібно обробити другу частину таким же чином.


1
Що сказав Уубер, це нормально, але я думаю, що в наступному реченні є помилка друку:> Коли ви додаєте його після (lat0, lon0), щоб закінчити першу частину розбитої> полілінії, використовуйте (lat2, -180), якщо lat0 від'ємний і в іншому випадку використовуйте (lat2, 180). Я думаю, що це повинно бути:> використовувати (lat2, -180), якщо lon0 є негативним, а в іншому випадку - (lat2, 180)
Georgi

@Georgi Дякую за те, що зловив це; Я думаю, ти маєш рацію, і я внесу зміни.
whuber

Мені довелося реалізувати це на Leaflet.js, ось мій код: gist.github.com/mikeatlas/0b69b354a8d713989147
Майк Атлас

Дякую, @Mike. Я люблю зигзагоподібні ілюстрації: саме такі обставини я передбачав, коли я писав цю відповідь. Якщо ви хочете по-справжньому суворий тест, подивіться, що відбувається з полілінією, яка проходить по самому меридіану + -180 градусів (і перетинає обидва полюси)!
whuber

@whuber Мені може знадобитися спробувати це: / Буде публікувати результати
Майк Атлас

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.