如何检查点是否在三角形内(在线上也可以)

时间:2013-11-27 16:38:27

标签: python

我已经搜索了所有执行此操作的算法,但我找不到一个按照我需要的方式执行此操作的算法。现在我基本上总结了三个内部三角形形成的区域,看它是否等于整个区域,但不知何故它不能正常工作,我也不知道它是否足够严格并涵盖所有情况。

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,因为它应该

1 个答案:

答案 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改变<= ε,其中ε是一个小数字。但这一切都取决于你的用例。

编辑:更新以处理退化三角形。