/// <summary> /// WGS84(原始坐标)ToBD09(百度坐标) /// </summary> /// <param name="mapPoint">WGS84(原始坐标)</param> /// <returns></returns> public static MapPoint WGS84ToBD09(MapPoint mapPoint, bool isOnline = true) { MapPoint point = new MapPoint(); if (isOnline) { var url = string.Format("http://api.map.baidu.com/geoconv/v1/?output=xml&coords={0},{1}&from=1&to=5&ak={2}", mapPoint.Longitude, mapPoint.Latitude, MapCommon.MapBaiduAk); var xml = HttpLibSyncRequest.Get(url); XmlDocument doc = new XmlDocument(); doc.LoadXml(xml); XmlElement root = doc.DocumentElement; XmlNode res = root.SelectSingleNode("result"); point.Longitude = Convert.ToDouble(res.SelectSingleNode("point/x").InnerText); point.Latitude = Convert.ToDouble(res.SelectSingleNode("point/y").InnerText); } else { var p = LocalMapWGS84Coordinates.BD09.Fix(mapPoint.Longitude, mapPoint.Latitude); if (p != null) { point.Longitude = p.x; point.Latitude = p.y; } } return point; }
/// <summary> /// BD09(百度坐标)ToWGS84(原始坐标) /// </summary> /// <param name="mapPoint">BD09(百度坐标)</param> /// <returns></returns> public static MapPoint BD09ToWGS84(MapPoint mapPoint) { MapPoint point = new MapPoint(); var p = LocalMapWGS84Coordinates.BD09.Reverse(mapPoint.Longitude, mapPoint.Latitude); if (p != null) { point.Longitude = p.x; point.Latitude = p.y; } return point; }
/// <summary> /// 获取两点间的距离 /// </summary> /// <param name="mapPoint1"></param> /// <param name="mapPoint2"></param> /// <returns>米</returns> public static double GetDistance(MapPoint mapPoint1, MapPoint mapPoint2) { double radLat1 = mapPoint1.Latitude * Math.PI / 180.0; double radLat2 = mapPoint2.Latitude * Math.PI / 180.0; double a = radLat1 - radLat2; double b = mapPoint1.Longitude * Math.PI / 180.0 - mapPoint2.Longitude * Math.PI / 180.0; double s = 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin(a / 2), 2) + Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Pow(Math.Sin(b / 2), 2))); s = s * MapCommon.EARTH_RADIUS; s = Math.Round(s * 10000) / 10; return s; }
/// <summary> /// 批量BD09(百度坐标)ToWGS84(原始坐标) /// </summary> /// <param name="mapPoint">BD09(百度坐标)集合</param> /// <returns></returns> public static MapPoint[] BD09ToWGS84(MapPoint[] mapPoints) { List<MapPoint> list = new List<MapPoint>(); for (int i = 0; i < mapPoints.Length; i++) { MapPoint point = new MapPoint(); var p = LocalMapWGS84Coordinates.BD09.Reverse(mapPoints[i].Longitude, mapPoints[i].Latitude); if (p != null) { point.Longitude = p.x; point.Latitude = p.y; list.Add(point); } } return list.ToArray(); }
/// <summary> /// 获取地理位置 /// </summary> /// <param name="mapPoint">WGS84(原始坐标)</param> /// <returns></returns> public static MapLocation GetLocationByWGS84(MapPoint mapPoint) { MapLocation location = new MapLocation(); var url = string.Format("http://api.map.baidu.com/geocoder/v2/?output=xml&coordtype=wgs84ll&location={0},{1},&ak={2}", mapPoint.Latitude, mapPoint.Longitude, MapCommon.MapBaiduAk); var xml = HttpLibSyncRequest.Get(url); XmlDocument doc = new XmlDocument(); doc.LoadXml(xml); XmlElement root = doc.DocumentElement; XmlNode res = root.SelectSingleNode("result"); location.Address = res.SelectSingleNode("formatted_address").InnerText; location.Province = res.SelectSingleNode("addressComponent/province").InnerText; location.City = res.SelectSingleNode("addressComponent/city").InnerText; location.District = res.SelectSingleNode("addressComponent/district").InnerText; location.Street = res.SelectSingleNode("addressComponent/street").InnerText; return location; }
public void Start() { MapCommon.MapBaiduAk = "8a5a51e831ab2b4e667db38c71b4f893"; var p = new MapPoint(116.32465, 40.056355); //通过百度接口转换 var p1 = MapCoordinates.WGS84ToBD09(p); //通过本地转换 var p2 = MapCoordinates.WGS84ToBD09(p, false); var r0 = MapGeocoder.GetDistance(p1, p2); var r1 = MapGeocoder.PointIsInCircle(new MapPoint(116.307834, 40.057031), 50, new MapPoint(116.308445, 40.056969)); Console.WriteLine(r1); var r2 = MapGeocoder.PointIsInRect(new MapPoint(116.285718, 40.063023), new MapPoint(116.34709, 40.038832), new MapPoint(116.314464, 40.04778)); Console.WriteLine(r2); var r3 = MapGeocoder.PointIsInPolygon(new MapPoint[] { new MapPoint(116.280831,40.050763), new MapPoint(116.322944,40.069318), new MapPoint(116.346803,40.040379), new MapPoint(116.304115,40.038722), }, new MapPoint(116.288449, 40.051757)); Console.WriteLine(r3); var r4 = MapGeocoder.PointIsInLineSegment( new MapPoint(116.29851, 40.054242), new MapPoint(116.313493, 40.06109), new MapPoint(116.303226, 40.055761)); var r5 = MapGeocoder.PointIsInLine(new MapPoint[] { new MapPoint(116.318398,40.062084), new MapPoint(116.331334,40.056175), new MapPoint(116.310924,40.05079), new MapPoint(116.321057,40.057335), new MapPoint(116.314733,40.058108), new MapPoint(116.303486,40.053303), new MapPoint(116.300432,40.055209), }, new MapPoint(116.331082, 40.056203)); Console.WriteLine(r5); Console.ReadKey(); }
/// <summary> /// 判断点是否在矩形 A B 两点即可构成一个矩形 /// </summary> /// <param name="mapAPoint">A点</param> /// <param name="mapBPoint">B点</param> /// <param name="mapPoint">当前点</param> /// <returns></returns> public static bool PointIsInRect(MapPoint mapAPoint, MapPoint mapBPoint, MapPoint mapPoint) { double maxx = 0; double minx = 0; double maxy = 0; double miny = 0; if (mapAPoint.Longitude > mapBPoint.Longitude) { maxx = mapAPoint.Longitude; minx = mapBPoint.Longitude; } else { maxx = mapBPoint.Longitude; minx = mapAPoint.Longitude; } if (mapAPoint.Latitude > mapBPoint.Latitude) { maxy = mapAPoint.Latitude; miny = mapBPoint.Latitude; } else { maxy = mapBPoint.Latitude; miny = mapAPoint.Latitude; } if (mapPoint.Longitude < maxx && mapPoint.Longitude > minx && mapPoint.Latitude < maxy && mapPoint.Latitude > miny) { return true; } else { return false; } }
/// <summary> /// 批量WGS84(原始坐标)ToBD09(百度坐标) /// </summary> /// <param name="mapPoints">WGS84(原始坐标)集合</param> /// <returns></returns> public static MapPoint[] WGS84ToBD09(MapPoint[] mapPoints, bool isOnline = true) { List<MapPoint> list = new List<MapPoint>(mapPoints.Length); if (isOnline) { var size = 100; var totalPage = mapPoints.Length / size; if (mapPoints.Length % size > 0) { totalPage++; } for (int i = 0; i < totalPage; i++) { var converts = mapPoints.Skip(i * size).Take(size); var url = string.Format("http://api.map.baidu.com/geoconv/v1/?output=xml&coords={0}&from=1&to=5&ak={1}", string.Join(";", converts.Select(p => p.Longitude + "," + p.Latitude).ToArray()), MapCommon.MapBaiduAk); var xml = HttpLibSyncRequest.Get(url); XmlDocument doc = new XmlDocument(); doc.LoadXml(xml); XmlElement root = doc.DocumentElement; var res = root.SelectSingleNode("result").Cast<XmlNode>().Select(p => new MapPoint() { Longitude = Convert.ToDouble(p.SelectSingleNode("x").InnerText), Latitude = Convert.ToDouble(p.SelectSingleNode("y").InnerText) }); list.AddRange(res); } } else { for (int i = 0; i < mapPoints.Length; i++) { MapPoint point = new MapPoint(); var p = LocalMapWGS84Coordinates.BD09.Fix(mapPoints[i].Longitude, mapPoints[i].Latitude); if (p != null) { point.Longitude = p.x; point.Latitude = p.y; list.Add(point); } } } return list.ToArray(); }
/// <summary> /// WGS84(原始坐标)ToGCJ02(火星坐标) /// </summary> /// <param name="mapPoint">WGS84(原始坐标)</param> /// <returns></returns> public static MapPoint WGS84ToGCJ02(MapPoint mapPoint) { MapPoint point = new MapPoint(); var p = LocalMapWGS84Coordinates.GCJ02.Fix(mapPoint.Longitude, mapPoint.Latitude); if (p != null) { point.Longitude = p.x; point.Latitude = p.y; } return point; }
/// <summary> /// 判断点是否在圆内(在边上也认为在圆内) /// </summary> /// <param name="mapCenterPoint">圆心坐标</param> /// <param name="radius">圆半径 米</param> /// <param name="mapPoint">当前点</param> /// <returns></returns> public static bool PointIsInCircle(MapPoint mapCenterPoint, double radius, MapPoint mapPoint) { double distance = GetDistance(mapCenterPoint, mapPoint); return distance <= radius; }
/// <summary> /// 判断点是否在线上 A->B->C->D /// </summary> /// <param name="mapPoints">线的点集合</param> /// <param name="mapPoint">当前点</param> /// <param name="offset">偏移 0-10 数值越大表示允许的误差越大 0表示绝对精确 默认1</param> /// <returns></returns> public static bool PointIsInLine(MapPoint[] mapPoints, MapPoint mapPoint, double offset = 1) { if (mapPoints.Length < 2) { throw new ArgumentException("线上的点必须大于2个!"); } //取出线上的每一段出来匹配 如果只要有点在其中一段上 那么说明点在线上 for (int i = 0, j = 1; i < mapPoints.Length - 1; i++, j++) { if (PointIsInLineSegment(mapPoints[i], mapPoints[j], mapPoint, offset)) { return true; } } return false; }
/// <summary> /// 判断点是否在线段上 A->B /// </summary> /// <param name="mapStartPoint">线段开始坐标</param> /// <param name="mapEndPoint">线段结束坐标</param> /// <param name="mapPoint">当前点</param> /// <param name="offset">偏移 0-10 数值越大表示允许的误差越大 0表示绝对精确 默认1</param> /// <returns></returns> public static bool PointIsInLineSegment(MapPoint mapStartPoint, MapPoint mapEndPoint, MapPoint mapPoint, double offset = 1) { //result>0 在线的左边 result<0在线的右边 result=0 在线上 var result = ((mapStartPoint.Longitude - mapPoint.Longitude) * (mapEndPoint.Latitude - mapPoint.Latitude) - (mapEndPoint.Longitude - mapPoint.Longitude) * (mapStartPoint.Latitude - mapPoint.Latitude)) * 1000000; var absResult = Math.Abs(result); if (absResult < offset) { //如果已经确定点在线上了(这里仅仅是确定是在这个线上,线是无线延长的 故还不是确定在线段里面) 这里还需要确定一下 这个点是否是在这两个点组成的矩形里面 return PointIsInRect(mapStartPoint, mapEndPoint, mapPoint); } return false; }
/// <summary> /// 判断点是否在多边形内 /// 射线法 /// 原理是向由点mapPoint向经度正方向发射一个射线,穿过多边形线段上的个数为奇数则在多边形内,偶数则在多边形外 /// </summary> /// <param name="mapPoints">点集合</param> /// <param name="mapPoint">当前点</param> /// <returns></returns> public static bool PointIsInPolygon(MapPoint[] mapPoints, MapPoint mapPoint) { if (mapPoints.Length < 3) { throw new ArgumentException("多边形顶点必须大于3个!"); } int j = 0, count = 0; for (int i = 0; i < mapPoints.Length; i++) { j = (i == mapPoints.Length - 1) ? 0 : j + 1; if ((mapPoints[i].Latitude != mapPoints[j].Latitude) && (((mapPoint.Latitude >= mapPoints[i].Latitude) && (mapPoint.Latitude < mapPoints[j].Latitude)) || ((mapPoint.Latitude >= mapPoints[j].Latitude) && (mapPoint.Latitude < mapPoints[i].Latitude))) && (mapPoint.Longitude < (mapPoints[j].Longitude - mapPoints[i].Longitude) * (mapPoint.Latitude - mapPoints[i].Latitude) / (mapPoints[j].Latitude - mapPoints[i].Latitude) + mapPoints[i].Longitude)) { count++; } } return (count % 2 > 0) ? true : false; }