ArcGIS二次开发——面要素等面积分割

ArcGIS二次开发——面要素等面积分割


  本文使用的ArcGIS版本为10.5,python为ArcGIS10.5自带的python(32位2.7.12)。读者如果不想自己写代码,可以修改代码中的polygon、spiltNum和step三个参数,运行结果将保存在当前脚本所在目录下,文件名为result.shp。本教程示例代码运行的结果有一定误差,但可以将误差减小最小,详见输入参数介绍。
  本教程所使用的示例代码可能不是很专业,因在实际工作中需要这样的功能,想到的办法。如果你有更好的面要素等面积分割方法欢迎在下方留言。
  polygon表示需要拆分的要素,可以是一个shp文件中包含多个polygon。
  spiltNum表示将每个多边形分成多少份。
  step的含义是:示例代码主要原理是对多边形从左向右扫描的过程,指针不是匀速向右进行,step代表了每次向右的距离,step值越小等面积分割的误差越小,程序运行时间越长。具体step的取值还要参考输入要素的坐标系统,不同坐标系统及地理坐标和投影的情况下差异较大,当然step粗略值的获取对于我们学地理信息专业的人来说几乎没有难度。

# -*- coding: utf-8 -*-
import os
import shapefile

def polygonsplit(polygon, spiltNum, step, outputFile, path_now):
    try:
        arcpy.AddField_management(polygon, "area", "DOUBLE", 18)
    except:
        print(u"面积字段已经存在")
    arcpy.CalculateField_management(polygon, "area", "!shape.geodesicArea@SQUAREKILOMETERS!", "PYTHON_9.3")
    area = 0
    with arcpy.da.SearchCursor(polygon, "area") as cursor:
        for row in cursor:
            area = row[0]
    print(u"总面积:" + str(area))
    print(u"每块面积:" + str(area / spiltNum))

    file = shapefile.Reader(polygon)
    shapes = file.shapes()
    print(file.bbox)
    topx = file.bbox[0]
    topy = file.bbox[3]
    buttonx = file.bbox[0]
    buttony = file.bbox[1]
    ltopx = file.bbox[0]
    ltopy = file.bbox[3]
    lbuttonx = file.bbox[0]
    lbuttony = file.bbox[1]
    tmparea = 0

    topx = file.bbox[0]
    topy = file.bbox[3]
    buttonx = file.bbox[0]
    buttony = file.bbox[1]
    
    for i in xrange(spiltNum):
        tmponesplitarea = 0
        print(tmponesplitarea)
        print(tmparea)
        if i < spiltNum - 1:
            while tmponesplitarea < (area / spiltNum):
                topx = topx + step
                topy = topy
                buttonx = buttonx + step
                buttony = buttony

                print(ltopx, ltopy)
                print(lbuttonx, lbuttony)
                
                print(topx, topy)
                print(buttonx, buttony)
            
                in_table = open("in_table.csv", "w")
                in_table.write("x_coords, y_coords\n")
                in_table.write("%s,%s\n" % (lbuttonx, lbuttony))
                in_table.write("%s,%s\n" % (buttonx, buttony))
                in_table.write("%s,%s\n" % (topx, topy))
                in_table.write("%s,%s\n" % (ltopx, ltopy))
                
                in_table.close()

                spRef = polygon[:-3] + "prj"

                out_Layer = "in_memory\\firestations_layer"
                arcpy.MakeXYEventLayer_management("in_table.csv", "x_coords", "y_coords", out_Layer, spRef)
            
                arcpy.PointsToLine_management(out_Layer, "in_memory\\PointsToLine_management", "", "", "CLOSE")

                arcpy.FeatureToPolygon_management("in_memory\\PointsToLine_management", "in_memory\\FeatureToPolygon_management", "", "ATTRIBUTES", "")

                arcpy.Clip_analysis(polygon, "in_memory\\FeatureToPolygon_management", r"data\\tmpresult.gdb\\Clip_analysis" + str(i), "")

                arcpy.Delete_management("in_memory\\PointsToLine_management")

                try:
                    arcpy.AddField_management(r"data\\tmpresult.gdb\\Clip_analysis" + str(i), "area", "DOUBLE", 18)
                except:
                    print(u"面积字段已经存在")

                arcpy.CalculateField_management(r"data\\tmpresult.gdb\\Clip_analysis" + str(i), "area", "!shape.geodesicArea@SQUAREKILOMETERS!", "PYTHON_9.3")
                
                with arcpy.da.SearchCursor(r"data\\tmpresult.gdb\\Clip_analysis" + str(i), "area") as cursor:
                    for row in cursor:
                        tmponesplitarea = row[0]
                print(u"临时面积:" + str(tmponesplitarea))
            ltopx = topx
            ltopy = topy
            lbuttonx = buttonx
            lbuttony = buttony
        else:
            print(ltopx, ltopy)
            print(lbuttonx, lbuttony)
            
            print(topx, topy)
            print(buttonx, buttony)
            
            in_table = open("in_table.csv", "w")
            in_table.write("x_coords, y_coords\n")
            in_table.write("%s,%s\n" % (buttonx, buttony))
            in_table.write("%s,%s\n" % (file.bbox[2], file.bbox[1]))
            in_table.write("%s,%s\n" % (file.bbox[2], file.bbox[3]))
            in_table.write("%s,%s\n" % (topx, topy))
            
            in_table.close()

            spRef = polygon[:-3] + "prj"

            out_Layer = "in_memory\\firestations_layer"
            arcpy.MakeXYEventLayer_management("in_table.csv", "x_coords", "y_coords", out_Layer, spRef)
        
            arcpy.PointsToLine_management(out_Layer, "in_memory\\PointsToLine_management", "", "", "CLOSE")

            arcpy.FeatureToPolygon_management("in_memory\\PointsToLine_management", "in_memory\\FeatureToPolygon_management", "", "ATTRIBUTES", "")

            arcpy.Clip_analysis(polygon, "in_memory\\FeatureToPolygon_management", r"data\\tmpresult.gdb\\Clip_analysis" + str(i), "")

            arcpy.Delete_management("in_memory\\PointsToLine_management")
            arcpy.Delete_management("in_memory\\FeatureToPolygon_management")

            try:
                arcpy.AddField_management(r"data\\tmpresult.gdb\\Clip_analysis" + str(i), "area", "DOUBLE", 18)
            except:
                print(u"面积字段已经存在")

            arcpy.CalculateField_management(r"data\\tmpresult.gdb\\Clip_analysis" + str(i), "area", "!shape.geodesicArea@SQUAREKILOMETERS!", "PYTHON_9.3")
            
            with arcpy.da.SearchCursor(r"data\\tmpresult.gdb\\Clip_analysis" + str(i), "area") as cursor:
                for row in cursor:
                    tmponesplitarea = row[0]
            print(u"临时面积:" + str(tmponesplitarea))

        #arcpy.Copy_management(r"data\\tmpresult.gdb\\Clip_analysis", "in_memory\\Clip_analysis" + str(i), "ShapeFile")
    inputFile = []
    for i in xrange(spiltNum):
        inputFile.append("data\\tmpresult.gdb\\Clip_analysis" + str(i))
    print(inputFile)
    arcpy.Merge_management(inputFile, outputFile)
    
    #arcpy.Delete_management("data\\tmpresult.gdb\\Clip_analysis")
    try:
        arcpy.Delete_management("data\\tmpresult.gdb")
    except:
        print(u"tmpresult.gdb文件删除失败,但不影响结果")
        
def fucinit(path_now):
    print(u"文件清理")
    gdbFile = path_now + "\\data\\tmpresult.gdb"
    print(gdbFile)
    try:
        arcpy.Delete_management(gdbFile)
        print(u"删除了缓存文件%s" % gdbFile)
        arcpy.CreateFileGDB_management(path_now + "\\data", "tmpresult.gdb")
        print(u"创建了缓存文件%s" % gdbFile)
    except:
        try:
            arcpy.CreateFileGDB_management(path_now + "\\data", "tmpresult.gdb")
            print(u"创建了缓存文件data\\tmpresult.gdb")
        except:
            print(u"缓存文件操作失败,可能导致后面处理的结果不正确")

def splitPolygon(polygon):
    print(u"文件打散")
    shpfilelist = []
    tmpfolder = path_now + "\\data\\tmp"
    if os.path.exists(tmpfolder) == True:
        shutil.rmtree(tmpfolder)
    os.mkdir(tmpfolder)
    arcpy.Split_analysis(polygon, polygon, "name", tmpfolder, "")
    for files in os.walk(tmpfolder):
        for onefile in files[2]:
            if onefile.endswith(".shp"):
                shpfile = files[0] + "\" + onefile
                shpfilelist.append(shpfile)
                print(shpfile)
    return shpfilelist

if __name__ == "__main__":
    import arcpy
    import os
    import shutil

    path_now = os.getcwd()

    arcpy.gp.overwriteOutput=1
    
    polygon = r"data\Export_Output_2.shp"
    spiltNum = 3
    step = 300
    fucinit(path_now)
    splitfilelist = []
    for onepolygon in splitPolygon(polygon):
        outputFile = polygon[:-3] + "_split.shp"
        splitfilelist.append(outputFile)
        polygonsplit(onepolygon, spiltNum, step, outputFile, path_now)

    arcpy.Merge_management(splitfilelist, path_now + "\\result.shp")

源码下载:https://download.csdn.net/download/bpwangxch/11833434

你可能感兴趣的:(python,ArcGIS二次开发)