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

时间:2023-08-22 18:49:09 

数据库中记录了商家在百度标注的经纬度(如: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

标签:经纬度定位
0
投稿

猜你喜欢

  • 深入理解Java并发编程之LinkedBlockingQueue队列

    2022-10-02 06:35:22
  • struts2中实现多个文件同时上传代码

    2023-05-11 16:24:39
  • C#实现图形界面的时钟

    2022-10-03 15:10:50
  • C语言中结构体与内存对齐实例解析

    2022-05-16 12:25:18
  • C#递归算法之快速排序

    2021-08-16 21:13:37
  • Android仿最新微信相机功能

    2022-06-08 00:35:08
  • Spring Aop 源码增强获取分享

    2023-06-22 21:59:22
  • C#支付宝新版支付请求接口调用

    2023-02-23 15:50:45
  • Lucene单值编码压缩算法源码解析

    2022-12-30 18:00:39
  • idea2020.3.3集成maven及遇到的坑(推荐)

    2021-11-18 04:18:54
  • 使用Logback设置property参数方式

    2022-07-28 01:06:01
  • 浅析C# 函数的传值与传址

    2023-11-22 04:46:57
  • C#判断访问来源是否为搜索引擎链接的方法

    2021-11-01 09:15:53
  • Java真题实练掌握哈希表的使用

    2023-11-09 06:33:15
  • Android开发之使用SQLite存储数据的方法分析

    2022-09-17 12:13:12
  • SpringBoot整合Mybatis与druid实现流程详解

    2022-09-17 17:05:31
  • C#实现char字符数组与字符串相互转换的方法

    2022-01-18 05:28:52
  • C#中out与ref的区别实例解析

    2022-01-27 13:29:09
  • 详解Java中的反射机制和动态代理

    2023-11-27 15:41:00
  • C#/VB.NET 在PDF中添加文件包(Portfolio)的方法

    2023-08-28 03:01:18
  • asp之家 软件编程 m.aspxhome.com