1.射线法简述
因为工作需要,所以需要判断某个坐标的点是不是在某个区域范围(单个闭合多边形)内。经过在网上搜索资料,发现射线法能解决我的问题,并且十分巧妙,记录一下。
据说这个办法也叫==奇偶规则法==,如果比较想一探究竟的话可以去了解一下,具体证明什么的我也无能为力,good luck。
原理:
1.如果一个点在一个多边形内部,那么以它为起始点,发射一条射线(任意方向),那么它至少会和一条边相交,也就是有一个交点。如图所示
2.如果点在多边形内部出发射线不止和一条边相交,在不经过端点和整条边的情况下,一定和边有奇数个交点(我也不知道怎么证明,但是画了很多图,确实是这么神奇。如果有大佬能证明再好不过了),看图,有3个交点
3.如果经过端点和边需要单独讨论。
综上,如果一个点在闭合多边形内部,那么它和多边形的交点是奇数个。
具体处理
1.单个闭合多边形需要端点都按顺时针或者逆时针顺序构建。这是构建多边形的基础,如果这一步出错了,后面的都无法进行
2.由于两个点A(x1,y1)、B(x2,y2)形成的坐标系方程是y=(y2(x-x1)+y1(x2-x))/(x2-x1),除数是x2-x1,如果A、B横坐标相同,则除数是0,为了避免这个问题,我们取目标点沿y轴正半轴平行线做射线,就像上面画的那样,也为了偷个懒,代入目标点的横坐标,得到连线和射线的交点纵坐标y,如果交点纵坐标大于目标点纵坐标,则必定相交,交点数+1,如果刚好相等,就在边上,直接返回在多边形内部(方程可以自己求,万一我错了我就是罪人,毕竟好久不读书了,勿喷)
3.如果射线经过了一个端点,无论计算两次还是1次都会出问题,如图
统一按2个或者1个算都是错的,所以处理方式是穿过两个点中的较大(或者较小)x轴坐标记一次交点,仍然是奇数次为图形内部,不信可以试试(反正我不会证明)(如果是从x轴发射射线,那就是取较大或者较小的y坐标记录交点)
4.经过一条边,也就是平行于y轴,这条边不计算交点
5.刚好在边上/就是端点,很简单,就不说了
6.对于max(y1,y2)<y的线段,不进行判断,因为是向上去取射线,所以绝对不会有任何交点,加快速度
7.同理,对于max(x1,x2)<x或者min(x1,x2)>x的线段,不进行判断,因为线段是平行于y轴的,所以绝对不会与线段有任何交点,加快速度
python代码
# 测试边界样例0.0,0.0;1.0,0.0;1.0,1.0;0.0,1.0
# 用;分割坐标点,用,分割横纵坐标
class Point:
def __init__(self, lng, lat):
try:
self.lng = float(lng)
self.lat = float(lat)
except Exception as e:
self