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