using System; namespace Billing { public static class LocationExtension { private const double PI = 3.1415926535897931; private const double A = 6378245d; private const double EE = 0.00669342162296594323; public static (double longitude, double latitude) Wgs84ToGcj02(this (double lon, double lat) position) { return Transform(position); } public static (double longitude, double latitude) Gcj02ToWgs84(this (double lon, double lat) position) { (double longitude, double latitude) = Transform(position); longitude = position.lon * 2d - longitude; latitude = position.lat * 2d - latitude; return (longitude, latitude); } public static (double longitude, double latitude) Gcj02ToBd09(this (double lon, double lat) position) { double x = position.lon; double y = position.lat; double z = Math.Sqrt(x * x + y * y) + 0.00002 * Math.Sin(y * PI); double theta = Math.Atan2(y, x) + 0.000003 * Math.Cos(x * PI); double longitude = z * Math.Cos(theta) + 0.0065; double latitude = z * Math.Sin(theta) + 0.006; return (longitude, latitude); } public static (double longitude, double latitude) Bd09ToGcj02(this (double lon, double lat) position) { double x = position.lon - 0.0065; double y = position.lat - 0.006; double z = Math.Sqrt(x * x + y * y) - 0.00002 * Math.Sin(y * PI); double theta = Math.Atan2(y, x) - 0.000003 * Math.Cos(x * PI); double longitude = z * Math.Cos(theta); double latitude = z * Math.Sin(theta); return (longitude, latitude); } private static (double longitude, double latitude) Transform(this (double lon, double lat) position) { if (IsOutOfChina(position.lon, position.lat)) { return position; } var offsetLatitude = TransformLatitude(position.lon - 105d, position.lat - 35d); var offsetLongitude = TransformLongitude(position.lon - 105d, position.lat - 35d); var radiusLatitude = position.lat / 180d * PI; var magic = 1d - EE * Math.Pow(Math.Sin(radiusLatitude), 2); var sqrtMagic = Math.Sqrt(magic); offsetLatitude = offsetLatitude * 180d / (A * (1d - EE) / (magic * sqrtMagic) * PI); offsetLongitude = offsetLongitude * 180d / (A / sqrtMagic * Math.Cos(radiusLatitude) * PI); return (position.lon + offsetLongitude, position.lat + offsetLatitude); } private static bool IsOutOfChina(double lon, double lat) { return lon < 72.004 || lon > 137.8347 || lat < 0.8293 || lat > 55.8171; } private static double TransformLatitude(double x, double y) { var ret = -100d + 2d * x + 3d * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.Sqrt(Math.Abs(x)); ret += (20d * Math.Sin(6d * x * PI) + 20d * Math.Sin(2d * x * PI)) * 2d / 3d; ret += (20d * Math.Sin(y * PI) + 40d * Math.Sin(y / 3d * PI)) * 2d / 3d; ret += (160d * Math.Sin(y / 12d * PI) + 320d * Math.Sin(y * PI / 30d)) * 2d / 3d; return ret; } private static double TransformLongitude(double x, double y) { var ret = 300d + x + 2d * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.Sqrt(Math.Abs(x)); ret += (20d * Math.Sin(6d * x * PI) + 20d * Math.Sin(2d * x * PI)) * 2d / 3d; ret += (20d * Math.Sin(x * PI) + 40d * Math.Sin(x / 3d * PI)) * 2d / 3d; ret += (150d * Math.Sin(x / 12d * PI) + 300d * Math.Sin(x / 30d * PI)) * 2d / 3d; return ret; } } }