geopandas对shapefile进行拓扑检查(must not overlay)

import geopandas
#path = "F:\\shapefile\\Detroit\\Detroit_height.shp"
path="F:\\shapefile\\Xian\\Xian\\Xian.shp"
    # 读取shapefile文件,可设置bbox选定区域
gdf = geopandas.read_file(path)
gdf=gdf[gdf.boundary.is_simple]
gdf.reset_index(drop=True,inplace=True)
print(len(gdf))

polygon1=gdf.loc[0,'geometry']
polygon2=gdf.loc[0,'geometry']
print(polygon1.overlaps(polygon2))           #自己和自己不算overlaps

spatial_index = gdf.sindex
#建立R树索引. gdf,geopandas dataframe 数据
for i in range(len(gdf)):
    polygon=gdf.loc[i,'geometry']
    possible_matches_index = list(spatial_index.intersection(polygon.bounds))
    possible_matches = gdf.iloc[possible_matches_index]
    #通过R树进行简单包含查询
    precise_matches = possible_matches[possible_matches.overlaps(polygon)]
    #将简单查询结果进行进行匹配,得到精确查询结果
    if len(precise_matches)>0:
        print("detect overlaps :{}".format(i))
    else:
        print("not detect overlaps :{}".format(i))

注意,进行拓扑检查之前,先要进行自相交检查(gdf.boundary.is_simple),且删除掉不符合的Polygon之后,还是进行索引重置(当然这不是必须的,但是本次代码需要)。利用Rtree建立空间索引之后,进行暴力相交检测。注意,两个完全相同的polygon不算overlaps.

之前的方法由于重复判断,因此会产生过多的overlay的polygon,而事实上没必要删除这么多,因此,采用了一下的方法(flag=0)

import geopandas
import time
#path = "F:\\shapefile\\Detroit\\Detroit_height.shp"
path="F:\\shapefile\\Xian\\Xian\\Xian.shp"

gdf = geopandas.read_file(path)
gdf=gdf[gdf.boundary.is_simple]
gdf.reset_index(drop=True,inplace=True)
print(len(gdf))

polygon1=gdf.loc[0,'geometry']
polygon2=gdf.loc[0,'geometry']
print(polygon1.overlaps(polygon2))           #自己和自己不算overlaps


gdf_copy=gdf.copy(deep=True)


def check_overlay(gdf,flag):
    spatial_index = gdf.sindex
    #建立R树索引.
    drop_list=[]
    for i in range(len(gdf)):
        polygon=gdf.loc[i,'geometry']
        possible_matches_index = list(spatial_index.intersection(polygon.bounds))
        possible_matches = gdf.iloc[possible_matches_index]
        #通过R树进行简单包含查询
        precise_matches = possible_matches[possible_matches.overlaps(polygon)]
        #将简单查询结果进行进行匹配,得到精确查询结果
        if flag==0:
            spatial_index.delete(i, polygon.bounds)
        if len(precise_matches)>0:
            drop_list.append(i)
    return drop_list

start=time.time()
drop_list=check_overlay(gdf,0)
stop=time.time()
print(len(drop_list))
print(len(gdf))
print(stop-start)

gdf.drop(axis=0,index=drop_list,inplace=True)
gdf.reset_index(drop=True,inplace=True)

start=time.time()
drop_list=check_overlay(gdf,1)
stop=time.time()
print(len(drop_list))
print(len(gdf))
print(stop-start)

运行结果:
(第一次检查,第二次测试第一次的检查是否成功)
geopandas对shapefile进行拓扑检查(must not overlay)_第1张图片
上面的拓扑检查无法检查出相等以及包含这种情况,因此,更正如下(相交(intersects)-边界相交(touches)=内部相交)

import geopandas

def check_overlap(gdf):
    spatial_index = gdf.sindex
    #建立R树索引.
    drop_list=[]
    for i in range(len(gdf)):
        polygon=gdf.loc[i,'geometry']
        possible_matches_index = list(spatial_index.intersection(polygon.bounds))
        possible_matches = gdf.iloc[possible_matches_index]
        #通过R树进行简单包含查询
        precise_matches_intersects = possible_matches[possible_matches.intersects(polygon)]
        precise_matches_touches = possible_matches[possible_matches.touches(polygon)]
        #将简单查询结果进行进行匹配,得到精确查询结果
        spatial_index.delete(i, polygon.bounds)
        if (len(precise_matches_intersects)-len(precise_matches_touches))>1:
            drop_list.append(i)
    return drop_list


if __name__=='__main__':
    path="f:\\shapefile\\Xian\\Xian\\Xian.shp"
    gdf=geopandas.read_file(path)
    gdf=gdf[gdf.boundary.is_simple]
    gdf.reset_index(drop=True,inplace=True)
    drop_list=check_overlap(gdf)
    print(len(gdf))
    print(len(drop_list))
    gdf.drop(axis=0,index=drop_list,inplace=True)
    gdf.reset_index(drop=True,inplace=True)
    print(len(gdf))
    gdf.to_file("F:\\shapefile\\1.shp")

你可能感兴趣的:(python)