Algoritmi per i segmenti corrispondenti


23

Quali sono i migliori algoritmi per abbinare i segmenti?

Sto cercando di abbinare i segmenti corrispondenti da due origini della mappa, una meno accurata ma con nomi di segmento e una più accurata senza nomi di segmenti. Voglio applicare semi-automaticamente i nomi dei segmenti alla mappa più accurata.

L'algoritmo richiesto ha una descrizione piuttosto vaga perché una "corrispondenza" non è ben definita e molti fattori (orientamento, lunghezza relativa, distanza) potrebbero avere un peso diverso in diversi scenari; Tuttavia, sto cercando una conoscenza di base degli approcci generali per la gestione di questo problema.

Le implementazioni di lavoro per l'ambiente open source (PostGIS, ben fatto, ...) sono calorosamente benvenute.

Segmenti di esempio : vedere la descrizione sotto le immagini.


Potresti pubblicare un'istantanea dei tuoi dati per fornire una panoramica della densità del segmento e quanto sono diversi?
luglio

1
Ho pubblicato alcune illustrazioni su flickr, vedi link.
Adam Matan,

1
Potresti provare a cercare "conflazione".
Kirk Kuykendall,

Risposte:


14

È possibile utilizzare la distanza di Hausdorff : i segmenti corrispondenti potrebbero essere segmenti "vicini" in base a questa distanza. È abbastanza semplice calcolare su segmenti.

Un'implementazione java gratuita è disponibile in JTS - vedere Pacchetto distanza JTS . Puoi anche dare un'occhiata alla JCS Conflation Suite (ora abbandonata, copia delle fonti ad es. Su https://github.com/oschrenk/jcs ).


2
La distanza di Hausdorff è anche in PostGIS, da GEOS, quindi è lo stesso algoritmo di JTS
Nicklas Avén

10

Non so quale sarebbe il "migliore", perché dipenderà dai dettagli dei tuoi segmenti.

Un approccio generalmente valido consiste nell'hash dei segmenti in informazioni geometriche cruciali . Ciò include, come minimo, la posizione del centro (x, y), l'orientamento (da 0 a 180 gradi) e la lunghezza. Con l'applicazione dei pesi appropriati e un po 'di perfezionamento dell'orientamento (poiché 180 "si avvolge" di nuovo a 0), è quindi possibile applicare quasi tutti gli algoritmi di raggruppamento statistico alla raccolta di tutti i segmenti. ( K-significherebbe una buona opzione, ma la maggior parte dei metodi gerarchici dovrebbe funzionare bene. Tali analisi dei cluster tendono ad essere veloci e facili da applicare.) Idealmente, i segmenti si comporteranno in coppie (o singleton per segmenti senza eguali) e il resto è facile.

Un modo per affrontare il problema dell'orientamento è creare una copia dei segmenti etichettati. Aggiungi 180 gradi all'orientamento della prima copia, se è inferiore a 90, e sottrarre altrimenti 180 gradi dall'orientamento. Questo allarga il tuo set di dati (ovviamente) ma per il resto non modifica l'algoritmo in alcun modo.

I pesi sono necessari perché le differenze di coordinate, lunghezze e orientamenti possono significare cose abbastanza diverse per quanto riguarda le somiglianze dei loro segmenti corrispondenti. In molte applicazioni le differenze tra i segmenti derivano da differenze nelle posizioni dei loro endpoint. Come approssimazione approssimativa, possiamo aspettarci che le variazioni tipiche nelle lunghezze dei segmenti siano circa le stesse delle variazioni tipiche tra i loro punti finali. Pertanto, i pesi associati a x, y e lunghezza dovrebbero essere più o meno gli stessi. La parte difficile è l'orientamento della ponderazione, poiché l'orientamento non può essere equiparato alla distanza e, peggio ancora, i segmenti corti avrebbero più probabilità di essere orientati male rispetto ai segmenti lunghi. Si consideri un metodo di prova ed errore che equivale a qualche grado di disorientamento alla dimensione di un divario tipico tra i segmenti e quindi lo regola fino a quando la procedura sembra funzionare bene. Per assistenza, lasciaL è una lunghezza tipica del segmento. Un cambiamento di orientamento di un angolo t di piccoli gradi t spazzerà una distanza di circa L / 2 * t / 60 (il 60 approssima il numero di gradi in un radiante), che è L / 120 volte t . Ciò suggerisce di iniziare con pesi unitari per x, ye lunghezza e un peso di L / 120 per l'orientamento.

In sintesi , questo suggerimento è:

  1. Creare copie dei segmenti etichettati (come descritto nel paragrafo relativo al perfezionamento dell'orientamento).

  2. Converti ogni segmento nel quadruplo (x, y, lunghezza, orientamento L / 120 *) dove L è una lunghezza tipica del segmento.

  3. Eseguire un'analisi cluster dei quadrupli. Utilizzare un buon pacchetto statistico ( R è gratuito).

  4. Utilizzare l'output di analisi del cluster come tabella di ricerca per associare segmenti etichettati a segmenti non etichettati vicini.


4

Ho lavorato su un progetto con un requisito simile circa 5 anni fa. Si trattava di combinare le coordinate delle linee centrali delle strade (con precisione delle coordinate relativamente elevata) con i collegamenti della rete di traffico Highway Performance Monitoring System (HPMS).

All'epoca l'FHWA non forniva alcun strumento per fare questo genere di cose. Potrebbe essere cambiato, potresti voler controllare. Anche se non stai lavorando con i dati autostradali, gli strumenti potrebbero essere comunque pertinenti.

L'ho scritto con ArcGIS, ma l'algoritmo dovrebbe funzionare in opensource, purché fornisca funzionalità di traccia simili a 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

Ecco un'idea

Se si separa una delle stringhe di linea per confrontare e verificare se i punti di vertice si trovano a una certa distanza dalle altre stringhe di linea per confrontare, è possibile controllare il test in molti modi.

quegli esempi funzionano in PostGIS (chi potrebbe indovinare :-))

Innanzitutto, se diciamo che esiste una corrispondenza se tutti i punti di vertice in una stringa lineare nella tabella_1 sono 0,5 metri (unità della mappa) o più vicini a una stringa lineare nella tabella_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;

Quindi possiamo dire che esiste una corrispondenza se più del 60% dei punti_punto in una stringa lineare nella tabella_1 si trova a distanza di una stringa lineare nella tabella_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

Oppure possiamo accettare che un punto non rientri nell'intervallo:

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;

Dovrai anche eseguire la query con table_1 e table_2 in ruoli invertiti.

Non so quanto sarà veloce. ST_Dumppoints è attualmente una funzione sql in PostGIS e non una funzione C che lo rende più lento di quanto dovrebbe essere. Ma penso che sarà abbastanza veloce comunque.

Gli indici spaziali aiuteranno molto per ST_Dwithin ad essere efficace.

HTH Nicklas


1
+1 Questo è molto simile all'approccio che ho finalmente usato (pubblicherò presto una risposta).
Adam Matan,

4

Ho scritto codice per gestire la corrispondenza dei segmenti di linea sciatta (e sovrapporli) in Boundary Generator. Ho scritto la matematica (abbastanza elementare) dietro di essa qui: http://blog.shoutis.org/2008/10/inside-boundary-generator-computational.html . Il codice è open source e collegato da quel post sul blog.

Il codice segue un approccio davvero semplice:

  • Un test segmento-segmento che ti dirà se due segmenti di linea si sovrappongono entro determinate tolleranze di angolo e distanza e la quantità di sovrapposizione.
  • Un indice spaziale rapido e sporco che elimina la necessità di testare ogni segmento di linea nel set di dati rispetto a tutti gli altri segmenti di linea nel set di dati.

Il vantaggio principale di questo approccio è ottenere manopole ben precise per angolo valido, distanze e lunghezza di sovrapposizione; il rovescio della medaglia, non è un modo per misurare generalmente la somiglianza di due segmenti di linea, quindi è molto più difficile, ad esempio, fare un raggruppamento statistico per determinare le probabili corrispondenze: sei bloccato con le manopole precise.

Nota: sto indovinando che con un numero sufficiente di trucchi SQL è possibile stipare il test segmento-segmento in una clausola WHERE ... :)

Saluti!


+1 Questo è un approccio gradevole; la costruzione del quadrifoglio lo rende superiore dal punto di vista computazionale. Ma è necessaria attenzione nei dettagli: quando si determina la vicinanza o la somiglianza del segmento (anziché l'intersezione), è necessario tenere conto del fatto che la struttura dei dati non fornisce una rappresentazione univoca di un segmento: il segmento che ha origine in x , nella direzione v , di lunghezza t è ugualmente bene il segmento che origina da x + t v nella direzione -v della lunghezza t .
whuber

1

Ho implementato un prototipo approssimativo per la corrispondenza delle mappe qui , che è relativamente facile da usare. Si basa sul motore di routing open source e scritto in Java. L'algoritmo utilizzato è descritto qui .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.