387 lines
15 KiB
C#
387 lines
15 KiB
C#
using System.Collections;
|
||
|
||
namespace AutoDispathingWork.Utils
|
||
{
|
||
/*
|
||
* 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;
|
||
}
|
||
|
||
public static Tuple<double, double> BaiduToGaode(double bdLat, double bdLng)
|
||
{
|
||
double x = bdLng - 0.0065;
|
||
double y = bdLat - 0.006;
|
||
double z = Math.Sqrt(x * x + y * y) - 0.00002 * Math.Sin(y * Math.PI);
|
||
double theta = Math.Atan2(y, x) - 0.000003 * Math.Cos(x * Math.PI);
|
||
double ggLng = z * Math.Cos(theta);
|
||
double ggLat = z * Math.Sin(theta);
|
||
|
||
return Tuple.Create(ggLat, ggLng);
|
||
}
|
||
|
||
|
||
/// <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 GpsUtil.TimeToValue(v[0], v[1], v[2] + "." + (v[3] ?? "0"));
|
||
}
|
||
else
|
||
{
|
||
return 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 = GpsUtil.Gps84ToGcj02(lat, lng);
|
||
list_gcj02.Add(gcj02[1].ToString("g18") + "," + gcj02[0].ToString("g18"));
|
||
var bd09 = 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(GpsUtil.GetLongitudeValue(lng) + "," + GpsUtil.GetLatitudeValue(lat));
|
||
var gcj02 = GpsUtil.Gps84ToGcj02(lat, lng);
|
||
list_gcj02.Add(gcj02[1].ToString("g18") + "," + gcj02[0].ToString("g18"));
|
||
var bd09 = 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 = GpsUtil.Gcj02ToGps84(lat, lng);
|
||
list_wgs84.Add(wgs84[1].ToString("g18") + "," + wgs84[0].ToString("g18"));
|
||
list_dx.Add(GpsUtil.GetLongitudeValue(wgs84[1]) + "," + GpsUtil.GetLatitudeValue(wgs84[0]));
|
||
var bd09 = 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 = GpsUtil.Bd09ToGps84(lat, lng);
|
||
list_wgs84.Add(wgs84[1].ToString("g18") + "," + wgs84[0].ToString("g18"));
|
||
list_dx.Add(GpsUtil.GetLongitudeValue(wgs84[1]) + "," + GpsUtil.GetLatitudeValue(wgs84[0]));
|
||
var gcj02 = 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; }
|
||
}
|
||
|
||
}
|
||
} |