【问题标题】:Testing point with in/out of a vector shapefile带有输入/输出矢量 shapefile 的测试点
【发布时间】:2016-01-16 08:36:28
【问题描述】:

这是我的问题。

1。简介

  • 多边形类型的 shapefile 代表研究区域

http://i8.tietuku.com/08fdccbb7e11c0a9.png

  • 某个点位于整个矩形地图中

http://i8.tietuku.com/877f87022bf817b8.png

我想测试每个点是否位于多边形内/外并做一些进一步的操作(例如,对研究区域内的网格点数量求和)

2。我的想法

由于堆栈溢出的信息,我有两种方法。

2.1 想法A

将shapefile光栅化成光栅文件,然后进行测试。

我还没有这样做,但我已经问了一个问题here 并得到了答案。

2.2 想法 B

我曾尝试使用poly.contain()测试散点位置,但结果与实际不符。

3。我的代码基于想法 B:

例如:

  • 原始数据由pt(一个熊猫数据框)表示,其中包含 1000 个网格 X、Y。
  • 我已经显示的 shapefile 是研究区域,我想过滤原始数据,只留下该区域内的点。
3.1 准备工作
# map four boundaries
xc1,xc2,yc1,yc2 = 113.49805889531724,115.5030664238035,37.39995194888143,38.789235929357105
# grid definition
lon_grid  = np.linspace(x_map1,x_map2,38)
lat_grid  = np.linspace(y_map1,y_map2,32)
3.1 准备工作
# generate (lon,lat)   
xx = lon_grid[pt.X.iloc[:].as_matrix()]
yy = lat_grid[pt.Y.iloc[:].as_matrix()]

sh = (len(xx),2)
data = np.zeros(len(xx)*2).reshape(*sh)
for i in range(0,len(xx),1):
    data[i] = np.array([xx[i],yy[i]])

# reading the shapefile
              
map = Basemap(llcrnrlon=x_map1,llcrnrlat=y_map1,urcrnrlon=x_map2,\
              urcrnrlat=y_map2)
map.readshapefile('/xx,'xx')
3.2 测试
patches=[]
for info, shape in zip(map.xxx_info, map.xxx):
    x,y=zip(*shape)
    patches.append(Polygon(np.array(shape), True) )
for poly in patches:
     mask = np.array([poly.contains_point(xy) for xy in data])
  • 然后,我有一个 numpy 数组掩码,其值为 0,1 代表内/外。
  • 将掩码组合成pt ==> pt = pt[[pt.mask == 1]],我可以过滤点

但问题在于使用poly,contains_point(xy),我无法得到与我的尝试匹配的结果。

我的想法 2 的一个例子

对值 0,1 求和:

unique, counts = np.unique(mask, return_counts=True)      
print np.asarray((unique, counts)).T
#result:  
> [[0 7]  
  [1 3]]

http://i4.tietuku.com/7d156db62c564a30.png

从唯一值来看,shapefile区域内必须有3个点,但结果显示多了一个点。

40分的另一个测试

http://i4.tietuku.com/5fc12514265b5a50.png

4。我的问题

结果是错误的,我还没弄明白。
但我认为问题的发生可能有两个原因:

  • 多边形 shapefile 错误(一个简单的多边形,我不认为问题仍然存在)。
  • 使用 poly.contains_point(xy) 不正确。

添加 2016-01-16

感谢您的回答,我发现的原因是 shapefile 本身。
当我把它改成 shapely.polygon 时,效果很好。

这是我的代码和结果

c =    fiona.open("xxx.shp")
pol = c.next()
geom = shape(pol['geometry'])
poly_data = pol["geometry"]["coordinates"][0]
poly = Polygon(poly_data)
ax.add_patch(plt.Polygon(poly_data))

xx = lon_grid[pt_select.X.iloc[:].as_matrix()]
yy = lat_grid[pt_select.Y.iloc[:].as_matrix()]

sh = (len(xx),2)
points = np.zeros(len(xx)*2).reshape(*sh)
for i in range(0,len(xx),1):
    points[i] = np.array([xx[i],yy[i]])
mask = np.array([poly.contains(Point(x, y)) for x, y in points])

ax.plot(points[:, 0], points[:, 1], "rx")
ax.plot(points[mask, 0], points[mask, 1], "ro")    

http://i4.tietuku.com/8d895efd3d9d29ff.png

【问题讨论】:

  • 对不起,我正在编辑它。

标签: python numpy matplotlib shapefile matplotlib-basemap


【解决方案1】:

你可以使用匀称:

import numpy as np
from shapely.geometry import Polygon, Point

poly_data = [[0, 0], [0, 1], [1, 0], [0.2, 0.5]]
poly = Polygon(poly_data)

points = np.random.rand(100, 2)

mask = np.array([poly.contains(Point(x, y)) for x, y in points])

这是情节代码:

将pylab导入为pl

fig, ax = pl.subplots()
ax.add_patch(pl.Polygon(poly_data))
ax.plot(points[:, 0], points[:, 1], "rx")
ax.plot(points[mask, 0], points[mask, 1], "ro")

输出:

您还可以使用 MultiPoint 来加快计算速度:

from shapely.geometry import Polygon, MultiPoint

poly_data = [[0, 0], [0, 1], [1, 0], [0.2, 0.5]]
poly = Polygon(poly_data)
points = np.random.rand(100, 2)
inside_points = np.array(MultiPoint(points).intersection(poly))

你也可以在 matplotlib 中使用Polygon.contains_point()

poly = pl.Polygon(poly_data)
mask = [poly.contains_point(p) for p in points]

【讨论】:

  • 有没有一种有效的方法可以将多点与多面相交,或者这不是一种有效的方法?我想限制与点的最大值和最小值相交的范围是个好主意。有什么想法吗?
猜你喜欢
  • 1970-01-01
  • 2012-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-28
  • 1970-01-01
  • 2017-03-18
  • 2016-06-17
相关资源
最近更新 更多