(二十九)arcpy开发&利用arcpy在arcgis中实现批量计算图斑四至坐标(polygon顶点计算,范围获取、pyhon类创建)

一、问题与解决方法

这个方法的灵感来自昨天昨天,下面来说一下实现功能。

一直以来都有对图斑(polygon)多边形四至坐标提取的需求,其实是这样的,之前在群里看到了林业部门的一个小伙伴有这样的需求,就是提取图斑(polygon)多边形最四至坐标,即一个多边形的最北点、最东点、最西点、最南点。一直以来,我也想着解决这个问题,都没有想到解决的办法,因为在多边形(polygon)中,arcgis的api接口提供的是范围(包络线),而今天我们正是利用这个范围的两个角点坐标,再由arcgis的api接口将多边形各个节点坐标提取出来,然后将坐标点一一与两个坐标的最大的X坐标XMax、最大的Y坐标YMax、最小的X坐标XMin、最小的Y坐标YMin相比较,如果多边形的节点坐标中某点的X值与XMax相等,则认为该点为最东点,如果某点的X值与XMin相等,则认为是最西点,而如果某点的Y值与YMax相等,则认为是最北点,再如果某点的Y值与YMin相等,则认为是最南点,至此整个算法就结束,相对来说是比较简单的。

当然也可以使用其他的解决办法,这里就没有去研究。

二、编写代码实现

这里使用的是arcpy,即使用的是python在arcgis中的接口进行开发。开发的编辑器使用的pycharm2018.2社区版,不得不说这个编辑器还是挺好用的,毕竟开发安卓的android studio以及java开发中比较常用的编辑器使用的是idea,这些编辑器都是出自一家公司之手。关于如何在pycharm中如果arcpy站点包的解决办法,已经在之前的博客中已经提到了,大家可以参考之前的博客即可。

在编写代码的时候,这里使用到python的类,具体的实现代码如下图所示。

# coding:utf-8
import arcpy
testData=ur"D:\Data\testPolygon.shp"

class SZInfo:
    Part=[]
    XMin=0
    YMin=0
    XMax=0
    YMax=0
    ID="0"

class Point:
    X=0
    Y=0

class SZResInfo:
    ID=""
    flag=""
    point=Point()


SZDataset = []
for row in arcpy.da.SearchCursor(testData, ["FID", "SHAPE@"]):
    print("Here comes feature {0}:".format(row[0]))

    tmpSZInfo=SZInfo()
    ID=row[0]
    mask = row[1]
    tmpSZInfo.XMin= mask.extent.XMin
    tmpSZInfo.YMin= mask.extent.YMin
    tmpSZInfo.XMax= mask.extent.XMax
    tmpSZInfo.YMax= mask.extent.YMax

    tmpSZInfo.ID=str(ID)

    partnum = 0
    for part in row[1]:
        print("Part {0}:".format(partnum))
        tempPart = []
        for pnt in part:
            if pnt:

              point=Point()
              point.X=pnt.X
              point.Y=pnt.Y
              tmpSZInfo.Part.append(point)


            else:
                print("Interior Ring:")
                #SZDataset.append(tempPart)
        partnum += 1
    SZDataset.append(tmpSZInfo)

szResDataset=[]
for szInfo in SZDataset:
    tmpRes=[]
    for point in szInfo.Part:
        if point.X==szInfo.XMin:#西至
            tmpSZResInfo=SZResInfo()
            tmpPoint=Point()
            tmpPoint.X=point.X
            tmpPoint.Y=point.Y

            tmpSZResInfo.flag="XiZhi"
            tmpSZResInfo.ID=szInfo.ID
            tmpSZResInfo.point=tmpPoint


            tmpRes.append(tmpSZResInfo)
        elif point.X==szInfo.XMax:#东至
            tmpSZResInfo = SZResInfo()
            tmpPoint = Point()
            tmpPoint.X = point.X
            tmpPoint.Y = point.Y

            tmpSZResInfo.flag = "DongZhi"
            tmpSZResInfo.ID = szInfo.ID
            tmpSZResInfo.point = tmpPoint
            tmpRes.append(tmpSZResInfo)

        elif point.Y==szInfo.YMax:#北至
            tmpSZResInfo = SZResInfo()
            tmpPoint = Point()
            tmpPoint.X = point.X
            tmpPoint.Y = point.Y

            tmpSZResInfo.flag = "BeiZhi"
            tmpSZResInfo.ID = szInfo.ID
            tmpSZResInfo.point = tmpPoint
            tmpRes.append(tmpSZResInfo)

        elif point.Y==szInfo.YMin:#南至
            tmpSZResInfo = SZResInfo()
            tmpPoint = Point()
            tmpPoint.X = point.X
            tmpPoint.Y = point.Y

            tmpSZResInfo.flag = "NanZhi"
            tmpSZResInfo.ID = szInfo.ID
            tmpSZResInfo.point = tmpPoint
            tmpRes.append(tmpSZResInfo)
    szResDataset.append(tmpRes)

for res in szResDataset:

    for item in res:

        if item.flag=="XiZhi":
            print ("ID为" + str(item.ID) +"西至坐标X为:"+str(item.point.X)+"Y为:"+str(item.point.Y))
        elif item.flag=="DongZhi":
            print("ID为" + str(item.ID) +"东至坐标X为:" + str(item.point.X) + "Y为:" + str(item.point.Y))
        elif item.flag=="BeiZhi":
            print("ID为" + str(item.ID) +"北至坐标X为:" + str(item.point.X) + "Y为:" + str(item.point.Y))
        elif item.flag=="NanZhi":
            print("ID为" + str(item.ID) +"南至坐标X为:" + str(item.point.X) + "Y为:" + str(item.point.Y))

    print("------------------------------------")
    print("------------------------------------")

中间遇到调试代码两个问题。

1.python类的初始化。

Python中类的初始化必须使用括号,即obj=Object(),其中Object为我们创建的类对象,而如果使用的是obj=Object的形式,则认为obj为一个全局变量。这样造成的结果是,最新修改的数据对全局变量的修改,如下图所示,在数组中保存一个全局变量,导致所有的数据都是一样的。

而正确的使用创建类对象方式,那么每次都是新的对象,所获取值都是不一样的,具体如下图所示。

2.类对象成员变量。

Python类对象成员变量,有多种结构。之所以要把这个问题提到日程,是因为遇到如下图的错误。报错的说,str对象没有point属性,一开始我很是纳闷,明明创建的对象有point属性,还有我创建的对象怎么变成str类型去了。

来看一下问题的原因,如下图所示紫色箭头是报错的地方,很显然我创建的对象变成了一个字符,该字符对象赋值了szInfo.ID值,而szInfo.ID为一个str对象,估计是python内部已经将tmpSZResInfo对象转为了str类型了,所以导致下面的那行代码报错了。而只要代码改为红色箭头所示的形式即可。

三、结果分析

编写好代码后,我们使用pycharm启动调试模式,在控制台中查看我们的运行结果。最后打印结果如下图所示。

我们来分析一下结果,以ID为0多边形为例。下图是北至坐标点。显然和上面在pycharm控制台中打印出的结果相一致。

再对比一下其他结果。显然从图面来说,已经正确的提取出图斑(polygon)的四至坐标。

四、后记

这里讲解一般的多边形,而如果出现有空洞的多边形没有考虑在范围之内。还有一个问题,这里是使用范围(包络线)两个角点来比较的,那么会带来一个问题,在一个图形中,很有可能几个点同时落在边界上面,具体如下所示。这样就要求根据工程的需要进行取舍。

至此,整个说明就讲解完了。祝你生活愉快,工作顺利。


                                                                      更多内容,请关注公众号

                                                       

 

转载自:https://blog.csdn.net/u010608964/article/details/83473739

You may also like...