Як дістати найближчу точку на рядку до заданої точки?


28

Я вже давно використовую PostGIS, але ніколи не довелося використовувати LINESTRINGгеометрію ...! :)

Ось що я хотів би зробити: у мене є таблиця рядків (представляє вулиці певного міста, SRID 3395), і я хотів би знайти найближчі рядки до заданої точки (GPS-позиція, SRID 4326).

Я знайшов рішення - обрати всі рядки рядків у моїй точці за допомогою expand()методу та визначити відстань між кожним рядком і моєю точкою за допомогою ST_Distance()методу.

Ось SQL:

SELECT myLineId, myLineName, ST_Distance(ST_Transform(GeomFromText('POINT(LON LAT)',4326),3395),myLineGeom) AS myLineDistance
FROM myLines
WHERE myLineGeom && expand(ST_Transform(GeomFromText('POINT(LON LAT)',4326),3395), 100)
ORDER BY myLineDistance;

Результати, які я отримую, виглядають нормально, але в мене є відчуття, що щось не так у моєму виконанні.

1) Як ви думаєте, хлопці, expand()можуть отримати всі зацікавлені рядки?

2) Як ви думаєте, хлопці, ST_Distance()це правильний метод використання? Я думаю, що я роблю це неправильно, оскільки відстань, яку я хотів би отримати, - це найменша відстань між точкою та моєю лінією, а не відстань між точкою та однією з точок лінії рядка.

Ілюстрація:

alt текст

Відповіді:


11

оголошення 1) Переглядаючи документацію для використовуваних функцій, я б сказав: "Так, всі відповідні рядки будуть знайдені".

розширити (геометрія, плавати)

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

A&B

Оператор "&&" - це оператор "перекриття". Якщо обмежувальне поле A перекриває обмежувальне поле B, оператор повертає значення true.

реклама 2) Ви повинні мати можливість досягти того, що ви хочете, завдяки:

line_interpolate_point(linestring, line_locate_point(LineString, Point))

line_interpolate_point (рядок рядка, місцезнаходження)

Інтерполює точку вздовж прямої. Перший аргумент повинен бути ЛІНІСТРІНГ. Другий аргумент - float8 між 0 і 1, що представляє частку від загальної довжини 2d, яку має розміщувати точка.

line_locate_point (LineString, Point)

Повертає поплавок між 0 і 1, що представляє місце найближчої точки на LineString до даної точки, як частка загальної довжини 2d лінії. Ви можете використовувати повернене місце для отримання точки (line_interpolate_point)

Джерело: http://main.merlin.com.ua/doc/postgis/docs/ch06.html


Для пункту 2) мені було просто цікаво, чи ST_відстань між геометрією POINT та геометрією LINESTRING дає найменше можливе відстань між тезами (він же - довжина перпендикулярної лінії між POINT та LINGESTRING); я хочу відстань від кожної ЛІНІСТРИНГОВОЇ геометрії :)
Vivi

І я думаю, що це не відстань, яку я шукаю, оскільки "функція line_locate_point дає значення між 0 і 1, що представляє місце найближчої точки на LineString до даної точки": /
Vivi,

Боюся, ви втратили мене в своєму останньому коментарі. Тепер я вже не впевнений, що ви хочете;)
underdark

1
Вибачте :) Мені б хотілося цього: надаючи геометрію LINESTRING (представляючи шлях) та геометрію POINT, я хочу мати найближчу геометрію POINT, яка знаходиться на шляху (яка може бути не точкою визначення геометрії LINESTRING). Чи зрозуміло? Можливо, я повинен оновити свій пост малюнком: D
Vivi,

Я не можу оновити свою публікацію, ось ось посилання на малюнок того, що я хотів би отримати: i.imgur.com/UwPxo.jpg
Vivi,

7

Привіт

Спочатку питання про те, що повертає ST_Distance. ST_Distance повертає найкоротшу відстань між лінією та точкою (або які типи геометрії вводяться). Це означає, що ST_Разрахунок між точкою (1 3) та рядком рядка (0 0,0 10) повернеться 1. Відстань не вимірюється між точка і (0 0) або точка і (0 10), але від точки (1 3) до (0 3).

Тож, наскільки я розумію, ST_Distance дає відповідь, яку ви хочете.

Якщо ви хочете знайти крапку (0 3) у наведеному вище прикладі, ви можете використовувати ST_Closestpoint, якщо у вас є PostGIS 1.5. Для мого прикладу ви використовуєте його так: ST_Closestpoint ('LINESTRING (0 0,0 10)' :: геометрія, ' POINT (1 3) ':: геометрія), тоді ви повинні отримати точку (0 3) взамін, точку на прямій, найближчій до вашої точки.

HTH Nicklas


5

Я знайшов це :) (Ну я здогадуюсь: P)

Використовуючи ST_Line_Locate_Point()і ST_Line_Interpolate_point()мені вдалося отримати точку, яка НЕ ​​є частиною визначення LINESTRING, але є в зазначеному рядку :) Все, що мені потрібно зробити, це пройти відстань від моєї точки до цієї точки, і я закінчив.

SELECT AsText(ST_Line_Interpolate_Point(myLineGeom,ST_Line_Locate_Point(myLineGeom,ST_Transform(GeomFromText('POINT(LON LAT)',4326),3395))))
FROM myLines
WHERE myGeom && expand(ST_Transform(GeomFromText('POINT(LON LAT)',4326),3395), 100)

ST_Line_Locate_Point()Спосіб знайти місце розташування найближчої точки на лінії в даній точці, то ST_Line_Interpolate_Pointспосіб перетворити це місце в точку.


1
Відстань між точкою та прямою дасть вам таку ж відповідь. Чому ти вважаєш, що ти повинен це зробити так?
Nicklas Avén

1
Я думаю, що ST_Distance можна використовувати з будь-яким типом геометрії. postgis.refractions.net/docs/ST_Distance.html :ST_Distance(geometry g1, geometry g2)
Magno C

2

Цей потік архіву Postgis може відповісти на вас http://postgis.refractions.net/pipermail/postgis-users/2007-June/016045.html


refractions.net не працює для мене: "термін дії refractions.net закінчився 14.09.2010 і очікує на поновлення або видалення."
underdark

@underdark це працює для мене
dassouki

@dassouki: це дивно: |
underdark

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