Calcola l'area all'interno dello script Python in ArcMap


14

Sto cercando di calcolare l'area di un poligono nel mio script Python. Creo un nuovo poligono dall'unione di due insieme e vorrei aggiungere l'area del poligono risultante a un campo nel file di output. Il poligono viene archiviato in un file di forma regolare e viene proiettato. Area preferibilmente in unità cartografiche.

Avrei pensato che fosse un compito abbastanza comune e semplice, ma nonostante un sacco di Googleing non sono stato finora in grado di trovare soluzioni funzionanti.

Avevo intenzione di utilizzare arcpy.updateCursorper inserire il valore una volta calcolato (in questa fase c'è solo una funzione nell'FC), quindi è più semplice se può essere restituito come variabile. Qualsiasi soluzione alternativa che compie la stessa attività (portando il valore dell'area nel campo corretto) funzionerà anche.

Ho anche provato il calcolatore di campo da Python. Modificato dalle pagine di aiuto, ho pensato che avrebbe funzionato quanto segue, ma finora nessuna fortuna.

arcpy.AddField_management(tempPgs, "Shape_area", 'DOUBLE')
exp = "float(!SHAPE.AREA!.split())"
arcpy.CalculateField_management(tempPgs, "Shape_area", exp)

Esecuzione di ArcGIS Basic 10.1 SP1 con Python 2.7 su Windows 7.

Le parti rilevanti del mio codice attuale si presentano così:

#/.../
arcpy.Copy_management(inpgs, outpgs)
arcpy.AddField_management(outpgs, 'Shape_area', 'LONG')
fields = AM.FieldLst(outpgs)

#/.../

# Identify and search for shapes smaller than minimum area
where1 = '"' + 'Shape_Area' + '" < ' + str(msz)
polyrows = arcpy.SearchCursor(inpgs, where1)

for prow in polyrows:
    grd1 = prow.GridID   # GridID on the current polygon
    grd2 = nDD.get(grd1) # GridID on the polygon downstream

    # Update features
    if grd2
        geometry1 = prow.Shape
        geometry2 = geometryDictionary[grd2]

        # Update temporary features
        arcpy.Merge_management([geometry1, geometry2], tempMerged)
        arcpy.Dissolve_management(tempMerged, tempPgs)

        fds = AM.FieldLst(tempPgs)

        for field in fields[2:]:
            arcpy.AddField_management(tempPgs, field, 'DOUBLE')

        for fd in fds[2:]:
            arcpy.DeleteField_management(tempPgs, fd)

        exp = "float(!SHAPE.AREA!.split())"
        arcpy.CalculateField_management(tempPgs, "Shape_area", exp)

        # Append them to output FC
        try:
            arcpy.Append_management(tempPgs, outpgs, "TEST")
        except arcgisscripting.ExecuteError:
            arcpy.Append_management(tempPgs, outpgs, "NO_TEST")

    elif ...

    else ...

Qual è il tuo tipo di output? Shapefile, file geodatabase, qualcos'altro? Il tuo file di output è proiettato o non proiettato?
blord-castillo,

Inoltre, potresti pubblicare un po 'di più dell'esempio di codice, in particolare il cursore che stai utilizzando per eseguire l'aggiornamento? Molto probabilmente è possibile ottenere ciò che si desidera utilizzando SHAPE@AREAcome parte del cursore per leggere l'area; ma la struttura del codice dipende dal fatto che l'area sia nelle stesse unità di ciò che si desidera scrivere.
blord-castillo,

Risposte:


29

Esistono tre modi diversi per trovare e memorizzare l'area poligonale in una classe di funzioni con arcpy: 1) calcolatrice di campo, 2) cursori arcpy "classici" e 3) arcpy.dacursori. Parte di questo è preso in prestito dalla mia precedente risposta sull'uso di SearchCursor .


1. Calcolatore di campo

  • Quando si utilizza la calcolatrice di campo, esistono tre diversi tipi di espressione che utilizzano diversi parser di espressioni. Questo è specificato nel terzo parametro dello strumento di geoprocessing Calculate Field . Quando accedi alle proprietà dell'oggetto Geometry usando like in !shape.area!, dovresti usare il parser Python 9.3.

  • L'espressione che avevi prima eseguito un split()comando sul risultato di !SHAPE.AREA!. Ciò restituisce un listoggetto Python , che non può essere lanciato in un floatoggetto.

  • Nella tua espressione, puoi specificare l'unità dell'area restituita usando il @SQUAREKILOMETERSflag, sostituendolo SQUAREKILOMETERScon le unità nella pagina di aiuto di Calculate Field .

Ecco il codice Python che userei per questo metodo:

tempPgs = "LayerName"
arcpy.AddField_management(tempPgs, "Shape_area", "DOUBLE")
exp = "!SHAPE.AREA@SQUAREKILOMETERS!"
arcpy.CalculateField_management(tempPgs, "Shape_area", exp, "PYTHON_9.3")

2. Arc 10.0 - Cursori "classici"

  • Quando si utilizzano i cursori classici (ovvero arcpy.UpdateCursor) l'oggetto cursore è un oggetto iterabile contenente rowoggetti. È necessario utilizzare i metodi getValuee setValueper ottenere la geometria dalla riga (come oggetto geometria e impostare il valore dell'area su rowcome float.

  • La riga di output viene archiviata in uno spazio temporaneo temporaneo fino a quando non si chiama il updateRowmetodo sul cursore. Ciò consente di salvare i nuovi dati nel set di dati effettivo.

Ecco il codice Python che userei per questo metodo:

tempPgs = "LayerName"
arcpy.AddField_management(tempPgs, "Shape_area", "DOUBLE")
geometryField = arcpy.Describe(tempPgs).shapeFieldName #Get name of geometry field
cursor = arcpy.UpdateCursor(tempPgs)
for row in cursor:
    AreaValue = row.getValue(geometryField).area #Read area value as double
    row.setValue("Shape_area",AreaValue) #Write area value to field
    cursor.updateRow(row)
del row, cursor #Clean up cursor objects

3. Arc 10.1 - cursori arcpy.da

  • Quando si utilizzano i nuovi cursori nel modulo di accesso ai dati (ad es. arcpy.da.UpdateCursor) È necessario passare un elenco di nomi di campo come secondo parametro nel costruttore del cursore. Ciò richiede un po 'più di lavoro in anticipo, ma gli rowoggetti risultanti sono elenchi Python, il che semplifica la lettura e la scrittura dei dati durante l'iterazione attraverso le righe del cursore. arcpy.da.UpdateCursorha anche prestazioni migliori rispetto arcpy.UpdateCursor, in parte perché salta i campi non importanti, in particolare la geometria.

  • Durante la lettura della geometria, è possibile scegliere uno di una serie di gettoni di geometria, per esempio SHAPE@TRUECENTROID, SHAPE@AREAo SHAPE@. L'uso di un token "più semplice" migliora notevolmente le prestazioni rispetto a SHAPE@, che contiene tutte le informazioni sulla geometria. L'elenco completo dei token è nella arcpy.da.UpdateCursorpagina di aiuto.

  • Come prima, la riga di output viene archiviata in uno spazio temporaneo temporaneo fino a quando non si chiama il updateRowmetodo sul cursore. Ciò consente di salvare i nuovi dati nel set di dati effettivo.

Ecco il codice Python che userei per questo metodo:

tempPgs = "LayerName"
arcpy.AddField_management(tempPgs, "Shape_area", "DOUBLE")
CursorFieldNames = ["SHAPE@AREA","Shape_area"]
cursor = arcpy.da.UpdateCursor(tempPgs,CursorFieldNames)
for row in cursor:
    AreaValue = row[0].area #Read area value as double
    row[1] = AreaValue #Write area value to field
    cursor.updateRow(row)
del row, cursor #Clean up cursor objects

5
Risposta meravigliosa Volevo solo dire che a partire dalla 10.2, faresti semplicemente row[1] = row[0]perché non c'è più un areaattributo. È inoltre possibile utilizzare il cursore come gestore di contesto in withun'istruzione e non doversi preoccupare di eliminare nulla.
Paul H,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.