Обчислення відстані між точкою та віртуальною лінією у два лат / фунги


14

Будь ласка, зверніться до прикладу та відповідного зображення.

Я хотів би домогтися наступного: забезпечити два місця (лат / LNG), які показані нижче як A і B . З цього виводиться віртуальна лінія, а потім обчислюється відстань між цією лінією та С (у будь-якому вимірі).

малюнок

Зараз я досяг цього в API Карт Google v3, але хотів би також мати можливість виконувати це за кулісами на моїй мові на вибір. Будь-які поради / ідеї будуть дуже вдячні!



@Kirk, Ні, AB - це просто пряма лінія
В'язень

@Michael, це цікавий момент. Мені доведеться поглянути на це!
В’язень

@Prisoner @Kirk Буквально під земною поверхнею буде проходити "пряма лінія". Взагалі його радіальна проекція назад на поверхню справді буде сегментом великого кола (використовуючи сферичну модель Землі).
whuber

1
@Prisoner Це надзвичайно корисна додаткова інформація! Так, ви праві. Вам все одно доведеться компенсувати той факт, що використання (лат., Лон) різнице викривляє відстані схід-захід порівняно з північ-південь. Як радить @Jose, спроектуйте координати. Це може бути настільки просто, як попередньо помножити довготи на косинус середньої широти, а потім зробити вигляд, що ви знаходитесь на площині Евкліда.
whuber

Відповіді:


6
def get_perp( X1, Y1, X2, Y2, X3, Y3):
    """************************************************************************************************ 
    Purpose - X1,Y1,X2,Y2 = Two points representing the ends of the line segment
              X3,Y3 = The offset point 
    'Returns - X4,Y4 = Returns the Point on the line perpendicular to the offset or None if no such
                        point exists
    '************************************************************************************************ """
    XX = X2 - X1 
    YY = Y2 - Y1 
    ShortestLength = ((XX * (X3 - X1)) + (YY * (Y3 - Y1))) / ((XX * XX) + (YY * YY)) 
    X4 = X1 + XX * ShortestLength 
    Y4 = Y1 + YY * ShortestLength
    if X4 < X2 and X4 > X1 and Y4 < Y2 and Y4 > Y1:
        return X4,Y4
    return None

Найкоротша довжина - це потрібна вам відстань, якщо я не помиляюся?


Так, я шукаю найкоротшу відстань від С до відрізка лінії. Це обчислює ця математика?
В’язень

1
Це справді спрацювало чудово, я передав три пункти (A, B, C) у наступному: i.imgur.com/bK9oB.jpg, і він повернувся з lat / lng X. Чудова робота!
В’язень

1
@Hairy, Останнє, як би я міг змінити це, щоб перейти до найближчої точки (не просто лінії), тож якби я поставив це повз точку приєднання лінії, як я можу змусити її перевірити відстань до бал?
В'язень

1
@Hairy Добрий початок, але, здається, занадто часто цей код повертається, Noneколи існує законне рішення. Проблема полягає в тому, що останні умовні умови передбачають X1 <X2 та Y1 <Y2, що не завжди може бути впевненим. Потрібен кращий тест на взаємозв'язок.
whuber

1
@Hairy Це здається, що цей обмін між вами та @prisoner був результативним. Я хотів би підкреслити, що я не мав нічого спільного з (або навіть будь-яким контролем над) будь-якими змінами в голосуванні або пунктами, які, можливо, сталися, і що мій коментар мав на меті лише допомогти вам покращити вашу відповідь.
whuber

11

Можливо, я роблю це занадто складно, але те, що ти хочеш, - це відстань від точки до лінії. Це відстань від точки вздовж АВ, яка пов'язує АВ із С з прямою, ортогональною до АВ. Цей вектор, перпендикулярний AB, задається через

v=[x2-x1, -(y2-y1)] # Point A is [x1,y1] Point B is [x2,y2]

(Я використовував квадратні дужки для визначення вектора або двоелементного масиву). Відстань між C [xp, yp] і точкою A дорівнює

u=[x1-xp, y1-xp]

Відстань між прямою та С - це просто проекція u на v. Якщо припустити mod (v) = 1 (просто нормалізувати його), то

distance = u*v = abs( (x2-x1)*(y1-yp) - (x1-xp)*(y2-y1) )

Єдине ускладнення полягає в тому, що ви, мабуть, хочете переконатися, що ваші координати не є WGS84 lat / log парами, а проектуються (або використовують геодезичні координати). Для цього можна використовувати OGR або Proj4 .


3
+ декілька мільйонів псевдоточок за невикористання тригонометричних функцій, до речі. Занадто багато людей витягують ArcTan, коли вони повинні дивитись на це: en.wikipedia.org/wiki/Dot_product
Трава

@Jose, дякую за відповідь! Я використовую lat / long від API google maps. Математична частина для мене зовсім нова, тому я підкажу і побачу, що я можу придумати. Якісь поради з математикою? Наприклад, [x2-x1, - (y2-y1)], що це означає?
В'язень

Я додав для цього коротку редагування. В основному, це позначення масиву, але якщо ви зберігаєте свої координати у змінних x1, x2, y1, y2 та xp, yp, вам потрібно лише написати праву частину останнього наданого рівняння. Це в значній мірі код C, Java, JS, Python і т.д. :)
Хосе

1
@Jose Ви обчислюєте відстань від C до лінії AB. Виходячи з рисунка, я вважаю, що ОП хоче відстань від C до відрізка AB. Для цього потрібна додаткова робота, щоб перевірити, чи лежить проекція С на пряму АВ між А і В чи ні. В останньому випадку використовуйте коротший з двох довжин CA і CB.
whuber

1
@Prisoner Основна відмінність полягає в тому, що лінія простягається назавжди (вона визначається лише вектором напрямку і точкою, або двома точками), тоді як відрізок між A і B - це біт нескінченної лінії, що йде між A і Б (має кінцеву довжину)
Хосе

4

Будучи трохи протилежною до всієї цієї математики, я б підійшов до неї з іншого боку. Я б зробив це "фактичним" рядком, а не віртуальною лінією, а потім використовував би наявні інструменти.

Якщо A і B мають атрибут, ви можете з’єднати їх, намалювавши лінію (у GIS Kosmo є інструмент, який створюватиме рядки з точок, і я вважаю, що для цього також існує плагін QGIS). Після того, як у вас з'являться лінії, функція "біля" на точковому шарі "С" дасть вам відстань до лінії. Нехай програмне забезпечення займається математикою для вас!


Дякую за коментар, але Волосатий придумав козири на цьому!
В'язень

1
(+1) Ви відзначаєте чудову крапку. Алгоритми обчислювальної геометрії, як відомо, є складними, аби на практиці вийти абсолютно правильно (як ми бачимо з усього запропонованого коду, який є корисним та ілюстративним, але ще не працює повністю). Використання ГІС-процедури високого рівня часто є хорошим способом запевнити, що ви отримаєте відповідь, яку очікуєте, і що вона правильна (за умови довіри до свого ГІС ;-)
whuber

1

Якщо ви використовували Java на android, це лише один рядок з функцією бібліотеки

import static com.google.maps.android.PolyUtil.distanceToLine;

distanceToLine:

public static double distanceToLine(LatLng p, LatLng start,LatLng end)

Обчислює відстань на кулі між точкою p і відрізком лінії починають закінчуватися.

Параметри: p - точка, яку потрібно виміряти

start - початок відрізка рядка

end - кінець відрізка рядка

Повертає: відстань у метрах (припускаючи сферичну землю)

Просто додайте бібліотеку до своєї

dependencies {
    compile 'com.google.maps.android:android-maps-utils:0.5+'
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.