zl程序教程

您现在的位置是:首页 >  其他

当前栏目

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

定位 使用 查询 范围 一点 经纬度 GPS 附近
2023-06-13 09:15:14 时间

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

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

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

复制代码代码如下:

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

  publicclassDegree
   {
       publicDegree(doublex,doubley)
       {
           X=x;
           Y=y;
       }
       privatedoublex;

       publicdoubleX
       {
           get{returnx;}
           set{x=value;}
       }
       privatedoubley;

       publicdoubleY
       {
           get{returny;}
           set{y=value;}
       }
   }


   publicclassCoordDispose
   {
       privateconstdoubleEARTH_RADIUS=6378137.0;//地球半径(米)

       ///<summary>
       ///角度数转换为弧度公式
       ///</summary>
       ///<paramname="d"></param>
       ///<returns></returns>
       privatestaticdoubleradians(doubled)
       {
           returnd*Math.PI/180.0;
       }

       ///<summary>
       ///弧度转换为角度数公式
       ///</summary>
       ///<paramname="d"></param>
       ///<returns></returns>
       privatestaticdoubledegrees(doubled)
       {
           returnd*(180/Math.PI);
       }

       ///<summary>
       ///计算两个经纬度之间的直接距离
       ///</summary>

       publicstaticdoubleGetDistance(DegreeDegree1,DegreeDegree2)
       {
           doubleradLat1=radians(Degree1.X);
           doubleradLat2=radians(Degree2.X);
           doublea=radLat1-radLat2;
           doubleb=radians(Degree1.Y)-radians(Degree2.Y);

           doubles=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;
           returns;
       }

       ///<summary>
       ///计算两个经纬度之间的直接距离(google算法)
       ///</summary>
       publicstaticdoubleGetDistanceGoogle(DegreeDegree1,DegreeDegree2)
       {
           doubleradLat1=radians(Degree1.X);
           doubleradLng1=radians(Degree1.Y);
           doubleradLat2=radians(Degree2.X);
           doubleradLng2=radians(Degree2.Y);

           doubles=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;
           returns;
       }

       ///<summary>
       ///以一个经纬度为中心计算出四个顶点
       ///</summary>
       ///<paramname="distance">半径(米)</param>
       ///<returns></returns>
       publicstaticDegree[]GetDegreeCoordinates(DegreeDegree1,doubledistance)
       {
           doubledlng=2*Math.Asin(Math.Sin(distance/(2*EARTH_RADIUS))/Math.Cos(Degree1.X));
           dlng=degrees(dlng);//一定转换成角度数 原PHP文章这个地方说的不清楚根本不正确后来lz又查了很多资料终于搞定了

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

           returnnewDegree[]{newDegree(Math.Round(Degree1.X+dlat,6),Math.Round(Degree1.Y-dlng,6)),//left-top
                                 newDegree(Math.Round(Degree1.X-dlat,6),Math.Round(Degree1.Y-dlng,6)),//left-bottom
                                 newDegree(Math.Round(Degree1.X+dlat,6),Math.Round(Degree1.Y+dlng,6)),//right-top
                                 newDegree(Math.Round(Degree1.X-dlat,6),Math.Round(Degree1.Y+dlng,6))//right-bottom
           };

       }
   }

测试方法:

复制代码代码如下:


staticvoidMain(string[]args)
       {
           doublea=CoordDispose.GetDistance(newDegree(116.412007,39.947545),newDegree(116.412924,39.947918));//116.416984,39.944959
           doubleb=CoordDispose.GetDistanceGoogle(newDegree(116.412007,39.947545),newDegree(116.412924,39.947918));
           Degree[]dd=CoordDispose.GetDegreeCoordinates(newDegree(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米左右

拿到圆的顶点就好办了

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

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

复制代码代码如下:
SELECTid,zuobiaoFROMdbo.zuobiaoWHEREzuobiao<>""AND
dbo.Get_StrArrayStrOfIndex(zuobiao,",",1)>116.41021AND
dbo.Get_StrArrayStrOfIndex(zuobiao,",",1)<116.413804AND
dbo.Get_StrArrayStrOfIndex(zuobiao,",",2)<39.949369AND
dbo.Get_StrArrayStrOfIndex(zuobiao,",",2)>39.945721