O2O地圖應用之判斷用戶訂單地址是否在服務範圍內

O2O地圖應用之判斷用戶訂單地址是否在服務範圍內

需求分析

在o2o項目中,常常要用到在用戶下單時判斷用戶所填地址的座標點是否在服務範圍內的狀況,這裏參考網上的實現方式,用C#來實現,經測試後有效,特此記錄。html

代碼

public class MapHelper
    {

        /// <summary>
        /// 判斷一個座標點在多邊形座標點的內部仍是外部
        /// </summary>
        /// <param name="point">要判斷的座標點</param>
        /// <param name="pts">多邊形座標點集合</param>
        /// <returns></returns>
        public static bool IsPointInPolygon(Point point, List<Point> pts)
        {
            int N = pts.Count;
            //若是點位於多邊形的頂點或邊上,也算作點在多邊形內,直接返回true
            bool boundOrVertex = true;
            //通過點的次數
            int intersectCount = 0;
            double precision = 2e-10;
            Point p1, p2;
            Point p = point;//當前點

            p1 = pts[0];

            for (int i = 1; i <= N; i++)
            {
                //若是點在多邊形上
                if (p.Equals(p1))
                {
                    return boundOrVertex;
                }

                p2 = pts[(i % N)];
                if (p.Lng<Math.Min(p1.Lng,p2.Lng)||p.Lng>Math.Max(p1.Lng,p2.Lng))
                {
                    p1 = p2;
                    continue;
                }

                if (p.Lng>Math.Min(p1.Lng,p2.Lng)&&p.Lng<Math.Max(p1.Lng,p2.Lng))
                {
                    if (p.Lat<=Math.Max(p1.Lat,p2.Lat))
                    {
                        if (p1.Lng==p2.Lng&&p.Lat>=Math.Min(p1.Lat,p2.Lat))
                        {
                            return boundOrVertex;
                        }

                        if (p1.Lat==p2.Lat)
                        {
                            if (p1.Lat==p.Lat)
                            {
                                return boundOrVertex;
                            }
                            else
                            {
                                intersectCount++;
                            }
                        }
                        else
                        {
                            double xinters = (p.Lng - p1.Lng) * (p2.Lat - p1.Lat) / (p2.Lng - p1.Lng) + p1.Lat;
                            if (Math.Abs(p.Lat-xinters)<precision)
                            {
                                return boundOrVertex;
                            }

                            if (p.Lat<xinters)
                            {
                                intersectCount++;
                            }
                        }
                    }
                }
                else
                {
                    if (p.Lng==p2.Lng&&p.Lat<=p2.Lat)
                    {
                        Point p3 = pts[(i+1)%N];
                        if (p.Lng>=Math.Min(p1.Lng,p3.Lng)&&p.Lng<=Math.Max(p1.Lng,p3.Lng))
                        {
                            intersectCount++;
                        }
                        else
                        {
                            intersectCount += 2;
                        }
                    }
                }
                p1 = p2;
            }

            if (intersectCount%2==0)
            {
                //偶數在多邊形外
                return false;
            }
            else
            {
                //奇數在多邊形內
                return true;
            }
        }
    }

    public class Point
    {
        /// <summary>
        /// 經度
        /// </summary>
        public double Lng { get; set; }
        /// <summary>
        /// 緯度
        /// </summary>
        public double Lat { get; set; }
    }

測試

這裏我用高德地圖標出了北京五環範圍的座標點集合,而後隨意選擇一個座標點來進行判斷:工具

座標點能夠用這個工具來獲取:高德地圖API測試

五環範圍:code

  • 香泉橋 116.222208,39.992436
  • 箭亭橋 116.327147,40.02046
  • 上清橋 116.353948,40.02299
  • 顧家莊橋 116.44128,40.020526
  • 東北五環 116.48441,40.013624
  • 平房橋 116.541101,39.942393
  • 東南五環 116.549202,39.851595
  • 舊宮新橋 116.43082,39.785968
  • 狼垈東橋 116.296044,39.777442
  • 宛平橋 116.225062,39.845517
  • 衙門口橋 116.211308,39.894396
  • 西五環 116.212595,39.944705

隨機座標:htm

  • 林萃橋地鐵站 116.37297,40.021857
  • 望京西園四區 116.47086,39.99648
  • 觀音禪寺 116.533811,39.880533
  • 俏狐國際 116.299713,39.772619
  • 芳園裏小區 116.416336,39.78394
  • 潤楓錦尚小區 116.429039,39.790535
class Program
    {
        static void Main(string[] args)
        {
            var Plist = new List<Point> {
                new Point {Lng=116.222208,Lat= 39.992436},
                new Point {Lng=116.327147,Lat= 40.02046},
                new Point {Lng=116.353948,Lat= 40.02299},
                new Point {Lng=116.44128,Lat= 40.020526},
                new Point {Lng=116.48441,Lat=40.013624 },
                new Point {Lng=116.541101,Lat= 39.942393},
                new Point {Lng=116.549202,Lat= 39.851595},
                new Point {Lng=116.43082,Lat=39.785968},
                new Point {Lng=116.296044,Lat=39.777442 },
                new Point {Lng=116.225062,Lat=39.845517 },
                new Point {Lng=116.211308,Lat= 39.894396},
                new Point {Lng=116.212595,Lat=39.944705}
            };

            //var p = new Point { Lng = 116.37297, Lat = 40.021857 };
            //林萃橋地鐵站   內

            //var p = new Point { Lng = 116.47086, Lat = 39.99648 };
            //望京西園四區  內

            //var p = new Point { Lng = 116.533811, Lat = 39.880533 };
            //觀音禪寺 內

            //var p = new Point { Lng = 116.299713, Lat = 39.772619 }; 
            //俏狐國際  外

            //var p = new Point { Lng = 116.416336, Lat = 39.78394 };  
            //芳園裏小區  外

            var p = new Point { Lng = 116.429039, Lat = 39.790535 };
            //潤楓錦尚小區  內

            bool isin = MapHelper.IsPointInPolygon(p, Plist);
            if (isin)
            {
                Console.WriteLine("隨機點在五環範圍內,能夠派單");
            }
            else
            {
                Console.WriteLine("隨機點不在五環範圍內");
            }
            Console.ReadKey();
        }
    }

總結

相關文章
相關標籤/搜索