Movendo / localizando pontos de deslocamento usando ArcPy ou ModelBuilder?

10

Eu tenho várias camadas de CAD não georreferenciadas (consulte esta pergunta ) que possuem recursos de anotação de texto. Criei um modelo para converter o texto em pontos, mas depois de converter a anotação em uma classe de característica de ponto, vejo que os pontos de ancoragem do texto do CAD não coincidem com o centro do texto do CAD (onde os pontos pertencem).

Portanto, gostaria de programar (usando ArcPy ou ModelBuilder) [mover] um recurso em relação à sua localização atual (delta x, y) usando um valor X, Y medido que fornecerei.

Isso me permitiria mover os pontos GIS de volta para onde eles pertencem, em vez do ponto de ancoragem de deslocamento do CAD.

Como posso realizar esta tarefa?


O @PolyGeo deu uma excelente resposta usando o SHAPE @ XY IN 10.1, mas atualmente estou executando o 10.0. Alguma idéia 10.0?

RyanKDalton
fonte

Respostas:

17

Esse código deve ser feito usando o token SHAPE @ XY que acompanha o arcpy.da.UpdateCursor no ArcGIS 10.1.

import arcpy
# Set some variables
fc = r"C:\temp\test.gdb\testFC"
fc2 = r"C:\temp\test.gdb\testFCcopy"
xOffset = 0.001
yOffset = 0.001
# Code to make a copy which will have its coordinates moved (and can be compared with original)
if arcpy.Exists(fc2):
    arcpy.Delete_management(fc2)
arcpy.Copy_management(fc,fc2)
# Perform the move
with arcpy.da.UpdateCursor(fc2, ["SHAPE@XY"]) as cursor:
    for row in cursor:
        cursor.updateRow([[row[0][0] + xOffset,row[0][1] + yOffset]])

O padrão de codificação usado aqui veio do ArcPy Café .

PolyGeo
fonte
Ugh! Levei até esta manhã para perceber que o SHAPE @ XY só está disponível na 10.1 e minha empresa ainda está usando a 10.0. Esta é uma ótima resposta (daqui para frente), mas vou esperar e ver se alguém tem alguma sugestão para a 10.0. Obrigado!
RyanKDalton
Mais informações sobre um processo semelhante para quem está lendo isso. Ainda 10.1. arcpy.wordpress.com/2013/06/07/disperse-overlapping-points
theJones
Isso realmente está definindo os valores em algum lugar? Nunca usei o UpdateCursor assim antes. Normalmente eu faço + = e atualizo a linha. Caso contrário, a única coisa que faço diferente na minha versão é que o UpdateCursor usa ['SHAPE @ X', 'SHAPE @ Y'] para que você possa acessá-los como linha [0] e linha [1] em vez de precisar fazer a linha [0 ] [0] e linha [0] [1]. Acho que é um pouco mais fácil de ler para mim.
eseglem
Sim, essa é uma maneira válida de atualizar as linhas. Na verdade, eu nunca tinha visto um valor passado em updateRow () até algumas semanas atrás. Na verdade, foi um exemplo para atualizar a geometria.
Paulo
Muito obrigado pela sua resposta PolyGeo! Fiquei bastante impressionado com o fato de o código funcionar sem modificações. Estou executando o ArcGIS Desktop 10.6
Rie Mino
8

Eu credito à @ artwork21 por me levar à minha solução final. Na verdade, encontrei um script quase completo no artigo de ajuda on-line do ArcGIS 10.0, chamado " Calcular exemplos de campos ", listado na subcategoria " Amostras de código - geometria " e " Para uma classe de recurso de ponto, altere a coordenada x de cada ponto em 100 "

O script final que usei na ferramenta "Calcular campo" do ModelBuilder foi:

Expressão:

shiftXYCoordinates(!SHAPE!,%ShiftX%,%ShiftY%)

onde ShiftX e ShiftY são variáveis ​​(como parâmetros) definidas na tela do ModelBuilder.

Tipo de expressão:

PYTHON_9.3

Bloco de código:

def shiftXYCoordinates(shape,x_shift,y_shift):
   point = shape.getPart(0)
   point.X += float(x_shift)
   point.Y += float(y_shift)
   return point

Como todos os modelos funcionam em um conjunto selecionado, você também deve poder criar isso como uma ferramenta genérica que funcionará em conjunto com outros modelos / ferramentas em outras sessões do modelbuilder. O modelo muito simples que criei (como um "plug-in" para outros modelos para alterar os valores das coordenadas) se parece com isso. Dessa forma, eu posso controlar a mudança de acordo com o conjunto de seleção (conforme definido em outros modelos):

ShiftXY Model

Funcionou como um encanto, obrigado a todos por sua contribuição!

RyanKDalton
fonte
é possível mudar o recurso pelo valor dentro da tabela, armazenado na coluna?
Losbaltica
1
Deveria ser. Basta atribuir os parâmetros ShiftX e ShiftY às colunas apropriadas.
21919 RyanKDalton #
Estou confuso com o que você está passando aqui como "forma". Você pode me ajudar por favor?
Jbchurchill
A "Expressão" mostra os parâmetros que estão sendo passados ​​para a função de bloco de código chamada shiftXYCoordinates (). Portanto, o primeiro parâmetro é! SHAPE !, que é o campo de forma da camada.
RyanKDalton
5

Você também pode usar este script da calculadora de campo para mover os locais dos recursos:

def XYsetVALUE( shape, X_value, Y_value): 
  myMoveX = 0.001
  myMoveY = 0.001
  point = shape.getPart(0) 
  point.X = X_value + myMoveX
  point.Y = Y_value + myMoveY
  return point 

XYsetVALUE (! SHAPE !,! X_COORD !,! Y_COORD!)

Você pode incluir um método extra Calcular campo em seu modelo usando a função acima.

artwork21
fonte
É uma maneira interessante de fazer isso, eu realmente não sabia que você poderia calcular em campo no campo de forma. Essa pode ser a maneira mais fácil de fazer isso, se for um deslocamento definido para todos os pontos. Provavelmente seria mais rápido executar point.X + = myMoveX e point.Y + = myMoveY em vez de precisar passar as coordenadas X e Y para ele.
eseglem
5

Eu adaptei a solução para mover / mudar pontos apontam para uma certa direção (ângulo) e uma determinada distância.

Parece:

def shiftXYCoordinates(shape,angle,distance):
point = shape.getPart(0)
point.Y += distance * math.cos(math.radians(angle))
point.X += distance * math.sin(math.radians(angle))
return point

e seja chamado como shiftXYCoordinates (! SHAPE !,! Angle!, 5000), se você tiver um “ângulo” de campo para os recursos de seus pontos (ou com uma constante, é claro). O ângulo deve ser dado em graus decimais. 0 mudará "para cima", 90 "para a direita" etc. Eu os obtive após criar recursos de índice de mapa de faixa e convertê-los em pontos.

Certifique-se também de selecionar o Nome do campo "Forma" antes de executar :)

(Solução testada no ArcMap 10.0 SP5)

kgl
fonte
4

Como você pode ver, é muito mais fácil na versão 10.1 quando você obtém acesso aos tokens do cursor.

import arcpy
# Code to move features in copy of same dataset
fc = r"C:\temp\test.gdb\testFC"
fc2 = r"C:\temp\test.gdb\testFCcopy"
xOffset = 0.001
yOffset = 0.001
if arcpy.Exists(fc2):
    arcpy.Delete_management(fc2)
arcpy.Copy_management(fc, fc2)

shape = arcpy.Describe(fc2).ShapeFieldName

cursor = arcpy.UpdateCursor(fc2)
for row in cursor:    
    point = row.getValue(shape).getPart()
    row.setValue(shape, arcpy.Point(point.X + xOffset, point.Y + yOffset))
    cursor.updateRow(row) 

del point, row, cursor
Paulo
fonte
2

Isso funciona para 10.0:

# Featureclass here
FC = r'featureclass'

fcount = 0
shapefield = arcpy.Describe(FC).shapeFieldName
featureUpdate = arcpy.UpdateCursor(FC)
for f in featureUpdate:
    # Hard coded shifts but easy enough to set up a lookup function if needed
    sLon = 0.001
    sLat = 0.001
    # Optional but I like to count to see where it is at in the process
    if fcount % 1000 == 0:
        print('Updating feature %s...' %(fcount))
    # Get the original value
    cF = f.getValue(shapefield)
    cPNT = cF.getPart()
    # Create a new point with the shifted value
    sPNT = arcpy.Point(cPNT.X - sLon, cPNT.Y - sLAT)
    # Set the shapefield to the new point and update feature
    f.setValue(shapefield, sPNT)
    featureUpdate.updateRow(f)
    fcount += 1
del featureUpdate
eseglem
fonte