Berechnen Sie die Fläche im Python-Skript in ArcMap

14

Ich versuche, die Fläche eines Polygons in meinem Python-Skript zu berechnen. Ich erstelle ein neues Polygon aus dem Zusammenführen von zwei und möchte den Bereich des resultierenden Polygons einem Feld in der Ausgabedatei hinzufügen. Das Polygon wird in einem regulären Shapefile gespeichert und projiziert. Fläche vorzugsweise in Karteneinheiten.

Ich hätte gedacht, dass dies eine recht häufige und einfache Aufgabe ist, aber trotz viel Googleing konnte ich bisher keine funktionierende Lösung finden.

Ich hatte vor arcpy.updateCursor, den Wert nach seiner Berechnung mit einzufügen (derzeit gibt es nur eine Funktion in der FC). Am einfachsten ist es also, wenn er als Variable zurückgegeben werden kann. Jede alternative Lösung, die dieselbe Aufgabe ausführt (den Bereichswert in das richtige Feld bringen), funktioniert auch.

Ich habe auch den Field-Rechner von Python ausprobiert. Geändert von den Hilfeseiten dachte ich, das folgende würde funktionieren, aber bisher kein Glück.

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

Ausführen von ArcGIS Basic 10.1 SP1 mit Python 2.7 unter Windows 7.

Relevante Teile meines aktuellen Codes sehen folgendermaßen aus:

#/.../
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 ...
Martin
quelle
Was ist Ihr Ausgabetyp? Shapefile, File-Geodatabase, noch etwas? Ist Ihre Ausgabedatei projiziert oder nicht projiziert?
Blord-Castillo
Könnten Sie auch etwas mehr von dem Codebeispiel veröffentlichen, insbesondere den Cursor, mit dem Sie das Update durchführen? Höchstwahrscheinlich können Sie das erreichen, was Sie möchten, indem Sie das SHAPE@AREAals Teil Ihres Cursors zum Lesen des Bereichs verwenden. Die Struktur des Codes hängt jedoch davon ab, ob sich Ihr Gebiet in denselben Einheiten befindet wie das, was Sie ausschreiben möchten.
Blord-Castillo

Antworten:

29

Es gibt drei verschiedene Möglichkeiten, Polygonbereiche mit Arcpy zu finden und in einer Feature-Class zu speichern: 1) Feldrechner, 2) "klassische" Arcpy-Cursor und 3) arcpy.daCursor. Ein Teil davon stammt aus meiner vorherigen Antwort zur Verwendung von SearchCursor .


1. Feldrechner

  • Bei Verwendung des Feldrechners gibt es drei verschiedene Ausdruckstypen, die unterschiedliche Ausdrucksparser verwenden. Dies wird im dritten Parameter des Geoverarbeitungswerkzeugs "Feld berechnen" angegeben . Wenn !shape.area!Sie mit like in auf die Eigenschaften des Geometry-Objekts zugreifen , sollten Sie den Python 9.3-Parser verwenden.

  • Der Ausdruck, den Sie zuvor split()für das Ergebnis von ausgeführt haben !SHAPE.AREA!. Dies gibt ein Python- listObjekt zurück, das nicht in ein floatObjekt umgewandelt werden kann.

  • In Ihrem Ausdruck können Sie die Einheit des zurückgegebenen Bereichs mithilfe des @SQUAREKILOMETERSFlags angeben, das SQUAREKILOMETERSauf der Hilfeseite Feld berechnen durch die Einheiten ersetzt wird .

Hier ist der Python-Code, den ich für diese Methode verwenden würde:

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 - "Klassische" Cursor

  • Bei Verwendung klassischer Cursor (dh arcpy.UpdateCursor) ist das Cursorobjekt ein iterierbares Objekt, das rowObjekte enthält. Sie müssen die Methoden getValueund setValueverwenden, um die Geometrie aus der Zeile (als Geometrieobjekt) abzurufen und den Flächenwert rowals Gleitkommazahl festzulegen.

  • Ihre Ausgabezeile wird in einem temporären Arbeitsbereich gespeichert, bis Sie die updateRowMethode auf dem Cursor aufrufen . Dadurch werden die neuen Daten im tatsächlichen Datensatz gespeichert.

Hier ist der Python-Code, den ich für diese Methode verwenden würde:

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 - arcpy.da-Cursor

  • Wenn Sie die neuen Cursor im Datenzugriffsmodul (dh arcpy.da.UpdateCursor) verwenden, müssen Sie eine Liste von Feldnamen als zweiten Parameter im Cursorkonstruktor übergeben. Dies erfordert etwas mehr Vorarbeit, aber die resultierenden rowObjekte sind Python-Listen, was das Lesen und Schreiben von Daten beim Durchlaufen von Cursorzeilen erleichtert. arcpy.da.UpdateCursorhat auch eine bessere Leistung als arcpy.UpdateCursor, teilweise, weil unwichtige Felder, insbesondere Geometrie, übersprungen werden.

  • Wenn Geometrie lesen, können Sie eine aus einer Reihe von Geometrie Token wählen, zum Beispiel SHAPE@TRUECENTROID, SHAPE@AREAoder SHAPE@. Durch die Verwendung eines "einfacheren" Tokens wird die Leistung im Vergleich zu einem Token SHAPE@, der alle Geometrieinformationen enthält, erheblich verbessert . Die vollständige Liste der Token finden Sie auf der arcpy.da.UpdateCursorHilfeseite.

  • Nach wie vor wird Ihre Ausgabezeile in einem temporären Arbeitsbereich gespeichert, bis Sie die updateRowMethode auf dem Cursor aufrufen . Dadurch werden die neuen Daten im tatsächlichen Datensatz gespeichert.

Hier ist der Python-Code, den ich für diese Methode verwenden würde:

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
dmahr
quelle
5
Wunderbare Antwort. Ich wollte nur sagen, dass Sie ab 10.2 einfach tun würden, row[1] = row[0]weil es kein areaAttribut mehr gibt . Sie können den Cursor auch als Kontextmanager in einer withAnweisung verwenden und müssen sich nicht um das Löschen von Elementen kümmern.
Paul H