Assegnare ID punto ai rispettivi attributi di inizio e fine della polilinea?


9

Ho due shapefile, Point e Polyline. Sto cercando di popolare il mio livello di polilinea con l'ID dati punto (systemID) dove le linee iniziano a dove finiscono; per esempio. creare due colonne (da e a). Alle linee è già stata assegnata la direzione del flusso. Sto usando gli strumenti ArcHydro ma anche Arcpy va bene.

In ArcHydro ho provato a utilizzare Strumenti di attributo> Genera da / a nodi per le linee ma crea valori per A e Da che non provengono dai miei dati punto. Un'altra mia alternativa era usare Feature to Vertices e unire il risultato alla mia tabella dei dati dei punti per ottenere il systemID. Ma poi dovrei aggiornare anche il livello della polilinea. Sono sicuro che esiste un modo più semplice per farlo.

Nota: non tutte le linee hanno punti sui vertici, i valori vuoti vanno bene per loro.


Quindi i tuoi punti hanno un campo 'systemID' che deve andare in FNode, campi TNode nelle polilinee, giusto?
Michael Stimson,

C'è una domanda come questa qui da qualche parte con una risposta che è fondamentalmente linea a punto inizio e fine come classi di caratteristiche separate, interseca i due (individualmente) con i dati dei punti per ottenere gli ID, quindi spaziali uniscili nuovamente alle linee usando la linea ID e assegnazione al campo iniziale o finale corretto (potrebbe essere un campo calcolato lì). Non riesco a trovarlo in questo momento però. L'ho trovato mentre cercavo questo .
Chris W,

Eccolo: gis.stackexchange.com/questions/85082 Ed è stato Feature Vertices ai punti, non linea o caratteristiche ai punti. Praticamente quello che dici alla fine della domanda.
Chris W,

@ Chris, mi piace molto la risposta di FelixIP su quella. Sono solo due join di attributi.
Michael Stimson,

Risposte:


12

A volte è meglio non usare una soluzione pronta all'uso. Questo è il motivo per cui suggerisco

  1. Compilare i campi X e Y nel livello del nodo, convertirli in numeri interi, ad esempio cm. Crea un campo stringa e popolalo concatenando rappresentazioni di stringa di numeri interi.
  2. Fai qualcosa di simile nella tabella dei collegamenti per il primo punto della forma.
  3. Unisci la tabella dei nodi ai collegamenti utilizzando gli ultimi campi creati e trasferisci nodeID nel campo FROM.

Vai a 2, ma usa l'ultimo punto per assegnare TO nodeID


Mi piace! Il campo calcola qualcosa come str (round (! Shape! .FirstPoint.X, 3)) + "," + str (round (! Shape! .FirstPoint.Y, 3)) (Python parser) per from node, str (round (! Shape! .LastPoint.X, 3)) + "," + str (tondo (! Shape! .LastPoint.Y, 3)) per il nodo, quindi simile al punto (come testo) quindi unisci ... Ottimo modo di unire lo spazio senza il dolore Felix! Arrotondare a cifre più significative per i dati geografici (come 7 o 8).
Michael Stimson,

Estremamente veloce anche in un ambiente di scripting, dove ovviamente il dizionario sostituisce il join lento della tabella
FelixIP,

Int (X * 100) se sono proiettati in metri. Usa il codice di Michael in modo esterno
FelixIP,

Decisamente più semplice del metodo nella domanda che ho collegato sopra. Meno passaggi, meno strumenti e nessuna limitazione del livello di licenza. Interessante idea di trasformare un join spaziale in un normale join di attributi.
Chris W,

1

Ho fatto la stessa cosa qualche mese fa. Ho usato arcpy ma la sceneggiatura è troppo lunga per essere pubblicata qui, quindi ti darò una descrizione di ciò che ho fatto.

  1. Ho usato un join spaziale per rilevare quali punti / nodi erano all'interno di una particolare funzione di linea.

  2. Poiché l'unione spaziale non tiene conto della direzione del flusso, ho usato arcpy per accertare quale fosse il punto iniziale e quale il punto finale. Sono stato in grado di farlo utilizzando la funzione di descrizione arcpy per estrarre le informazioni sulle coordinate per i vertici di inizio / fine della funzione linea e confrontandole con i valori delle coordinate dei punti collegati.

  3. Alla fine, una volta capito quali dei punti da / a erano quali ho usato la funzione setValue per popolare i campi da / a nel set di dati della polilinea originale.

Ovviamente, c'è un po 'più di questo, ma ho delineato i punti principali.


Nella mia rete geometrica, la direzione del flusso potrebbe essere in una qualsiasi delle direzioni cardinali. Non avrei potuto accertare una direzione del flusso dal confronto di coordinate grezze a meno che non stessi usando anche un raster di direzione del flusso o qualcosa di equivalente. Anche questo può essere problematico perché a volte i tubi sono inclinati contro i contorni naturali o l'acqua viene pompata in salita. Come si può essere certi che la direzione del flusso sia corretta?
Priscilla

1

Sono stato ispirato da @FelixIP, ma volevo scrivere una soluzione senza join o la creazione di file extra, poiché la mia rete è abbastanza grande con 400K + pipe e 500K + nodi.

La costruzione della rete geometrica forza la X, Y dei nodi e le estremità del tubo coincidono. Puoi accedere a queste posizioni con i token forma in cursori arcpy e abbinarli. I token di forma per le linee restituiscono una matrice di vertici nell'ordine in cui sono stati disegnati. Nella mia rete, l'ordine di disegno dei tubi è fortemente QA perché lo usiamo per impostare le direzioni del flusso. Quindi, il primo vertice è l'inizio della pipe e l'ultimo vertice è la fine della pipe.

Riferimento: ASSETID = ID del tubo, UNITID = ID nodo all'inizio del tubo, UNITID2 = ID nodo alla fine del tubo.

nodes = "mergeNodes"
pipes = "SEWER_1"

nodeDict = {}
pipeDict = {}

#populate node dictionary with X,Y as the key and node ID as the value
for node in arcpy.da.SearchCursor(nodes, ["UNITID", "SHAPE@XY"]):
    nodeDict[(node[1][0], node[1][1])] = node[0]

#populate pipe dictionary with pipe ID as the key and list of X,Y as values 
#vertices populated in the order that the line was draw
#so that [0] is the first vertex and [-1] is the final vertex
for pipe in arcpy.da.SearchCursor(pipes, ["ASSETID", "SHAPE@"]):
    for arrayOb in pipe[1]:
        for point in arrayOb:
            if pipe[0] in pipeDict:
                pipeDict[pipe[0]].append((point.X, point.Y))
            else: 
                pipeDict[pipe[0]] = [(point.X, point.Y)]

#populate UNITID with the first vertex of the line
#populate UNITID2 with the final vertex of the line
with arcpy.da.UpdateCursor(pipes, ["ASSETID", "UNITID", "UNITID2"]) as cur:
    for pipe in cur:
        if pipeDict[pipe[0]][0] in nodeDict:
            pipe[1] = nodeDict[pipeDict[pipe[0]][0]]
        if pipeDict[pipe[0]][-1] in nodeDict:
            pipe[2] = nodeDict[pipeDict[pipe[0]][-1]]
        cur.updateRow(pipe)

Questo è il 90% di quello che faccio, ma non passo attraverso le pipe due volte, perché il dizionario dei nodi è già disponibile.
FelixIP,
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.