判断点是否在多边形内部
注:
从网上看了好些个,思路了解了下,然后粘代码测试,发现很多都是错的,而且错的都一样,这里粘贴一个测试过的。主要差别在于应该先判断线段是否在左边,否则就会出现边界问题,计算错误。
# 判断点和线的位置关系
def isRayIntersectsSegment(poi,s_poi,e_poi): #[x,y] [lng,lat]
# print(poi,s_poi,e_poi)
#输入:判断点,边起点,边终点,都是[lng,lat]格式数组
if s_poi[0]<poi[0] and e_poi[0]<poi[0]: #线段在射线左边
return False
if s_poi[1]==e_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
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 is_in_polygon(p,polygon):
#polygon.append(polygon[0])
# 注意,需要传入的列表中,首尾需要相连,即最后一个点是需要和第一个点相同的。
# 构建多边形时需要注意不能有交叉存在
x_num = 0
for i in range(len(polygon)-1):
if isRayIntersectsSegment(p,polygon[i],polygon[i+1]):
x_num += 1
return x_num % 2 == 1
这里也给出后端服务代码,使用python-flask搭建
from flask_cors import CORS
import json
import flask
from flask import request
cfg = None
app = flask.Flask(__name__)
CORS(app,supports_credentials=True)
# 判断点和线的位置关系
def isRayIntersectsSegment(poi,s_poi,e_poi): #[x,y] [lng,lat]
# print(poi,s_poi,e_poi)
#输入:判断点,边起点,边终点,都是[lng,lat]格式数组
if s_poi[0]<poi[0] and e_poi[0]<poi[0]: #线段在射线左边
return False
if s_poi[1]==e_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
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 is_in_polygon(p,polygon):
x_num = 0
for i in range(len(polygon)-1):
if isRayIntersectsSegment(p,polygon[i],polygon[i+1]):
x_num += 1
return x_num % 2 == 1
@app.route('/cfg',methods=['POST','GET'])
def set_cfg():
global cfg
if request.method == 'POST':
cfg = request.json['data']
cfg.append(cfg[0])# 这里多边形闭环(如果已经闭环,请注释)
return 'ok'
else:
return 'wrong requests'
@app.route('/p',methods=['POST'])
def p_in_polygon():
p = request.json
f = is_in_polygon(p,cfg)
return json.dumps({"in":f})
if __name__ == '__main__':
#app.debug = True
app.run('0.0.0.0',3000)