Affecter des ID de point aux attributs respectifs de début et de fin de la polyligne

9

J'ai deux fichiers de formes, Point et Polyline. J'essaie de remplir ma couche de polyligne avec l'ID de données de point (systemID) où les lignes commencent à leur fin; par exemple. créer deux colonnes (de et vers). Les lignes sont déjà affectées à la direction du flux. J'utilise les outils ArcHydro mais Arcpy est également très bien.

Dans ArcHydro, j'ai essayé d'utiliser Outils d'attributs> Générer des nœuds de / vers pour les lignes, mais cela crée des valeurs pour To et From qui ne sont pas à partir de mes données de point. Mon autre alternative était d'utiliser Feature to Vertices et de joindre le résultat à ma table de données de points pour obtenir l'ID système. Mais je devrais également mettre à jour le calque de polyligne. Je suis sûr qu'il existe un moyen plus simple de le faire.

Remarque: toutes les lignes n'ont pas de points aux sommets, les valeurs vides leur conviennent.

JrUser
la source
Vos points ont donc un champ 'systemID' qui doit aller dans FNode, des champs TNode dans les polylignes ... est-ce vrai?
Michael Stimson
Il y a une question comme celle-ci quelque part avec une réponse qui est essentiellement le début et la fin ligne à point en tant que classes d'entités distinctes, intersectez les deux (individuellement) avec vos données de point pour obtenir les identifiants, puis reliez-les spatialement aux lignes en utilisant la ligne ID et affectation au champ de début ou de fin correct (peut être un champ calculé ici). Je n'arrive pas à le trouver pour l'instant. Je l'ai trouvé en fouillant pour celui-ci .
Chris W
Le voici: gis.stackexchange.com/questions/85082 Et c'était des sommets d'entités aux points, pas des lignes ou des entités aux points. À peu près ce que vous mentionnez à la fin de la question.
Chris W
@ChrisW, j'aime beaucoup la réponse de FelixIP par rapport à celle-là. Ce ne sont que deux jointures d'attributs.
Michael Stimson

Réponses:

12

Parfois, il vaut mieux ne pas utiliser la solution prête à l'emploi. Voilà pourquoi je suggère

  1. Remplissez les champs X et Y dans la couche de nœuds, convertissez-les en entiers, par exemple cm. Créez un champ de chaîne et remplissez-le en concaténant des représentations de chaîne d'entiers.
  2. Faites la même chose dans la table des liens pour le premier point de la forme.
  3. Joignez la table des nœuds aux liens à l'aide des derniers champs créés et transférez nodeID dans le champ FROM.

Aller à 2, mais utiliser le dernier point pour attribuer TO nodeID

FelixIP
la source
J'aime ça! Le champ calcule quelque chose comme str (round (! Shape! .FirstPoint.X, 3)) + "," + str (round (! Shape! .FirstPoint.Y, 3)) (analyseur Python) pour from node, str (round (! Shape! .LastPoint.X, 3)) + "," + str (rond (! Shape! .LastPoint.Y, 3)) pour le nœud, puis similaire au point (sous forme de texte) puis rejoindre ... Excellente façon de rejoindre l'espace sans la douleur Félix! Arrondissez à des chiffres plus significatifs pour les données géographiques (comme 7 ou 8).
Michael Stimson
Extrêmement rapide également dans un environnement de script, où bien sûr le dictionnaire remplace la jointure lente de la table
FelixIP
Int (X * 100) s'ils sont projetés en mètres.Alternativement, utilisez le code de Michael
FelixIP
Certainement plus simple que la méthode de la question que j'ai liée ci-dessus. Moins d'étapes, moins d'outils et aucune restriction de niveau de licence. Idée intéressante pour transformer une jointure spatiale en jointure d'attribut régulière.
Chris W
1

J'ai fait la même chose il y a quelques mois. J'ai utilisé arcpy mais le script est beaucoup trop long pour être posté ici, donc je vais vous donner un aperçu de ce que j'ai fait.

  1. J'ai utilisé une jointure spatiale pour détecter quels points / nœuds se trouvaient dans une entité linéaire particulière.

  2. Étant donné que la jointure spatiale ne prend pas en compte la direction du flux, j'ai utilisé arcpy pour déterminer quel était le point de départ et quel était le point d'arrivée. J'ai pu le faire en utilisant la fonction de description arcpy pour extraire des informations de coordonnées pour les sommets de début / fin de l'entité linéaire et les comparer aux valeurs de coordonnées des points connectés.

  3. Enfin, une fois que j'ai déterminé quels étaient les points de destination / d'arrivée, j'ai utilisé la fonction setValue pour remplir les champs de / vers dans le jeu de données de polyligne d'origine.

De toute évidence, il y a un peu plus que cela, mais j'ai souligné les principaux points.

Geord359
la source
Dans mon réseau géométrique, la direction de l'écoulement pourrait être dans n'importe quelle direction cardinale. Je ne pouvais pas déterminer la direction du flux à partir de la comparaison des coordonnées brutes, sauf si j'utilisais également un raster de direction de flux ou quelque chose d'équivalent. Même cela peut être problématique car parfois les tuyaux sont inclinés contre les contours naturels ou l'eau est pompée en montée. Comment pouvez-vous être certain que votre sens d'écoulement est correct?
Priscilla
1

J'ai été inspiré par @FelixIP, mais je voulais écrire une solution sans jointures ni création de fichiers supplémentaires, car mon réseau est assez grand avec 400K + tubes et 500K + nœuds.

La construction du réseau géométrique oblige les X, Y des nœuds et les extrémités des tuyaux à coïncider. Vous pouvez accéder à ces emplacements avec les jetons de forme dans les curseurs arcpy et les faire correspondre. Les jetons de forme pour les lignes renvoient un tableau des sommets dans l'ordre où ils ont été dessinés. Dans mon réseau, l'ordre de tirage des tuyaux est fortement contrôlé par la qualité, car nous l'utilisons pour définir les directions d'écoulement. Ainsi, le premier sommet est le début du tuyau et le dernier sommet est la fin du tuyau.

Référence: ASSETID = id du tuyau, UNITID = id du nœud au début du tuyau, UNITID2 = id du nœud à la fin du tuyau.

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
la source
C'est 90% de ce que je fais, mais je ne passe pas deux fois par les tuyaux, car le dictionnaire de nœuds est déjà disponible.
FelixIP