平面中判断点在三角形内算法(重心法)

本文详细介绍了使用重心法判断点是否在二维平面内的三角形内的算法。该方法基于向量方程,通过计算线性方程组求解参数u和v,进而确定点的位置。代码实现部分展示了如何在C++中实现这个算法,用于检查点是否在三角形内部。
摘要由CSDN通过智能技术生成

1. 概述

在文章《判断点是否在三角形内》中还提到了一种判断点在三角形内外的算法——重心法。这种算法同样用到了三角形的空间向量方程,但是值得注意的是,这种算法却只能判断平面中点在三角形的内外关系(已知空间向量方程,是可以判断三维空间关系的:空间中判断点在三角形内算法(方程法))。

2. 详论

2.1. 原理

重心法的推导过程与空间中判断点在三角形内算法(方程法))的推导过程比较相似。对于三个顶点为V0,V1,V2组成的空间三角形,对于三角形内的任一点P,有如下参数方程:

P ⃗ = ( 1 − u − v ) V 0 ⃗ + u V 1 ⃗ + v V 2 ⃗ \vec{P} = (1 - u - v) \vec{V_0} + u \vec{V_1} + v \vec{V_2} P =(1uv)V0 +uV1 +vV2

变换位置,我们可以将其调整为:
V 0 P ⃗ = u ( V 0 V 1 ⃗ ) + v ( V 0 V 2 ⃗ ) \vec{V_0P} = u(\vec{V_0V_1}) + v(\vec{V_0V_2}) V0P =u(V0V1 )+v(V0V2 )

将上式分别点乘 V 0 V 1 ⃗ \vec{V_0V_1} V0V1 V 0 V 2 ⃗ \vec{V_0V_2} V0V2 ,有:
{ V 0 P ⃗ ⋅ V 0 V 1 ⃗ = u ( V 0 V 1 ⋅ V 0 V 1 ⃗ ⃗ ) + v ( V 0 V 2 ⃗ ⋅ V 0 V 1 ⃗ ) V 0 P ⃗ ⋅ V 0 V 2 ⃗ = u ( V 0 V 1 ⃗ ⋅ V 0 V 2 ⃗ ) + v ( V 0 V 2 ⃗ ⋅ V 0 V 2 ⃗ ) \begin{cases} \vec{V_0P} \cdot \vec{V_0V_1} = u(\vec{V_0V_1 \cdot \vec{V_0V_1}}) + v(\vec{V_0V_2} \cdot \vec{V_0V_1}) \\ \vec{V_0P} \cdot \vec{V_0V_2} = u(\vec{V_0V_1} \cdot \vec{V_0V_2}) + v(\vec{V_0V_2} \cdot \vec{V_0V_2}) \\ \end{cases} {V0P V0V1 =u(V0V1V0V1 )+v(V0V2 V0V1 )V0P V0V2 =u(V0V1 V0V2 )+v(V0V2 V0V2 )

很显然,这是个2行2列的线性方程组,通过克莱姆法则来求解:
{ D = ( V 0 V 1 ⋅ V 0 V 1 ⃗ ⃗ ) ∗ ( V 0 V 2 ⃗ ⋅ V 0 V 2 ⃗ ) − ( V 0 V 2 ⃗ ⋅ V 0 V 1 ⃗ ) ∗ ( V 0 V 1 ⃗ ⋅ V 0 V 2 ⃗ ) D 1 = ( V 0 P ⃗ ⋅ V 0 V 1 ⃗ ) ∗ ( V 0 V 2 ⃗ ⋅ V 0 V 2 ⃗ ) − ( V 0 V 2 ⃗ ⋅ V 0 V 1 ⃗ ) ∗ ( V 0 P ⃗ ⋅ V 0 V 2 ⃗ ) D 2 = ( V 0 V 1 ⋅ V 0 V 1 ⃗ ⃗ ) ∗ ( V 0 P ⃗ ⋅ V 0 V 2 ⃗ ) − ( V 0 P ⃗ ⋅ V 0 V 1 ⃗ ) ∗ ( V 0 V 1 ⃗ ⋅ V 0 V 2 ⃗ ) \begin{cases} D = (\vec{V_0V_1 \cdot \vec{V_0V_1}}) * (\vec{V_0V_2} \cdot \vec{V_0V_2}) - (\vec{V_0V_2} \cdot \vec{V_0V_1}) * (\vec{V_0V_1} \cdot \vec{V_0V_2}) \\ D1 = (\vec{V_0P} \cdot \vec{V_0V_1}) * (\vec{V_0V_2} \cdot \vec{V_0V_2}) - (\vec{V_0V_2} \cdot \vec{V_0V_1}) * (\vec{V_0P} \cdot \vec{V_0V_2}) \\ D2 = (\vec{V_0V_1 \cdot \vec{V_0V_1}}) * (\vec{V_0P} \cdot \vec{V_0V_2}) - (\vec{V_0P} \cdot \vec{V_0V_1}) * (\vec{V_0V_1} \cdot \vec{V_0V_2}) \\ \end{cases} D=(V0V1V0V1 )(V0V2 V0V2 )(V0V2 V0V1 )(V0V1 V0V2 )D1=(V0P V0V1 )(V0V2 V0V2 )(V0V2 V0V1 )(V0P V0V2 )D2=(V0V1V0V1 )(V0P V0V2 )(V0P V0V1 )(V0V1 V0V2 )

{ u = D 1 / D v = D 2 / D \begin{cases} u = D1 / D \\ v = D2 / D \\ \end{cases} {u=D1/Dv=D2/D

2.2. 实现

详细的代码实现如下:

//空间三角形
//按照逆时针顺序插入值并计算法向量
template <class T>
class Triangle
{
public:
    Vec3<T> v0;
    Vec3<T> v1;
    Vec3<T> v2;

    Triangle()
    {

    }

    Triangle(Vec3<T> v0, Vec3<T> v1, Vec3<T> v2)
    {
        this->v0 = v0;
        this->v1 = v1;
        this->v2 = v2;     
    }

    void Set(Vec3<T> v0, Vec3<T> v1, Vec3<T> v2)
    {
        this->v0 = v0;
        this->v1 = v1;
        this->v2 = v2;    
    }


    // 判断平面点P是否在平面三角形内(重心法)
    bool PointInTriangle2D(Vec3<T>& P)
    {
        auto v01 = v1 - v0 ;
        auto v02 = v2 - v0 ;
        auto v0p = P - v0 ;

        double dot00 = v01 * v01 ;
        double dot01 = v01 * v02 ;
        double dot02 = v01 * v0p ;
        double dot11 = v02 * v02 ;
        double dot12 = v02 * v0p ;

        double D = (dot00 * dot11 - dot01 * dot01);
        if(D == 0.0)
        {
            return false;
        }
        double inverDeno = 1 / D ;

        double u = (dot11 * dot02 - dot01 * dot12) * inverDeno ;
        if (u < 0 || u > 1)
        {
            return false ;
        }

        double v = (dot00 * dot12 - dot01 * dot02) * inverDeno ;
        if (v < 0 || v > 1)
        {
            return false ;
        }

        return u + v <= 1 ;
    }

};

2.3. 总结

本质上,这个算法与空间中判断点在三角形内算法(方程法)是同一种算法的不同推导,都是通过空间三角形中点的向量方程来求解的,但是是采用了不同的解法。不过为什么一个可以判断空间关系,一个只能判断平面关系呢?关键在于点是否能让向量方程成立,这个求解算法可以求解u,v,但没有保证空间内的向量方程能够成立。

3. 参考

  1. 判断点是否在三角形内
  2. 空间中判断点在三角形内算法(方程法))

详细代码

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

charlee44

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值