I am trying to detect if a given point(x,y) is in a polygon of n*2 array. But it seems that some points on the borders of the polygon return that it's not include.
def point_inside_polygon(x,y,poly):
n = len(poly)
inside =False
p1x,p1y = poly[0]
for i in range(n+1):
p2x,p2y = poly[i % n]
if y > min(p1y,p2y):
if y <= max(p1y,p2y):
if x <= max(p1x,p2x):
if p1y != p2y:
xinters = (y-p1y)*(p2x-p1x)/float((p2y-p1y))+p1x
if p1x == p2x or x <= xinters:
inside = not inside
p1x,p1y = p2x,p2y
return inside
Here is a simple way with multiple options
from shapely.geometry import Point, Polygon
# Point objects(Geo-coordinates)
p1 = Point(24.952242, 60.1696017)
p2 = Point(24.976567, 60.1612500)
# Polygon
coords = [(24.950899, 60.169158), (24.953492, 60.169158), (24.953510, 60.170104), (24.950958, 60.169990)]
poly = Polygon(coords)
Using within Function:
Syntax: point.within(polygon)
# Check if p1 is within the polygon using the within function
print(p1.within(poly))
# True
# Check if p2 is within the polygon
print(p2.within(poly))
# False
Using contains Function:
Syntax: polygon.contains(point)
# Check if polygon contains p1
print(poly.contains(p1))
# True
# Check if polygon contains p2
print(poly.contains(p2))
# False
Using touches Function:
Syntax: polygon.touches(point)
poly1 = Polygon([(0, 0), (1, 0), (1, 1)])
point1 = Point(0, 0)
poly1.touches(point1)
# True
If you want to speed up the process then please use
import shapely.speedups
shapely.speedups.enable()
and
Make use of Geopandas
Reference:
https://automating-gis-processes.github.io/CSC18/lessons/L4/point-in-polygon.html#point-in-polygon-using-geopandas
https://shapely.readthedocs.io/en/latest/manual.html
https://streamhacker.com/2010/03/23/python-point-in-polygon-shapely/
You may use contains_point
function from matplotlib.path
with small negative and positive radius (small trick). Something like this:
import matplotlib.path as mplPath
import numpy as np
crd = np.array([[0,0], [0,1], [1,1], [1,0]])# poly
bbPath = mplPath.Path(crd)
pnts = [[0.0, 0.0],[1,1],[0.0,0.5],[0.5,0.0]] # points on edges
r = 0.001 # accuracy
isIn = [ bbPath.contains_point(pnt,radius=r) or bbPath.contains_point(pnt,radius=-r) for pnt in pnts]
The result is
[True, True, True, True]
By default (or r=0
) all the points on borders are not included, and the result is
[False, False, False, False]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With