在三角形abc中:判断点是否在三角形内部

判断点是否在三角形内

概述

给定三角形ABC和一点P(x,y),判断点P是否在ABC内。这是游戏设计中一个常见的问题。也是《算法竞赛入门经典(第一版)》中5.4.3节“果园中的树”中的问题。

重心法

该方法简单易懂,速度也快,只是多了点向量运算的知识。 
在xy坐标系平面中有一个三角形ABC,P是xy平面上的任一点,如下图所示。 
这里写图片描述 
对于平面内任意一点P,都可以由如下方程来表示:

AP = u*AC + v*AB (1)其中,两个大写字母表示向量,小写字母表示标量。

由该方程中u、v的符号可以判断出点P与三角形ABC的位置关系。

-P位于三角形内

u > 0v > 0u + v < 1

-P位于三角形边上

u = 0 且 0 < v < 1 //P在AB边上v = 0 且 0 < u < 1 //P在AC边上u > 0 且 v > 0 且 u+v < 1 //P在AB边上

-P位于三角形顶点上

u = 0 且 v = 0 //P位于A点u = 0 且 v = 1 //P位于B点u = 1 且 v = 0 //P位于C点

-P位于三角形外

u<0 或 v<0 或 n+v>1

-u,v 的求解

记AP=(x1,y1),AC=(x2,y2),AB=(x3,y3),则代入方程(1)解得:

u = (x1*y3-x3*y1)/(x2*y3-x3*y2)v = (x1*y2-x2*y1)/(x3*y2-x2*y3)

或者用向量形式进行计算(以下默认两个大写字母表示一个向量)

分别在方程(1)的左右两端同时点乘AC、AB,得到下式:AP·AC = u*AC·AC + v*AB·ACAP·AB = u*AC·AB + v*AB·AB

因为两个向量点乘后得到一个数,所以上式解得:

u = [(AP·AC)(AB·AB)-(AP·AB)(AB·AC)]/[(AC·AC)(AB·AB)-(AC·AB)(AB·AC)]v = [(AP·AC)(AC·AB)-(AP·AB)(AC·AC)]/[(AB·AC)(AC·AB)-(AB·AB)(AC·AC)]

同向法

假设点P位于三角形内,会有这样一个规律,当我们沿着ABCA的方向在三条边上行走时,会发现点P始终位于边AB,BC和CA的右侧。我们就利用这一点来判断点P的位置。

当选定线段AB时,点C位于AB的右侧,同理选定BC时,点A位于BC的右侧,最后选定CA时,点B位于CA的右侧,所以当选择某一条边时,我们只需验证点P与该边所对的点在同一侧即可。 
这里写图片描述

要判断两个点是否在某条线段的同一侧可以通过叉积来实现。连接PA,将PA和AB做叉积,再将CA和AB做叉积,如果两个叉积的结果方向一致,那么两个点在同一侧。

判断两个向量是否同向可以用点积实现,如果点积大于0,则两向量夹角是锐角,否则是钝角。

– 确定叉积方向的“右手定则”

在一个满足右手定则的坐标系中,c = a x b,当右手的四指从a以不超过180度的转角转向b时,竖起的大拇指指向是c的方向。

还有一种稍显复杂的方法,需要先求出三条边的方程,然后利用同向法来判断。 
例如,三个顶点为A(a1,a2),B(b1,b2),C(c1,c2). P点坐标为(p1,p2)。 
记三条边方程为:

BC: fa(x,y)=0AC: fb(x,y)=0AB: fc(x,y)=0

以AB为例,在三角形内的点P必须与点C在AB的同侧,即fc(p1,p2)*fc(c1,c2)>0 
记u、v、w为下式:

u = fa(x,y)*fa(a1,a2)v = fb(x,y)*fb(b1,b2)w = fc(x,y)*fc(c1,c2)

则由u、v、w三个数的符号可以确定任意点P(x,y)与三角形ABC的位置关系。

三个数都是正数:P在三角形内;至少有一个负数:P在三角形外;有且只有一个0,另两个为正数:P在三角形边上;有二个0:在三角形的顶点上。

内角和

连接点P和三角形的三个顶点得到三条线段PA,PB和PC,求出这三条线段与三角形各边的夹角,如果所有夹角之和为180度,那么点P在三角形内,否则不在。此法直观,但效率低下。

这里写图片描述

相关推荐

相关文章