Skip to content

Instantly share code, notes, and snippets.

@aslotnick
Last active February 6, 2018 17:28
Show Gist options
  • Save aslotnick/6c98708562313c6dd72e to your computer and use it in GitHub Desktop.
Save aslotnick/6c98708562313c6dd72e to your computer and use it in GitHub Desktop.
Simple point-in-polygon UDF for Amazon Redshift based on http://geospatialpython.com/2011/08/point-in-polygon-2-on-line.html
CREATE FUNCTION point_in_polygon(point_x float, point_y float, polygon_wkt varchar(max))
RETURNS boolean IMMUTABLE AS
$$
### begin section copied from http://geospatialpython.com/2011/08/point-in-polygon-2-on-line.html (I modifed to return boolean)
# Improved point in polygon test which includes edge
# and vertex points
def point_in_poly(x,y,poly):
# check if point is a vertex
if (x,y) in poly: return True
# check if point is on a boundary
for i in range(len(poly)):
p1 = None
p2 = None
if i==0:
p1 = poly[0]
p2 = poly[1]
else:
p1 = poly[i-1]
p2 = poly[i]
if p1[1] == p2[1] and p1[1] == y and x > min(p1[0], p2[0]) and x < max(p1[0], p2[0]):
return True
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:
xints = (y-p1y)*(p2x-p1x)/(p2y-p1y)+p1x
if p1x == p2x or x <= xints:
inside = not inside
p1x,p1y = p2x,p2y
if inside: return True
else: return False
### end section copied from http://geospatialpython.com/2011/08/point-in-polygon-2-on-line.html
#extremely simplistic parsing, assumes that the Polygon is in WKT format and is a valid simple polygon
vertices_string = [p.split(' ') for p in polygon_wkt[9:-2].split(',')]
vertices = [(float(v[0]), float(v[1])) for v in vertices_string]
return point_in_poly(point_x, point_y, vertices)
$$
LANGUAGE plpythonu;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment