zoukankan      html  css  js  c++  java
  • 使用GPS经纬度定位附近地点(某一点范围内查询)

    需要手机查找附近N米以内的商户,致想法是已知一个中心点,一个半径,求圆包含于圆抛物线里所有的点,经纬度是一个点,半径是一个距离,不能直接加减,下面提供C#的解决方法

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

    来自:jb51

  • 相关阅读:
    Windows API Reference for C#, VB.NET and VB6
    工程建设项目综合信息管理系统
    GridView,Repeater分页控件:WebPager 开源了
    asp.net服务器控件开发学习之路(一)
    ajaxToolkit:TabContainer 背景色的设置
    TreeView 树结构的断层处理
    C# 集合类(二):Queue
    AutoCAD.net(三)用VS.NET2005开发ObjectARX程序 调试方法
    AutoCAD.net(一):更改AutoCAD窗口的标题和图标
    C# 集合类(四):Hashtable
  • 原文地址:https://www.cnblogs.com/tyjsjl/p/3799460.html
Copyright © 2011-2022 走看看