2D空间求一点是否在多边形内

转自:https://www.cnblogs.com/hont/p/6105997.html

大致流程:

1.随便选取多边形上任意一条边,以比较点和边的中心点做一条射线(这里用的伪射线)。

2.用这条射线与其他所有边判断是否相交。

3.将所有与线段相交的数量相加,如果是奇数就在多边形内。

 

特殊情况:

1.刚好在点上或者在线上。实际运用时会有点误差,但不影响。

2.必须是闭合线段,且不能存在包含的情况。但如果是一个数组生成的线段,不会有这种情况

 

代码(Unity3D):

复制代码

using UnityEngine;
using System.Collections;

public class Test1 : MonoBehaviour
{
    const float RAYCAST_LEN = 100000f;
    public Transform[] points;
    public Transform compare;


    bool IsContract(Transform compare)
    {
        var comparePoint = (points[1].position + points[0].position) * 0.5f;
        var originPoint = compare.transform.position;
        comparePoint += (comparePoint - originPoint).normalized * RAYCAST_LEN;

        Debug.DrawLine(originPoint, comparePoint);

        int count = 0;
        for (int i = 0; i < points.Length; i++)
        {
            var a = points[i % points.Length];
            var b = points[(i + 1) % points.Length];

            var r = IsIntersection(a.position, b.position, originPoint, comparePoint);

            if (r) count++;
        }

        return count % 2 == 1;
    }

    void OnDrawGizmos()
    {
        if (compare == null) return;

        var oldColor = Gizmos.color;

        if (IsContract(compare))
            Gizmos.color = Color.red;

        for (int i = 0; i < points.Length; i++)
        {
            var a = points[i % points.Length];
            var b = points[(i + 1) % points.Length];

            Gizmos.DrawLine(a.position, b.position);
        }

        Gizmos.color = oldColor;
    }

    bool IsIntersection(Vector3 a, Vector3 b, Vector3 c, Vector3 d)
    {
        var crossA = Mathf.Sign(Vector3.Cross(d - c, a - c).y);
        var crossB = Mathf.Sign(Vector3.Cross(d - c, b - c).y);

        if (Mathf.Approximately(crossA, crossB)) return false;

        var crossC = Mathf.Sign(Vector3.Cross(b - a, c - a).y);
        var crossD = Mathf.Sign(Vector3.Cross(b - a, d - a).y);

        if (Mathf.Approximately(crossC, crossD)) return false;

        return true;
    }
}

复制代码

 

 

另外参考的文章中没有说差乘判断两个线段是否相交的具体做法,这里说明一下

 

大致流程:

现在有线段AB和线段CB

用线段AB的方向和C,D两点分别做差乘比较。如果C,D在同侧则return跳出

用线段CD的方向和A,B两点分别做差乘比较。如果A,B在同侧则return跳出

最终返回相交

 

脚本就是上面的IsIntersection函数,最终实现效果(只适用于2D空间,如果是XY轴向要取差乘的z分量做比较):

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值