相交 - 点是否在射线上

发布时间 2023-11-23 23:24:11作者: yanghui01

效果

 

//点是否在射线上
public static bool IsPointOnRay(Vector2 o, Vector2 dir, Vector2 p)
{
    var op = p - o;
    if (Mathf.Approximately(op.sqrMagnitude, 0)) //o和p重叠
        return true;

    //共线且夹角为0度则在射线上
    float cross = V2Cross(ref dir, ref op);
    if (!Mathf.Approximately(cross, 0)) //float.Epsilon, 先判断共线
        return false;

    float dot = Vector2.Dot(dir, op); //|dir|*|op|*cos(a); 共线时, cos值>0就是0度
    return dot > 0;
}

 

点与射线的位置关系 

在射线上

不在射线上

 

 测试代码

using System;
using UnityEngine;

public class RayTest : MonoBehaviour
{
    public Transform m_DirTransform;
    public Transform m_PointTransform;

    public int m_ApiType = 1;
    [Range(1, 3999999)]
    public int m_InvokeCount = 1; //用于测试大批量调用时的性能
    public bool m_AutoIcrApiType = false; //自动调用每一个函数, 看看各个函数的执行耗时

    private bool m_IsOnRay = false;

    void Update()
    {
        m_IsOnRay = false;
        if (m_PointTransform && m_DirTransform)
        {
            var origin = this.transform.position;
            var dir = m_DirTransform.position - origin;

            var t1 = DateTime.Now;
            switch (m_ApiType)
            {
            case 1:
                for (int i = 0; i < m_InvokeCount; ++i)
                    m_IsOnRay = Shape2DHelper.IsPointOnRay(origin, dir, m_PointTransform.position);
                break;
            }

            if (m_InvokeCount > 1 && m_AutoIcrApiType)
            {
                if (m_ApiType < 2)
                    m_ApiType++;
            }

            if (m_InvokeCount > 1)
            {
                var t2 = DateTime.Now;
                var dur = t2 - t1;
                if (dur.TotalMilliseconds >= 100)
                {
                    Debug.Log($"totalMs:{dur.TotalMilliseconds}");
                }
            }
        }
    }

    private void OnDrawGizmos()
    {
        if (m_DirTransform)
        {
            var origin = this.transform.position;
            origin.z = 0;
            var endPoint = m_DirTransform.position;
            endPoint.z = 0;

            if (m_IsOnRay)
            {
                Gizmos.color = Color.red;
                Gizmos.DrawLine(origin, endPoint);
                Gizmos.color = Color.white;
            }
            else
            {
                Gizmos.DrawLine(origin, endPoint);
            }
        }
    }

}