ArcGISPython实习指导讲解.docx
《ArcGISPython实习指导讲解.docx》由会员分享,可在线阅读,更多相关《ArcGISPython实习指导讲解.docx(43页珍藏版)》请在冰豆网上搜索。
ArcGISPython实习指导讲解
实习一Python基础学习
1.什么是python
Python是一种不受局限、跨平台的开源编程语言,它功能强大且简单易学。
因而得到了广泛应用和支持。
ArcGIS9.0社区中引入了Python。
此后,Python被视为可供地理处理用户选择的脚本语言并得以不断发展。
每个版本都进一步增强了Python体验,从而为您提供更多的功能以及更丰富、更友好的Python体验。
ESRI已将Python完全纳入ArcGIS中,并将其视为可满足用户需求的语言。
下面仅介绍Python的部分优势:
∙易于学习,非常适合初学者,也特别适合专家使用
∙可伸缩程度高,适于大型项目或小型的一次性程序(称为脚本)
∙可移植,跨平台
∙可嵌入(使ArcGIS可脚本化)
∙稳定成熟
∙用户社区规模大
Python已延伸到ArcGIS中,成为了一种用于进行数据分析、数据转换、数据管理和地图自动化的语言,因而有助于提高工作效率。
2.在ArcGIS中使用Python
(1)打开ArcMap,在工具栏中点击“
”按钮,位置如图1-1所示,即可打开Python编辑窗口。
图1-1
(2)Python程序为解释运行,输入一行代码,按“回车”键后即可运行,如图1-2。
图1-2
3.行和缩进
学习Python与其他语言最大的区别就是,Python的代码块不使用大括号({})来控制类,函数以及其他逻辑判断。
python最具特色的就是用缩进来写模块。
(1)缩进的空白数量是可变的,但是所有代码块语句必须包含相同的缩进空白数量,这个必须严格执行。
在Python窗口中输入如图1-3所示的代码块并运行,该代码块是严格缩进的。
图1-3
(2)以下代码将会执行错误,如图1-4:
图1-4
实习二使用ArcPy
ArcPy是一个以成功的arcgisscripting模块为基础并继承arcgisscripting功能进而构建而成的站点包。
目的是为以实用高效的方式通过Python执行地理数据分析、数据转换、数据管理和地图自动化创建基础。
该包提供了丰富纯正的Python体验,具有代码自动完成功能(输入关键字和点即可获得该关键字所支持的属性和方法的弹出列表;从中选择一个属性或方法即可将其插入),并针对每个函数、模块和类提供了参考文档。
在Python中使用ArcPy的另一个主要原因是,Python是一种通用的编程语言。
Python是一种支持动态输入的解释型语言,适用于交互式操作以及为称为脚本的一次性程序快速制作原型,同时其具有编写大型应用程序的强大功能。
用ArcPy编写的ArcGIS应用程序的优势在于,可以使用由来自多个不同领域的GIS专业人员和程序员组成的众多Python小群体开发的附加模块。
1.通过Python使用工具
每个地理处理工具都具有一组固定的参数,这些参数为工具提供执行所需的信息。
在Python中使用工具时,必须正确设置工具的参数值,以便在脚本运行时工具可以执行。
下面以缓冲区分析为例练习通过Python使用工具的方法。
(1)点缓冲
1)在ArcMap中打开实验数据中的“point.shp”文件,如图2-1。
图2-1
2)打开Python窗口,在其中输入图2-2所示的代码,其中workspace的路径根据数据在电脑中的实际路径设置。
在调用工具(图中红色部位)的时候会在窗口右侧出现提示信息,根据提示信息,输入相关参数,运行结果如图2-3。
运行后会在目录中生成一个“pointBuffer.shp”文件,这个文件的文件名和路径均在代码中设置。
图2-2
图2-3
(2)线缓冲
1)在ArcMap中打开实验数据中的“line.shp”文件,选中其中的一条线,如图2-4。
图2-4
2)打开Python窗口,在其中输入图2-5所示的代码,运行结果如图2-6。
图2-5
图2-6
3)取消选中,重新运行一次代码,运行结果如图2-7所示。
从两次运行结果可以看出,地理处理工具处理对象首先应是选中的要素,如果没有选中要素,则默认为图层中所有对象。
图2-7
(3)多层缓冲
在输入要素周围的指定距离内创建多个缓冲区。
使用缓冲距离值可随意合并和融合这些缓冲区,以便创建非重叠缓冲区。
在ArcMap中打开实验数据中的“line.shp”文件,运行如图2-8所示的程序,结果如图2-9。
多个缓冲区的距离为“[10,20,30]”,可根据实际情况自己设定。
图2-8
图2-9
2.使用Python处理游标
游标是一种数据访问对象,可用于在表中迭代一组行或者向表中插入新行。
游标有三种形式:
搜索、插入或更新。
arcpy.da.InsertCursor(in_table,field_names)
插入行
arcpy.da.SearchCursor(in_table,field_names,{where_clause},{spatial_reference},{explode_to_points},{sql_clause})
只读访问
arcpy.da.UpdateCursor(in_table,field_names,{where_clause},{spatial_reference},{explode_to_points},{sql_clause})
更新或删除行
读取几何
(1)读取点
1)在ArcMap中打开“point.shp”文件,点的相对位置如图2-10。
图2-10
2)在Python窗口中运行如图2-11所示的代码,“SHAPE@XY”表示一个要素的质心XY坐标,点的质心为其本身。
cursor为一个搜索游标,其中“forrowincursor”是用一个for循环来遍历游标中的每一行。
运行结果如图2-12所示,红框中的数据为点的坐标。
图2-11
(2)读取折线或面
1)在ArcMap中打开实验数据中的“line.shp”文件,两个线要素相对位置如图2-13。
图2-13
2)在Python窗口中运行如图2-14所示的代码,结果如图2-15所示。
红色方框中的数据为两个先要素的折点坐标。
搜索游标中“OID@”表示要素的FID,“SHAPE@”表示几何要素对象。
图2-14
图2-15
写入几何
通过使用插入游标可以实现写入几何功能,
(1)写入点
将“point.shp”加载到ArcMap中,在Python窗口中输入图2-16所示的代码并运行,运行结束后点击左下方的“
”按钮,刷新一下地图窗口,结果如图2-17。
在写入点要素时,只有单个点对象用于设置点要素几何。
使用“SHAPE@XY”,就可轻松地创建点。
图2-16
图2-17
(2)写入线
将“line.shp”加载到ArcMap中,在Python窗口中输入图2-18所示的代码并运行,运行结果如图2-19。
代码中“arcpy.Array”表示数组对象可包含任意数量的地理处理对象,例如点、几何或空间参考。
(点坐标可自行设置)
图2-18
图2-19
实习三创建ArcGISPythonAdd-in
加载项是一种自定义项,它可以插入到ArcGISforDesktop应用程序(即ArcMap、ArcCatalog、ArcGlobe和ArcScene)中以便提供补充功能以完成自定义任务,例如工具条上的工具集合。
1.创建加载项项目
(1)选择加载项项目文件夹:
解压“addin_assistant.zip”(图3-1)文件,在解压后的文件夹处找到addin_assistant.exe(图3-2)文件并双击。
将打开浏览文件夹对话框,在其中输入用来存储加载项项目的文件夹。
必须选择一个空文件夹或创建一个新文件夹(图3-3),单击确定。
图3-1
图3-2
图3-3
(2)输入项目设置:
选择工作文件夹之后,将显示向导的第一个面板(图3-4)。
可在此处输入项目设置。
这些设置是项目的元数据,存储在config.xml文件中。
使用加载项时,这些设置在部署期间十分重要。
图3-4
2.创建工具条
单击加载项内容选项卡,右键单击工具条,然后单击“新建工具条”,如图3-5。
向导的右侧面板将显示工具条的属性,如图3-6。
工具条必须具有标题和ID。
标题用于为工具条提供标注。
ID表示唯一的名称,用于区分不同工具条。
ID不能包含空格。
默认情况下,启动应用程序时初始显示工具条这一选项处于选中状态。
如果不希望在启动应用程序时显示工具条,可以取消选中此选项。
图3-5
图3-6
3.创建按钮
(1)输入工具条属性后,即可创建新按钮。
右键单击名为“工具条”的新工具条并选择“新建按钮”,如图3-7。
图3-7
(2)新建按钮后,为按钮键入相应的属性信息,如图3-8,
图3-8
按钮具有多个属性需要设置。
以下列出了所有这些属性及其对应的说明。
这些属性存储在项目的config.xml文件中
属性
描述
标题(必填)
定义按钮标题。
下图显示了ArcGIS加载项管理器中使用的标题,有助于标识不同类型的可用自定义内容(加载项类型在括号中标识):
类(必填)
在桌面应用程序中单击按钮后执行的Python类。
Python类是写入按钮业务逻辑的位置。
构造类时应使用Python单词首字母大写命名约定,例如应使用“ZoomToSelectedFeatures”而不是“zoomtoselectedfeatures”。
ID(必填)
用于标识按钮的唯一名称。
您可以为给定项目创建多个按钮,此ID便用来区分不同的按钮。
理想情况下,应使用更有意义的值替换默认ID。
ID不应包含任何空格。
可以使用下划线连接单词。
不应使用Python关键字。
有关保留字信息,请查阅Python文档。
工具提示(可选)
将鼠标指针悬停在桌面应用程序中的按钮上方时出现的简短描述。
消息(可选)
按钮功能的详细描述。
将鼠标指针悬停在按钮上方时,此消息会显示在工具提示下方。
图像(可选)
此图像应为16*16像素的图像,用于符号化按钮。
图像格式应为任意一种常用图片格式(即.bmp、.jpg等)。
图像将复制到加载项项目中创建的图像文件夹中。
4.编辑Python脚本
此时已为定义加载项按钮所需的属性添加了值。
此工作流的下一步是编辑Python脚本并更新Python类,以包含“缩放至所选要素”这一功能。
如果未选择任何要素,则会缩放至所有图层的全图。
要将此功能添加到自定义按钮,执行以下步骤:
(1)在arcgis软件目录下找到如图3-9所示的Python编辑器,打开通过向导创建的工作文件夹下的“install”文件夹中Python脚本。
图3-9
(2)在onClick(self)函数中键入相关代码,如图3-10.
图3-10
(3)保存脚本,如果出现图3-11所示的警告信息,则需要在脚本头上加上“#codinggbk”如图3-12.
图3-11
图3-12
5.测试按钮
(1)创建加载项文件:
转到工作文件夹,双击该文件夹以运行makeaddin.py(图3-13)脚本。
此脚本将加载项所需的全部文件和文件夹都复制到工作文件夹中的加载项压缩文件中。
文件名包括工作文件夹名称和.esriaddin扩展名(图3-14)。
图3-13
图3-14
(2)安装加载项:
双击新的加载项文件以启动ESRIArcGIS加载项安装工具。
调用此工具后,它分析加载项文件内的config.xml,并显示创建加载项时输入的项目设置以及加载项是否包含受信数字签名(如图3-15)。
图3-15
(3)使用加载项:
此时可使用为ArcGISforDesktop应用程序设计的自定义功能。
启动桌面应用程序(ArcMap)。
自定义工具条(
)可能已经处于可见状态并可用于测试。
如果不可见,可转到自定义菜单,然后单击加载项管理器。
加载项管理器对话框将列出针对当前应用程序安装的加载项。
应显示作为项目设置而输入的加载项信息,如名称、描述和图像。
如果加载项列于管理器中,可单击自定义按钮打开自定义对话框。
要将工具条添加到应用程序,可单击工具条选项卡,然后选择您所创建的工具条。
(4)将示例数据加载到ArcMap中,开始编辑后任意选中一个要素(如图3-16),单击自定义工具条中的“
”按钮,地图会自动缩放到选中要素的位置(如图3-17)。
图3-16
图3-17
实习四宗地四至提取
1.四至提取步骤
界址线表示地块的边界线,界址点表示界址线的转折点或交点。
界址点、线是确定地块位置的重要资料。
界址点、线属性信息要采集的重要内容。
属性信息中,规定的界标类型有九种,分别是钢钉、水泥桩、石灰桩、喷涂、瓷标志、无标识和其他界标;界址线类别有九种,分别是田埂、沟渠、道路、行树、围墙、墙壁、栅栏、两点连线;界址线位置分为内中外三种,分别对应界址线地物的自有、共有和他有;毗邻地物权利人代表界址线两侧对应也是需四的承包地块方名称,中间用逗号隔开。
四至提取就是提取宗地四邻(东南西北)的地块权属,或者相邻道路。
1)提取界址点的步骤:
循环读取地块要素类的地块,取出每个地块的所有节点,若点要素类中没有坐标相同的点,则将节点存入点要素类中。
界址点位置由农户种地时自行约定,实际上表现为田埂的拐角,无明显地物标志,故界标类型默认设为“其他界标”。
2)界址线提取的步骤:
①循环读取地块,将面状的地块转换为多段线,再将多段线转换为单个的线段,若线要素类中没有相同的线段,则将线段作为界址线存入界址线要素类中。
②查找与界址线相交的地块并取出地块的“CBFMC”属性,将属性赋值给界址线的毗邻地物权利人属性。
界址线类别和界址线位置的判断标准是,如果与界址线相交的地块有两个则界址线类别为“田埂”,界址线位置为“中”;如果与界址线相交的地块只有一个则界址线类别为“道路”,界址线位置为“内”。
3)四至提取中心法:
图4-1,中间的点为地块的中心或质心,四至区域通过与x轴成45°和135°的两条直线划分,周围地块的中心落入哪个四至区域则选择其作为地块对应的四至地块。
图4-1
具体步骤为:
1循环读取地块图层,获取地块的中心点
2对当前地块作缓冲区,根据叠置关系找到当前地块周围的地块,并求得周围地块的中心;
3连接当前地块的中心与周围地块的中心,根据斜率判断地块的四至;
4对地块的四至信息进行更新。
4)四至提取界址线法:
地块对应的四至地块与该地块东、南、西、北四个方向最远四个界址点相接。
而且其中的每个界址点对应该地块的两条界址线,斜率绝对值较小的界址线为该地块与其南至和北至地块共有的界址线;斜率绝对值较大的界址线则为该地块与其东至和西至地块共有的界址线。
界址线中的毗邻地物权利人属性中有两个名字,一个是该地块的承包方名称,另一个则为其毗邻承包地块权利人姓名;如果毗邻地物权利人中只有一个名字,该地块在这条界址线处没有毗邻地块,四至信息默认设置为“道路”。
具体步骤是:
1循环读取地块图层,取出一个地块的所有节点,将其存入一个链表中;
2通过Y坐标值的比较找到地块南北方向上两个最远界址点;通过X坐标值比较地块东西方向两个最远界址点,将这些点以东南西北的顺序进行存储;
3通过九交模型查找与每个方向最远界址点相接的两条界址线,然后通过斜率判断与地块四至有关的四条界址线;
4根据这四条界址线寻找本地块毗邻地块得到四至信息并写入地块四至属性之中。
2.代码实现
1)设置默认地理数据库:
在Python中如果没有设置工作环境(env.workspace),默认的环境为“默认地理数据库”。
在目录中右键单击“test.mdb”,选择“设为默认地理数据库”,如图4-2。
图4-2
2)根据第一小节中的界址点、线与四至提取步骤在Python窗口中进行代码编写和调试;
3)代码成功运行后,根据实习三中的步骤,自定义一个工具条和四个按钮如图4-3,将Python窗口中的代码复制到与按钮对应的函数中。
图4-3
4)提取完成后打开“jzd”图层属性表,如图4-4,
图4-4
5)提取完成后打开“jzx”图层属性表,如图4-5
图4-5
5)提取完成后打开“dk”图层属性表,如图4-6,
图4-6
附:
参考代码
#coding:
gbk
importarcpy
importpythonaddins
classBound1(object):
"""Implementationforbound1_addin.button(Button)"""
def__init__(self):
self.enabled=True
self.checked=False
defonClick(self):
curdk=arcpy.da.SearchCursor("dk",["OID@","SHAPE@","DKBM","CBFMC"],"")
forrowincurdk:
mdk=row[1]
cbfmc=row[3]
forpartinrow[1]:
arrpoint=[]
forpntinpart:
arrpoint.append(pnt)
boundpoints=[]#存储四个方向上的最远点
eastPoint=arrpoint[0]
southPoint=arrpoint[0]
westPoint=arrpoint[0]
northPoint=arrpoint[0]
#根据坐标判求得四个方向最远点
formpntinarrpoint:
ifnorthPoint.Y<=mpnt.Y:
northPoint=mpnt
ifsouthPoint.Y>=mpnt.Y:
southPoint=mpnt
ifeastPoint.X<=mpnt.X:
eastPoint=mpnt
ifwestPoint.X>=mpnt.X:
westPoint=mpnt
boundpoints.append(eastPoint)
boundpoints.append(southPoint)
boundpoints.append(westPoint)
boundpoints.append(northPoint)
containedjzxs=[]#存储与四个点相交的8条界址线
cjzxqlrs=[]#存储与四个点相交的8条界址线的毗邻地物权利人
forboundPointinboundpoints:
njzx=arcpy.da.SearchCursor("jzx",["OID@","SHAPE@","PLDWQLR"],"")
forcrowjzxinnjzx:
jzxpoint=[]
cjzxqlr=crowjzx[2]
jzx=crowjzx[1]
forpartjzxincrowjzx[1]:
forjzxpntinpartjzx:
jzxpoint.append(jzxpnt)
ptstart=jzxpoint[0]
ptend=jzxpoint[1]
isStartTouch=ptstart.touches(mdk)
isEndTouch=ptend.touches(mdk)
isContain=(isStartTouchandisEndTouch)
isTouch=jzx.touches(boundPoint)
isBoundjzx=(isContainandisTouch)
ifisBoundjzx:
containedjzxs.append(jzx)
cjzxqlrs.append(cjzxqlr)
delnjzx
dksz=[]
default="道路"
#根据界址线的斜率确定哪个是与四至相关的界址线
#地块东至
ifabs(((containedjzxs[0].firstPoint.Y-containedjzxs[0].lastPoint.Y)/(containedjzxs[0].firstPoint.X-containedjzxs[0].lastPoint.X)))>=abs(((containedjzxs[1].firstPoint.Y-containedjzxs[1].lastPoint.Y)/(containedjzxs[1].firstPoint.Y-containedjzxs[1].lastPoint.Y))):
mboundStrings=cjzxqlrs[0].split(",")
iflen(mboundStrings)==1:
dksz.append(default)
else:
forbStringinmboundStrings:
ifnot(bString==cbfmc):
dksz.append(bString)
else:
mboundStrings=cjzxqlrs[1].split(",")
iflen(mboundStrings)==1:
dksz.append(default)
else:
forbStringinmboundStrings:
ifnot(bString==cbfmc):
dksz.append(bString)
#地块南至
ifabs(((containedjzxs[2].firstPoint.Y-containedjzxs[2].lastPoint.Y)/(containedjzxs[2].firstPoint.X-containedjzxs[2].lastPoint.X)))>=abs(((containedjzxs[3].firstPoint.Y-containedjzxs[3].lastPoint.Y)/(containedjzxs[3].firstPoint.Y-containedjzxs[3].lastPoint.Y))):
mboundStrings=cjzxqlrs[3].split(",")
iflen(mboundStrings)==1:
dksz.append(default)
else:
forbStringinmboundStrings:
ifnot(bString==cbfmc):
dksz.append(bString)
else:
mboundStrings=cjzxqlrs[2].split(",")
iflen(mboundStrings)==1:
dksz.append(default)
else:
forbStringinmboundStrings:
ifnot(bString==cbfmc):
dksz.append(bString)