检测二维平面内一个点在多边形内的方法

最近项目需要, 所以查了一下实现2D平面内判断一个点在多边形内的方法. 感觉这个方法非常巧妙且计算量不大.

在这个方法中, 多边形边界是用点来描述的. 多边形的凸凹性不受限制, 也就是说, 多边形可以是凸也可以是凹的.

对于任意两个构成多边形边界的点, 有如下这种情况:(这里假设这两个点连线斜率为正于是画成了下面的样子)

这里写图片描述

构成多边形的点是 ( x i , y i ) (x_i, y_i) (xi,yi) ( x i + 1 , y i + 1 ) (x_{i+1}, y_{i+1}) (xi+1,yi+1), 要判断的点是 ( x 0 , y 0 ) (x_0, y_0) (x0,y0). 红色的线是一条从 ( x 0 , y 0 ) (x_0, y_0) (x0,y0)出发斜率为 ∞ \infty 的射线.

首先判断 ( x 0 , y 0 ) (x_0, y_0) (x0,y0)是否在 x i x_i xi x i + 1 x_{i+1} xi+1之间. 故该点需要满足
x i &lt; x 0 &lt; x i + 1 或 者 是 x i + 1 &lt; x 0 &lt; x i x_i&lt;x_0&lt;x_{i+1}或者是\\ x_{i+1}&lt;x_0&lt;x_{i} xi<x0<xi+1xi+1<x0<xi

接下来还需要判断 ( x 0 , y 0 ) (x_0, y_0) (x0,y0)是不是在黑色的线的下面
k = y i + 1 − y i x i + 1 − x i y 0 &lt; k ( x 0 − x i ) + y i k=\frac{y_{i+1}-y_i}{x_{i+1} - x_i}\\ y_0&lt;k(x_0-x_i)+y_i k=xi+1xiyi+1yiy0<k(x0xi)+yi
这样就完成了判断点 ( x 0 , y 0 ) (x_0, y_0) (x0,y0)在黑色直线下的过程.

接下来对于构成多边形边界的所有的点 x i x_i xi x i + 1 x_{i+1} xi+1都应用上面的方法进行判断. 只要满足上述准则, 就设置计数器加1.
如果要判断的点 ( x 0 , y 0 ) (x_0, y_0) (x0,y0)在多边形的范围内, 那一定满足计数器为奇数, 也就是对2取余为1.
例如, 下图计数器结果是1.

这里写图片描述

下图中结果是3.
这里写图片描述

代码如下

bool contains(double x0, double y0)
{
	int crossings = 0;
	for(int i=0; i<N; i++)
	{
		double slope = (y[i+1] - y[i])/(x[i+1] - x[i]);
		bool cond1 = (x[i] < x0) && (x[i+1] > x0);
		bool cond2 = (x[i+1] < x0) && (x[i] > x0);
		bool above = (y0 < slope * (x0 - x[i]) + y[i]);
		if((cond1 || cond2) && above)
		{
			crossings++;
		}
	}
	return (crossings %2 != 0)
}

参考文献
https://github.com/sromku/polygon-contains-point

小结
前面有一篇博客是来说如何判断两个三角形是否相交的问题. 仔细想想之后发现, 本篇文章提供的方法虽然简单, 但是不能用在那个问题上. 例如这种情况 :
两个三角形相交
没有一个点在三角形内, 然而两个三角形却是相交的.

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值