Algorytmy dopasowywania segmentów


23

Jakie są najlepsze algorytmy do dopasowania segmentów?

Próbuję dopasować odpowiadające segmenty z dwóch źródeł mapy, jedno mniej dokładne, ale z nazwami segmentów, a drugie bardziej dokładne bez nazw segmentów. Chcę półautomatycznie zastosować nazwy segmentów do dokładniejszej mapy.

Żądany algorytm ma dość niejasny opis, ponieważ „dopasowanie” nie jest dobrze zdefiniowane, a wiele czynników (orientacja, długość względna, odległość) może mieć różną wagę w różnych scenariuszach; Jednak szukam podstawowej wiedzy na temat ogólnych podejść do rozwiązywania tego problemu.

Serdecznie witamy działające implementacje środowiska open source (PostGIS, foremne, ...).

Przykładowe segmenty : patrz opis poniżej zdjęć.


Czy możesz zamieścić migawkę swoich danych, aby uzyskać przegląd gęstości segmentów i ich zróżnicowania?
— Julien

1
Opublikowałem kilka ilustracji na Flickr, patrz link.
— Adam Matan

1
Możesz spróbować wyszukać „konflację”.
— Kirk Kuykendall

Odpowiedzi:


14

Można zastosować odległość Hausdorffa : pasujące segmenty mogą być segmentami „bliskimi” zgodnie z tą odległością. Obliczanie segmentów jest dość proste.

Darmowa implementacja Java jest dostępna w JTS - patrz Pakiet JTS Distance . Możesz także zajrzeć na JCS Conflation Suite (teraz porzucony, kopia źródeł np. Na https://github.com/oschrenk/jcs ).


2
Odległość Hausdorffa jest również w PostGIS, od GEOS, więc jest to ten sam algorytm, co JTS
— Nicklas Avén

10

Nie wiem, co byłoby „najlepsze”, ponieważ będzie to zależeć od danych szczegółowych Twoich segmentów.

Ogólnie dobrym podejściem jest łączenie segmentów w kluczowe informacje geometryczne . Obejmuje to co najmniej lokalizację środka (x, y), orientację (od 0 do 180 stopni) i długość. Przy zastosowaniu odpowiednich wag i pewnej zmienności orientacji (ponieważ 180 „zawija się” z powrotem do zera), możesz następnie zastosować prawie dowolny algorytm statystycznego grupowania do zbioru wszystkich segmentów. (Średnia K byłaby dobrym rozwiązaniem, ale większość metod hierarchicznych powinna działać dobrze. Takie analizy skupień są zwykle szybkie i łatwe do zastosowania.) Idealnie segmenty będą występować w parach (lub singletonach dla niedopasowanych segmentów), a reszta jest proste.

Jednym ze sposobów rozwiązania problemu z orientacją jest wykonanie kopii oznaczonych segmentów. Dodaj 180 stopni do orientacji pierwszej kopii, jeśli jest mniejsza niż 90, i w przeciwnym razie odejmij 180 stopni od orientacji. To powiększa twój zestaw danych (oczywiście), ale poza tym w żaden sposób nie zmienia algorytmu.

Potrzebne są ciężary, ponieważ różnice we współrzędnych, długościach i orientacjach mogą oznaczać całkiem różne rzeczy dotyczące podobieństwa ich odpowiednich segmentów. W wielu aplikacjach różnice między segmentami wynikają z różnic w lokalizacjach ich punktów końcowych. Jako przybliżone przybliżenie możemy spodziewać się, że typowa zmiana długości segmentów będzie mniej więcej taka sama jak typowa różnica między ich punktami końcowymi. Dlatego wagi powiązane z x, y i długością powinny być mniej więcej takie same. Trudną częścią jest orientacja ważenia, ponieważ orientacji nie można zrównać z odległością, a co gorsza, krótkie segmenty byłyby bardziej źle ustawione niż długie segmenty. Rozważ metodę prób i błędów, która równoważy kilka stopni błędnej orientacji do wielkości typowej przerwy między segmentami, a następnie dostosowuje ją, aż procedura wydaje się działać dobrze. Aby uzyskać wskazówki, pozwólL będzie typową długością segmentu. Zmiana orientacji o niewielki kąt t stopni zmieści odległość w przybliżeniu L / 2 * t / 60 (60 oznacza przybliżoną liczbę stopni na jednym radianie), czyli L / 120 razy t . Sugeruje to rozpoczęcie od ciężarów jednostkowych dla x, y i długości oraz masy L / 120 dla orientacji.

Podsumowując , ta sugestia to:

  1. Wykonaj kopie oznaczonych segmentów (zgodnie z opisem w akapicie dotyczącym zmiany orientacji).

  2. Przelicz każdy segment na poczwórny (x, y, długość, orientacja L / 120 *), gdzie L jest typową długością segmentu.

  3. Wykonaj analizę skupień czwórek. Użyj dobrego pakietu statystycznego ( R jest bezpłatny).

  4. Użyj wyników analizy skupień jako tabeli przeglądowej do powiązania oznaczonych segmentów z pobliskimi segmentami nieznakowanymi.


4

Pracowałem nad projektem o podobnych wymaganiach około 5 lat temu. Polegało to na połączeniu współrzędnych z linii środkowych ulic (ze stosunkowo wysoką precyzją współrzędnych) z łączami sieci ruchu w systemie monitorowania autostrady (HPMS).

W tym czasie FHWA nie zapewniało żadnych narzędzi do tego typu rzeczy. To mogło się zmienić, możesz to sprawdzić. Nawet jeśli nie pracujesz z danymi o autostradzie, narzędzia mogą być nadal odpowiednie.

Napisałem go w ArcGIS, ale algorytm powinien działać w open source, o ile zapewnia możliwości śledzenia podobne do 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

Oto pomysł

Jeśli oderwiesz jeden z linii w celu porównania i przetestujesz, czy punkty wierzchołkowe znajdują się w pewnej odległości od drugiego linii w celu porównania, możesz kontrolować test na wiele sposobów.

te przykłady działają w PostGIS (kto może zgadywać :-))

Po pierwsze, jeśli powiemy, że istnieje dopasowanie, jeśli wszystkie punkty wierzchołków w linii w tabeli_1 mają 0,5 metra (jednostki mapy) lub są bliżej linii w tabeli_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;

Następnie możemy powiedzieć, że istnieje dopasowanie, jeśli więcej niż 60% punktów wierzchołków w linii w tabeli_1 znajduje się w odległości od linii w tabeli_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

Lub możemy zaakceptować, że jeden punkt nie jest w zasięgu:

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;

Będziesz także musiał uruchomić zapytanie z table_1 i table_2 w odwróconych rolach.

Nie wiem jak szybko to będzie. ST_Dumppoints jest obecnie funkcją SQL w PostGIS, a nie funkcją C, która sprawia, że ​​jest wolniejsza niż powinna. Ale myślę, że i tak będzie dość szybko.

Indeksy przestrzenne bardzo pomogą ST_Dwithin w skuteczności.

HTH Nicklas


1
+1 Jest to bardzo podobne do podejścia, które w końcu zastosowałem (wkrótce opublikuje odpowiedź).
— Adam Matan

4

Napisałem kod do obsługi niedopasowanego dopasowywania segmentów linii (i nakładania się na nie) w Boundary Generator. Zapisałem (dość elementarną) matematykę tutaj: http://blog.shoutis.org/2008/10/inside-boundary-generator-computational.html . Kod jest open source i powiązany z tym postem na blogu.

Kod stosuje bardzo proste podejście:

  • Test segmentu segmentu, który pokaże, czy dwa segmenty linii zachodzą na siebie w ramach tolerancji kąta i odległości, a także stopień nakładania się.
  • Szybki indeks przestrzenny, który eliminuje potrzebę testowania każdego segmentu linii w zbiorze danych względem wszystkich innych segmentów linii w zbiorze danych.

Główną zaletą tego podejścia jest to, że otrzymujesz całkiem precyzyjne pokrętła dla prawidłowego kąta, odległości i długości zakładki; z drugiej strony, nie jest to sposób ogólnego pomiaru podobieństwa dwóch segmentów linii, więc znacznie trudniej jest np. przeprowadzić grupowanie statystyczne w celu ustalenia prawdopodobnych dopasowań - utkniesz z precyzyjnymi pokrętłami.

Uwaga: Zgaduję, że przy wystarczającej liczbie kotletów SQL można wcisnąć test segmentu segmentu w klauzulę WHERE ... :)

Twoje zdrowie!


+1 To miłe podejście; zbudowanie kwadratu czyni go lepszym obliczeniowo. Należy jednak zachować ostrożność w szczegółach: przy określaniu bliskości lub podobieństwa segmentu (zamiast przecięcia) należy wziąć pod uwagę fakt, że struktura danych nie zapewnia unikalnej reprezentacji segmentu: segmentu rozpoczynającego się od x , w kierunku v , długość T równie dobrze Segment pochodzącą z x + t v w kierunku -v o długości t .
— whuber

1

I zostały wdrożone szorstką prototyp mapy dopasowywania tutaj , co jest względne łatwy w użyciu. Jest oparty na silniku routingu typu open source i napisany w Javie. Zastosowany algorytm opisano tutaj .

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.