我已经搜索了所有执行此操作的算法,但我找不到一个按照我需要的方式执行此操作的算法。现在我基本上总结了三个内部三角形形成的区域,看它是否等于整个区域,但不知何故它不能正常工作,我也不知道它是否足够严格并涵盖所有情况。
def isInsideTriangle(P,p1,p2,p3): #is P inside triangle made by p1,p2,p3?
x,x1,x2,x3 = P[0],p1[0],p2[0],p3[0]
y,y1,y2,y3 = P[1],p1[1],p2[1],p3[1]
full = abs (x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2))
first = abs (x1 * (y2 - y) + x2 * (y - y1) + x * (y1 - y2))
second = abs (x1 * (y - y3) + x * (y3 - y1) + x3 * (y1 - y))
third = abs (x * (y2 - y3) + x2 * (y3 - y) + x3 * (y - y2))
return abs(first + second + third - full) < .0000001
实施例:
print isInsideTriangle((-10,0),(-10,-10),(10,-10),(0,10))
应为true,返回false
但
print isInsideTriangle((0,0),(-10,0),(10,0), (0,10))
返回true,因为它应该
答案 0 :(得分:3)
从评论到您的问题,我认为您要求的是,如果在边缘,则应该将该点视为三角形。在这种情况下,交叉乘积(在另一个问题中称为“符号”)将为零,在这种情况下,您可以将比较改为将“零”视为“右侧”,即
def sign(p1, p2, p3):
return (p1[0] - p3[0]) * (p2[1] - p3[1]) - (p2[0] - p3[0]) * (p1[1] - p3[1])
def PointInAABB(pt, c1, c2):
return c2[0] <= pt[0] <= c1[0] and \
c2[1] <= pt[1] <= c1[1]
def PointInTriangle(pt, v1, v2, v3):
b1 = sign(pt, v1, v2) <= 0
b2 = sign(pt, v2, v3) <= 0
b3 = sign(pt, v3, v1) <= 0
return ((b1 == b2) and (b2 == b3)) and \
PointInAABB(pt, map(max, v1, v2, v3), map(min, v1, v2, v3))
现在,这在数值上不是很稳定(你不应该将浮点数比作相等),除非这些点实际上是相同的而不是相等的(即来自同一个源)。
如果你想要一些更稳定的东西,也许你可以用<= 0
改变<= ε
,其中ε
是一个小数字。但这一切都取决于你的用例。
编辑:更新以处理退化三角形。