Quale algoritmo viene utilizzato dallo strumento ArcGIS Watershed?


10

Qualcuno sa quale tipo di algoritmo viene utilizzato nello strumento ArcGIS Watershed (nel pacchetto Analista spaziale)?

Pochissime informazioni fornite sul sito web di Esri ... ma sospetto che potrebbe essere una sorta di ricerca approfondita / approfondita.

Ho consultato queste pagine della Guida in linea di ArcGIS:

Quindi sì, usa la direzione del flusso raster, ma quale algoritmo sta usando per attraversare il raster?

Nota: non sto cercando risposte sulla falsariga di "usa D8 .." ... D8 non è in realtà un algoritmo, ma un modello per aiutare a definire l'algoritmo che useresti. Vale a dire che è possibile implementare lo schema D8 all'interno di un algoritmo di ricerca approfondito e / o di un algoritmo di ricerca all'avanguardia


James, sto provando a fare la stessa cosa, cioè creare un'app che prende una determinata coordinata e ci dà una delineazione spartiacque. Sto usando Python. Parliamo dei nostri progressi.

Sto anche usando Python. Sto iniziando con il problema più semplice di calcolare una griglia di direzione del flusso e passare da lì.
James,

Risposte:


6

Il metodo che ho implementato in un paio di lingue e credo che ESRI usi (scusate, nessun riferimento diverso da Jenson e Domingue citati altrove in questa pagina) è quello di iniziare da una cella "pour-point" o da una cella fornita dall'utente sul bordo della griglia di direzione del flusso (fdr), esaminare i suoi otto vicini per trovare quale di questi flussi diretti nella cella corrente e assegnare quelle celle all'attuale "spartiacque" nella griglia di uscita. Quindi la funzione si chiama ricorsivamente una volta per ciascuno dei vicini affluenti. Questo processo si ripete fino a quando tutte le celle in afflusso sono esaurite per un punto di scorrimento, quindi si ripeterà per tutti i punti di scorrimento.

Il design dell'algoritmo ricorsivo può essere piuttosto costoso perché può finire per provare a conservare molti dati in memoria, dover scambiare / pagina sul disco e quindi generalmente subire rallentamenti di I / O.

(vedi il commento di Whuber sotto sui diversi metodi di ricorsione, se vuoi RYO)

_____________ MODIFICA _____________

Scoperto il mio vecchio codice C come esempio (nota: anche se la maggior parte dei pitoni potrebbe voler correre dalla stanza, non dovrebbe essere troppo male). Ho pensato che potesse essere interessante illustrare. Anche se sono solo ora superficialmente familiare con ampiezza prima e profonda ricorsione, sto pensando che la mia routine è davvero la prima (e che la mia descrizione del linguaggio naturale sopra era fuorviante) basata su questo post di stackoverflow (si spera @ whuber o un'altra persona più intelligente di me possono confermare / negare).

Codice: spiegazione: idirè il raster dei valori della direzione del flusso. offsetsi riferisce alla cella centrale attualmente in fase di analisi e offcontrolla ciascuno dei vicini di quella cella. Ciò chiama un'altra funzione, does_it_flow_into_meche restituisce un valore booleano sul fatto che il flowdir della cella vicina punti alla cella corrente. Se è vero per un vicino, ricorrere a quel luogo.

void shed(int init_x, int init_y, int basin_id){

int i, j, offset, off, flow_dir;

offset = ((init_y - 1) * nc) + (init_x - 1);
*(basin + offset) = basin_id;


/* kernel analysis */
for (i = -1; i <  2; i++) {
    for (j = -1; j <  2; j++) {
        if ((i) || (j)) {

            off = offset + (j * nc +  i);
            flow_dir = *(idir + off);


            if (does_it_flow_into_me(i,j,flow_dir)){
                shed(init_x+i, init_y+j,basin_id);
            }
        } /*not center */
    } /* do - j */
} /* do - i */
}

Descrivi l'ampiezza della prima ricorsione. Per mezzo di un piccolo stack è possibile implementare un'efficace ricorsione in profondità, che richiede poca memoria. Il problema principale delle prestazioni riguarderebbe i grandi bacini idrografici in cui i pannelli della griglia potrebbero essere scambiati e rimossi ripetutamente dalla RAM. Come discusso nei commenti ad altre risposte, tuttavia, il vero problema riguarda la gestione delle celle in cui non esiste una direzione D8 determinata in modo univoco, in particolare le cellule che si trovano all'interno di ampie toppe orizzontali piatte (come quelle create da routine preliminari di riempimento del lavandino).
whuber

Sicuramente un problema di immondizia in-garbage out. Quello che io e la maggior parte delle ragazze non riusciamo a ripulire l'input! Sembra che devo andare a cercare la prima ricorsione in profondità per mettere un po 'di smalto sul mio trucco.
Roland,

Non penso che si tratti di immondizia - ricorda, indipendentemente da come l'implementazione è scomposta, l'input originale è lo stesso DEM piuttosto che la codifica D8 di qualcuno - ma è sicuramente una sfida. Il mondo reale ha molti luoghi così piatti che la direzione del flusso è difficile da determinare: qualsiasi corpo idrico statico è un buon esempio. In effetti, devi trovare sbocchi di laghi e altre aree pianeggianti e devi affrontare aree piane che hanno più sbocchi. Ciò richiede ricerche non locali , che sono difficili da fare.
whuber

Probabilmente sono confuso allora. Sto pensando che stiamo discutendo help.arcgis.com/en/arcgisdesktop/10.0/help../index.html#//… , che prende flowdir come input. Non voglio trascinarci tra le erbacce se non ho letto il resto abbastanza da vicino!
Roland,

No, penso che tu abbia ragione: mentre rileggo la domanda, vedo che si concentra specificamente sull'elaborazione della direzione del flusso come input, piuttosto che sulla situazione più generale che stavo immaginando. Quindi +1 alla tua risposta per indirizzarla direttamente e con approfondimenti e consigli utili.
whuber

4

La guida di ArcGIS dice:

Gli spartiacque possono essere delineati da un DEM calcolando la direzione del flusso e utilizzandolo nello strumento Spartiacque. Per determinare l'area che contribuisce, un raster che rappresenta la direzione del flusso deve prima essere creato con lo strumento Direzione flusso.

La direzione del flusso viene calcolata dal DEM utilizzando il metodo D8 , dove il flusso viene estratto calcolando per ogni cella, a quale dei suoi 8 vicini, fluirà l'acqua da questa cella.

Esistono molte alternative a D8, come Rho8, Froh8 e Stream Tubes, ma la maggior parte dei software GIS, incluso ArcGIS, tende a utilizzare D8, poiché è più semplice e meno intensivo dal punto di vista computazionale rispetto ad altri.


Alcuni anni fa, stavo lavorando a un progetto Watershed Delineation e stavamo affrontando diversi problemi dovuti ad ArcGIS usando il metodo D8. I due problemi principali erano

  • D8 consente solo il flusso direzionale Uni. L'acqua può defluire solo in una direzione da una cella.
  • I flussi di flusso generati presentavano un'enorme distorsione lungo l'asse diagonale. Ciò ha dato origine a flussi dall'aspetto strano.

Dai nostri dati, sapevamo che questi due problemi erano grandi problemi, quindi avevo sviluppato alcuni strumenti per generare direzioni di flusso usando metodi ibridi.

Uno dei miei primi compiti era l'ingegnerizzazione inversa dello strumento di calcolo delle catture. Ho scoperto che era logicamente abbastanza semplice. Se desideri trovare il bacino per un dato punto (chiamato anche punto di scorrimento), devi prima trovare la cella a cui appartiene. Spesso tenterai di agganciarlo al punto con l'accumulo di flusso più elevato in una determinata tolleranza.

Per questa cella troverai tutte le celle nel vicinato che contribuiscono ad esso. Per ciascuna di queste celle di quartiere, trovi le celle che contribuiscono a loro e così via. Continui questo processo iterativo fino a quando non trovi nuove celle. Questo è quando hai raggiunto le linee di cresta o il limite dello spartiacque.

Ho scoperto che il mio semplice codice che ha fatto questo per i raster ASCII, ha prodotto risultati quasi simili rispetto allo strumento Watershed di ArcGIS. A volte c'era una differenza di alcune celle al limite, quindi sono convinto che ArcGIS segua un algoritmo D8 non modificato.


Grazie per l'elaborazione. Ma qual è l'algoritmo per usare le direzioni D8 per trovare spartiacque? Si prega di vedere i commenti che seguono la risposta di Dmahr .
whuber

Ciao, grazie, ma questo non risponde davvero alla domanda. Ci colpisci con la frase "Per questa cellula troverai tutte le celle del vicinato che contribuiscono ad esso. Per ciascuna di queste celle del vicinato, trovi le cellule che contribuiscono ad esse e così via". Esistono molti algoritmi diversi per implementare quella ricerca. La domanda è quale
James,

4

Questo è stato chiesto prima , anche se forse in un contesto leggermente diverso. Tutti gli strumenti di geoprocessing nel set di strumenti idrologici di Analista spaziale utilizzano il modello di direzione del flusso D8 , come indicato nella pagina Funzionamento della direzione del flusso :

Esistono otto direzioni di uscita valide relative alle otto celle adiacenti in cui il flusso potrebbe spostarsi. Questo approccio è comunemente indicato come un modello di flusso a otto direzioni (D8) e segue un approccio presentato in Jenson e Domingue (1988).

Una copia del documento Jenson e Domingue (1988) è disponibile qui .

Tutti gli strumenti che utilizzano i raster Direzione flusso come input utilizzano questo modello di direzione flusso per associazione. Ciò include inclusione di spartiacque, accumulo del flusso, lunghezza del flusso, riempimento, ecc.


Quindi suppongo che sarebbe una domanda successiva, come viene modificato l'algoritmo per restituire il bacino?
James,

Lo strumento Watershed consente di spostarsi verso l'alto della direzione del flusso dai punti di scorrimento. È il contrario dello strumento di accumulo del flusso, tranne per il fatto che invece del raster di output che descrive il numero di celle, riporta l'ID del punto di scorrimento.
Dmahr,

1
Ok, immagino di dover essere un po 'più specifico. Conosco il concetto di ciò che fa. Non so quale algoritmo sia implementato. Cioè suppongo che sia una sorta di algoritmo di ricerca, ma potrebbe essere ancora; larghezza prima, profondità prima, approfondimento iterativo profondità prima ecc ...
James

1
grazie dmahr. @whuber: Per quanto ne so, algoritmi di ricerca diversi potrebbero dare risultati leggermente diversi? E sì, trovare un algoritmo generico non è un problema, ma è utile imparare come ESRI gestisce aree specifiche del bacino (come parti piatte di un DTM).
James,

1
James Per favore modifica la tua domanda per chiarire l'ultimo punto, in modo che questo thread smetta di raccogliere risposte altrimenti "inutili D8". (Ciò che è utile sui commenti di D8 è che se si accetta che D8 porta a un grafico di direzione del flusso unico, allora esiste una soluzione unica e corretta al problema di delineazione degli spartiacque, perché gli spartiacque sono proprietà del grafico stesso. Pertanto, se ci sono eventuali ambiguità in cui devono trovarsi (a) nella definizione di "spartiacque", (b) come vengono calcolate le direzioni D8 o (c) come vengono gestite le celle orizzontali (cioè, senza una direzione D8 unica).)
whuber

0

Per riflettere meglio su questa domanda, ho eseguito un'analisi spartiacque in arco: ho preso un DEM (riempito), ho calcolato la direzione del flusso e ho posizionato alcuni punti corrispondenti alle posizioni su una rete di flusso precedentemente calcolata. Ho eseguito lo strumento "spartiacque" e mi ha dato alcuni bei bacini, praticamente coprendo la maggior parte dell'area rimanente "a monte" (come ci si aspetterebbe):

immagine spartiacque

Ho quindi codificato un algoritmo di ricerca rapida in Python (come la risposta sopra), che ispeziona la griglia di direzione del flusso e 'segue' i percorsi del flusso. Per ogni nodo, controllo gli 8 vicini e se un vicino scorre nel nodo corrente, chiamo ricorsivamente la stessa funzione con il nodo vicino dell'input.

Codice pseudo (ish):

class d8():
    def __init__(self, arr):
       self.catchment = set()
       self.arr = arr

    def search(self, node):
        """ Searches all neighbouring nodes to find flow paths """ 

        # add the current node to the catchment
        self.catchment.add(node)

        # search the neighbours, ignore ones we already visited
        for each_neighbour:
            if neighbour is in self.catchment:
               do nothing

            # if the neighbour flows into the current node, visit that neighbour
            elif neighbour_flows_into_me:
               self.search(neighbour)

Ho eseguito quella funzione utilizzando la stessa griglia di input della direzione del flusso e uno degli stessi punti. Il problema è che l'arco restituisce un bacino di circa 40000 celle per quel punto, il mio algoritmo restituisce solo 72 celle.

Qualcuno sa cosa sto facendo di sbagliato?

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.