在ArcMap中计算Python脚本中的面积


14

我正在尝试在我的Python脚本中计算多边形的面积。我通过将两个多边形合并在一起来创建一个新的多边形,我想将所得多边形的区域添加到输出文件中的字段中。多边形存储在常规shapefile中并进行投影。面积最好以地图为单位。

我本来以为这是一个非常普通和简单的任务,但是尽管谷歌搜索很多,但到目前为止我仍然找不到有效的解决方案。

我打算在arcpy.updateCursor计算完值后立即使用它插入值(此阶段FC中只有一个功能),所以最简单的方法是将其作为变量返回。任何完成相同任务(将面积值输入正确的字段)的替代解决方案也将起作用。

我也尝试过Python的Field计算器。从帮助页面修改后,我认为以下方法会起作用,但到目前为止还算不上什么。

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

在Windows 7上使用Python 2.7运行ArcGIS Basic 10.1 SP1。

我当前代码的相关部分如下所示:

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

您的输出类型是什么?Shapefile,文件地理数据库还有其他东西吗?您的输出文件是投影的还是非投影的?
blord-castillo 2013年

此外,您是否可以发布更多的代码示例,尤其是用于更新的游标?您最有可能使用SHAPE@AREA游标的一部分来读取区域来实现所需的功能。但是代码的结构取决于您所在的区域是否与要写入的区域相同。
blord-castillo 2013年

Answers:


29

使用arcpy有三种不同的方法可以将面区域查找和存储到要素类中:1)字段计算器,2)“经典” arcpy光标和3)arcpy.da光标。其中一些是从我先前有关使用SearchCursor的答案中借用的


1.现场计算器

  • 使用字段计算器时,存在三种使用不同表达式解析器的不同表达式类型。这是在“ 计算字段”地理处理工具的第三个参数中指定的。使用in中的like访问Geometry对象的属性时!shape.area!,应使用Python 9.3解析器。

  • 您之前split()对的结果执行命令的表达式!SHAPE.AREA!。这将返回一个Python list对象,该对象无法转换为float对象。

  • 在表达式中,您可以使用@SQUAREKILOMETERS标志指定返回区域SQUAREKILOMETERS的单位,而用Calculate Field帮助页面上的单位代替。

这是我将用于此方法的Python代码:

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-“经典”光标

  • 使用经典游标时(即arcpy.UpdateCursor),游标对象是一个可迭代的包含row对象。您需要使用getValuesetValue方法从行中获取几何(作为几何对象,并将area值设置row为float)。

  • 输出行将存储在临时暂存空间中,直到您updateRow在游标上调用该方法为止。这会将新数据保存到实际数据集中。

这是我将用于此方法的Python代码:

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游标

  • 在数据访问模块(即arcpy.da.UpdateCursor)中使用新的游标时,您需要传入字段名称列表作为游标构造函数中的第二个参数。这需要先做一些工作,但是生成的row对象是Python列表,这使得遍历游标行时读取和写入数据更加容易。arcpy.da.UpdateCursor还比拥有更好的性能arcpy.UpdateCursor,部分是因为它跳过了不重要的字段,尤其是几何。

  • 当阅读的几何形状,你可以选择一些几何形状的令牌之一,例如SHAPE@TRUECENTROIDSHAPE@AREASHAPE@。与相比SHAPE@,使用“更简单”的令牌可大大提高性能,后者包含所有几何信息。令牌的完整列表在arcpy.da.UpdateCursor帮助页面上。

  • 和以前一样,您的输出行将存储在临时暂存空间中,直到您updateRow在游标上调用该方法为止。这会将新数据保存到实际数据集中。

这是我将用于此方法的Python代码:

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
很棒的答案。只是想说从10.2开始,您将这样做,row[1] = row[0]因为不再有area属性。您还可以将游标用作with语句中的上下文管理器,而不必担心删除任何内容。
Paul H
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.