¿Edición de puntos finales en polilínea usando ArcPy?

8

Estoy tratando de hacer una herramienta de ajuste de punto final de polilínea en Python usando ArcGIS 10. usando un Cursor de búsqueda que leí en los valores a una matriz de objetos de línea (que contienen el ID de entidad de la línea y dos objetos "EndPoint" - primero y último, que contiene las coordenadas X e Y de cada uno), luego procese algunos datos de interpolación de los puntos para dar a todos los puntos sus valores correctos.

Hasta ahora, esa parte funciona perfectamente. Sin embargo, cuando intento volver y editar el archivo de forma, puedo ver los datos que estoy cambiando, pero parece que no puedo editarlo.

Aquí está el código para actualizar los campos:

# --------------------------
#
# Update the file with the new EPs
#
# --------------------------

# Create update cursor
#
rows = arcpy.UpdateCursor(outputDirectory + "\\" + trails_fc + ".shp")

# Enter for loop for each feature/row
#
i = 0
for row in rows:
    # Create the geometry object
    #
    feat = row.getValue(shapefieldname)

    partnum = 0

    if feat.getPart(partnum)[0].X != allLines[i].startEP.x:
        arcpy.AddMessage("Change: " + str(feat.getPart(partnum)[0].X) + " to " + str(allLines[i].startEP.x) )
        feat.getPart(partnum)[0].X = allLines[i].startEP.x

    rows.updateRow(row)

    arcpy.AddMessage("Now is: " + str(feat.getPart(partnum)[0].X))

    i+=1

Mi lectura consta de declaraciones como esta:

Cambiar: -105.512166832 a -105.699533165 Ahora es: -105.512166832

Por alguna razón, las filas no se actualizan. Y para mi vida, no puedo encontrar un tutorial o instrucciones sobre cómo editar un punto en particular en una polilínea. Solo puedo encontrar cómo editar un punto como un campo en un archivo de forma de puntos.

¿Alguien tiene alguna idea?

Lobo kivak
fuente
1
¿Solo tiene una licencia ArcView? Si tiene ArcEditor / ArcInfo, ¿qué está tratando de lograr construyendo su propia herramienta de ajuste que la herramienta de geoprocesamiento SNAP de Arc10 no logrará (ArcToolbox> Herramientas de edición)? ( help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#//… )
RyanKDalton
Es posible que haya otra forma, pero estoy tratando de entender cómo manipular las coordenadas, ya sea que la herramienta sea completamente original o no. Es mucho más experiencia que funcionalidad.
Kivak Wolf el

Respuestas:

6

Desafortunadamente, no puede asignar directamente nuevos valores a la geometría existente de una entidad; más bien, debe crear un nuevo objeto de geometría y actualizar el campo de forma de la entidad con ese nuevo objeto. Afortunadamente, los objetos de matriz tienen un replacemétodo. Entonces, en lugar de intentar modificar directamente la coordenada X del punto dentro de la matriz, debe:

  • Cree un nuevo arcpy.Pointobjeto con las coordenadas correctas (parece que ya lo ha hecho)
  • Obtenga una copia del objeto de matriz almacenado en el campo Forma de la fila
  • Use el replacemétodo para establecer el punto deseado en su matriz con su punto modificado
  • Hacer un nuevo objeto Polyline con esa matriz
  • Use el setValuemétodo del objeto de fila para actualizar el campo Forma con su nueva polilínea correcta
  • Use el updateRowmétodo del objeto cursor para insertar la fila modificada en el conjunto de datos.

Concretamente:

for r in cur:
    ary = r.getValue("SHAPE").getPart(0)
    ary.replace(0,correct_point_object) # first arg 0 replaces the first point in the line
    newLine = arcpy.Polyline(ary)
    r.setValue("SHAPE",newLine)
    cur.updateRow(r)

Tenga en cuenta que el replacemétodo toma un índice y un valor. Desafortunadamente, no acepta, por ejemplo, -1 como índice del último punto de la matriz. Sin embargo puedes decir my_array[my_array.count].

Parece que está precalculando las coordenadas X en otro lugar y recuperándolas más tarde. Si este es el caso, probablemente iría por completo y crearía nuevos objetos de polilínea con los puntos correctos para cada línea mientras calcula las coordenadas correctas. Esto probablemente será más fácil y más limpio. De esa manera su código podría ser más como

row_num = 0
    for r in cur:
        r.setValue(shapeField,correct_geometry_list[row_num])
        cur.updateRow(r)
        row_num += 1

Lo cual, al menos para mí, es un poco más claro ... ¡pero eso es estilístico!

Editar para agregar:

No podría encajar esto en un comentario. Sin ver su código, es difícil saber dónde podría estar cayendo. Aquí hay un script completo probado que funciona para mí. Esperemos que sirva de referencia. Tenga en cuenta que aquí estoy calculando la nueva geometría directamente de la anterior, en lugar de hacer dos pasadas; eso puede o no ser posible dependiendo de cómo esté haciendo sus cálculos de posición de ajuste. También esta vez estoy construyendo una nueva matriz basada en la anterior en lugar de usar el replacemétodo, en caso de que sea necesario.

import arcpy

def offsetPoint(old_point,X_distance,Y_distance):
    """Trivial function to offset a point - replace with what you're
actually doing."""
    new_point = arcpy.Point(old_point.X+X_distance,
                            old_point.Y+Y_distance)
    return new_point

def offsetFirstPointInLine(line_geom,X_distance,Y_distance):
    """Takes a Polyline geometry object and returns a new Polyline with
the first point of the first part offset by the distance given."""
    array = line_geom.getPart(0)
    first_point = array[0]
    new_point = offsetPoint(first_point,X_distance,Y_distance)

    # Build a new array with your new point in the 0th position, and
    # the rest of the points from the old array.
    new_array = arcpy.Array([new_point]+
                            [array.getObject(x) for x in range(1,array.count)])

    # Then make a new Polyline object with that array.
    new_line = arcpy.Polyline(new_array)
    return new_line

fc = r"C:\Users\student\Documents\ArcGIS\Default.gdb\SomeStorms"

cur = arcpy.UpdateCursor(fc)

for r in cur:
    geom = r.getValue("SHAPE")
    r.setValue("SHAPE",offsetFirstPointInLine(geom,-45000,-5000))
    cur.updateRow(r)

del r,cur

Esperemos que eso ayude a aclararlo.

ThomM
fuente
Tuve esta sensación de hundimiento que podría ser el caso. ¡Muchas gracias por explicar cómo hacerlo! Creo que crearé las polilíneas enteras como dijiste. De esa forma tengo más control sobre eso si quiero volver y ajustar otra cosa.
Kivak Wolf
Bueno, desafortunadamente no pude hacerlo funcionar. Algo muy extraño está sucediendo. Si uso "ary = r.getValue (" SHAPE "). GetPart (0)" e inmediatamente creo una polilínea a partir de ary y establezco el valor, el archivo de forma se ve completamente diferente. Esto no debería suceder, ¿verdad?
Kivak Wolf el
Es difícil decir qué está mal exactamente; Actualicé la respuesta con una solución más completa en caso de que ayude. En realidad, parece que está creando la matriz y luego modifica el punto; más bien, debe hacer un nuevo punto, luego modificar la matriz para incluir ese punto (o hacer una nueva matriz con ese punto como se indicó anteriormente).
ThomM
ThomM: ¡Gracias por la explicación ampliada! ¡Realmente lo aprecio! Como descubrí ayer, estoy creando arcpy.Array (), arcpy.Point () s, y estoy usando la clase arcpy.Ployline () correctamente. Pero parece que puede haber un error en la programación real del constructor de la clase arcpy.Ployline (). He enviado un informe de error, pero parece que el constructor de arcpy.Polyline () está 'descartando' o ignorando arcpy.Point () s con valores similares pero aún únicos. Entonces, aunque pensé que mi problema era la falta de comprensión de cómo funciona, parece que podría ser un error.
Kivak Wolf