📜  求一个点是否在三点 A、B、C 的内、外或外接圆上(1)

📅  最后修改于: 2023-12-03 14:55:58.480000             🧑  作者: Mango

判断点是否在三点内、外或外接圆上

在计算机科学中,经常需要判断点是否在三角形的内、外或外接圆上。这对于计算几何、计算机图形学和游戏开发等领域都非常重要。

问题描述

假设三角形 ABC 的三个顶点分别为 A(x1,y1),B(x2,y2),C(x3,y3),一个点 P(x,y)。如何判断 P 是否在 ABC 的内、外或外接圆上?

解决方案

判断点是否在三角形的内、外或外接圆上的问题可以分别考虑,下面我们将分别介绍三种判断方法。

1. 判断点是否在三角形内部

思路

判断点是否在三角形内部,可以通过计算三个点组成的三角形面积和点 P 到三边距离的乘积来判断。如果点 P 在三角形内部,那么点 P 到三边的距离乘积之和就等于三角形的面积。

具体来说,假设三角形 ABC 的三个顶点分别为 A(x1,y1),B(x2,y2),C(x3,y3),一个点 P(x,y),三边分别为 AB、BC、AC,三角形面积为 S,则

$$ S_{ABC} = \frac{1}{2}\left | x_{1}(y_{2}-y_{3}) + x_{2}(y_{3}-y_{1}) + x_{3}(y_{1}-y_{2})\right | $$

点 P 到线段 AB、BC、AC 的距离为:

$$ d_{AB} = \frac{\left |\vec{AB}\times \vec{AP} \right |}{\left | \vec{AB} \right |} $$

$$ d_{BC} = \frac{\left |\vec{BC}\times \vec{BP} \right |}{\left | \vec{BC} \right |} $$

$$ d_{AC} = \frac{\left |\vec{AC}\times \vec{AP} \right |}{\left | \vec{AC} \right |} $$

其中, | | 表示向量的模长, $\times$ 表示向量的叉积。

代码实现

def point_in_triangle(x1, y1, x2, y2, x3, y3, x, y):
    S = abs(0.5 * (x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)))
    s1 = abs(0.5 * (x1 * (y - y2) + x2 * (y1 - y) + x * (y2 - y1)))
    s2 = abs(0.5 * (x * (y2 - y3) + x2 * (y3 - y) + x3 * (y - y2)))
    s3 = abs(0.5 * (x1 * (y3 - y) + x * (y1 - y3) + x3 * (y - y1)))
    return abs(s1 + s2 + s3 - S) < 1e-6

示例

>>> point_in_triangle(0, 0, 3, 0, 0, 4, 1, 1)
True
>>> point_in_triangle(0, 0, 3, 0, 0, 4, 2, 2)
False
2. 判断点是否在三角形外部

思路

判断点是否在三角形外部,可以根据向量夹角的正负性来判断。假设点 P 在三角形 ABC 外部,以边 AB 为例,那么向量 $\vec{AP}$ 和向量 $\vec{AB}$ 的夹角为 $\theta$,如果 $\theta > \pi/2$,那么点 P 就在线段 AB 的逆时针方向,否则在 AB 的顺时针方向。

同理,可以分别判断点 P 和线段 BC,AC 的相对位置,如果点 P 在三条边的同侧,那么点 P 就在三角形外部。

代码实现

def point_outside_triangle(x1, y1, x2, y2, x3, y3, x, y):
    p1 = (x2 - x1) * (y - y1) - (x - x1) * (y2 - y1)
    p2 = (x3 - x2) * (y - y2) - (x - x2) * (y3 - y2)
    p3 = (x1 - x3) * (y - y3) - (x - x3) * (y1 - y3)
    return p1 > 0 and p2 > 0 and p3 > 0 or p1 < 0 and p2 < 0 and p3 < 0

示例

>>> point_outside_triangle(0, 0, 3, 0, 0, 4, 1, 1)
False
>>> point_outside_triangle(0, 0, 3, 0, 0, 4, 4, 4)
True
3. 判断点是否在三角形外接圆上

思路

判断点是否在三角形外接圆上,可以先求出三角形的外接圆圆心和半径,然后判断点 P 是否在圆心为 O,半径为 R 的圆上即可。

假设三角形 ABC 的三个顶点分别为 A(x1,y1),B(x2,y2),C(x3,y3),三边分别为 AB、BC、AC,圆心为 O(x0,y0),半径为 R,则:

$$ x_{0} = \frac{A.C\cdot(B.Y-C.Y) + B.A\cdot(C.Y-A.Y) + C.B\cdot(A.Y-B.Y)}{2S} $$

$$ y_{0} = \frac{A.C\cdot(C.X-B.X) + B.A\cdot(A.X-C.X) + C.B\cdot(B.X-A.X)}{2S} $$

$$ R = \frac{A.B.C}{4S} $$

其中, S=0.5(x1y2+x2y3+x3y1-x1y3-x2y1-x3y2) 为三角形 ABC 的面积。

代码实现

def point_on_circumcircle(x1, y1, x2, y2, x3, y3, x, y):
    a = math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2)
    b = math.sqrt((x2 - x3) ** 2 + (y2 - y3) ** 2)
    c = math.sqrt((x3 - x1) ** 2 + (y3 - y1) ** 2)
    S = abs(0.5 * (x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)))
    x0 = (a * c * (y2 - y3) + b * a * (y3 - y1) + c * b * (y1 - y2)) / (2 * S)
    y0 = (a * c * (x3 - x2) + b * a * (x1 - x3) + c * b * (x2 - x1)) / (2 * S)
    R = a * b * c / (4 * S)
    return abs((x - x0) ** 2 + (y - y0) ** 2 - R ** 2) < 1e-6

示例

>>> point_on_circumcircle(0, 0, 3, 0, 0, 4, 1.5, 2)
True
>>> point_on_circumcircle(0, 0, 3, 0, 0, 4, 0, 0)
False
总结

本文介绍了如何判断一个点是否在三点 A、B、C 的内、外或外接圆上。其中,判断点是否在三角形内部、外部和外接圆上的方法分别是计算点在边上的投影和三角形的外接圆的圆心和半径。这些知识对于计算几何、计算机图形学和游戏开发等领域都非常重要。