Atribuindo IDs de ponto aos respectivos atributos de início e fim da polilinha?

9

Eu tenho dois shapefiles, Point e Polyline. Estou tentando preencher minha camada de polilinha com o ID de dados do ponto (systemID) onde as linhas começam onde terminam; por exemplo. crie duas colunas (de e para). As linhas já têm a direção do fluxo atribuída a elas. Estou usando as ferramentas ArcHydro, mas o Arcpy também é bom.

No ArcHydro, tentei usar as Ferramentas de atributo> Gerar nós de / para linhas, mas ele cria valores para Para e De que não são dos meus dados de ponto. Minha outra alternativa foi usar o Feature to Vertices e associar o resultado à minha tabela de dados do ponto para obter o systemID. Mas então eu teria que atualizar a camada de polilinha também. Estou certo de que existe uma maneira mais fácil de fazê-lo.

Nota: nem todas as linhas têm pontos nos vértices, valores em branco são adequados para eles.

JrUser
fonte
Portanto, seus pontos têm um campo 'systemID' que precisa ser inserido nos campos FNode, TNode nas polilinhas ... está certo?
Michael Stimson
Há uma pergunta como essa por aqui em algum lugar com uma resposta que é basicamente a linha para apontar o início e o fim como classes de recurso separadas, intercepte os dois (individualmente) com os dados do ponto para obter os IDs e junte-os espacialmente às linhas usando a linha ID e atribuição ao campo inicial ou final correto (pode ser um campo calculado aqui). Parece que não consigo encontrá-lo agora. Encontrei enquanto procurava por este .
Chris W
Aqui está: gis.stackexchange.com/questions/85082 E eram os Vértices de recursos para pontos, não de linha ou recursos para pontos. Praticamente o que você mencionou no final da pergunta.
Chris W
@ Chris, eu realmente gosto da resposta da FelixIP sobre essa. São apenas duas associações de atributos.
Michael Stimson

Respostas:

12

Às vezes, é melhor não usar a solução pronta para uso. É por isso que sugiro

  1. Preencha os campos X e Y na camada do nó, converta-os em números inteiros, digamos cm. Crie um campo de sequência e preencha-o concatenando representações de sequência de números inteiros.
  2. Faça algo semelhante na tabela de links para o primeiro ponto na forma.
  3. Associe a tabela de nós aos links usando os campos criados mais recentes e transfira o nodeID para o campo FROM.

Vá para 2, mas use o último ponto para atribuir TO nodeID

FelixIP
fonte
Gosto disso! O campo calcula algo como str (round (! Shape! .FirstPoint.X, 3)) + "," + str (round (! Shape! .FirstPoint.Y, 3)) (analisador Python) para from node, str (round (! Forma! .lastPoint.X, 3)) + "" + str (round (! Forma! .lastPoint.Y, 3)) para a nó, em seguida, semelhante ao ponto (como texto), então junte-se ... Excelente maneira de união espacial sem a dor Felix! Arredonde para dígitos mais significativos para dados geográficos (como 7 ou 8).
Michael Stimson
Extemely rápido como bem em um ambiente de script, onde de substitui curso dicionário mesa lento juntar
FelixIP
Int (X * 100) se eles são projetados em código de metres.Alternaively uso Michael
FelixIP
Definitivamente mais simples do que o método na questão que eu vinculei acima. Menos etapas, menos ferramentas e nenhuma restrição no nível de licença. Ideia interessante de transformar uma junção espacial em uma junção de atributo regular.
Chris W
1

Fiz a mesma coisa há alguns meses. Eu usei o arcpy, mas o script é muito longo para ser postado aqui, então vou dar uma descrição do que fiz.

  1. Usei uma junção espacial para detectar quais pontos / nós estavam dentro de um recurso de linha específico.

  2. Como a junção espacial não leva em consideração a direção do fluxo, usei o arcpy para determinar qual era o ponto inicial e qual era o ponto final. Consegui fazer isso usando a função de descrição arcpy para extrair informações de coordenadas dos vértices de início / fim do recurso de linha e compará-las com os valores de coordenadas dos pontos conectados.

  3. Por fim, depois de descobrir quais dos pontos de / para os quais usei a função setValue para preencher os campos de / para no conjunto de dados da polilinha original.

Obviamente, há um pouco mais do que isso, mas eu descrevi os pontos principais.

Geord359
fonte
Na minha rede geométrica, a direção do fluxo pode estar em qualquer uma das direções principais. Eu não poderia determinar uma direção de fluxo a partir da comparação de coordenadas brutas, a menos que eu também estivesse usando uma varredura de direção de fluxo ou algo equivalente. Até isso pode ser problemático, porque às vezes os tubos são inclinados contra os contornos naturais ou a água é bombeada para cima. Como você pode ter certeza de que sua direção de fluxo está correta?
Priscilla
1

Fui inspirado pelo @FelixIP, mas queria escrever uma solução sem junções ou criação de arquivos extras, pois minha rede é bastante grande com tubos de 400K + e nós de 500K +.

A construção da rede geométrica força o X, Y dos nós e as extremidades do tubo a serem coincidentes. Você pode acessar esses locais com os tokens de forma nos cursores do arco-íris e combiná-los. Os tokens de forma para linhas retornam uma matriz dos vértices na ordem em que foram desenhados. Na minha rede, a ordem de extração dos tubos é altamente controlada por controle de qualidade, porque usamos isso para definir as direções do fluxo. Portanto, o primeiro vértice é o início do tubo, e o último vértice é o fim do tubo.

Referência: ASSETID = identificação do tubo, UNITID = identificação do nó no início do tubo, UNITID2 = identificação do nó no final do 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)
Priscilla
fonte
Isso é 90% do que faço, mas não passo por pipes duas vezes, porque o dicionário de nós já está disponível.
FelixIP