Алгоритми відповідності сегментів


23

Які найкращі алгоритми для відповідності сегментам?

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

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

Робочі реалізації для середовища з відкритим кодом (PostGIS, стройний, ...) вітаються з радістю.

Зразки сегментів : Дивіться опис нижче зображень.


Чи можете ви опублікувати знімок даних, щоб отримати огляд щільності сегмента та наскільки вони відрізняються?
липень

1
Я розмістив кілька ілюстрацій на flickr, дивіться посилання.
Адам Матан

1
Ви можете спробувати пошукати "конфлікт".
Кірк Куйкендалл

Відповіді:


14

Відстань Хаусдорфа може бути використано: відповідні сегменти можуть бути «закрити» сегменти в Відповідно до цього відстанню. Обчислити по сегментах досить просто.

У JTS доступна безкоштовна реалізація Java - див. Дистанційний пакет JTS . Ви також можете ознайомитись з пакетом конфігурацій JCS (тепер покинутий, копія джерел, наприклад, на https://github.com/oschrenk/jcs ).


2
Відстань Хаусдорфа також у PostGIS від GEOS, тому це той самий алгоритм, що і JTS
Nicklas Avén

10

Я не знаю, що було б "найкращим", бо це буде залежати від деталей ваших сегментів.

Як правило, хороший підхід полягає в розміщенні сегментів на вирішальну геометричну інформацію . Це, як мінімум, включає розташування центру (х, у), орієнтацію (від 0 до 180 градусів) та довжину. Якщо застосовано відповідні ваги та певну орієнтацію орієнтації (оскільки 180 "обертів" назад до 0), ви можете застосувати майже будь-який алгоритм статистичного кластеризації до колекції всіх сегментів. ( K-засоби були б хорошим варіантом, але більшість ієрархічних методів повинні працювати добре. Такі кластерні аналізи, як правило, швидко і легко застосовуються.) В ідеалі сегменти відбуватимуться парами (або одиночними для невідповідних сегментів), а решта легко.

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

Ваги потрібні, оскільки різниця координат, довжини та орієнтації може означати зовсім різні речі щодо подібності відповідних їх сегментів. У багатьох програмах відмінності між сегментами виникають через відмінності в місцях розташування їх кінцевих точок. Як приблизне наближення, ми можемо очікувати, що типові зміни довжини сегмента будуть приблизно такими ж, як типові зміни між їх кінцевими точками. Тому ваги, пов'язані з x, y і довжиною, повинні бути приблизно однаковими. Хитра частина - орієнтація на зважування, тому що орієнтацію не можна порівнювати з відстані, і, що ще гірше, короткі сегменти будуть скоріше неправильно орієнтованими, ніж довгі сегменти. Розглянемо метод проб і помилок, який прирівнює кілька ступенів дезорієнтації до розміру типового проміжку між сегментами, а потім коригує це, поки процедура, здається, працює добре. Для вказівки нехайL - типова довжина відрізка. Зміна орієнтації на малий кут t градусів промітить відстань приблизно L / 2 * t / 60 (60 приблизна до кількості градусів в одному радіані), що L / 120 разів t . Це дозволяє почати з одиничних ваг для x, y та довжини та ваги L / 120 для орієнтації.

Підсумовуючи це, це пропозиція:

  1. Зробіть копії мічених сегментів (як описано в параграфі про підготування орієнтації).

  2. Перетворіть кожен сегмент у чотиричлен (x, y, довжина, L / 120 * орієнтація), де L - типова довжина відрізка.

  3. Виконай кластерний аналіз чотириразових. Використовуйте хороший статистичний пакет ( R безкоштовно).

  4. Використовуйте висновок аналізу кластерів як таблицю пошуку, щоб пов'язувати мічені сегменти з розташованими поблизу незазначеними сегментами.


4

Я працював над проектом із подібною вимогою близько 5 років тому. Він передбачав поєднання координат від центральних ліній вулиць (з відносно високою точністю координат) із мережевими каналами руху дорожньої системи (HPMS).

У той час FHWA не надавала жодних інструментів для цього. Можливо, це змінилося, можливо, ви захочете перевірити. Навіть якщо ви не працюєте з даними про дороги, інструменти все ще можуть бути актуальними.

Я написав це з ArcGIS, але алгоритм повинен працювати у відкритих джерелах , якщо він забезпечує можливості відстеження, схожі на ISegmentGraph :

// features is a collection of features with higher geometry
// Links are a collection features with attributes but low res geometry
For each Link in lowResFeatureclass
    point startPoint = SnapToClosestPoint(Link.StartPoint, hiResfeatures);
    if(startPoint == null)
       continue;
    point endPoint = SnapToClosest(Link.EndPoint, hiResfeatures);
    if(endPoint == null)
       continue;
    polyline trace = Trace(hiResfeatures,startPoint,endPoint);
    if(polyline != null)
    {
        // write out a link with high precision polyline
        Write(Link,polyline);
    }
Next Link

4

Ось ідея

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

ці приклади працюють у PostGIS (хто може здогадатися :-))

По-перше, якщо ми скажемо, що існує збіг, якщо всі вершинні точки в рядку рядка в таблиці_1 дорівнюють 0,5 метра (одиниці карти) або ближче до рядка рядка в таблиці_2:

SELECT a.id, b.id FROM
(SELECT ST_NPoints(the_geom) as num_of_points,
(ST_Dumppoints(the_geom)).geom as p, id FROM table_1) a 
INNER JOIN 
table_2 b 
ON ST_DWithin(a.p, b.the_geom, 0.5) GROUP BY a.id, b.id
HAVING COUNT(*)=num_of_points;

Тоді ми можемо сказати, що існує збіг, якщо більше 60% точок вершини у рядковій рядку таблиці_1 знаходиться в межах відстані від рядка рядка в таблиці_2

SELECT a.id, b.id FROM
(SELECT ST_NPoints(the_geom) as num_of_points, 
(ST_Dumppoints(the_geom)).geom as p, id FROM table_1) a 
INNER JOIN 
table_2 b 
ON ST_DWithin(a.p, b.the_geom, 0.5) GROUP BY a.id, b.id
HAVING COUNT(b.id)/num_of_points::float > 0.6

Або ми можемо прийняти, що одна точка не в діапазоні:

SELECT a.id, b.id FROM
(SELECT ST_NPoints(the_geom) as num_of_points, 
(ST_Dumppoints(the_geom)).geom as p, id FROM table_1) a 
INNER JOIN 
table_2 b 
ON ST_DWithin(a.p, b.the_geom, 0.5) GROUP BY a.id, b.id
HAVING COUNT(b.id)-num_of_points <= 1;

Вам також доведеться запустити запит з таблицею_1 та table_2 у перетворених ролях.

Я не знаю, як швидко це буде. ST_Dumppoints в даний час є sql-функцією в PostGIS, а не C-функцією, яка робить її повільніше, ніж повинна бути. Але я думаю, все одно це буде досить швидко.

Просторові індекси дуже допоможуть ST_Dwithin для ефективності.

HTH Nicklas


1
+1 Це дуже схоже на підхід, який я нарешті використав (відповідь незабаром).
Адам Матан

4

Я написав код, щоб обробляти неохайний відрізок рядків (і перекривати їх) у Boundary Generator. Я записав (досить елементарну) математику за цим посиланням: http://blog.shoutis.org/2008/10/inside-boundary-generator-computational.html . Код є відкритим кодом та пов'язаний з цього допису в блозі.

Код дотримується дійсно простого підходу:

  • Тест на сегмент сегмента, який дозволить дізнатись, чи перекриваються два відрізки ліній у межах заданих допусків кута та відстані та величина перекриття.
  • Швидкий просторовий індекс, що виключає необхідність перевіряти кожен сегмент рядка в наборі даних щодо всіх інших сегментів рядків у наборі даних.

Основна перевага такого підходу полягає в тому, що ви отримуєте чітко точні ручки для дійсного кута, відстані та довжини перекриття; З іншого боку, це не спосіб загального вимірювання подібності двох сегментів рядків, тому набагато складніше, наприклад, зробити статистичне кластеризацію для визначення ймовірних збігів - ви застрягли з точними ручками.

Примітка. Я здогадуюсь, що за допомогою достатньої кількості відбитків SQL ви можете перетворити тест сегмента на сегмент WHERE ... :)

Ура!


+1 Це приємний підхід; побудова квадрату робить його обчислювально вище. Але потрібно подбати про деталі: визначаючи близькість або схожість сегмента (замість перетину), потрібно враховувати той факт, що ваша структура даних не забезпечує унікального зображення сегмента: сегмент, що походить з x , у напрямку v , довжиною t однаково добре відрізок, що походить від x + t v у напрямку -v довжини t .
whuber

1

Я реалізував грубий прототип для узгодження з картою тут , що відносна проста у використанні. Він заснований на двигуні маршрутизації з відкритим кодом та написаний на Java. Використовуваний алгоритм описаний тут .

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