Python 检查地理点是在多边形内部还是外部

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43892459/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 23:29:38  来源:igfitidea点击:

Check if geo-point is inside or outside of polygon

pythonpolygoncoordinate-systemsshapelypoint-in-polygon

提问by Federico Gentile

I am using python and I have defined the latitudes and longitudes (in degrees) of a polygon on the map. My goal is to check if a generic point Pof coordinates x,yfalls within such polygon. I would like therefore to have a function that allows me to check such condition and return Trueor Falseif the point is inside or outside the polygon.

我正在使用 python 并且我已经定义了地图上多边形的纬度和经度(以度为单位)。我的目标是检查通用P坐标点是否x,y落在这样的多边形内。因此,我希望有一个函数可以让我检查这种条件并返回,True或者False该点是否在多边形内部或外部。

enter image description here

在此处输入图片说明

In this example the point is outside so the result would be False

在这个例子中,点在外面,所以结果是 False

Question: Is there a library/package that allows to reach my goal? if yes which one do you recommend? would you be able to give a small example on how to use it?

问题:是否有一个库/包可以实现我的目标?如果是,你推荐哪一个?你能举一个关于如何使用它的小例子吗?

Here is the code I have written so far:

这是我到目前为止编写的代码:

import numpy as np

# Define vertices of polygon (lat/lon)
v0 = [7.5, -2.5] 
v1 = [2, 3.5]
v2 = [-2, 4]
v3 = [-5.5, -4]
v4 = [0, -10]
lats_vect = np.array([v0[0],v1[0],v2[0],v3[0],v4[0]])
lons_vect = np.array([v0[1],v1[1],v2[1],v3[1],v4[1]])

# Point of interest P
x, y = -6, 5 # x = Lat, y = Lon

## START MODIFYING FROM HERE; DO NOT MODIFY POLYGON VERTICES AND DATA TYPE
# Check if point of interest falls within polygon boundaries
# If yes, return True
# If no, return False

In order to plot the polygon and the point of interest I used cartopy and I wrote the following lines of code:

为了绘制多边形和兴趣点,我使用了 cartopy 并编写了以下代码行:

import cartopy.crs as ccrs
import matplotlib.pyplot as plt
ax = plt.axes(projection=ccrs.PlateCarree())
ax.stock_img() 

# Append first vertex to end of vector to close polygon when plotting
lats_vect = np.append(lats_vect, lats_vect[0])
lons_vect = np.append(lons_vect, lons_vect[0])
plt.plot([lons_vect[0:-1], lons_vect[1:]], [lats_vect[0:-1], lats_vect[1:]],
         color='black', linewidth=1, 
         transform=ccrs.Geodetic(),
         )   

plt.plot(y, x, 
        '*',          # marker shape
        color='blue',  # marker colour
        markersize=8  # marker size
        )  

plt.show()  

Note:

注意

  • points are connected to each other by Great Circles!
  • I have researched in the internt and I ended up finding some similar questions like this onebut I had no success since they all use of .shpfiles which I do not have.
  • 点通过大圆圈相互连接!
  • 我研究的Internt的,我最终找到了一些类似的问题像这样的,但我没有成功,因为它们都使用的.shp是我没有的文件。

回答by Federico Gentile

Here is a possible solution to my problem.

这是我的问题的可能解决方案。

  1. Geographical coordinates must be stored properly. Example np.array([[Lon_A, Lat_A], [Lon_B, Lat_B], [Lon_C, Lat_C]])
  2. Create the polygon
  3. Create the point to be tested
  4. Use polygon.contains(point)to test if point is inside (True) or outside (False) the polygon.
  1. 必须正确存储地理坐标。例子np.array([[Lon_A, Lat_A], [Lon_B, Lat_B], [Lon_C, Lat_C]])
  2. 创建多边形
  3. 创建要测试的点
  4. 使用polygon.contains(point)如果点在内部测试(True)或外部(False)的多边形。

Here is the missing part of the code:

这是代码的缺失部分:

from shapely.geometry import Point
from shapely.geometry.polygon import Polygon

lons_lats_vect = np.column_stack((lons_vect, lats_vect)) # Reshape coordinates
polygon = Polygon(lons_lats_vect) # create polygon
point = Point(y,x) # create point
print(polygon.contains(point)) # check if polygon contains point
print(point.within(polygon)) # check if a point is in the polygon 

Note: the polygon does not take into account great cycles apparently, therefore it is necessary to split the edges into many segments thus increasing the number of vertices.

注意:多边形显然没有考虑大循环,因此需要将边分成许多段从而增加顶点数。



Special case: If point lies on borders of Polygon特殊情况:如果点位于多边形的边界上

E.g. print(Polygon([(0, 0), (1, 0), (1, 1)]).contains(Point(0, 0)))will fail

例如print(Polygon([(0, 0), (1, 0), (1, 1)]).contains(Point(0, 0)))会失败

So one can use

所以可以使用

print(polygon.touches(point)) # check if point lies on border of polygon 

回答by lfvv

Another way to do it is by using the even-odd algorithm explained in this link https://wrf.ecse.rpi.edu//Research/Short_Notes/pnpoly.htmlThe python code is given in wikipedia https://en.wikipedia.org/wiki/Even–odd_rule

另一种方法是使用此链接中解释的奇偶算法https://wrf.ecse.rpi.edu//Research/Short_Notes/pnpoly.html维基百科https://en 中给出了 python 代码。 wikipedia.org/wiki/Even–odd_rule

Folks, just remember that the ORDER OF POINTS that make the polygon MATTER! I mean, different order results in different polygons.

伙计们,请记住使多边形变得重要的点顺序!我的意思是,不同的顺序会导致不同的多边形。