Encontre linhas invertidas na rede geométrica ArcMap?

8

Eu tenho trabalhado em um projeto traçando linhas em uma rede geométrica. Eu tive que inverter a direção da linha (fluxo) em muitas linhas para fazer os traços funcionarem. Agora estou em um ponto em que preciso atualizar o conjunto de dados mestre e, portanto, fazer essas mesmas reversões de linha no banco de dados.

Meu pensamento é que eu executaria um pequeno script arcpy para verificar o / para XY de todas as linhas em relação ao / para as linhas correspondentes no conjunto de dados mestre - qualquer uma com o XY correspondente ao mestre de XY (e vice-versa) -versa) seria gravado para virar.

Embora eu ache que esse script não deve ser muito difícil de escrever, agora estou me perguntando se já existe uma ferramenta disponível para identificar as linhas invertidas para mim. Ainda não encontrei um no ArcToolbox, mas posso estar procurando a coisa errada.

Observe que existem outras alterações geométricas no meu conjunto de dados que não quero encontrar, apenas linhas correspondentes idênticas (correspondidas em um ID) nas quais a única diferença é a direção. Linhas onde XY é diferente, quero ignorar.

Por exemplo, as seguintes linhas mostrando a direção da linha

insira a descrição da imagem aqui

As linhas na área azul que desejo anotar, a única diferença é a direção da linha. A linha na área vermelha não quero ser gravada, pois a linha realmente se moveu.

insira a descrição da imagem aqui

Existe uma ferramenta no ArcGIS Desktop (10.5) que pode identificar linhas que foram invertidas, mas ignora outras alterações na geometria? Se sim, qual?

Acabei de encontrar a ferramenta "Detectar alterações de recursos", que estou testando agora (é muito, muito lenta). Não tenho certeza se isso vai encontrar apenas linhas invertidas, ou tudo. Claro que posso ter definido os parâmetros incorretamente.

A ferramenta Detectar alterações de recurso concluiu o processamento - levou quase 20 minutos para ser executada - mas encontrou apenas 9 recursos em que a direção da linha havia mudado. Estou esperando pelo menos 10.000 recursos invertidos.

Midavalo
fonte
Estou surpreso que tenha encontrado, porque trata as linhas invertidas como idênticas.
FelixIP # 14/17
1
@FelixIP Verificação de linhas capotou é uma das opções da ferramenta, e identifica-los na saída de forma diferente
Midavalo
Eu vejo. Enfim, sua primeira idéia é o que eu faço. Designe nós de e para os dois conjuntos e traga o par antigo para o novo. É possível que a ferramenta flip dentro do fgdb resulte em vértices ligeiramente diferentes. Não é um caso com shapefiles.
FelixIP
Você poderia atualizar um campo com o azimute da linha e associá-lo ao original e comparar as diferenças nesse campo?
Fezter
Selecione idêntico e, em seguida, usando um SHAPE @ cusror e o objeto arcpy.geometry, é possível obter o line.firstPoint. isso irá selecionar novamente os que você deseja.
precisa saber é o seguinte

Respostas:

3

Eu usaria um dicionário para fazer isso. Estou surpreso com a rapidez com que são.

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
fonte
Na verdade, eu mesmo consegui resolver isso na época, mas esqueci de atualizar com uma resposta. Vou ver se consigo encontrar o que produzi e compará-lo com este :) #
Midavalo
'estes não são os {0} oids que você está procurando'! RI MUITO.
Fezter