Collegamento delle caratteristiche della linea e determinazione della lunghezza della linea più lunga


12

Ho una funzione di linea (vedi immagine) che rappresenta un fiume che ho creato usando lo strumento Stream_to_Feature. La tabella degli attributi contiene diversi record che rappresentano linee diverse: il problema è che la linea più lunga (facilmente distinguibile visivamente) non è rappresentata come una singola linea nella tabella, in realtà è composta da molte linee più piccole. Le linee sembrano toccarsi, anche se non si incrociano.

Come posso unire queste linee e quindi determinare la lunghezza della linea più lunga usando ArcObjects o metodi manuali che posso convertire in ArcObjects? Una soluzione ancora migliore consisterebbe nel sbarazzarsi di tutti gli affluenti e lasciandomi solo con il canale fluviale come una linea.

Linea caratteristica - fiume


1
Si collegano affatto? Hai detto che non attraversano, ma ciò significa che non condividono un vertice?
Nathanus,

1
Scusa, avrei dovuto essere più chiaro. Condividono i vertici, ma non si incrociano completamente.
Radar

Sai dov'è la foce del fiume? Il fiume è sempre un albero (un percorso unico da ciascun punto del fiume alla foce)?
Kirk Kuykendall,

3
In realtà, non vuoi la lunghezza della "linea più lunga". Potrebbe essere un percorso da una portata a monte a un'altra portata a monte remota. Ciò accadrà quando due rami principali del torrente si uniranno vicino alla sua bocca. Invece, vuoi il percorso più lungo tra la bocca e qualsiasi altro endpoint sul flusso. (Questa caratterizzazione non richiede nemmeno che il flusso sia rappresentato come un albero: può intrecciare e avere isole.)
whuber

@whuber - la tua valutazione è corretta - hai idea di come posso realizzare questo usando i percorsi?
Radar

Risposte:


18

Innanzitutto, un piccolo background per indicare perché questo non è un problema difficile. Il flusso attraverso un fiume garantisce che i suoi segmenti, se correttamente digitalizzati, possono sempre essere orientati per formare un grafico aciclico diretto (DAG). A sua volta, un grafico può essere ordinato in modo lineare se e solo se è un DAG, usando una tecnica nota come ordinamento topologico . L'ordinamento topologico è veloce: i suoi requisiti di tempo e spazio sono entrambi O (| E | + | V |) (E = numero di spigoli, V = numero di vertici), il che è buono come si arriva. La creazione di un ordinamento così lineare semplificherebbe la ricerca del flusso principale.

Ecco quindi uno schizzo di un algoritmo . La bocca del torrente giace lungo il suo letto principale. Spostati a monte lungo ciascun ramo attaccato alla bocca (potrebbe essercene più di uno, se la bocca è una confluenza) e trova ricorsivamente il letto principale che porta a quel ramo. Seleziona il ramo per il quale la lunghezza totale è massima: questo è il tuo "backlink" lungo il letto principale.

Per chiarire questo, offro alcuni pseudocodici (non testati) . L'input è un insieme di segmenti di linea (o archi) S (comprendente il flusso digitalizzato), ciascuno con due punti finali distinti inizio (S) e fine (S) e una lunghezza positiva, lunghezza (S); e la foce p , che è un punto. L'output è una sequenza di segmenti che uniscono la bocca con il punto a monte più distante.

Dovremo lavorare con "segmenti contrassegnati" (S, p). Questi sono costituiti da uno dei segmenti S insieme a uno dei suoi due punti finali, p . Dovremo trovare tutti i segmenti S che condividono un endpoint con un punto sonda q , contrassegnare quei segmenti con i loro altri endpoint e restituire il set:

Procedure Extract(q: point, A: set of segments): Set of marked segments.

Quando non è possibile trovare tale segmento, Estrai deve restituire il set vuoto. Come effetto collaterale, Estrai deve rimuovere tutti i segmenti che sta ritornando dall'insieme A, modificando così A stesso.

Non sto dando un'implementazione di Extract: il tuo GIS fornirà la possibilità di selezionare segmenti S che condividono un endpoint con q . Contrassegnarli è semplicemente una questione di confronto tra inizio (S) e fine (S) con q e ritorno di uno qualsiasi dei due punti finali non corrispondenti.

Ora siamo pronti a risolvere il problema.

Procedure LongestUpstreamReach(p: point, A: set of segments): (Array of segments, length)
    A0 = A                        // Optional: preserves A
    C = Extract(p, A0)            // Removes found segments from the set A0!
    L = 0; B = empty array
    For each (S,q) in C:          // Loop over the segments meeting point p
        (B0, M) = LongestUpstreamReach(q, A0)
        If (length(S) + M > L) then
            B = append(S, B0)
            L = length(S) + M
        End if
    End for
    Return (B, L)
End LongestUpstreamReach

La procedura "append (S, B0)" attacca il segmento S alla fine dell'array B0 e restituisce il nuovo array.

(Se il flusso è davvero un albero: niente isole, laghi, trecce, ecc., Allora puoi rinunciare al passaggio della copia di A in A0 .)

Alla domanda originale viene data risposta formando l'unione dei segmenti restituiti da LongestUpstreamReach.

Per illustrare , consideriamo lo stream nella mappa originale. Supponiamo che sia digitalizzato come una raccolta di sette archi. L'arco a va dalla bocca al punto 0 (parte superiore della mappa, a destra nella figura in basso, che è ruotata) a monte della prima confluenza al punto 1. È un arco lungo, diciamo 8 unità lunghe. L'arco b si dirama a sinistra (nella mappa) ed è corto, lungo circa 2 unità. L'arco c si dirama a destra ed è lungo circa 4 unità, ecc. Lasciando "b", "d" e "f" denotano i rami del lato sinistro mentre procediamo dall'alto verso il basso sulla mappa e "a", "c", "e" e "g" gli altri rami e numerando i vertici da 0 a 7, possiamo rappresentare in modo astratto il grafico come la raccolta di archi

A = {a=(0,1), b=(1,2), c=(1,3), d=(3,4), e=(3,5), f=(5,6), g=(5,7)}

Suppongo che abbiano lunghezze 8, 2, 4, 1, 2, 2, 2 per una a g , rispettivamente. La bocca è vertice 0.

figura

Il primo esempio è la chiamata a Extract (5, {f, g}). Restituisce il set di segmenti contrassegnati {(f, 6), (g, 7)}. Si noti che il vertice 5 è alla confluenza di archi f e g (i due archi nella parte inferiore della mappa) e che (f, 6) e (g, 7) contrassegnare ciascuno di questi archi con i loro monte punti finali.

Il prossimo esempio è la chiamata a LongestUpstreamReach (0, A). La prima azione che effettua è la chiamata a Estrai (0, A). Ciò restituisce un set contenente il segmento contrassegnato (a, 1) e rimuove il segmento a dall'insieme A0 , che ora è uguale a {b, c, d, e, f, g}. Esiste un'iterazione del ciclo, dove (S, q) = (a, 1). Durante questa iterazione viene effettuata una chiamata a LongestUpstreamReach (1, A0). Ricorsivamente, deve restituire la sequenza (g, e, c) o (f, e, c): entrambi sono ugualmente validi. La lunghezza (M) che restituisce è 4 + 2 + 2 = 8. (Nota che LongestUpstreamReach non modifica A0 .) Alla fine del ciclo, segmenta unè stato aggiunto al letto del flusso e la lunghezza è stata aumentata a 8 + 8 = 16. Pertanto il primo valore restituito è costituito dalla sequenza (g, e, c, a) o (f, e, c, a), con una lunghezza di 16 in entrambi i casi per il secondo valore restituito. Questo mostra come LongestUpstreamReach si sposta a monte della foce, selezionando ad ogni confluenza il ramo con la distanza più lunga ancora da percorrere e tiene traccia dei segmenti attraversati lungo il suo percorso.

Un'implementazione più efficiente è possibile quando ci sono molte trecce e isole, ma per la maggior parte degli scopi ci sarà uno sforzo sprecato se LongestUpstreamReach è implementato esattamente come mostrato, perché ad ogni confluenza non c'è sovrapposizione tra le ricerche nei vari rami: il calcolo il tempo (e la profondità dello stack) sarà direttamente proporzionale al numero totale di segmenti.


+1 Ora se solo lo avessero saputo prima di nominare il fiume Missouri.
Kirk Kuykendall,

1
@Kirk L'esplorazione ricorsiva dell'Ovest americano all'inizio del 1800 non fu facile :-).
whuber

questo è incredibilmente utile! Vedrò se riesco a ottenere questa configurazione nel mio GIS e condividere un codice utile una volta che lo faccio funzionare. Saluti!
Radar

Bella risposta whuber
Ragi Yaser Burhum,

2

Lo strumento Linea non divisa può essere utile per ciò che stai cercando di fare, anche se dovrai divinare un metodo per differenziare un ramo di flusso da un altro (per il campo di dissolvenza). Ciò presuppone però che tu abbia una licenza ArcInfo.

Se non si dispone di tale licenza, è possibile prendere in considerazione l'approccio ArcObjects prendendo l'XY di ciascun vertice, compilando un IPointCollectioncon loro e quindi creando un IGeometrycome a PolyLineClass.


1

È possibile utilizzare RivEX è uno strumento ArcGIS 9.1 (che funzionerà in 9.3 e 10). Ha strumenti per identificare i problemi topologici con le reti fluviali e molti strumenti di elaborazione. Uno di questi strumenti trova il gambo principale .

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.