Segmenti corrispondenti di diverse lunghezze


13

Sto cercando di abbinare piccoli segmenti con un segmento più grande a cui sono probabilmente legati: cuscinetto relativamente vicino, simile e uno di fronte all'altro.

Ecco un tipico esempio dei dati che ho:

segmenti

Qui avrei bisogno di abbinare il segmento 652 a 198969, pur avendo 711 e 707 non corrispondenti a nulla.

Ho cercato diversi metodi, in particolare la distanza di Hausdorff (in base alle risposte qui ). L'ho calcolato usando PostGIS ma sto ottenendo risultati strani: la distanza più breve che ottengo è tra 707 e 198985 e 652 ha una distanza maggiore rispetto al 198969 rispetto al 198985, ad esempio (posso aggiungere la query e i risultati se necessario).

Hausdorff è davvero il metodo corretto per risolvere questo? Ci sono altri approcci? Ho pensato di creare semplicemente una serie di controlli sui parametri che ho citato (distanza, rilevamento, ecc.) Ma ho paura di dover aggiungere un sacco di condizioni per gestire casi limite o cose come il limite su quanto sono uno di fronte all'altro.

Aggiornamento: ho trovato un metodo che sembra un compromesso accettabile:

  • Per prima cosa trovo i 10 segmenti neri più vicini a quello blu che sto cercando di abbinare (usando l' <->operatore PostGIS ) che sono a meno di 10 metri di distanza.
  • Quindi creo un nuovo segmento trovando i punti più vicini alle estremità del segmento blu su ciascuno di quelli neri (usando ST_ClosestPoint) e filtrando i risultati la cui lunghezza è inferiore al 90% di quello blu (nel senso che i segmenti non lo sono rivolto verso l'alto o che la differenza di rilevamento è superiore a ~ 20 °)
  • Quindi ottengo il primo risultato ordinato in base alla distanza e alla distanza di Hausdorff, se presente.

Potrebbe esserci qualche fine tuning da fare, ma per ora sembra fare un lavoro accettabile. Sto ancora cercando altri metodi o controlli aggiuntivi da eseguire se ho perso alcuni casi limite.


1
Perché non usare semplicemente gli endpoint dei segmenti (blu) per identificare potenziali corrispondenze tra i segmenti target (neri)? Le corrispondenze di segmento che stai cercando si verificano quando entrambi gli endpoint sono vicini a una destinazione comune, che è una semplice query da eseguire. Questo metodo gestisce le discrepanze dovute a errori nelle posizioni degli endpoint del segmento, che altrimenti potrebbero essere difficili da affrontare: notare che un segmento molto corto (blu) ha un rilevamento molto meno preciso di un segmento più lungo.
whuber

1
Sì, sto effettivamente provando qualcosa in questo senso, aggiornerò la domanda con i dettagli.
Jukurrpa,

1
Non sei sicuro di averti compreso correttamente, ma hai provato a creare centroidi per le linee blu e quindi a controllare le distanze da esse alle linee più vicine, lasciando di conseguenza la distanza più breve?
Cyril M,

1
Ciao Cyril, non sto più lavorando a questo problema, ma il problema era anche quello di abbinare i segmenti blu in base al loro orientamento e a quanto "affrontano" i segmenti neri. Il che significa che in questo caso il 711 non dovrebbe corrispondere a nulla anche se è abbastanza vicino ai segmenti neri
Jukurrpa

Risposte:


1

Ecco un paio di funzioni che ho scritto che dovrebbero permetterti di fare ciò che devi fare. Controlla se la linea è polilinea o segmento se la polilinea esplode la linea, quindi confronta l'azimut e l'inverso del primo punto e dell'ultimo punto sulle linee, imposta criteri accettabili per il codice per prendere una decisione. Questi sono metodi arcpici ma potrebbero essere modificati.

restituisce azimut dal segmento di linea ESRI @shape

def returnAzimuth(shape):
    point1 = shape.firstPoint
    point2 = shape.lastPoint
    dX = point2.X-point1.X
    dY = point2.Y-point1.Y
    az = math.atan2(dX,dY)*180/math.pi
    if az<0:
        az = az+360
        return az
    return az

ritorna inverso dai punti ESRI

def returnInverse(point1,point2):
    dX = point2.X-point1.X
    dY = point2.Y-point1.Y
    dis = sqrt(dX**2+dY**2)
    az = math.atan2(dX,dY)*180/math.pi
    if az<0:
        az = az+360
        return az,dis
    return az,dis

esplodere la polilinea nel segmento di linea

def explodePolyline(shape):
    sr = "insert your spatial reference"
    lines=[]
    pnts = shape.getPart(0)
    for x in range(len(pnts)-1):
        array = arcpy.Array()
        point1 = arcpy.Point(pnts.getObject(x).X,pnts.getObject(x).Y,pnts.getObject(x).Z)
        point2 = arcpy.Point(pnts.getObject(x+1).X,pnts.getObject(x+1).Y,pnts.getObject(x+1).Z)
        array.add(point1)
        array.add(point2)
        line = arcpy.Polyline(array,sr,True,True)
        print(line)
        lines.append(line)
    return lines

attraversa il tuo tavolo in questo modo

for shape in Table:
    for shape2 in Table:
         check if shape is polyline:
            if yes, explode and compare returned line segments with shape2
                for seg in returnedlinesegments
                    if seg.firstpoint=shape2.lastpoint and shape.az=shape2.az
                        do stuff.....
            if no, compare shape and shape2
                if shape.firstpoint=shape2.lastpoint and shape.az=shape2.az
                   do stuff.....

queste proprietà dovrebbero essere disponibili in Postgis - firstpoint, lastpoint, pointarray Assumo le proprietà esri sopra perché è quello che conosco meglio, ma quanto sopra può essere facilmente modificato per funzionare con Postgis.

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.