C#以中心点经纬度和范围半径为基准计算矩形四个顶点的经纬度

最近要做附近的人查询算法,在网上找了相关示例,发现代码有些问题,经过我整理测试,终于完成该算法,特此记录。

1.经纬度座标实例,方便实例化和传值。

/// <summary>
    /// 经纬度座标
    /// </summary>    
    public class Degree
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="x">经度</param>
        /// <param name="y">纬度</param>
        public Degree(double x, double y)
        {
            X = x;
            Y = y;
        }
        /// <summary>
        /// 经度
        /// </summary>
        private double x;
        /// <summary>
        /// 经度
        /// </summary>
        public double X
        {
            get { return x; }
            set { x = value; }
        }
        /// <summary>
        /// 纬度
        /// </summary>
        private double y;
        /// <summary>
        /// 纬度
        /// </summary>
        public double Y
        {
            get { return y; }
            set { y = value; }
        }
    }

2.开始写算法。

public class CoordinatesHelper
    {
        private const double EARTH_RADIUS = 6378137.0;//地球赤道半径(单位:m。6378137m是1980年的标准,比1975年的标准6378140少3m)

        /// <summary>
        /// 角度数转换为弧度公式
        /// </summary>
        /// <param name="d"></param>
        /// <returns></returns>
        private static double radians(double d)
        {
            return d * Math.PI / 180.0;
        }

        /// <summary>
        /// 弧度转换为角度数公式
        /// </summary>
        /// <param name="d"></param>
        /// <returns></returns>
        private static double degrees(double d)
        {
            return d * (180 / Math.PI);
        }

        /// <summary>
        /// 计算两点之间的距离
        /// 单位:米
        /// </summary>
        /// <param name="Degree1"></param>
        /// <param name="Degree2"></param>
        /// <returns></returns>
        public static double GetDistance(Degree Degree1, Degree Degree2)
        {
            double radLat1 = radians(Degree1.Y);
            double radLat2 = radians(Degree2.Y);
            double a = radLat1 - radLat2;
            double b = radians(Degree1.X) - radians(Degree2.X);

            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 * EARTH_RADIUS;
            s = Math.Round(s * 10000) / 10000;
            return s;
        }

        /// <summary>
        /// 计算两个经纬度之间的直接距离(google 算法)
        /// </summary>
        public static double GetDistanceGoogle(Degree Degree1, Degree Degree2)
        {
            double radLat1 = radians(Degree1.Y);
            double radLng1 = radians(Degree1.X);
            double radLat2 = radians(Degree2.Y);
            double radLng2 = radians(Degree2.X);

            double s = Math.Acos(Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Cos(radLng1 - radLng2) + Math.Sin(radLat1) * Math.Sin(radLat2));
            s = s * EARTH_RADIUS;
            s = Math.Round(s * 10000) / 10000;
            return s;
        }

        /// <summary>
        /// 以一个经纬度为中心计算出四个顶点
        /// </summary>
        /// <param name="Degree1">中心点</param>
        /// <param name="distance">半径(米)</param>
        /// <returns></returns>
        public static Degree[] GetDegreeCoordinates(Degree Degree1, double distance)
        {
            double dlng = 2 * Math.Asin(Math.Sin(distance / (2 * EARTH_RADIUS)) / Math.Cos(Degree1.X));
            dlng = degrees(dlng);//一定转换成角度数

            double dlat = distance / EARTH_RADIUS;
            dlat = degrees(dlat);//一定转换成角度数
            
            return new Degree[] { new Degree(Math.Round(Degree1.X - dlng,6), Math.Round(Degree1.Y + dlat,6)),//left-top
                                   new Degree(Math.Round(Degree1.X - dlng,6), Math.Round(Degree1.Y - dlat,6)),//left-bottom
                                   new Degree(Math.Round(Degree1.X + dlng,6), Math.Round(Degree1.Y + dlat,6)),//right-top
                                   new Degree(Math.Round(Degree1.X + dlng,6), Math.Round(Degree1.Y - dlat,6)) //right-bottom
            };
        }
    }

附:

1.因为我们地处东经、北半球区域,所以计算出来的四个顶点的经纬度,要符合以下标准才算基本正确

同一水平线的两个点的纬度是相同的,同一竖直线的经度是相同的

a.左上点:经度比中心点的经度小,纬度比中心点的纬度大

b.左下点:经度比中心点的经度小,纬度比中心点的纬度小

c.右上点:经度比中心点的经度大,纬度比中心点的纬度大

d.右下点:经度比中心点的经度大,纬度比中心点的纬度小

2.我整理的代码和原文的不同之处这里不作赘述,经过测试,四个顶点的座标都处于正常取值范围,误差范围暂未测试。

点赞