1. 程式人生 > >[ArcPy] 將道路(shp)平均分配給志願者 生成6*6格網 | 第六屆全國大學生GIS技能大賽試題

[ArcPy] 將道路(shp)平均分配給志願者 生成6*6格網 | 第六屆全國大學生GIS技能大賽試題


所有檔案下載:http://download.csdn.net/download/summer_dew/10164828

前言

題目

建立一個6*6的格網,將商業圈道路資料隨機分配到不同的志願者進行管理

資料說明

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欄位連線,可以得到分配的志願者名字

這裡寫圖片描述