-- coding: UTF-8 --
def isRayIntersectsSegment(poi, s_poi, e_poi): # [x,y] [lng,lat]
# 输入:判断点,边起点,边终点,都是[lng,lat]格式数组
if e_poi[1] == s_poi[1]: # 排除与射线平行、重合,线段首尾端点重合的情况
return False
if s_poi[1] > poi[1] and e_poi[1] > poi[1]: # 线段在射线上边
return False
if s_poi[1] < poi[1] and e_poi[1] < poi[1]: # 线段在射线下边
return False
if s_poi[1] == poi[1] and e_poi[1] > poi[1]: # 交点为下端点,对应spoint
return False
if e_poi[1] == poi[1] and s_poi[1] > poi[1]: # 交点为下端点,对应epoint
return False
if s_poi[0] < poi[0] and e_poi[1] < poi[1]: # 线段在射线左边
return False
xseg = e_poi[0] - (e_poi[0] - s_poi[0]) * (e_poi[1] - poi[1]) / (e_poi[1] - s_poi[1]) # 求交
if xseg < poi[0]: # 交点在射线起点的左侧
return False
return True # 排除上述情况之后
def isPoiWithinPoly(poi, poly):
# 输入:点,多边形三维数组
# poi = [114.3771791319310,22.7497690992367]
# poly=[[114.373239,22.766905],[114.377016,22.762948],[114.379763,22.755033],[114.386801,22.755983],[114.392809,22.758199],[114.400877,22.761681],[114.400877,22.769437],[114.40534,22.775769],[114.412893,22.77561],[114.417013,22.769437],[114.420618,22.763897],[114.42079,22.762473],[114.415983,22.760573],[114.408945,22.758832],[114.402422,22.756457],[114.394354,22.753925],[114.385084,22.751708],[114.379419,22.751234],[114.375986,22.748701],[114.373411,22.746168],[114.366888,22.743001],[114.364656,22.741102]] #三维数组
# 可以先判断点是否在外包矩形内
# if not isPoiWithinBox(poi,mbr=[[0,0],[180,90]]): return False
# 但算最小外包矩形本身需要循环边,会造成开销,本处略去
sinsc = 0 # 交点个数
for epoly in poly: # 循环每条边的曲线->each polygon 是二维数组[[x1,y1],…[xn,yn]]
for i in range(len(epoly) - 1): # [0,len-1]
s_poi = epoly[i]
e_poi = epoly[i + 1]
if isRayIntersectsSegment(poi, s_poi, e_poi):
sinsc += 1 # 有交点就加1
return True if sinsc % 2 == 1 else False