GeoJSON C#判斷某一點是否在某一區域範圍以內

GeoJSON是一種對各類地理數據結構進行編碼的格式,基於Javascript對象表示法的地理空間信息數據交換格式。GeoJSON對象能夠表示幾何、特徵或者特徵集合。GeoJSON支持下面幾何類型:點、線、面、多點、多線、多面和幾何集合。GeoJSON裏的特徵包含一個幾何對象和其餘屬性,特徵集合表示一系列特徵。數據結構

public class PositionAlgorithmHelper
    {
        /// <summary>
        /// 判斷當前位置是否在不規則形狀裏面
        /// </summary>
        /// <param name="nvert">不規則形狀的定點數</param>
        /// <param name="vertx">當前x座標</param>
        /// <param name="verty">當前y座標</param>
        /// <param name="testx">不規則形狀x座標集合</param>
        /// <param name="testy">不規則形狀y座標集合</param>
        /// <returns></returns>
        public static bool PositionPnpoly(int nvert, List<double> vertx, List<double> verty, double testx, double testy)
        {
            int i, j, c = 0;
            for (i = 0, j = nvert - 1; i < nvert; j = i++)
            {
                if (((verty[i] > testy) != (verty[j] > testy)) && (testx < (vertx[j] - vertx[i]) * (testy - verty[i]) / (verty[j] - verty[i]) + vertx[i]))
                {
                    c = 1 + c; ;
                }
            }
            if (c % 2 == 0)
            {
                return false;
            }
            else
            {
                return true;
            }
        }



        /// <summary>  
        /// 判斷點是否在多邊形內.  
        /// ----------原理----------  
        /// 注意到若是從P做水平向左的射線的話,若是P在多邊形內部,那麼這條射線與多邊形的交點必爲奇數,  
        /// 若是P在多邊形外部,則交點個數必爲偶數(0也在內)。  
        /// 因此,咱們能夠順序考慮多邊形的每條邊,求出交點的總個數。還有一些特殊狀況要考慮。假如考慮邊(P1,P2),  
        /// 1)若是射線正好穿過P1或者P2,那麼這個交點會被算做2次,處理辦法是若是P的從座標與P1,P2中較小的縱座標相同,則直接忽略這種狀況  
        /// 2)若是射線水平,則射線要麼與其無交點,要麼有無數個,這種狀況也直接忽略。  
        /// 3)若是射線豎直,而P0的橫座標小於P1,P2的橫座標,則必然相交。  
        /// 4)再判斷相交以前,先判斷P是否在邊(P1,P2)的上面,若是在,則直接得出結論:P再多邊形內部。  
        /// </summary>  
        /// <param name="checkPoint">要判斷的點</param>  
        /// <param name="polygonPoints">多邊形的頂點</param>  
        /// <returns></returns>  
        public static bool IsInPolygon2(Position checkPoint, List<Position> polygonPoints)
        {
            int counter = 0;
            int i;
            double xinters;
            Position p1, p2;
            int pointCount = polygonPoints.Count;
            p1 = polygonPoints[0];
            for (i = 1; i <= pointCount; i++)
            {
                p2 = polygonPoints[i % pointCount];
                if (checkPoint.y > Math.Min(p1.y, p2.y)//校驗點的Y大於線段端點的最小Y  
                    && checkPoint.y <= Math.Max(p1.y, p2.y))//校驗點的Y小於線段端點的最大Y  
                {
                    if (checkPoint.x <= Math.Max(p1.x, p2.x))//校驗點的X小於等線段端點的最大X(使用校驗點的左射線判斷).  
                    {
                        if (p1.y != p2.y)//線段不平行於X軸  
                        {
                            xinters = (checkPoint.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;
                            if (p1.x == p2.x || checkPoint.x <= xinters)
                            {
                                counter++;
                            }
                        }
                    }

                }
                p1 = p2;
            }

            if (counter % 2 == 0)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        /// <summary>  
        /// 判斷點是否在多邊形內.  
        /// ----------原理----------  
        /// 注意到若是從P做水平向左的射線的話,若是P在多邊形內部,那麼這條射線與多邊形的交點必爲奇數,  
        /// 若是P在多邊形外部,則交點個數必爲偶數(0也在內)。  
        /// </summary>  
        /// <param name="checkPoint">要判斷的點</param>  
        /// <param name="polygonPoints">多邊形的頂點</param>  
        /// <returns></returns>  
        public static bool IsInPolygon(Position checkPoint, List<Position> polygonPoints)
        {
            bool inside = false;
            int pointCount = polygonPoints.Count;
            Position p1, p2;
            for (int i = 0, j = pointCount - 1; i < pointCount; j = i, i++)//第一個點和最後一個點做爲第一條線,以後是第一個點和第二個點做爲第二條線,以後是第二個點與第三個點,第三個點與第四個點...  
            {
                p1 = polygonPoints[i];
                p2 = polygonPoints[j];
                if (checkPoint.y < p2.y)
                {//p2在射線之上  
                    if (p1.y <= checkPoint.y)
                    {//p1正好在射線中或者射線下方  
                        if ((checkPoint.y - p1.y) * (p2.x - p1.x) > (checkPoint.x - p1.x) * (p2.y - p1.y))//斜率判斷,在P1和P2之間且在P1P2右側  
                        {
                            //射線與多邊形交點爲奇數時則在多邊形以內,若爲偶數個交點時則在多邊形以外。  
                            //因爲inside初始值爲false,即交點數爲零。因此當有第一個交點時,則必爲奇數,則在內部,此時爲inside=(!inside)  
                            //因此當有第二個交點時,則必爲偶數,則在外部,此時爲inside=(!inside)  
                            inside = (!inside);
                        }
                    }
                }
                else if (checkPoint.y < p1.y)
                {
                    //p2正好在射線中或者在射線下方,p1在射線上  
                    if ((checkPoint.y - p1.y) * (p2.x - p1.x) < (checkPoint.x - p1.x) * (p2.y - p1.y))//斜率判斷,在P1和P2之間且在P1P2右側  
                    {
                        inside = (!inside);
                    }
                }
            }
            return inside;
        }  

    }
    public class Position
    {
        /// <summary>
        /// 緯度
        /// </summary>
        public double x { get; set; }

        /// <summary>
        /// 經度
        /// </summary>
        public double y { get; set; }
    }

測試:紅色區域是許多座標組成的不規則圖像,記錄下座標位置,進行座標範圍內和範圍外任取一點進行測試.能夠判斷這一點是否在範圍以內。ide

    class Program
    {
        static void Main(string[] args)
        {
            test1();
        }

        /// <summary>
        /// test1
        /// </summary>
        public static void test1()
        {
            //不規則圖像座標
            List<Position> position = new List<Position>();
            position.Add(new Position() { x = 6, y = 0 });
            position.Add(new Position() { x = 10, y = 2 });
            position.Add(new Position() { x = 16, y = 2 });
            position.Add(new Position() { x = 20, y = 6 });
            position.Add(new Position() { x = 14, y = 10 });
            position.Add(new Position() { x = 16, y = 6 });
            position.Add(new Position() { x = 12, y = 6 });
            position.Add(new Position() { x = 14, y = 8 });
            position.Add(new Position() { x = 10, y = 8 });
            position.Add(new Position() { x = 8, y = 6 });
            position.Add(new Position() { x = 12, y = 4 });
            position.Add(new Position() { x = 6, y = 4 });
            position.Add(new Position() { x = 8, y = 2 });

            //用戶當前位置座標
            List<Position> userPositions = new List<Position>();
            userPositions.Add(new Position() { x = 14, y = 4 });
            userPositions.Add(new Position() { x = 15, y = 4 });
            userPositions.Add(new Position() { x = 10, y = 6 });
            userPositions.Add(new Position() { x = 8, y = 5 });

            //不規則圖像x座標集合
            List<double> xList = position.Select(x => x.x).ToList();
            //不規則圖像y座標集合
            List<double> yList = position.Select(x => x.y).ToList();

            foreach (var userPosition in userPositions)
            {
                bool result = PositionAlgorithmHelper.PositionPnpoly(position.Count, xList, yList, userPosition.x, userPosition.y);

                if (result)
                {
                    Console.WriteLine(string.Format("{0},{1}【在】座標內", userPosition.x, userPosition.y));
                }
                else
                {
                    Console.WriteLine(string.Format("{0},{1}【不在】座標內", userPosition.x, userPosition.y));
                }
            }
        }
    }
相關文章
相關標籤/搜索