[ArcPy] 将道路(shp)平均分配给志愿者 生成6*6格网 | 第六届全国大学生GIS技能大赛试题


第六届全国大学生GIS应用技能大赛 下午题目
完整试题:http://www.higis.cn/753

所有文件下载:http://download.csdn.net/download/summer_dew/10164828

前言

题目

创建一个6*6的格网,将商业圈道路数据随机分配到不同的志愿者进行管理

【方法一】用ArcGIS创建渔网-> 将志愿者的编号、道路ID进行连接
【缺点】没有体现随机分配

【方法二】用Arcpy创建每个志愿者的工作范围,并随机生成每个面的ID,达到随机分配的要求

数据说明

road.shp 商业圈道路数据

volunteer.xls 志愿者统计表

分析

问题实际上,就是把道路数据平均分成36块,然后每一块分配一个志愿者

  1. 怎么把道路数据平均分36块:得到道路数据的范围,按范围平均分
  2. 怎么把志愿者分配到每块中:生成一个6*6的随机矩阵,值在0-35之内,并值不能重复。然后将volunteer表格按id连接到里面

结果

ArcPy实现

代码

	# -*- coding:utf-8 -*-
	# Author: PasserQi
	# Time:2017/12/18
	# Func:将shp文件分成6*6份,每份赋予分配0-35中不同的值,输出形式为面状shp
	# Desc:若要创建ArcGIS自定义工具,该文件不能出现中文
	import sys,arcpy
	import arcgisscripting,os
	import random
	
	# 制作ArcGIS自定义工具箱时,得到初始参数
	# filein = sys.argv[1]
	# fileout = sys.argv[2]
	# rowNum = int(sys.argv[3])
	# 测试数据
	filein = r'E:\user\Desktop\RandShp\Data\road.shp'
	fileout = r'E:\user\Desktop\RandShp\rand_polygon.shp'
	number = 6
	
	# @function:产生number*number个不重复的随机数,数值范围在0 <= n <= number-1
	# @param: number
	# @return: list
	def getRandList(number):
	    randList = []
	    while len(randList) != number*number:
	        n = random.randint(0, number*number-1) #产生随机数:0 <= n <= number-1
	        if n in randList: #已经生成过了
	            continue
	        else:
	            randList.append(n)
	    return randList
	
	
	if __name__ == '__main__':
	    desc = arcpy.Describe(filein) #获取shp的信息
	    # shp的范围
	    XMin = desc.extent.XMin
	    XMax = desc.extent.XMax
	    YMin = desc.extent.YMin
	    YMax = desc.extent.YMax
	    step_x = (XMax - XMin) / number # x的步长
	    step_y = (YMax - YMin) / number # y的步长
	
	    #得到number*number个不重复的随机数
	    randList =  getRandList(number)
	
	    # ------------------------------------
	    # 保存成shp文件
	    gp = arcgisscripting.create()
	    # 创建shp文件
	    outWorkspace = os.path.split(fileout)[0]
	    outName = os.path.split(fileout)[-1]
	    spat_ref = desc.spatialReference
	    gp.CreateFeatureClass_management(outWorkspace, outName, "POLYGON", "", "", "", spat_ref)
	    # 添加字段
	    gp.AddField_management(fileout, "number", "LONG")
	    # 获取fileout文件的游标,插入数据
	    cur = gp.InsertCursor(fileout)
	    # 新的一行
	    newRow = cur.newRow()
	    # 插入数据
	    for i in range(0,number):
	        for j in range(0,number):
	            XYarray = gp.CreateObject("array")
	            point = gp.CreateObject("point")
	            # 左下角点
	            point.X = XMin + i*step_x
	            point.Y = YMin + j*step_y
	            XYarray.add(point)
	            # 左上角
	            point.X = XMin + (i + 1) * step_x
	            point.Y = YMin + j * step_y
	            XYarray.add(point)
	            # 右上角
	            point.X = XMin + (i + 1) * step_x
	            point.Y = YMin + (j + 1) * step_y
	            XYarray.add(point)
	            # 右下角
	            point.X = XMin + i * step_x
	            point.Y = YMin + (j+1) * step_y
	            XYarray.add(point)
	            # 左下角点
	            point.X = XMin + i * step_x
	            point.Y = YMin + j * step_y
	            XYarray.add(point)
	
	            newRow.setValue("Shape",XYarray) #实体的形状,面状一定要闭合的点
	            newRow.setValue("number",randList[i*6+j] ) #插入随机分配的值
	            cur.InsertRow(newRow) #新的一行
	    del cur,newRow

制作ArcGIS自定义工具

注意:若要将py文件制作成ArcGIS自定义工具,py文件中不能出现中文字符,否则会有异常错误。这里先将中文字符全部删除,再创建

为road.shp生成6*6的格网

生成的6*6格网

按road.shp范围生成了一个6*6的格网rand_polygon.shp,每个格网都有一个number属性,标识该格分配的志愿者id

连接志愿者表

将voluteer.xls中的id与rand_polygon.shp的number字段连接,可以得到分配的志愿者名字

转载自:https://blog.csdn.net/summer_dew/article/details/78845119

You may also like...

退出移动版