判斷點在多邊形內部

點在多邊形內部的判斷有不少種方法,性能最好也準確的算法應屬射線法。算法

推薦Milo Yip大神的知乎上的回答性能

射線法思想

射線法是由從點出發向一個方向發送射線,判斷與邊相交的次數,若是爲奇數則爲多邊形的內部,若是爲偶數則爲外部。code

首先是數據類,存儲多邊形的點和最大最小的XY,用來作快速判斷blog

// 多邊形點的數據存儲
    class PolygonConfig
    {
        public float maxX;
        public float maxY;
        public float minX;
        public float minY;
        public List<Vector2> points = new List<Vector2>();

        public void SetMaxAndMinXY()
        {
            if (points.Count > 0)
            {
                maxX = points[0].x;
                maxY = points[0].y;
                minX = points[0].x;
                minY = points[0].y;
            }

            for (int i = 1; i < points.Count; i++)
            {
                maxX = Mathf.Max(maxX, points[i].x);
                maxY = Mathf.Max(maxY, points[i].y);
            }
        }
    }

下面是判斷的核心方法
ip

  • 首先是經過最大最小的XY來快速篩選點是否在四邊形中
  • 核心代碼部分
    • 這裏咱們作向上的射線(射線方向隨意,這裏咱們向上作)
    • 第一組判斷(points[i].x <= point.x && points[j].x > point.x) || (points[j].x <= point.x && points[i].x > point.x) 這裏主要的意思就是點的x座標是否在多邊形的一個邊的x軸座標內。(可理解成: i.x < p.x < j.x)
    • 第二組判斷(points[j].y - points[i].y) / (points[j].x - points[i].x) * (point.x - points[i].x) + points[i].y > point.y 讓咱們分開來理解,首先是(points[j].y - points[i].y) / (points[j].x - points[i].x)是x軸差值和y軸差值的比值,(point.x - points[i].x)是點與邊中一點的x軸差值,二者的相乘就肯定了一個y,y值再加上那邊中一點的y值,若是大於點的y則穿過,不然沒穿過。
  • 進過全部邊的判斷完成後,奇數爲在中心,因此小技巧就是inPolygon的取反。
private bool IsPointInPolygon(PolygonConfig polygon, Vector2 point)
    {
        // 構建矩形,進行快速篩選
        if (point.x > polygon.maxX || point.x < polygon.minX || point.y > polygon.maxY || point.y < polygon.minY)
        {
            return false;
        }

        bool inPolygon = false;
        var points = polygon.points;
        for (int i = 0, j = points.Count - 1; i < points.Count; j = i++)
        {
            if (((points[i].x <= point.x && points[j].x > point.x) || (points[j].x <= point.x && points[i].x > point.x))
                && ((points[j].y - points[i].y) / (points[j].x - points[i].x) * (point.x - points[i].x) + points[i].y > point.y))
            {
                inPolygon = !inPolygon;
            }
        }
        return inPolygon;
    }
相關文章
相關標籤/搜索