这个方法引用自群友的博客 https://www.xiaofengyu.com/?p=143
使用百度地图的时候,常常会用到判断一个点是否在一个多边形的范围内,该方法用到的是射线法,
通过修改Javascrpit的代码过来的,射线法的意思就是从点出发和任意的一边的交叉点数为奇数则为在改区域内,
参考文档http://erich.realtimerendering.com/ptinpoly/
public class location { 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(location point, List<location> 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比较时候的容差 location 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; }
}