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


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.