欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

使用GPS经纬度定位附近地点(某一点范围内查询)

程序员文章站 2024-02-24 12:37:10
数据库中记录了商家在百度标注的经纬度(如:116.412007, 39.947545) 最初想法,以圆心点为中心点,对半径做循环,半径每增加一个像素(暂定1米)再对周长做...

数据库中记录了商家在百度标注的经纬度(如:116.412007, 39.947545)

最初想法,以圆心点为中心点,对半径做循环,半径每增加一个像素(暂定1米)再对周长做循环,到数据库中查询对应点的商家(真是一个长时间的循环工作),上网百度类似的文章有了点眉目

大致想法是已知一个中心点,一个半径,求圆包含于圆抛物线里所有的点,这样的话就需要知道所要求的这个圆的对角线的顶点,问题来了 经纬度是一个点,半径是一个距离,不能直接加减

复制代码 代码如下:

/// <summary>
    /// 经纬度坐标
    /// </summary>   

  public class degree
    {
        public degree(double x, double y)
        {
            x = x;
            y = y;
        }
        private double x;

        public double x
        {
            get { return x; }
            set { x = value; }
        }
        private double y;

        public double y
        {
            get { return y; }
            set { y = value; }
        }
    }


    public class coorddispose
    {
        private const double earth_radius = 6378137.0;//地球半径(米)

        /// <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>

        public static double getdistance(degree degree1, degree degree2)
        {
            double radlat1 = radians(degree1.x);
            double radlat2 = radians(degree2.x);
            double a = radlat1 - radlat2;
            double b = radians(degree1.y) - radians(degree2.y);

            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.x);
            double radlng1 = radians(degree1.y);
            double radlat2 = radians(degree2.x);
            double radlng2 = radians(degree2.y);

            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="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);//一定转换成角度数  原php文章这个地方说的不清楚根本不正确 后来lz又查了很多资料终于搞定了

            double dlat = distance / earth_radius;
            dlat = degrees(dlat);//一定转换成角度数

            return new degree[] { new degree(math.round(degree1.x + dlat,6), math.round(degree1.y - dlng,6)),//left-top
                                  new degree(math.round(degree1.x - dlat,6), math.round(degree1.y - dlng,6)),//left-bottom
                                  new degree(math.round(degree1.x + dlat,6), math.round(degree1.y + dlng,6)),//right-top
                                  new degree(math.round(degree1.x - dlat,6), math.round(degree1.y + dlng,6)) //right-bottom
            };

        }
    }

测试方法:

复制代码 代码如下:

static void main(string[] args)
        {
            double a = coorddispose.getdistance(new degree(116.412007, 39.947545), new degree(116.412924, 39.947918));//116.416984,39.944959
            double b = coorddispose.getdistancegoogle(new degree(116.412007, 39.947545), new degree(116.412924, 39.947918));
            degree[] dd = coorddispose.getdegreecoordinates(new degree(116.412007, 39.947545), 102);
            console.writeline(a+" "+b);
            console.writeline(dd[0].x + "," + dd[0].y );
            console.writeline(dd[3].x + "," + dd[3].y);
            console.readline();
        }

试了很多次 误差在1米左右

拿到圆的顶点就好办了

数据库要是sql 2008的可以直接进行空间索引经纬度字段,这样应该性能更好(没有试过)

lz公司数据库还老 2005的 这也没关系,关键是经纬度拆分计算,这个就不用说了 网上多的是 最后上个实现的sql语句

复制代码 代码如下:

select id,zuobiao from dbo.zuobiao where zuobiao<>'' and
dbo.get_strarraystrofindex(zuobiao,',',1)>116.41021 and
dbo.get_strarraystrofindex(zuobiao,',',1)<116.413804 and
dbo.get_strarraystrofindex(zuobiao,',',2)<39.949369 and
dbo.get_strarraystrofindex(zuobiao,',',2)>39.945721