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)