判断一个点是否在矩形内会经常用到,比如判断点是否在障碍物里,判断游戏中的玩家是否在某一区域。网上的解释都是抄来抄去的,有的明显错误也没发现,要么就是扔了一段代码,什么解释也没有,让人云里雾里。因此这里好好的讲解以下。
首先要明确的是矩形也可以旋转。因此,在矩形内检查点的简单解决方案在这里不起作用。
- 关于射线法:1.当射线经过顶点时,判断就会出现异常情况。 2. 点在边上:这种情况也不能用交点个数的奇偶性来判断了。
- 关于面积法:就是计算所有边和目标点组成的三角形面积和是否等于总的多边形面积,如果相等,则点在该区域的内部。这种方法计算量较大,多边形的面积计算也是比较麻烦;
- 还有夹角法:判断所有边和目标点的夹角和是否为360度,计算量同样很大。
那么该如何处理这个问题呢?想要解决这个问题首先要了解叉积的概念,叉积 ( x 1 , y 1 ) × ( x 2 , y 2 ) = x 1 ∗ y 2 − x 2 ∗ y 1 (x1,y1) \times (x2,y2)=x1*y2-x2*y1 (x1,y1)×(x2,y2)=x1∗y2−x2∗y1,大小表示两个向量围成的平行四边形的面积,正负表示两个向量的相对位置。用处:求面积或者判断两点的相对位置。顺带提一下点积: ( x 1 , y 1 ) ⋅ ( x 2 , y 2 ) = x 1 ∗ x 2 + y 1 ∗ y 2 (x1,y1) \cdot(x2,y2)=x1*x2 + y1*y2 (x1,y1)⋅(x2,y2)=x1∗x2+y1∗y2,用处:判断直线是否正交。关于叉积的另一篇精彩解释
叉积首先可以判断两点间的相对位置:一个点位于另一个点的顺时针或逆时针方向:以p0为参考点,如果multi大于0,则p2在p1的逆时针方向,反正,如果multi小于0,则p2在p1的顺时针方向,特殊的,当multi等于0,p1、p2、p0三点共线。
然后我们就可以判断线段间的关系:
最后,我们就可以判断点是否落在矩形内了:
如上图一所示,只需要判断该点是否在上下两条边和左右两条边之间就行,判断一个点是否在两条线段之间夹着,就转化成,判断一个点是否在某条线段的一边上,就可以利用叉乘的方向性,来判断夹角是否超过了180度 。因此只要满足 ( P 1 P 2 → × P 1 P → ) ∗ ( P 3 P 4 → × P 3 P → ) > = 0 (\overrightarrow{P_1P_2} \times \overrightarrow{P_1P})*(\overrightarrow{P_3P_4} \times \overrightarrow{P_3P})>=0 (P1P2