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;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								}
							 |