¿Encontrar líneas volteadas en la red geométrica ArcMap?

8

He estado trabajando en un proyecto de trazado de líneas en una red geométrica. He tenido que invertir la dirección de la línea (flujo) en muchas líneas para que funcionen las trazas. Ahora estoy en un punto en el que tengo que actualizar el conjunto de datos maestros y, por lo tanto, hacer esas mismas inversiones de línea en la base de datos.

Mi pensamiento es que ejecutaría un pequeño script arcpy para verificar el / a XY de cada línea contra el / de las líneas coincidentes en el conjunto de datos maestros, cualquiera que tenga el XY que coincida con el maestro de XY (y viceversa -versa) se registraría para voltear.

Aunque creo que este script no debería ser demasiado difícil de escribir, ahora me pregunto si ya hay una herramienta disponible que identifique las líneas invertidas para mí. Todavía no he podido encontrar uno en ArcToolbox, pero puede que esté buscando algo incorrecto.

Tenga en cuenta que hay otros cambios de geometría en mi conjunto de datos que no quiero encontrar, solo líneas coincidentes idénticas (coincidentes en una ID) donde la única diferencia es la dirección. Líneas donde XY es diferente que quiero ignorar.

Por ejemplo, las siguientes líneas muestran la dirección de la línea.

ingrese la descripción de la imagen aquí

Las líneas en el área azul de las que quiero tomar nota, la única diferencia es la dirección de la línea. La línea en el área roja no quiero grabar ya que la línea se ha movido realmente.

ingrese la descripción de la imagen aquí

¿Existe una herramienta en ArcGIS Desktop (10.5) que pueda identificar líneas que se han volteado, pero ignorar otros cambios de geometría? ¿Si es así, Cuál?

Acabo de encontrar la herramienta "Detectar cambios en las funciones", que estoy probando en este momento (es muy, muy lenta). No estoy seguro de si esto va a encontrar solo líneas invertidas, o todo. Por supuesto, puedo haber configurado los parámetros incorrectamente.

La herramienta Detectar cambios de características finalizó el procesamiento, tardó cerca de 20 minutos en ejecutarse, pero solo encontró 9 características en las que la dirección de la línea había cambiado. Espero al menos 10000 funciones invertidas.

Midavalo
fuente
Me sorprende que haya encontrado alguno, porque trata las líneas volteadas como idénticas.
FelixIP
1
@FelixIP Verificar las líneas volteadas es una de las opciones de la herramienta, y las identifica de manera diferente en la salida
Midavalo
Veo. De todos modos tu primera idea es lo que hago. Asigne desde y hacia nodos a ambos conjuntos y lleve el par antiguo a nuevo. Es posible que la herramienta de volteo dentro de fgdb dé como resultado vértices ligeramente diferentes. No es un caso con shapefiles.
FelixIP
¿Podría actualizar un campo con el acimut de la línea y unirlo al original y comparar las diferencias en ese campo?
Fezter
Seleccione idéntico, luego, utilizando un SHAPE @ cusror y el objeto arcpy.geometry, puede obtener el line.firstPoint. esto volverá a seleccionar los que desee.
Ben S Nadler

Respuestas:

3

Yo usaría un diccionario para hacer eso. Me sorprende lo rápido que son.

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
fuente
Realmente logré resolver esto yo mismo en ese momento, pero olvidé actualizar con una respuesta. Voy a ver si puedo encontrar lo que
produje
¡"estos no son los {0} oids que estás buscando"! Jajaja
Fezter