图形几何——三角形:判断点是否在三角形内(重心坐标法, Barycentric coordinates)

判断点是否在三角形内(重心坐标法, Barycentric coordinates)

从矢量的角度理解重心坐标的定义

在这里插入图片描述

对于任意三个非共线点,附近有任何一个点,都能满足以下条件
P = A + β A C ⃗ + γ A B ⃗ \begin{equation} \begin{split} P = A + \beta \vec{AC} + \gamma \vec{AB} \end{split} \end{equation} P=A+βAC +γAB
其几何意义解释为,从点 A A A出发,沿着 A C ⃗ \vec{AC} AC 方向走一个长度 β ∣ A C ⃗ ∣ \beta |\vec{AC}| βAC ,再沿着 A B ⃗ \vec{AB} AB 方向走一个长度 γ ∣ A B ⃗ ∣ \gamma |\vec{AB}| γAB ,则能够得到任意点 P P P的坐标(如果 β 或 γ \beta或\gamma βγ为负,则表示为 A C ⃗ \vec{AC} AC A B ⃗ \vec{AB} AB 的反方向)
如果我们将矢量操作还原为点操作,则上式还原为
P = A + β ( C − A ) + γ ( B − A ) = A + β C − β A + γ B − γ A = A − β A − γ A + β C + γ B = ( 1 − β − γ ) A + β C + γ B \begin{equation} \begin{split} P = &A + \beta(C -A) + \gamma( B - A) \\ & = A + \beta C -\beta A + \gamma B - \gamma A \\ & = A -\beta A - \gamma A + \beta C + \gamma B \\ & = (1 -\beta - \gamma) A + \beta C + \gamma B \\ \end{split} \end{equation} P=A+β(CA)+γ(BA)=A+βCβA+γBγA=AβAγA+βC+γB=(1βγ)A+βC+γB

从面积的角度理解三角形重心坐标的定义

在这里插入图片描述

在图形几何学中,重心坐标是一种表示一个点相对于三角形顶点的线性组合的方式。对于三角形 Δ A B C \Delta ABC ΔABC的点 P P P,根据上面的推导结果,重心坐标`P$同样可以用矢量或者点的形式表示,写作
P = A + β A C ⃗ + γ A B ⃗ = α A + β B + γ C \begin{equation} \begin{split} P &= A + \beta \vec{AC} + \gamma \vec{AB} \\ &=\alpha A + \beta B + \gamma C \end{split} \end{equation} P=A+βAC +γAB =αA+βB+γC
其中 α = 1 − β − γ \alpha = 1 -\beta - \gamma α=1βγ。也就是说,三角形内部任意一点 P P P都能由任意一个端点,向另外两个端点的矢量方向的移动(即矢量的系数不能为负)组合表示,有
α + β + γ = 1 \begin{equation} \begin{split} \alpha + \beta + \gamma = 1 \end{split} \end{equation} α+β+γ=1
即对于三角形中的任意点 P P P,其重心坐标表示为各顶点的加权和,其中 α + β + γ = 1 \alpha + \beta + \gamma = 1 α+β+γ=1,且 α , β , γ \alpha, \beta, \gamma α,β,γ均为非负数,因此我们可以使用重心坐标来判断点是否在三角形内
而从三角形面积角度出发,如果 P P P点在三角形的内部,那么它必定满足以下条件
S Δ A B P + S Δ B C P + S Δ A C P = S Δ A B C S Δ A B P S Δ A B C + S Δ B C P S Δ A B C + S Δ A C P S Δ A B C = 1 \begin{equation} \begin{split} S_{\Delta ABP} + S_{\Delta BCP} + S_{\Delta ACP} &= S_{\Delta ABC} \\ \dfrac{S_{\Delta ABP}}{S_{\Delta ABC}} + \dfrac{S_{\Delta BCP}}{S_{\Delta ABC}} + \dfrac{S_{\Delta ACP}}{S_{\Delta ABC}} &= 1 \end{split} \end{equation} SΔABP+SΔBCP+SΔACPSΔABCSΔABP+SΔABCSΔBCP+SΔABCSΔACP=SΔABC=1
从这里可以看出,它们的定义是等效的,即
{ α = S Δ A B P S Δ A B C = 1 − β − γ β = S Δ B C P S Δ A B C γ = S Δ A C P S Δ A B C \begin{equation} \begin{cases} \alpha = \dfrac{S_{\Delta ABP}}{S_{\Delta ABC}} = 1-\beta - \gamma\\ \beta = \dfrac{S_{\Delta BCP}}{S_{\Delta ABC}} \\ \gamma = \dfrac{S_{\Delta ACP}}{S_{\Delta ABC}} \end{cases} \end{equation} α=SΔABCSΔABP=1βγβ=SΔABCSΔBCPγ=SΔABCSΔACP
所以我们只需要计算 β \beta β以及 γ \gamma γ的值。展开如下
β = S Δ A C P S Δ A B C γ = S Δ A B P S Δ A B C \begin{equation} \begin{split} \beta = \dfrac{S_{\Delta ACP}}{S_{\Delta ABC}} \\ \gamma = \dfrac{S_{\Delta ABP}}{S_{\Delta ABC}} \\ \end{split} \end{equation} β=SΔABCSΔACPγ=SΔABCSΔABP
省略展开的计算步骤,后可得
{ β = ( y a − y b ) x p + ( x b − x a ) y p + x a y b − x b y a ( y a − y b ) x c + ( x b − x a ) y c + x a y b − x b y a γ = ( y a − y c ) x p + ( x c − x a ) y p + x a y c − x c y a ( y a − y c ) x c + ( x c − x a ) y b + x a y c − x c y a α = 1 − β − γ \begin{equation} \begin{cases} \beta = \dfrac{(y_a - y_b)x_p + (x_b - x_a)y_p + x_ay_b - x_by_a}{(y_a-y_b)x_c + (x_b - x_a)y_c + x_ay_b - x_by_a} \\ \gamma = \dfrac{(y_a - y_c)x_p + (x_c - x_a)y_p + x_ay_c - x_cy_a}{(y_a-y_c)x_c + (x_c - x_a)y_b + x_ay_c - x_cy_a} \\ \alpha = 1-\beta - \gamma\\ \end{cases} \end{equation} β=(yayb)xc+(xbxa)yc+xaybxbya(yayb)xp+(xbxa)yp+xaybxbyaγ=(yayc)xc+(xcxa)yb+xaycxcya(yayc)xp+(xcxa)yp+xaycxcyaα=1βγ
上面这个写法过于抽象,一般写作矢量表达结果,如下
{ β = A C ⃗ × A P ⃗ A B ⃗ × A C ⃗ γ = A B ⃗ × A P ⃗ A B ⃗ × A C ⃗ α = 1 − β − γ \begin{equation} \begin{cases} \beta = \dfrac{\vec{AC}\times \vec{AP}}{\vec{AB} \times \vec{AC}} \\ \gamma = \dfrac{\vec{AB}\times \vec{AP}}{\vec{AB} \times \vec{AC}} \\ \alpha = 1-\beta - \gamma\\ \end{cases} \end{equation} β=AB ×AC AC ×AP γ=AB ×AC AB ×AP α=1βγ
如果我们需要判断点是否在三角形内部,只需要根据上式计算出 α , β \alpha, \beta α,β以及 γ \gamma γ的值之后再判断即可,判断条件总结为
{ S Δ A B C > 0 , 保证三个点能组成三角形 ∀ { α , β , γ } ∈ [ 0 , 1 ] , 等于 0 或 1 的情况表示 P 在三角形的边上 \begin{equation} \begin{cases} S_{\Delta ABC} > 0, &保证三个点能组成三角形 \\ \forall \{\alpha, \beta, \gamma\} \in [0,1],&等于0或1的情况表示P在三角形的边上 \end{cases} \end{equation} {SΔABC>0{α,β,γ}[0,1],保证三个点能组成三角形等于01的情况表示P在三角形的边上

下面是一个C++程序,可以用三角形的线性组合来表示三角形内的任意一: ```c++ #include <iostream> using namespace std; // 定义三维向量 struct Vector3 { double x, y, z; Vector3(double x = 0, double y = 0, double z = 0): x(x), y(y), z(z) {} }; // 定义三角形 struct Triangle { Vector3 v1, v2, v3; Triangle(Vector3 v1, Vector3 v2, Vector3 v3): v1(v1), v2(v2), v3(v3) {} }; // 计算三角形面积 double triangleArea(Triangle t) { Vector3 v1 = t.v2 - t.v1; Vector3 v2 = t.v3 - t.v1; return 0.5 * sqrt(pow(v1.y * v2.z - v1.z * v2.y, 2) + pow(v1.z * v2.x - v1.x * v2.z, 2) + pow(v1.x * v2.y - v1.y * v2.x, 2)); } // 判断是否三角形内部 bool isInsideTriangle(Triangle t, Vector3 p) { double area1 = triangleArea(Triangle(t.v1, t.v2, p)); double area2 = triangleArea(Triangle(t.v2, t.v3, p)); double area3 = triangleArea(Triangle(t.v3, t.v1, p)); double areaSum = area1 + area2 + area3; double triangleAreaSum = triangleArea(t); return areaSum >= triangleAreaSum - 1e-6; // 使用 1e-6 作为精度误差 } // 计算三角形的线性组合 Vector3 barycentric(Triangle t, Vector3 p) { Vector3 v1 = t.v2 - t.v1; Vector3 v2 = t.v3 - t.v1; Vector3 v3 = p - t.v1; double d00 = v1.x * v1.x + v1.y * v1.y + v1.z * v1.z; double d01 = v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; double d11 = v2.x * v2.x + v2.y * v2.y + v2.z * v2.z; double d20 = v3.x * v1.x + v3.y * v1.y + v3.z * v1.z; double d21 = v3.x * v2.x + v3.y * v2.y + v3.z * v2.z; double denom = d00 * d11 - d01 * d01; double v = (d11 * d20 - d01 * d21) / denom; double w = (d00 * d21 - d01 * d20) / denom; double u = 1.0 - v - w; return Vector3(u, v, w); } int main() { // 定义三角形和测试 Vector3 v1(0, 0, 0), v2(1, 0, 0), v3(0, 1, 0), p(0.5, 0.5, 0); // 构建三角形并检查是否三角形内部 Triangle t(v1, v2, v3); if (isInsideTriangle(t, p)) { cout << "The point is inside the triangle." << endl; // 计算三角形的线性组合 Vector3 b = barycentric(t, p); cout << "barycentric coordinates: u=" << b.x << ", v=" << b.y << ", w=" << b.z << endl; } else { cout << "The point is outside the triangle." << endl; } return 0; } ``` 这个程序中,我们首先定义了一个 Vector3 结构体表示三维向量,然后定义了一个 Triangle 结构体表示三角形。接着,我们实现了 triangleArea 函数来计算三角形面积,isInsideTriangle 函数来判断一个是否三角形内部,以及 barycentric 函数来计算三角形的线性组合。 在主函数中,我们定义了三角形和测试,并构建了一个 Triangle 对象。然后,我们调用 isInsideTriangle 函数来检查是否三角形内部,如果三角形内部,就调用 barycentric 函数来计算三角形的线性组合并输出结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值