坐标距离算法
经过这两天的研究,我想有些东西有必要写一下,同时也帮助需要的人
这是一个查找附近的人的一个算法,在网上找了这篇文章 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,或在下发为我留言