版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/pp634077956/article/details/54289565
给定任意一个点的坐标和一个三角形,判定这个点是否在三角形内部。
本文独立思考完成,没有参考别的资料,可能方法不是太简洁。
基本思路:
[0]:考虑点在三角形内部的特征:任何一条经过该点的直线都一定会和这个三角形有交点,也就是会与某些边有交点。考虑这样的直线的特殊情况使得经过外部的点的直线和三角形没有交点。容易联想到党该直线平行于某一条边的时候,这样的直线一定会与三角形没有交点(可以将三角形外部的平面划分为6个区域来思考)。
[1]:问题转换成:枚举经过该点的直线的三种情况,并检测每一种情况与三条边的交点。实际上我们不需要检测与之平行的那一条边(有交点也一定是顶点),只需要检测另外两条边即可。我们可以通过斜率和点坐标计算出直线方程,写成
ay+bx+c=0
的形式,注意处理斜率为无穷大的情况(此时a = 0),然后联立两个方程可以解得交点。
[2]:判断交点在不在线段的范围之内,这样就可以判断与这条边是否有交点。
(x−xmin)∗(x−xmax)≤0...(1)
(y−ymin)∗(y−ymax)≤0...(2)
[3]最后可以知道:假如存在一条直线与三角形没有交点,那么必然在三角形外部:
def get_line(x,y,k):
#return ax+by+c = 0
return (0,1,-x) if k==None else (-1,k,y-k*x)
def line_intersection(a1,b1,c1,a2,b2,c2):
assert(a2*b1!=a1*b2)
x = (a1*c2-a2*c1)/(a2*b1-a1*b2)
y = -(b2*x+c2)/a2 if a2!=0 else -(b1*x+c1)/a1
return x,y
def check(x,y,bound):
(x1,x2),(y1,y2) = bound[0],bound[1]
return (x-x1)*(x-x2)<=0 and (y-y1)*(y-y2)<=0# in the segment
def is_inner(x0,y0,p1,p2,p3):
points = set([p1,p2,p3])
for p in (p1,p2,p3):
x3,y3 = p
((x1,y1),(x2,y2)) = points-set([p])
k = None if x1==x2 else (y2-y1)/(x2-x1)
a1,b1,c1 = get_line(x0,y0,k)
for (x,y) in ((x1,y1),(x2,y2)):
k_seg = None if x==x3 else (y3-y)/(x3-x)
a2,b2,c2 = get_line(x,y,k_seg)
x_intersec,y_intersec = line_intersection(a1,b1,c1,a2,b2,c2)
bound = ((x,x3),(y,y3))
if not check(x_intersec,y_intersec,bound):#not intersected
return False
return True