¿Desplazamiento / desplazamiento de ubicaciones de puntos con ArcPy o ModelBuilder?

10

Tengo un número de capas CAD no georreferenciadas (vea esta pregunta ) que tienen características de anotación de texto. He creado un modelo para convertir el texto en puntos, pero después de convertir la anotación en una clase de entidad Punto, veo que los puntos de anclaje del texto CAD no coinciden con el centro del texto CAD (que es donde pertenecen los puntos).

Por lo tanto, me gustaría programáticamente (usando ArcPy o ModelBuilder) [mover] una entidad relativa a su ubicación actual (delta x, y) usando un valor X, Y medido que proporcionaré.

Esto me permitiría mover los puntos SIG a donde pertenecen, en lugar del punto de anclaje CAD compensado.

¿Cómo puedo realizar esta tarea?


@PolyGeo dio una excelente respuesta usando SHAPE @ XY IN 10.1, pero actualmente estoy ejecutando 10.0. ¿Alguna idea 10.0?

RyanKDalton
fuente

Respuestas:

17

Este código debe hacerlo utilizando el token SHAPE @ XY que viene con arcpy.da.UpdateCursor en 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]])

El patrón de codificación utilizado aquí proviene de ArcPy Café .

PolyGeo
fuente
Ugh! Me tomó hasta esta mañana darme cuenta de que SHAPE @ XY solo está disponible en 10.1, y mi compañía todavía está usando 10.0. Esta es una gran respuesta (en adelante), pero voy a esperar y ver si alguien tiene alguna sugerencia para 10.0. ¡Gracias!
RyanKDalton
Más información sobre un proceso similar para cualquiera que lea esto. Todavía 10.1. arcpy.wordpress.com/2013/06/07/disperse-overlapping-points
theJones
¿Esto realmente establece los valores en cualquier lugar? Nunca he usado el cursor de actualización de esa manera antes. Por lo general, hago + = y luego actualizo la fila. De lo contrario, lo único que hago diferente en mi versión es que UpdateCursor usa ['SHAPE @ X', 'SHAPE @ Y'] para que pueda acceder a ellos como fila [0] y fila [1] en lugar de tener que hacer la fila [0 ] [0] y fila [0] [1]. Creo que es un poco más fácil de leer para mí.
eseglem
Sí, esa es una forma válida de actualizar las filas. En realidad, nunca había visto pasar un valor en updateRow () hasta hace unas semanas. En realidad fue un ejemplo para actualizar la geometría.
Paul
Muchas gracias por tu respuesta PolyGeo! De hecho, estaba bastante impresionado de que el código funcionara sin modificaciones. Estoy ejecutando ArcGIS Desktop 10.6
Rie Mino
8

Le doy crédito a @ artwork21 por llevarme a mi solución final. En realidad, encontré un script casi completo en el artículo de ayuda en línea de ArcGIS 10.0 llamado " Calcular ejemplos de campo ", que se enumera en la subcategoría " Muestras de código: geometría " y " Para una clase de entidad de punto, cambie la coordenada x de cada punto por 100 "

La secuencia de comandos final que utilicé dentro de la herramienta ModelBuilder "Calcular campo" fue:

Expresión:

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

donde ShiftX y ShiftY son variables (como parámetros) definidas en el lienzo de ModelBuilder.

Tipo de expresión:

PYTHON_9.3

Bloque 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

Dado que todos los modelos funcionan en un conjunto seleccionado, también debería poder crear esto como una herramienta genérica que funcionará junto con otros modelos / herramientas en otras sesiones de modelbuilder. El modelo muy simple que creé (como un "complemento" para otros modelos para cambiar los valores de coordenadas) se ve así. De esa manera puedo controlar el cambio en función de cada conjunto de selección (como se define en otros modelos):

ShiftXY Model

Funcionó de maravilla, ¡gracias a todos por su aporte!

RyanKDalton
fuente
¿Es posible cambiar la función por el valor dentro de la tabla, almacenado en la columna?
Losbaltica 01 de
1
Debería ser. Simplemente asigne los parámetros ShiftX y ShiftY a las columnas apropiadas.
RyanKDalton 01 de
Estoy confundido por lo que estás pasando aquí como "forma". ¿Me puedes ayudar por favor?
jbchurchill
La "Expresión" muestra los parámetros que se pasan a la función de bloque de código llamada shiftXYCoordinates (). Entonces, el primer parámetro es! SHAPE !, que es el campo de forma de la capa.
RyanKDalton
5

También puede usar este script de calculadora de campo para mover ubicaciones de entidades:

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!)

Puede incluir un método adicional Calcular campo dentro de su modelo utilizando la función anterior.

artwork21
fuente
Esa es una forma interesante de hacerlo, en realidad no sabía que podía calcular el campo en el campo de forma. Esta puede ser la forma más fácil de hacerlo si se trata de un desplazamiento establecido para todos los puntos. Probablemente sería más rápido hacer point.X + = myMoveX y point.Y + = myMoveY en lugar de tener que pasar las coordenadas X e Y para ello.
eseglem
5

Adapté la solución para mover / cambiar los puntos en una determinada dirección (ángulo) y una distancia dada.

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

y ser llamado como shiftXYCoordinates (! SHAPE !,! Angle!, 5000), si tiene un "ángulo" de campo para sus entidades de puntos (o con una constante, por supuesto). El ángulo debe darse en grados decimales. 0 se desplazará "hacia arriba", 90 "hacia la derecha", etc. Los obtuve después de crear entidades de índice de mapa de banda y convertirlas en puntos.

También asegúrese de seleccionar el nombre del campo "Forma" antes de ejecutar :)

(Solución probada en ArcMap 10.0 SP5)

kgl
fuente
4

Como puede ver, es mucho más fácil en 10.1 cuando tiene acceso a los tokens de 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
Paul
fuente
2

Esto 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
fuente