开源GIS-geos实现空间快速连接

 开源GIS-geos实现空间快速连接

  其中关于空间计算的只有简单的判断

  标题

  而要真正实现空间连接,是需要将两个shp文件进行里外循环,例如,以其中一个shp的要素个数为外循环,以另一个shp要素数量为内循环,逐一判断是否存在空间上的关联(包含、被包含。。。)

  如此做循环肯定会影响程序执行的速度。因此可以使用Rtree作为索引,加快循环的检索。

  话不多说,下面上代码,以“包含”的空间关系做空间连接为例

  #-----------------打开OSM数据---------------------------

  osm_ds = ogr.Open(osmfile)

  osm_lyr=osm_ds.GetLayer(0)

  feat=osm_lyr.GetFeature(0)

  keys_osm=feat.keys()

  spatial=osm_lyr.GetSpatialRef()

  count=osm_lyr.GetFeatureCount()

  #---打开BUffer-----------

  buffer_s=ogr.Open(bufferfile)

  buff_lyr=buffer_s.GetLayer(0)

  buff_feature=buff_lyr.GetFeature(0)

  keys_buff=buff_feature.keys()

  #--创建索引--

  shp_index=index.Index()

  #--shp几何数据导入Rtree--

  for i,feat in enumerate(buff_lyr):

  # geom=feat.GeometryDef()

  geom = feat.GetGeometryRef()

  bbox=geom.GetEnvelope()#--left,right,buttom,top

  # print("Type of bbox",type(bbox),":",bbox)

  shp_index.insert(i,(bbox[0],bbox[2],bbox[1],bbox[3]))#---idx.insert(0, (left, bottom, right, top))

  #--空间连接

  # print()

  gdal.SetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES")

  gdal.SetConfigOption( "SHAPE_ENCODING", "UTF-8")

  Spatial_driver = ogr.GetDriverByName("ESRI Shapefile")

  spatial_ds = Spatial_driver.CreateDataSource(matchedfile)

  match_lyr = spatial_ds.CreateLayer(‘matched‘,spatial) # 创建缓冲区

  #创建字段

  # print("osm_keys:",keys_osm)

  osm_def = osm_lyr.GetLayerDefn()

  # for i,each in enumerate(keys_osm):

  # fielddef=osm_def.GetFieldDefn(i)

  # if fielddef==None:

  # break

  # # print(fielddef)

  # # print(each)

  # fieldDefn = ogr.FieldDefn(each,fielddef.GetType())

  # match_lyr.CreateField(fieldDefn)

  # print("Buffer_keys:", keys_buff)

  keys_match=keys_buff.copy()

  keys_match.extend(keys_osm)

  # print("matchedfile Fields:", keys_match)

  buff_def = buff_lyr.GetLayerDefn()

  count_field=0

  for i,key in enumerate(keys_match):

  field=None

  if key in keys_buff:

  field=buff_def.GetFieldDefn(i)

  count_field+=1

  else:

  field = osm_def.GetFieldDefn(i-count_field)

  if field is None:

  break

  fieldDef= ogr.FieldDefn(key,ogr.OFTString)

  fieldDef.SetWidth(254)

  match_lyr.CreateField(fieldDef)

  #---添加几何属性和字段属性----------

  match_feat = ogr.Feature(match_lyr.GetLayerDefn())

  # print("--创建空间连接...")

  for i,osm_feat in enumerate(osm_lyr):

  # print(i+1,"/%d"%count,end=‘,‘)

  geom = osm_feat.geometry().Clone()

  match_feat.SetGeometry(geom)

  # print("type of geom",type(geom))

  #--buffer属性

  feat_within=[]

  #--在Rtree中寻找相交的部分要素

  bbox=geom.GetEnvelope()

  feat_id = list(shp_index.intersection((bbox[0],bbox[2],bbox[1],bbox[3])))

  # for buffer_feat in buff_lyr: 大连人流手术费用

  # if geom.Within(buffer_feat.geometry().Clone()):

  # feat_within.append(buffer_feat)

  #---被包含的要素--

  for idx in feat_id:

  feat_temp=buff_lyr.GetFeature(idx)

  if geom.Within(feat_temp.geometry().Clone()):

  feat_within.append(feat_temp)

  if len(feat_within)==1:

  for key in keys_match:

  if key in keys_osm:

  match_feat.SetField(key, str(osm_feat.GetField(key)))

  # print(key, "(one):", osm_feat.GetField(key), end=‘,‘)

  if key in keys_buff:

  # print(key, "(one):", feat_within[0].GetField(key), end=‘,‘)

  match_feat.SetField(key, (feat_within[0].GetField(key)))

  elif len(feat_within)>1:

  data = getMostvalue(feat_within)

  for key in keys_match:

  if key in keys_osm:

  match_feat.SetField(key, str(osm_feat.GetField(key)))

  # print(key, "(one of):", osm_feat.GetField(key), end=‘,‘)

  if key in keys_buff:

  # print(key,"(one of):",feat_within[data].GetField(key),end=‘,‘)

  match_feat.SetField(key,str(feat_within[data].GetField(key)))

  else:

  # --osm属性

  for key in keys_match:

  if key in keys_osm:

  match_feat.SetField(key, str(osm_feat.GetField(key)))

  # print(key, "(None):", osm_feat.GetField(key), end=‘,‘)

  else:

  match_feat.SetField(key,"None")

  print(key, "(None):","None", end=‘,‘)

  match_lyr.CreateFeature(match_feat)

  # print()

  feat_within.clear()

  #--进度条---

  # time.sleep(0.5)

  # sys.stdout.write("创建空间连接... %2f%% \r" % (100*(i+1)/count))

  # sys.stdout.flush()

  # print()

  spatial_ds.Destroy()

  以上是个人在做的一个项目的程序,简单的实现了快速的空间连接,关于Rtree的教程,可以百度搜索Rtree,使用的库包为geos和rtree。

开源GIS-geos实现空间快速连接

上一篇:Docker(4):Dockerfile


下一篇:剑指 Offer 10- I. 斐波那契数列