Trouver des lignes inversées dans le réseau géométrique ArcMap?

8

Je travaille sur un projet de traçage de lignes dans un réseau géométrique. J'ai dû inverser la direction de la ligne (débit) sur de nombreuses lignes pour que les traces fonctionnent. Maintenant, je suis à un point où je dois mettre à jour le jeu de données maître, et donc faire ces mêmes inversions de ligne dans la base de données.

Ma pensée est que je lancerais un petit script arcpy pour vérifier le to / from XY pour chaque ligne par rapport au to / from des lignes correspondantes dans le jeu de données maître - tous ceux qui ont le to XY correspondant au maître de XY (et vice -versa) serait enregistré pour retournement.

Bien que je pense que ce script ne devrait pas être trop difficile à écrire, je me demande maintenant s'il existe déjà un outil qui identifiera les lignes inversées pour moi? Je n'ai pas encore pu en trouver dans ArcToolbox, mais je cherche peut-être la mauvaise chose.

Notez qu'il y a d'autres changements de géométrie dans mon jeu de données que je ne veux pas trouver, juste des lignes correspondantes identiques (appariées sur un ID) où la seule différence est la direction. Lignes où XY est différent que je veux ignorer.

Par exemple, les lignes suivantes indiquant la direction de la ligne

entrez la description de l'image ici

Les lignes dans la zone bleue dont je veux prendre note, la seule différence est la direction de la ligne. La ligne dans la zone rouge que je ne veux pas enregistrer car la ligne a effectivement bougé.

entrez la description de l'image ici

Existe-t-il un outil dans ArcGIS Desktop (10.5) qui peut identifier les lignes qui ont été inversées, mais ignorer les autres changements de géométrie? Si oui, lequel?

Je viens de trouver l'outil "Détecter les changements de fonctionnalités", que je teste actuellement (il est très très lent). Je ne sais pas si cela va trouver des lignes inversées, ou tout. Bien sûr, j'ai peut-être mal réglé les paramètres.

L'outil Détecter les changements de fonction a terminé le traitement - il a fallu près de 20 minutes pour s'exécuter - mais n'a trouvé que 9 fonctions dont la direction de la ligne avait changé. J'attends au moins 10000 fonctionnalités inversées.

Midavalo
la source
Je suis surpris qu'il en ait trouvé, car il traite les lignes inversées comme identiques.
FelixIP
1
@FelixIP La vérification des lignes inversées est l'une des options de l'outil, et elle les identifie différemment dans la sortie
Midavalo
Je vois. Quoi qu'il en soit, votre première idée est ce que je fais. Attribuez des nœuds de et vers les deux ensembles et apportez l'ancienne paire à la nouvelle. Il est possible que l'outil de retournement à l'intérieur de fgdb donne des sommets légèrement différents. Pas un cas avec des fichiers de formes.
FelixIP
Pourriez-vous mettre à jour un champ avec l'azimut de la ligne et le joindre à l'original et comparer les différences dans ce champ?
Fezter
Sélectionnez identique, puis en utilisant un SHAPE @ cusror et l'objet arcpy.geometry, vous pouvez obtenir le line.firstPoint. cela va resélectionner ceux que vous voulez.
Ben S Nadler

Réponses:

3

J'utiliserais un dictionnaire pour cela. Je suis surpris de leur rapidité.

import arcpy 

def GetDict(fc,precision):
    fields = ['SHAPE@','OID@']
    # use a dictionary with x1-y1-xn-yn key
    dict = {}
    with arcpy.da.SearchCursor(fc, fields) as cursor:
        for row in cursor:
            fpx = round(row[0].firstPoint.X,precision)
            fpy = round(row[0].firstPoint.Y,precision)
            lpx = round(row[0].lastPoint.X,precision)
            lpy = round(row[0].lastPoint.Y,precision)
            key= u'{0}-{1}-{2}-{3}'.format(fpx,fpy,lpx,lpy)
            if not dict.has_key(key):
                dict[key] = row[0]
    return dict

def GetOIDsOfLinesInNeedofFlipping(fc,dict,precision):
    fields = ['SHAPE@','OID@']
    flipoids = []
    changedoids = [] # polyline has been more than just flipped
    with arcpy.da.SearchCursor(fc, fields) as cursor:
        for row in cursor:
            fpx = round(row[0].firstPoint.X,precision)
            fpy = round(row[0].firstPoint.Y,precision)
            lpx = round(row[0].lastPoint.X,precision)
            lpy = round(row[0].lastPoint.Y,precision)
            ftkey= u'{0}-{1}-{2}-{3}'.format(fpx,fpy,lpx,lpy)
            tfkey= u'{0}-{1}-{2}-{3}'.format(lpx,lpy,fpx,fpy)
            if not dict.has_key(ftkey):
                if dict.has_key(tfkey):
                    flipoids.append(row[1])
                else:
                    changedoids.append(row[1])
    if len(changedoids) > 0:
        print(u'these are not the {0} oids you are looking for'.format(len(changedoids)))
    return flipoids

def FlipPolylines(fc,oids):
    fields = ['SHAPE@','OID@']
    with arcpy.da.UpdateCursor(fc, fields) as cursor:
        for row in cursor:
            if row[1] in oids:
                # https://gis.stackexchange.com/a/67422/59
                if row[0].partCount > 1: 
                    print "Warning: multiple parts! extra parts are automatically trimmed!"
                lp= row[0].getPart(0)
                rPnts=arcpy.Array()
                for i in range(len(lp)): rPnts.append(lp[len(lp)-i-1])
                rPoly=arcpy.Polyline(rPnts)
                row[0] = rPoly
                cursor.updateRow(row)
    return

def main():
    precision = 1
    dict = GetDict(r'H:\filegdbs\sewer.gdb\sewermains',precision) #the "master"
    print(u'keys = {0}'.format(len(dict)))
    oids = GetOIDsOfLinesInNeedofFlipping(r'H:\filegdbs\sewer.gdb\sewermainsflipped',dict,precision)
    print(u'{0} polylines need flipping'.format(len(oids)))
    if len(oids) > 0:
        FlipPolylines(r'H:\filegdbs\sewer.gdb\sewermainsflipped',oids)
    else:
        print("none need flipping")
    return


if __name__ == '__main__':
    main()
Kirk Kuykendall
la source
J'ai réussi à résoudre ce problème moi-même à l'époque, mais j'ai oublié de mettre à jour avec une réponse. Je vais voir si je peux trouver ce que j'ai produit et le comparer à celui-ci :)
Midavalo
'ce ne sont pas les {0} oids que vous recherchez'! LOL.
Fezter