arcgis中邻接矩阵文件的生成
首先我要说明的是,arcgis 9.2中已经实现基于基本一阶邻接关系的空间自相关计算,也
就是说arcgis系统本身已通过一定算法解决了本文以及之前blog中涉及的相关问题。
以下内容仅限于算法设计的兴趣及对arcgis相关功能实现的探讨。
arcgis 9.2中对于空间关联矩阵文件的构建做了拓展,你可以DBF属性中任意值为Unique的
字段来建立矩阵。原先矩阵的关联字段只能使用Object ID构建,而现在你可以使用其它唯
一值的字段了,甚至是中文的地名字段(当然需要注意的是,字段值中不能有空格!而且
似乎用户自定义的文件中若使用OID构建运行时会报错)
下面是之前的面向9.0版本开发的VBA代码,现增添了计算MoranI值的程序,一并打包(生
成的邻接文件可用于9.0/9.1版本的相关计算,也可以用于VBA自带的MoranI计算,但不能
直接用于9.2中):
http://lilybbs.net/file/T/toolbar/VBA.rar
为了满足9.2中的邻接矩阵构建,鄙人近日对算法进行了扩充,并基于GDAL/OGR运算包在P
ython平台下进行了算法实现。特别要指出的是,由于GDAL相关函数的限制,算法中相应的
相邻多边形计算未能完全实现,仅仅搜索出了外接矩形(Envelop)相邻的多边形。因此大
家会发现生成的邻接矩阵行数会比原来的多一些。(相信随着GDAL的完善,最终可以在Py
thon平台上脱离ArcGIS实现相应功能)
附python源文件
1 """ 2 多边形的邻接矩阵生成 3 pnm.py - by toolbar 4 5 update time: 2006.12.19 6 """ 7 #引入操作系统库 8 import os 9 #引入TK库 10 from Tkinter import * 11 #引入消息对话框 12 from tkMessageBox import * 13 #引入文件对话框 14 from tkFileDialog import * 15 #引入_GDAL.dll 16 import _gdal 17 #引入OGR库 18 from gdal import ogr 19 20 #主程序类 21 class Main: 22 #字体定义 23 _font=('宋体',9) 24 #初始化 25 def __init__(self,master): 26 self.master=master 27 Frame(master).pack(side=BOTTOM,expand=YES,fill=BOTH) 28 master.title('多边形邻接计算'.decode('mbcs')) 29 master.geometry('300x200+350+250') 30 #第一行框架 31 frame1=Frame(master) 32 frame1.pack(side=TOP,expand=YES) 33 #第二行框架 34 frame2=Frame(master) 35 frame2.pack(side=TOP,expand=YES) 36 #第一行控件(文件输入) 37 Label(frame1,text='输入文件'.decode('mbcs'),font=self._font).pack(side=LEFT,fill=BOTH) 38 fin=StringVar() 39 Entry(frame1,relief=SUNKEN,textvariable=fin,width=36).pack(side=LEFT) 40 list=Listbox(frame2,height=3,width=37) 41 Button(frame1,text='...',width=2,command=lambda w=fin,l=list,s=self:w.set(s.filein(l))).pack(side=LEFT) 42 #第二行控件(文件输入) 43 Label(frame2,text='选择变量'.decode('mbcs'),font=self._font).pack(side=LEFT,fill=BOTH) 44 fieldin=StringVar() 45 #list=Listbox(frame,height=3,width=37) 46 scroll=Scrollbar(frame2,command=list.yview) 47 list.config(yscrollcommand=scroll.set) 48 list.pack(side=LEFT) 49 scroll.pack(side=LEFT,fill=Y) 50 #第三行框架 51 frame3=Frame(master) 52 frame3.pack(side=TOP,expand=YES) 53 #第三行控件(文件输出) 54 Label(frame3,text='输出文件'.decode('mbcs'),font=self._font).pack(side=LEFT,fill=BOTH) 55 fout=StringVar() 56 Entry(frame3,relief=SUNKEN,textvariable=fout,width=36).pack(side=LEFT) 57 Button(frame3,text='...',width=2,command=lambda w=fout,s=self:w.set(s.fileout())).pack(side=LEFT) 58 #第四行框架 59 frame4=Frame(master) 60 frame4.pack(side=TOP,expand=YES) 61 #第四行控件(执行按钮) 62 Button(frame4,text='确 认'.decode('mbcs'),font=self._font, 63 command=lambda w1=fin,w2=fout,l=list,s=self:s.adjcent(w1.get(),w2.get(),l.selection_get())).pack(side=LEFT) 64 Button(frame4,text='清 空'.decode('mbcs'),font=self._font, 65 command=lambda w1=fin,w2=fout:(w1.set(''),w2.set(''))).pack(side=RIGHT) 66 #GUI显示循环 67 master.mainloop() 68 69 #文件输入 70 def filein(self,list): 71 a=askopenfilename(title='打开文件'.decode('mbcs'),filetypes=[('Shape file','*.shp'),('All files','*.*')]) 72 if a: 73 shapefile=ogr.Open(a) 74 shapelayer=shapefile.GetLayer() 75 layerinfo=shapelayer.GetLayerDefn() 76 for i in range(0,layerinfo.GetFieldCount()-1): 77 list.insert(END,layerinfo.GetFieldDefn(i).GetName()) 78 return os.path.abspath(a) 79 else: 80 return '' 81 82 #文件输出 83 def fileout(self): 84 a=asksaveasfilename(title='保存文件'.decode('mbcs'),filetypes=[('Neighbor file','*.txt'),('All files','*.*')]) 85 if a: 86 return os.path.abspath(a) 87 else: 88 return '' 89 90 #执行邻接函数 91 def adjcent(self,FileIn,FileOut,list): 92 textfile=open(FileOut,'w') 93 textfile.writelines(list+'\n') 94 shapefile=ogr.Open(FileIn) 95 shapelayer=shapefile.GetLayer() 96 #showinfo(title='',message=str(fcount)) 97 shapefeature=shapelayer.GetNextFeature() 98 while shapefeature: 99 shapegeometry=shapefeature.GetGeometryRef() 100 for i in range(0,shapelayer.GetFeatureCount()-1): 101 shapefeature1=shapelayer.GetFeature(i) 102 if shapefeature1.GetFID()==shapefeature.GetFID():continue 103 shapegeometry1=shapefeature1.GetGeometryRef() 104 if shapegeometry1.Intersect(shapegeometry): 105 #s=str(shapefeature.GetFID())+' '+str(shapefeature1.GetFID())+' 1\n' 106 t=shapefeature.GetFieldIndex(list) 107 s=str(shapefeature.GetField(t))+' '+str(shapefeature1.GetField(t))+' 1\n' 108 textfile.writelines(s) 109 self.master.title(str(shapefeature.GetFID())) 110 shapefeature=shapelayer.GetNextFeature() 111 textfile.close() 112 showinfo(message='Done!') 113 114 if __name__=='__main__': 115 Main(Tk())
(python版本2.4.1,ArcGIS 9.2已自带;GDAL版本1.3.2,需安装)
谈论完了自己的算法,也很好奇ArcGIS 9.2中是怎么实现一阶邻接对象矩阵生成的。查找
了一下toolbox下的ArcScript源代码,发现ESRI的实现主要是通过了两个步骤:(1)使用
polygon to line功能,生成的line文件将自带有弧段左右多边形的拓扑信息;(2)对生
成line文件的左右多边形字段进行Frequency统计,剔除重复的冗余,在此基础上再生成邻
接矩阵文件就不难了(一次表格遍历即可)
有兴趣的话,可以在toolbox相应功能上右键‘edit’即可查看ESRI的源代码~
enjoy~
e-mail:shisong.zhu@gmail.com
GISer in China, for engineering