#!/usr/bin/python
#-*- coding: UTF-8 -*-
#
# pip.py
# point in polygon
#
# 2016-01-07
#
# point(pt) is inside polygon(poly)
########################################################################
# gets extent of vertices vl
#
def extent_vertices(vl):
min_x = 0.0
min_y = 0.0
max_x = 0.0
max_y = 0.0
i = 0
for (x, y) in vl:
if not i:
(min_x, min_y) = (x, y)
(max_x, max_y) = (x, y)
i = 1
else:
if x < min_x:
min_x = x
if y < min_y:
min_y = y
if x > max_x:
max_x = x
if y > max_y:
max_y = y
return (min_x, min_y, max_x, max_y)
# points p, q are on the same of line l
#
def same_side(l_start, l_end, p, q):
dx, dy = float(l_end[0] - l_start[0]), float(l_end[1] - l_start[1])
dx1, dy1 = float(p[0] - l_start[0]), float(p[1] - l_start[1])
dx2, dy2 = float(q[0] - l_end[0]), float(q[1] - l_end[1])
d = (dx * dy1 - dy * dx1) * (dx * dy2 - dy * dx2)
if d >= 0:
return 1
else:
return 0
# are line segments s1, s2 intersect ?
#
def intersect_segs(s1_start, s1_end, s2_start, s2_end):
if not same_side(s1_start, s1_end, s2_start, s2_end) and not same_side(s2_start, s2_end, s1_start, s1_end):
return 1
else:
return 0
# is point pt(x, y) in polygon poly
# returns:
# 0 : not in
# 1 : in
def pt_in_poly(pt, poly):
np = len(poly)
if np < 3:
return 0
(x, y) = pt
(min_x, min_y, max_x, max_y) = extent_vertices(poly)
if x < min_x or x > max_x or y < min_y or y > max_y:
return 0
# set a horizontal beam line (pt, w) from pt to the ultra right
w = (max_x + max_x*0.1 + 1, y)
c = 0
for i in range(0, np):
j = (i+1) % np
if pt == poly[i]:
return 1
elif intersect_segs(poly[i], poly[j], pt, w):
c = c + 1
elif poly[i][1] == w[1]:
k1 = (np + i - 1) % np
while (k1 != i and poly[k1][1] == w[1]):
k1 = (np + k1 - 1) % np
k2 = (i+1) % np
while (k2 != i and poly[k2][1] == w[1]):
k2 = (k2 + 1) % np
if k1 != k2 and not same_side(pt, w, poly[k1], poly[k2]):
c = c + 1
if k2 <= i:
break
i = k2
return c % 2
epsilon = 0.0000001
assert pt_in_poly((0, 0), [(-1, -1), (-1, 1), (1, 1), (1, -1)]) == 1, "(1) appliaction error"
assert pt_in_poly((-1, -1), [(-1, -1), (-1, 1), (1, 1), (1, -1)]) == 1, "(2) appliaction error"
assert pt_in_poly((-1, 1), [(-1, -1), (-1, 1), (1, 1), (1, -1)]) == 1, "(3) appliaction error"
assert pt_in_poly((-1 - epsilon, -1), [(-1, -1), (-1, 1), (1, 1), (1, -1)]) == 0, "(4) appliaction error"
assert pt_in_poly((-1 + epsilon, -1 + epsilon), [(-1, -1), (-1, 1), (1, 1), (1, -1)]) == 1, "(5) appliaction error"
assert pt_in_poly((-1 + epsilon, -1 + epsilon), [(-1, -1), (-1, 1), (1, 1), (1, -1)]) == 1, "(6) appliaction error"
assert pt_in_poly((0, 0), [(-1, -1), (-1, 1), (1, 1), (1, 0), (2, -1)]) == 1, "(7) appliaction error"
assert pt_in_poly((0, 0), [(-1, -1), (-1, 1), (1, 1), (1, 0), (2, 1), (2, -1)]) == 1, "(8) appliaction error"
assert pt_in_poly((0, 0), [(-1, -1), (-1, 1), (1, 1), (1, 0), (2, 1), (2, 0), (2, -1)]) == 1, "(9) appliaction error"
assert pt_in_poly((0, 0), [(-1, -1), (-1, 1), (1, 1), (1, 0), (2, 0), (3, 0), (2, -1)]) == 1, "(10) appliaction error"
assert pt_in_poly((-2, 0), [(-1, -1), (-1, 1), (1, 1), (1, 0), (2, 0), (3, 0), (2, -1)]) == 0, "(11) appliaction error"
assert pt_in_poly((3, 0), [(-1, -1), (-1, 1), (1, 1), (1, 0), (2, 0), (3, 0), (2, -1)]) == 1, "(12) appliaction error"