Hitung area dalam skrip Python di ArcMap

14

Saya mencoba menghitung luas poligon dalam skrip Python saya. Saya membuat poligon baru dari menggabungkan keduanya, dan saya ingin menambahkan area poligon yang dihasilkan ke bidang di file output. Poligon disimpan dalam bentuk biasa, dan diproyeksikan. Area sebaiknya dalam unit peta.

Saya akan berpikir ini menjadi tugas yang cukup umum dan sederhana, tetapi meskipun banyak Googleing saya belum dapat menemukan solusi yang berfungsi sejauh ini.

Saya berencana menggunakan arcpy.updateCursoruntuk memasukkan nilai setelah dihitung (hanya ada satu fitur di FC pada tahap ini), jadi yang paling mudah adalah jika dapat dikembalikan sebagai variabel. Solusi alternatif apa pun yang menyelesaikan tugas yang sama (memasukkan nilai area ke bidang yang benar) juga akan berfungsi.

Saya juga telah mencoba kalkulator Field dari Python. Dimodifikasi dari halaman bantuan saya pikir berikut ini akan berhasil, tetapi sejauh ini tidak berhasil.

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

Menjalankan ArcGIS Basic 10.1 SP1 dengan Python 2.7 di Windows 7.

Bagian yang relevan dari kode saya saat ini terlihat seperti ini:

#/.../
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
sumber
Apa tipe output Anda? Shapefile, file geodatabase, sesuatu yang lain? Apakah file output Anda diproyeksikan atau tidak?
blord-castillo
Juga, dapatkah Anda memposting sedikit lebih banyak sampel kode, khususnya kursor yang Anda gunakan untuk melakukan pembaruan? Kemungkinan besar Anda dapat mencapai apa yang ingin Anda gunakan SHAPE@AREAsebagai bagian dari kursor untuk membaca area tersebut; tetapi struktur kode tergantung pada apakah area Anda berada dalam unit yang sama dengan apa yang ingin Anda tulis.
blord-castillo

Jawaban:

29

Ada tiga cara berbeda untuk menemukan dan menyimpan area poligon ke dalam kelas fitur dengan arcpy: 1) bidang kalkulator, 2) kursor "klasik", dan 3) arcpy.dakursor. Beberapa dari ini dipinjam dari jawaban saya sebelumnya tentang menggunakan SearchCursor .


1. Kalkulator bidang

  • Saat menggunakan kalkulator bidang, ada tiga tipe ekspresi berbeda yang menggunakan parser ekspresi berbeda. Ini ditentukan dalam parameter ketiga dari alat geoprocessing Bidang Hitung . Saat mengakses properti dari objek Geometry menggunakan like in !shape.area!, Anda harus menggunakan parser Python 9.3.

  • Ekspresi yang sebelumnya Anda lakukan split()perintah pada hasil !SHAPE.AREA!. Ini mengembalikan listobjek Python , yang tidak bisa dilemparkan ke floatobjek.

  • Dalam ekspresi Anda, Anda dapat menentukan unit area yang dikembalikan dengan menggunakan @SQUAREKILOMETERSbendera, menggantikan SQUAREKILOMETERSdengan unit pada halaman bantuan Hitung Bidang .

Berikut kode Python yang akan saya gunakan untuk metode ini:

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 - kursor "Klasik"

  • Saat menggunakan kursor klasik (yaitu arcpy.UpdateCursor) objek kursor adalah objek berisi iterable row. Anda perlu menggunakan getValuedan setValuemetode untuk mendapatkan geometri dari baris (sebagai objek geometri dan mengatur nilai area ke rowsebagai float.

  • Baris output Anda disimpan dalam ruang awal sementara sampai Anda memanggil updateRowmetode pada kursor. Ini menyimpan data baru ke dalam dataset aktual.

Berikut kode Python yang akan saya gunakan untuk metode ini:

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

  • Saat menggunakan kursor baru dalam modul akses data (yaitu arcpy.da.UpdateCursor), Anda harus memasukkan daftar nama bidang sebagai parameter kedua dalam konstruktor kursor. Ini membutuhkan beberapa pekerjaan di muka, tetapi rowobjek yang dihasilkan adalah daftar Python, yang membuatnya lebih mudah untuk membaca dan menulis data saat iterasi melalui baris kursor. arcpy.da.UpdateCursorjuga memiliki kinerja yang lebih baik daripada arcpy.UpdateCursor, sebagian karena melompati bidang yang tidak penting, terutama geometri.

  • Ketika membaca geometri, Anda dapat memilih salah satu dari sejumlah token geometri, misalnya SHAPE@TRUECENTROID, SHAPE@AREAatau SHAPE@. Menggunakan token "sederhana" sangat meningkatkan kinerja dibandingkan dengan SHAPE@, yang berisi semua informasi geometri. Daftar token lengkap ada di arcpy.da.UpdateCursorhalaman bantuan.

  • Seperti sebelumnya, baris output Anda disimpan dalam ruang awal sementara hingga Anda memanggil updateRowmetode pada kursor. Ini menyimpan data baru ke dalam dataset aktual.

Berikut kode Python yang akan saya gunakan untuk metode ini:

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
sumber
5
Jawaban yang bagus Hanya ingin mengatakan bahwa pada 10.2, Anda hanya akan melakukan row[1] = row[0]karena tidak ada lagi areaatribut. Anda juga dapat menggunakan kursor sebagai manajer konteks dalam withpernyataan dan tidak perlu khawatir menghapus apa pun.
Paul H