ArcMap'teki Python betiği içindeki alanı hesapla


14

Python betiğimin içindeki bir çokgenin alanını hesaplamaya çalışıyorum. İkisini birleştirmekten yeni bir çokgen oluşturuyorum ve elde edilen çokgenin alanını çıktı dosyasındaki bir alana eklemek istiyorum. Çokgen normal bir şekil dosyasında saklanır ve yansıtılır. Alan tercihen harita birimlerinde.

Bunun oldukça yaygın ve basit bir görev olduğunu düşünürdüm, ancak birçok Googleing'e rağmen şimdiye kadar çalışan bir çözüm bulamadım.

arcpy.updateCursorHesaplandıktan sonra değeri eklemek için kullanmayı planlıyordum (bu aşamada FC'de yalnızca bir özellik var), bu yüzden en kolayı değişken olarak döndürülebilirse. Aynı görevi gerçekleştiren herhangi bir alternatif çözüm (alan değerini doğru alana almak) da işe yarayacaktır.

Ayrıca Python Alan hesap makinesi denedim. Aşağıdakilerin işe yarayacağını düşündüğüm yardım sayfalarından değiştirildi, ancak şimdiye kadar şans yok.

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

Windows 7'de ArcGIS Basic 10.1 SP1'i Python 2.7 ile çalıştırmak.

Geçerli kodumun ilgili bölümleri şöyle:

#/.../
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 ...

Çıktı türünüz nedir? Shapefile, dosya geodatabase, başka bir şey? Çıktı dosyanız yansıtılıyor veya öngörülüyor mu?
blord-castillo

Ayrıca, kod güncellemesinden biraz daha fazlasını, özellikle de güncellemeyi yapmak için kullandığınız imleci gönderebilir misiniz? Büyük olasılıkla SHAPE@AREAalanı okumak için imlecinizin bir parçası olarak istediğinizi elde edebilirsiniz ; ancak kodun yapısı, bölgenizin yazmak istediğinizle aynı birimlerde olup olmadığına bağlıdır.
blord-castillo

Yanıtlar:


29

Çokgen alanını bulmak ve arcpy ile bir özellik sınıfında saklamak için üç farklı yol vardır: 1) alan hesap makinesi, 2) "klasik" kavisli imleçler ve 3) arcpy.daimleçler. Bunlardan bazıları SearchCursor kullanımı ile ilgili önceki yanıtımdan ödünç alınmıştır .


1. Alan hesaplayıcısı

  • Alan hesap makinesini kullanırken, farklı ifade ayrıştırıcıları kullanan üç farklı ifade türü vardır. Bu, Alan Hesapla coğrafi işleme aracının üçüncü parametresinde belirtilir . Geometry nesnesinin özelliklerine like in kullanarak erişirken, !shape.area!Python 9.3 ayrıştırıcısını kullanmalısınız.

  • Daha önce sahip olduğunuz ifade split()sonucuna bir komut verdi !SHAPE.AREA!. Bu, bir listnesneye dönüştürülemeyen bir Python nesnesi döndürür float.

  • @SQUAREKILOMETERSİfadenizde, Alanı Hesapla yardım sayfasındakiSQUAREKILOMETERS birimlerle değiştirerek , bayrağı kullanarak döndürülen alanın birimini belirtebilirsiniz .

İşte bu yöntem için kullanacağım Python kodu:

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

2. Ark 10.0 - "Klasik" imleçler

  • Klasik imleçler (yani arcpy.UpdateCursor) kullanıldığında imleç nesnesi, yinelenebilir içerikli rownesnelerdir. Geometriyi satırdan almak için getValueve setValueyöntemlerini kullanmanız gerekir (bir geometri nesnesi olarak ve alan değerini rowbir kayan nokta olarak ayarlayın.

  • Çıktı satırınız, siz imleçteki updateRowyöntemi çağırıncaya kadar geçici bir çizik alanında saklanır . Bu, yeni verileri gerçek veri kümesine kaydeder.

İşte bu yöntem için kullanacağım Python kodu:

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 imleçler

  • Veri erişim modülünde (yani arcpy.da.UpdateCursor) yeni imleçleri kullanırken , imleç yapıcısında ikinci parametre olarak alan adları listesini iletmeniz gerekir. Bu, daha önce biraz daha çalışma gerektirir, ancak sonuçta elde edilen rownesneler, imleç satırları üzerinden yineleme yaparken veri okumayı ve yazmayı kolaylaştıran Python listeleridir. kısmen önemsiz alanları, özellikle geometriyi atladığından arcpy.da.UpdateCursordaha iyi bir performansa sahiptir arcpy.UpdateCursor.

  • Geometriyi okurken, geometri birkaç jeton birini, mesela seçebilir SHAPE@TRUECENTROID, SHAPE@AREAya da SHAPE@. "Daha basit" bir simge kullanmak SHAPE@, tüm geometri bilgilerini içeren performansa kıyasla büyük ölçüde iyileştirir . Jetonların tam listesi arcpy.da.UpdateCursoryardım sayfasındadır.

  • Daha önce olduğu gibi, siz imleçteki updateRowyöntemi çağırana kadar çıktı satırınız geçici bir çizik alanında saklanır . Bu, yeni verileri gerçek veri kümesine kaydeder.

İşte bu yöntem için kullanacağım Python kodu:

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
Harika cevap. Sadece 10.2'den itibaren, row[1] = row[0]artık bir areaözellik olmadığı için yapacağınızı söylemek istedim . İmleci bir withdeyimde bağlam yöneticisi olarak da kullanabilirsiniz ve hiçbir şeyi silme konusunda endişelenmenize gerek yoktur.
Paul H
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.