¿Asignar ID de punto a los respectivos atributos de inicio y fin de la polilínea?

9

Tengo dos shapefiles, Point y Polyline. Estoy tratando de llenar mi capa de polilínea con el ID de datos de punto (systemID) donde las líneas comienzan donde terminan; p.ej. crear dos columnas (desde y hasta). Las líneas ya tienen asignada la dirección del flujo. Estoy usando las herramientas de ArcHydro pero Arcpy también está bien.

En ArcHydro, he intentado usar Herramientas de atributo> Generar nodos de / a para líneas, pero crea valores para To y From que no son de mis datos de puntos. Mi otra alternativa era usar Feature to Vertices y unir el resultado a mi tabla de datos de puntos para obtener el ID del sistema. Pero entonces también tendría que actualizar la capa de polilínea. Estoy seguro de que hay una manera más fácil de hacerlo.

Nota: no todas las líneas tienen puntos en los vértices, los valores en blanco están bien para ellos.

JrUser
fuente
Entonces, sus puntos tienen un campo 'systemID' que debe ir en los campos FNode, TNode en las polilíneas ... ¿es correcto?
Michael Stimson
Hay una pregunta como esta por aquí en algún lugar con una respuesta que es básicamente de principio a fin de línea a punta como clases de entidad separadas, intersecta las dos (individualmente) con los datos de puntos para obtener los identificadores, luego únelos espacialmente a las líneas usando la línea ID y asignación al campo correcto de inicio o finalización (podría ser un campo calculado allí). Sin embargo, parece que no puedo encontrarlo ahora. Lo encontré mientras buscaba este .
Chris W
Aquí está: gis.stackexchange.com/questions/85082 Y fue Feature Vertices a puntos, no líneas o características a puntos. Más o menos lo que mencionas al final de la pregunta.
Chris W
@ Chris, realmente me gusta la respuesta de FelixIP sobre esa. Son solo dos uniones de atributos.
Michael Stimson

Respuestas:

12

A veces es mejor no usar una solución lista para usar. Por eso sugiero

  1. Rellene los campos X e Y en la capa de nodo, conviértalos a enteros, digamos cm. Cree un campo de cadena y complételo concatenando representaciones de cadenas de enteros.
  2. Haga algo similar en la tabla de enlaces para el primer punto de la forma.
  3. Unir la tabla de nodos a enlaces utilizando los campos creados más recientemente y transferir el ID de nodo al campo DESDE.

Ir a 2, pero usar el último punto para asignar TO nodeID

FelixIP
fuente
¡Gusta! El campo calcula algo como str (round (! Shape! .FirstPoint.X, 3)) + "," + str (round (! Shape! .FirstPoint.Y, 3)) (analizador Python) para desde el nodo, str (round (! Shape! .LastPoint.X, 3)) + "," + str (round (! Shape! .LastPoint.Y, 3)) para el nodo, luego similar al punto (como texto) luego únete ... Excelente forma de unión espacial sin el dolor Felix! Redondear a dígitos más significativos para datos geográficos (como 7 u 8).
Michael Stimson
Extremadamente rápido también en un entorno de secuencias de comandos, donde, por supuesto, el diccionario reemplaza la unión de la tabla lenta
FelixIP
Int (X * 100) si se proyectan en metros. Alternativamente use el código de Michael
FelixIP
Definitivamente más simple que el método en la pregunta que he vinculado anteriormente. Menos pasos, menos herramientas y sin restricciones de nivel de licencia. Una idea interesante para convertir una unión espacial en una unión de atributo regular.
Chris W
1

Hice lo mismo hace unos meses. Utilicé arcpy pero el guión es demasiado largo para publicarlo aquí, así que te daré un resumen de lo que hice.

  1. Utilicé una unión espacial para detectar qué puntos / nodos estaban dentro de una entidad de línea particular.

  2. Debido a que la unión espacial no tiene en cuenta la dirección del flujo, utilicé arcpy para determinar cuál era el punto inicial y cuál era el punto final. Pude hacer esto usando la función de descripción arcpy para extraer información de coordenadas para los vértices de inicio / fin de la entidad de línea y los comparé con los valores de coordenadas de los puntos conectados.

  3. Finalmente, una vez que resolví cuáles de los puntos para / desde los cuales usé la función setValue para llenar los campos para / desde en el conjunto de datos de polilínea original.

Obviamente, hay un poco más que esto, pero he esbozado los puntos principales.

Geord359
fuente
En mi red geométrica, la dirección del flujo podría estar en cualquiera de las direcciones cardinales. No podría determinar una dirección de flujo a partir de la comparación de coordenadas sin procesar a menos que también estuviera usando un ráster de dirección de flujo o algo equivalente. Incluso eso puede ser problemático porque a veces las tuberías se inclinan contra los contornos naturales o el agua se bombea cuesta arriba. ¿Cómo puede estar seguro de que su dirección de flujo es correcta?
Priscilla
1

Me inspiré en @FelixIP, pero quería escribir una solución sin combinaciones o la creación de archivos adicionales, ya que mi red es bastante grande con 400K + tuberías y 500K + nodos.

La construcción de la red geométrica obliga a que X, Y de los nodos y los extremos de la tubería coincidan. Puede acceder a estas ubicaciones con los tokens de forma en cursores de arco y combinarlos. Los tokens de forma para líneas devuelven una matriz de vértices en el orden en que fueron dibujados. En mi red, el orden de extracción de las tuberías está fuertemente controlado por calidad porque lo usamos para establecer las direcciones de flujo. Entonces, el primer vértice es el comienzo de la tubería, y el último vértice es el final de la tubería.

Referencia: ASSETID = identificación de la tubería, UNITID = identificación del nodo al inicio de la tubería, UNITID2 = identificación del nodo al final de la tubería.

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)
Priscila
fuente
Esto es el 90% de lo que hago, pero no paso por las tuberías dos veces, porque el diccionario de nodos ya está disponible.
FelixIP