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