Алгоритмы для сопоставления сегментов

23

Каковы лучшие алгоритмы для сопоставления сегментов?

Я пытаюсь сопоставить соответствующие сегменты из двух источников карты, один менее точный, но с именами сегментов, а другой более точный без названий сегментов. Я хочу полуавтоматически применить имена сегментов к более точной карте.

Запрашиваемый алгоритм имеет довольно расплывчатое описание, потому что «совпадение» не является четко определенным, и многие факторы (ориентация, относительная длина, расстояние) могут иметь различный вес в разных сценариях; Тем не менее, я ищу базовые знания об общих подходах к решению этой проблемы.

Рабочие реализации для среды с открытым исходным кодом (PostGIS, shapely, ...) горячо приветствуются.

Примеры сегментов : см. Описание ниже изображения.

Адам Матан
источник
Не могли бы вы опубликовать снимок ваших данных, чтобы предоставить обзор плотности сегментов и насколько они различаются?
Жюльен
1
Я разместил несколько иллюстраций на flickr, см. Ссылку.
Адам Матан
1
Вы можете попробовать поискать «слияние».
Кирк Куйкендалл

Ответы:

14

Расстояние Хаусдорфа может быть использовано: соответствующие сегменты могут быть «закрыть» сегменты в соответствии с этим расстоянием. Это довольно просто для вычисления на сегментах.

Бесплатная реализация Java доступна в JTS - см. JTS Distance Package . Вы также можете взглянуть на JCS Conflation Suite (сейчас заброшенный, копия источников, например, на https://github.com/oschrenk/jcs ).

жюльен
источник
2
Расстояние Хаусдорфа также в PostGIS, от GEOS, так что это тот же алгоритм, что и в JTS
Никлас Авен
10

Я не знаю, что будет «лучшим», потому что это будет зависеть от особенностей ваших сегментов.

Как правило, хороший подход заключается в хешировании сегментов в важную геометрическую информацию . Это будет включать, как минимум, местоположение центра (x, y), ориентацию (от 0 до 180 градусов) и длину. С применением подходящих весов и некоторой коррекции ориентации (потому что 180 «оборачивается» обратно к 0), вы можете затем применить практически любой статистический алгоритм кластеризации для сбора всех сегментов. ( K-means был бы хорошим вариантом, но большинство иерархических методов должно работать хорошо. Такие кластерные анализы, как правило, бывают быстрыми и простыми в применении.) В идеале, сегменты будут встречаться парами (или одиночными для несопоставленных сегментов), а остальные это легко.

Одним из способов решения проблемы ориентации является создание копии помеченных сегментов. Добавьте 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. Используйте результаты кластерного анализа в качестве справочной таблицы, чтобы связать помеченные сегменты с соседними немечеными сегментами.

Whuber
источник
4

Я работал над проектом с аналогичным требованием около 5 лет назад. Он включал в себя объединение координат от уличных центральных линий (с относительно высокой точностью координат) с транспортными сетевыми связями системы мониторинга эффективности шоссе (HPMS).

В то время FHWA не предоставляла никаких инструментов для подобных вещей. Это могло измениться, вы можете проверить. Даже если вы не работаете с данными о шоссе, инструменты могут быть полезны.

Я написал это с ArcGIS, но алгоритм должен работать в OpenSource, если он предоставляет возможности трассировки, аналогичные 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 (кто бы мог догадаться :-))

Во-первых, если мы говорим, что есть совпадение, если все точки вершин в строке строки в table_1 равны 0,5 метра (единицы карты) или ближе к строке строки в table_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% точек vertex_points в строке строки в table_1 находится на расстоянии от строки строки в table_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;

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

Я не знаю, как быстро это будет. ST_Dumppoints в настоящее время является sql-функцией в PostGIS, а не C-функцией, которая делает ее медленнее, чем должна быть. Но я думаю, что все равно будет довольно быстро.

Пространственные индексы очень помогут для ST_D с эффективностью.

HTH Никлас

Никлас Авен
источник
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. Используемый алгоритм описан здесь .

Karussell
источник