GPS、谷歌、百度、高德坐标相互转换
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Web; using Newtonsoft.Json; namespace SandManagement.Models { /* * WGS84坐标系 地球坐标系,国际通用坐标系 * GCJ02坐标系 火星坐标系,WGS84坐标系加密后的坐标系;Google国内地图、高德、QQ地图 使用 * BD09坐标系 百度坐标系,GCJ02坐标系加密后的坐标系 * */ public class GpsUtil { public static double pi = 3.1415926535897932384626; public static double x_pi = 3.1415926535897932384626;// * 3000.0 / 180.0; //转换BD09时偏移 //public static double cbz = 6378137.0; //长半轴 public static double cbz = 6378245.0; //长半轴 public static double ee = 0.00669342162296594323; public static double TransformLat(double x, double y) { double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.Sqrt(Math.Abs(x)); ret += (20.0 * Math.Sin(6.0 * x * pi) + 20.0 * Math.Sin(2.0 * x * pi)) * 2.0 / 3.0; ret += (20.0 * Math.Sin(y * pi) + 40.0 * Math.Sin(y / 3.0 * pi)) * 2.0 / 3.0; ret += (160.0 * Math.Sin(y / 12.0 * pi) + 320 * Math.Sin(y * pi / 30.0)) * 2.0 / 3.0; return ret; } public static double TransformLon(double x, double y) { double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.Sqrt(Math.Abs(x)); ret += (20.0 * Math.Sin(6.0 * x * pi) + 20.0 * Math.Sin(2.0 * x * pi)) * 2.0 / 3.0; ret += (20.0 * Math.Sin(x * pi) + 40.0 * Math.Sin(x / 3.0 * pi)) * 2.0 / 3.0; ret += (150.0 * Math.Sin(x / 12.0 * pi) + 300.0 * Math.Sin(x / 30.0 * pi)) * 2.0 / 3.0; return ret; } public static double[] transform(double lat, double lon) { if (OutOfChina(lat, lon)) { return new double[] { lat, lon }; } double dLat = TransformLat(lon - 105.0, lat - 35.0); double dLon = TransformLon(lon - 105.0, lat - 35.0); double radLat = lat / 180.0 * pi; double magic = Math.Sin(radLat); magic = 1 - ee * magic * magic; double SqrtMagic = Math.Sqrt(magic); dLat = (dLat * 180.0) / ((cbz * (1 - ee)) / (magic * SqrtMagic) * pi); dLon = (dLon * 180.0) / (cbz / SqrtMagic * Math.Cos(radLat) * pi); double mgLat = lat + dLat; double mgLon = lon + dLon; return new double[] { mgLat, mgLon }; } /// <summary> /// 是否是国内地址 /// </summary> /// <param name="lat"></param> /// <param name="lon"></param> /// <returns></returns> public static bool OutOfChina(double lat, double lon) { if (lon < 72.004 || lon > 137.8347) return true; if (lat < 0.8293 || lat > 55.8271) return true; return false; } /** * 84 to 火星坐标系 (GCJ-02) World Geodetic System ==> Mars Geodetic System * * @param lat * @param lon * @return */ public static double[] Gps84ToGcj02(double lat, double lon) { if (OutOfChina(lat, lon)) { return new double[] { lat, lon }; } double dLat = TransformLat(lon - 105.0, lat - 35.0); double dLon = TransformLon(lon - 105.0, lat - 35.0); double radLat = lat / 180.0 * pi; double magic = Math.Sin(radLat); magic = 1 - ee * magic * magic; double SqrtMagic = Math.Sqrt(magic); dLat = (dLat * 180.0) / ((cbz * (1 - ee)) / (magic * SqrtMagic) * pi); dLon = (dLon * 180.0) / (cbz / SqrtMagic * Math.Cos(radLat) * pi); double mgLat = lat + dLat; double mgLon = lon + dLon; return new double[] { mgLat, mgLon }; } /** * * 火星坐标系 (GCJ-02) to 84 * * @param lon * @param lat * @return * */ public static double[] Gcj02ToGps84(double lat, double lon) { double[] gps = transform(lat, lon); double lontitude = lon * 2 - gps[1]; double latitude = lat * 2 - gps[0]; return new double[] { latitude, lontitude }; } /// <summary> /// 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 将 GCJ-02 坐标转换成 BD-09 坐标 /// 高德谷歌转为百度 /// </summary> /// <param name="lat"></param> /// <param name="lon"></param> /// <returns></returns> public static double[] Gcj02ToBd09(double lat, double lon) { double x = lon, y = lat; double z = Math.Sqrt(x * x + y * y) + 0.00002 * Math.Sin(y * x_pi); double theta = Math.Atan2(y, x) + 0.000003 * Math.Cos(x * x_pi); double tempLon = z * Math.Cos(theta) + 0.0065; double tempLat = z * Math.Sin(theta) + 0.006; double[] gps = { tempLat, tempLon }; return gps; } /// <summary> /// 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 * * 将 BD-09 坐标转换成GCJ-02 坐标 /// 百度坐标转为高德谷歌坐标 /// </summary> /// <param name="lat"></param> /// <param name="lon"></param> /// <returns></returns> public static double[] Bd09ToGcj02(double lat, double lon) { double x = lon - 0.0065, y = lat - 0.006; double z = Math.Sqrt(x * x + y * y) - 0.00002 * Math.Sin(y * x_pi); double theta = Math.Atan2(y, x) - 0.000003 * Math.Cos(x * x_pi); double tempLon = z * Math.Cos(theta); double tempLat = z * Math.Sin(theta); double[] gps = { tempLat, tempLon }; return gps; } /// <summary> /// gps84转为bd09 /// GPS坐标转为百度坐标 /// </summary> /// <param name="lat"></param> /// <param name="lon"></param> /// <returns></returns> public static double[] Gps84ToBd09(double lat, double lon) { double[] gcj02 = Gps84ToGcj02(lat, lon); double[] bd09 = Gcj02ToBd09(gcj02[0], gcj02[1]); return bd09; } /// <summary> /// 百度坐标转成GPS坐标 /// </summary> /// <param name="lat"></param> /// <param name="lon"></param> /// <returns></returns> public static double[] Bd09ToGps84(double lat, double lon) { double[] gcj02 = Bd09ToGcj02(lat, lon); double[] gps84 = Gcj02ToGps84(gcj02[0], gcj02[1]); //保留小数点后六位 gps84[0] = Retain6(gps84[0]); gps84[1] = Retain6(gps84[1]); return gps84; } /// <summary> /// 保留小数点后六位 /// </summary> /// <param name="num"></param> /// <returns></returns> private static double Retain6(double num) { //String result = String.Format("%.6f", num); return Double.Parse(num.ToString("0.000000")); } /// <summary> /// 获取经度(lon) /// </summary> /// <returns></returns> public static string GetLongitudeValue(double value) { ArrayList arrList = LgetValid(value); if (arrList == null) return string.Empty; if (arrList.Count != 3) return string.Empty; return string.Format("{0}.{1}.{2}", arrList[0], arrList[1], arrList[2], value > 0 ? "E" : "W"); } /// <summary> /// 获取纬度(lat) /// </summary> /// <returns></returns> public static string GetLatitudeValue(double value) { ArrayList arrList = LgetValid(value); if (arrList == null) return string.Empty; if (arrList.Count != 3) return string.Empty; return string.Format("{0}.{1}.{2}", arrList[0], arrList[1], arrList[2], value > 0 ? "N" : "S"); } /// <summary> /// 获取经纬度度分秒 /// </summary> /// <param name="value"></param> /// <returns></returns> public static ArrayList LgetValid(double value) { ArrayList aList = new ArrayList(); string excute = ChangeValue(value); string[] sArray = excute.Split('|'); aList.Insert(0, sArray[0]); aList.Insert(1, sArray[1]); aList.Insert(2, sArray[2]); return aList; } /// <summary> /// 经纬度转换 /// </summary> /// <param name="str">经度</param> /// <param name="num">保留8位值</param> /// <returns></returns> protected static string ChangeValue(double degree) { if (degree < 0) { degree = -degree; } double minute = (degree - (int)degree) * 60; double second = (minute - (int)minute) * 60; return ((int)degree).ToString() + "|" + ((int)minute).ToString() + "|" + second.ToString("0.000"); } /// <summary> /// 度时分 转换成 WGS84 /// </summary> /// <param name="Degrees"></param> /// <param name="Minutes"></param> /// <param name="Seconds"></param> /// <returns></returns> public static double TimeToValue(string Degrees, string Minutes, string Seconds) { double Value = double.Parse(Degrees) + double.Parse(Minutes) / 60 + double.Parse(Seconds) / 3600; return double.Parse(Value.ToString("0.000000")); } /// <summary> /// 批量转换 /// </summary> /// <param name="arr">字符串数组["lng,lat","lng,lat"...]</param> /// <param name="type">地心坐标,WGS84,GCJ02,BD09</param> public static GpsUtilObject piliangzhuan(List<string> arr, string typename) { //地心 var list_dx = new List<string>(); //WGS84 var list_wgs84 = new List<string>(); //GCJ02 var list_gcj02 = new List<string>(); ///BD09 var list_bd09 = new List<string>(); ///BD092 var list_bd092 = new List<string>(); foreach (var ar in arr) { var item = ar.Split(',').ToList(); //地心 转 w84 Func<string, double> dxTow84 = (value) => { var v = value.Split('.').ToList(); if (v.Count > 3) { return Models.GpsUtil.TimeToValue(v[0], v[1], v[2] + "." + (v[3] ?? "0")); } else { return Models.GpsUtil.TimeToValue(v[0], v[1], v[2]); } }; switch (typename) { case "地心坐标": { list_dx.Add(ar); double lng = dxTow84(item[0]); double lat = dxTow84(item[1]); list_wgs84.Add(lng + "," + lat); var gcj02 = Models.GpsUtil.Gps84ToGcj02(lat, lng); list_gcj02.Add(gcj02[1].ToString("g18") + "," + gcj02[0].ToString("g18")); var bd09 = Models.GpsUtil.Gps84ToBd09(lat, lng); list_bd09.Add(bd09[1].ToString("g18") + "," + bd09[0].ToString("g18")); } break; case "WGS84": { double lng = double.Parse(item[0]); double lat = double.Parse(item[1]); list_wgs84.Add(ar); list_dx.Add(Models.GpsUtil.GetLongitudeValue(lng) + "," + Models.GpsUtil.GetLatitudeValue(lat)); var gcj02 = Models.GpsUtil.Gps84ToGcj02(lat, lng); list_gcj02.Add(gcj02[1].ToString("g18") + "," + gcj02[0].ToString("g18")); var bd09 = Models.GpsUtil.Gps84ToBd09(lat, lng); list_bd09.Add(bd09[1].ToString("g18") + "," + bd09[0].ToString("g18")); } break; case "GCJ02": { double lng = double.Parse(item[0]); double lat = double.Parse(item[1]); list_gcj02.Add(ar); var wgs84 = Models.GpsUtil.Gcj02ToGps84(lat, lng); list_wgs84.Add(wgs84[1].ToString("g18") + "," + wgs84[0].ToString("g18")); list_dx.Add(Models.GpsUtil.GetLongitudeValue(wgs84[1]) + "," + Models.GpsUtil.GetLatitudeValue(wgs84[0])); var bd09 = Models.GpsUtil.Gcj02ToBd09(lat, lng); list_bd09.Add(bd09[1].ToString("g18") + "," + bd09[0].ToString("g18")); } break; case "BD09": { double lng = double.Parse(item[0]); double lat = double.Parse(item[1]); list_bd09.Add(ar); var wgs84 = Models.GpsUtil.Bd09ToGps84(lat, lng); list_wgs84.Add(wgs84[1].ToString("g18") + "," + wgs84[0].ToString("g18")); list_dx.Add(Models.GpsUtil.GetLongitudeValue(wgs84[1]) + "," + Models.GpsUtil.GetLatitudeValue(wgs84[0])); var gcj02 = Models.GpsUtil.Bd09ToGcj02(lat, lng); list_gcj02.Add(gcj02[1].ToString("g18") + "," + gcj02[0].ToString("g18")); } break; default: break; } } return new GpsUtilObject { dx = string.Join("|", list_dx), wgs84 = string.Join("|", list_wgs84), gcj02 = string.Join("|", list_gcj02), bd09 = string.Join("|", list_bd09) }; } public class GpsUtilObject { /// <summary> /// 地心坐标 /// </summary> public string dx { get; set; } /// <summary> /// WGS84 /// </summary> public string wgs84 { get; set; } /// <summary> /// GCJ02 /// </summary> public string gcj02 { get; set; } /// <summary> /// BD09 /// </summary> public string bd09 { get; set; } } } }
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现