136 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			C#
		
	
	
	
			
		
		
	
	
			136 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			C#
		
	
	
	
using System;
 | 
						||
using System.Collections.Generic;
 | 
						||
using System.Linq;
 | 
						||
using System.Text;
 | 
						||
using System.Threading.Tasks;
 | 
						||
 | 
						||
namespace SgManager.AI
 | 
						||
{
 | 
						||
 | 
						||
    public class Gpslocation
 | 
						||
    {
 | 
						||
        public double lat;
 | 
						||
        public double lng;
 | 
						||
    }
 | 
						||
    public class GpsPolygonHelper
 | 
						||
    {
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 坐标点是否在多边形内判断
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="point"></param>
 | 
						||
        /// <param name="pts"></param>
 | 
						||
        /// <returns></returns>
 | 
						||
 | 
						||
        public static bool isPointInPolygon(Gpslocation point, List<Gpslocation> pts)
 | 
						||
        {
 | 
						||
 | 
						||
            //检查类型
 | 
						||
            if (point == null || pts == null)
 | 
						||
                return false;
 | 
						||
 | 
						||
            var N = pts.Count;
 | 
						||
            var boundOrVertex = true; //如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true
 | 
						||
            var intersectCount = 0; //cross points count of x 
 | 
						||
            var precision = 2e-10; //浮点类型计算时候与0比较时候的容差
 | 
						||
            Gpslocation p1, p2; //neighbour bound vertices
 | 
						||
            var p = point; //测试点
 | 
						||
            p1 = pts[0]; //left vertex        
 | 
						||
            for (var i = 1; i <= N; ++i)
 | 
						||
            {
 | 
						||
                //check all rays            
 | 
						||
                if (p.lat.Equals(p1.lat) && p.lng.Equals(p1.lng))
 | 
						||
                {
 | 
						||
                    return boundOrVertex; //p is an vertex
 | 
						||
                }
 | 
						||
 | 
						||
                p2 = pts[i % N]; //right vertex            
 | 
						||
                if (p.lat < Math.Min(p1.lat, p2.lat) || p.lat > Math.Max(p1.lat, p2.lat))
 | 
						||
                {
 | 
						||
                    //ray is outside of our interests                
 | 
						||
                    p1 = p2;
 | 
						||
                    continue; //next ray left point
 | 
						||
                }
 | 
						||
 | 
						||
                if (p.lat > Math.Min(p1.lat, p2.lat) && p.lat < Math.Max(p1.lat, p2.lat))
 | 
						||
                {
 | 
						||
                    //ray is crossing over by the algorithm (common part of)
 | 
						||
                    if (p.lng <= Math.Max(p1.lng, p2.lng))
 | 
						||
                    {
 | 
						||
                        //x is before of ray                    
 | 
						||
                        if (p1.lat == p2.lat && p.lng >= Math.Min(p1.lng, p2.lng))
 | 
						||
                        {
 | 
						||
                            //overlies on a horizontal ray
 | 
						||
                            return boundOrVertex;
 | 
						||
                        }
 | 
						||
 | 
						||
                        if (p1.lng == p2.lng)
 | 
						||
                        {
 | 
						||
                            //ray is vertical                        
 | 
						||
                            if (p1.lng == p.lng)
 | 
						||
                            {
 | 
						||
                                //overlies on a vertical ray
 | 
						||
                                return boundOrVertex;
 | 
						||
                            }
 | 
						||
                            else
 | 
						||
                            {
 | 
						||
                                //before ray
 | 
						||
                                ++intersectCount;
 | 
						||
                            }
 | 
						||
                        }
 | 
						||
                        else
 | 
						||
                        {
 | 
						||
                            //cross point on the left side                        
 | 
						||
                            var xinters =
 | 
						||
                                (p.lat - p1.lat) * (p2.lng - p1.lng) / (p2.lat - p1.lat) +
 | 
						||
                                p1.lng; //cross point of lng                        
 | 
						||
                            if (Math.Abs(p.lng - xinters) < precision)
 | 
						||
                            {
 | 
						||
                                //overlies on a ray
 | 
						||
                                return boundOrVertex;
 | 
						||
                            }
 | 
						||
 | 
						||
                            if (p.lng < xinters)
 | 
						||
                            {
 | 
						||
                                //before ray
 | 
						||
                                ++intersectCount;
 | 
						||
                            }
 | 
						||
                        }
 | 
						||
                    }
 | 
						||
                }
 | 
						||
                else
 | 
						||
                {
 | 
						||
                    //special case when ray is crossing through the vertex                
 | 
						||
                    if (p.lat == p2.lat && p.lng <= p2.lng)
 | 
						||
                    {
 | 
						||
                        //p crossing over p2                    
 | 
						||
                        var p3 = pts[(i + 1) % N]; //next vertex                    
 | 
						||
                        if (p.lat >= Math.Min(p1.lat, p3.lat) && p.lat <= Math.Max(p1.lat, p3.lat))
 | 
						||
                        {
 | 
						||
                            //p.lat lies between p1.lat & p3.lat
 | 
						||
                            ++intersectCount;
 | 
						||
                        }
 | 
						||
                        else
 | 
						||
                        {
 | 
						||
                            intersectCount += 2;
 | 
						||
                        }
 | 
						||
                    }
 | 
						||
                }
 | 
						||
                p1 = p2; //next ray left point
 | 
						||
            }
 | 
						||
 | 
						||
            if (intersectCount % 2 == 0)
 | 
						||
            {
 | 
						||
                //偶数在多边形外
 | 
						||
                return false;
 | 
						||
            }
 | 
						||
            else
 | 
						||
            {
 | 
						||
                //奇数在多边形内
 | 
						||
                return true;
 | 
						||
            }
 | 
						||
 | 
						||
        }
 | 
						||
    }
 | 
						||
}
 |