• 坐标距离算法


      经过这两天的研究,我想有些东西有必要写一下,同时也帮助需要的人

      这是一个查找附近的人的一个算法,在网上找了这篇文章 http://blog.csdn.net/dyllove98/article/details/9795815,他的算最小正方形的四个顶点有点问题。

        
       第一步 ,我们试想一下,如果我们要查找附近五公里的人,是不是最先想到根据自己的经纬度(如果连经纬度都不知道怎么回事,我想你应该知道度娘),再往数据库里面获取其他人的经纬度,根据两个经纬度获取他们的距离,

    如果距离小于5公里的话,那就符合条件。 

      获取距离用两种情况,第一种就是全部查出来在代码里面进行算,第二种情况就是在sql 里面写个函数,在数据库里面算

          代码算距离算法:

     

        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;
             }

          radians是个角度转弧度的算法

         private static double degrees(double d)
             {
                 return d * (180 / Math.PI);
             }
    

         如果不知道里面的算法是个怎样的原理,你可以百度相关的三角函数公式

          sql 距离算法

      

    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    ALTER function [dbo].[fnGetDistance](@LatBegin float, @LngBegin float, @LatEnd float, @LngEnd float) returns float  
    as
    begin
      --距离(千米)  
      declare @Distance float;
      declare @EARTH_RADIUS float;
      set @EARTH_RADIUS = 6378.137;
      
      declare @RadLatBegin float, 
              @RadLatEnd float,
              @RadLatDiff float,
              @RadLngDiff float;
      set @RadLatBegin = @LatBegin * pi()/180.0;
      set @RadLatEnd = @LatEnd * pi()/180.;
      set @RadLatDiff = @RadLatBegin - @RadLatEnd;
      set @RadLngDiff = @LngBegin * pi()/180.0 - @LngEnd * pi()/180.0;
      set @Distance = 2 * asin(sqrt(power(sin(@RadLatDiff/2), 2) + cos(@RadLatBegin)
                      * cos(@RadLatEnd) * power(sin(@RadLngDiff/2), 2)));
      set @Distance = @Distance * @EARTH_RADIUS;
      --set @Distance = Round(@Distance * 10000) / 10000    
      return @Distance 
    end

     

      如果你跟我上面的想法一致的话,我只能对你说处理小数据量还可以。

      例如:我们现在要做一个停车管理系统,需车位的可以查附近的供车位的,供车位的可以查附近需车位的,如果数据库里面有一万条供车位的经纬度,需车位访问服务器,服务器要进行十万次距离换算,如果同时有十个人进行访问的话,那服务器被你轻而易举的百万数据量访问了。

        那有什么办法可以解决呢?

      

     先看这张图,我们知道原点的坐标也就是我们的经纬度,也在知道半径(附近几公里),就可以得到圆的最小正方形,从而根据公式可以得到 正方形的四个顶点 就晓得了 最小经纬度和最大经纬度

    把我们得到的经纬度往数据库里面一查 ,就能轻然一举的把符合范围内的人查

    出来。

    根据经纬度和距离,得到四个顶点的距离算法

     private static void GetlatLon(double GLON, double GLAT, double distance, double angle, out double newLon,out double newLat)
             {
                 double Ea = 6378137;     //   赤道半径  
                 double Eb = 6356725;     //   极半径
                 double dx = distance  * Math.Sin(angle * Math.PI / 180.0);
                 double dy = distance  * Math.Cos(angle * Math.PI / 180.0);
                 //double ec = 6356725 + 21412 * (90.0 - GLAT) / 90.0;
    
                 // 21412 是赤道半径与极半径的差
                 double ec = Eb + (Ea - Eb) * (90.0 - GLAT) / 90.0;
                 double ed = ec * Math.Cos(GLAT * Math.PI / 180);
                 newLon = (dx / ed + GLON * Math.PI / 180.0) * 180.0 / Math.PI;
                 newLat = (dy / ec + GLAT * Math.PI / 180.0) * 180.0 / Math.PI;
               
             }
             public static Degree[] GetRectRange(double centorLogitude,double centorlatitude, double distance)
             {
    
                 double temp = 0.0;
                 double maxLatitude;
                 double minLatitude;
                 double maxLongitude;
                 double minLongitude;
                 GetlatLon(centorLogitude, centorlatitude, distance, 0, out temp, out maxLatitude);
    
                 GetlatLon(centorLogitude, centorlatitude, distance, 180, out temp, out minLatitude);
    
                 GetlatLon(centorLogitude, centorlatitude, distance, 90, out maxLongitude, out temp);
    
                 GetlatLon(centorLogitude, centorlatitude, distance, 270, out minLongitude, out temp);
                 maxLatitude = Math.Round(maxLatitude,6);
                 minLatitude = Math.Round(minLatitude,6);
                 maxLongitude = Math.Round(maxLongitude,6);
                 minLongitude = Math.Round(minLongitude,6);
                 return new Degree[] {
                    new Degree(minLongitude,maxLatitude),//left-top
                    new Degree(minLongitude,minLatitude),//left-bottom
                    new Degree(maxLongitude,maxLatitude),//right-top
                    new Degree(maxLongitude,minLatitude)  //right-bottom
                 };
    
             }

    这些东西经过测试的 相差不到 1,2米

    还是那就话如有不懂的地方 请联系我 QQ:209229923,或在下发为我留言

  • 相关阅读:
    html书签展示(带搜索)
    PHP 无限级分类(递归)
    文件服务器的搭建
    php swoole 和 websocket的初次碰撞
    Linux 服务管理的两种方式service和systemctl
    Jquery 代码参考
    分享几个网址二维码生成api
    WordPress 缩率图学习笔记
    Linux 究级基础入门命令整理
    ltrim的思考
  • 原文地址:https://www.cnblogs.com/xuehaiyiye/p/5511647.html
Copyright © 2020-2023  润新知