鉴于我有一个包含机场列表及其相关经纬度坐标的表格,我将如何获取距离另一个坐标 100 英里范围内的机场列表?我的最终目标是让用户按城市搜索并找到该城市纬度和经度 100 英里范围内的机场。我有所有的数据只是不知道从哪里开始。
我的数据在 SQL Server 中。
鉴于我有一个包含机场列表及其相关经纬度坐标的表格,我将如何获取距离另一个坐标 100 英里范围内的机场列表?我的最终目标是让用户按城市搜索并找到该城市纬度和经度 100 英里范围内的机场。我有所有的数据只是不知道从哪里开始。
我的数据在 SQL Server 中。
create function dbo.F_GREAT_CIRCLE_DISTANCE
(
@Latitude1 float,
@Longitude1 float,
@Latitude2 float,
@Longitude2 float
)
returns float as
begin
declare @radius float
declare @lon1 float
declare @lon2 float
declare @lat1 float
declare @lat2 float
declare @a float
declare @distance float
-- Sets average radius of Earth in Miles
set @radius = 3956
-- Convert degrees to radians
set @lon1 = radians( @Longitude1 )
set @lon2 = radians( @Longitude2 )
set @lat1 = radians( @Latitude1 )
set @lat2 = radians( @Latitude2 )
set @a = sqrt(square(sin((@lat2-@lat1)/2.0E)) + (cos(@lat1) * cos(@lat2) * square(sin((@lon2-@lon1)/2.0E))) )
set @distance = @radius * ( 2.0E *asin(case when 1.0E < @a then 1.0E else @a end ))
return @distance
end
你可以使用System.Device.Location.GeoCoordinate
类
GeoCoordinate city = ....;
double distance = .......;
List<GeoCoordinate> airports = .......; //load from db.
var found = airports.Where(c=>c.GetDistanceTo(city) < distance);
编辑
对于那些可能对真正的工作代码感兴趣的人
var airports1 = Airports.Search(51, 0, 100).ToList(); //~London
var airports2 = Airports.Search(40.714623, -74.006605,100).ToList(); //~NY
public class Airports
{
public class Airport
{
public string Name;
public GeoCoordinate Location;
public override string ToString()
{
return Name;
}
}
static Lazy<List<Airport>> _Airports = new Lazy<List<Airport>>(() =>
{
using (var wc = new WebClient())
{
var json = wc.DownloadString("http://www.flightradar24.com/AirportDataService2.php");
var jObj = new JavaScriptSerializer().Deserialize<Dictionary<string,string[]>>(json);
return jObj.Values
.Select(j => new Airport
{
Name = (string)j[2],
Location = new GeoCoordinate(double.Parse(j[3].ToString(), CultureInfo.InvariantCulture),double.Parse(j[4].ToString(), CultureInfo.InvariantCulture))
})
.ToList();
}
}, true);
public static IEnumerable<Airport> Search(double lat,double lon, double distInMiles)
{
var loc = new GeoCoordinate(lat, lon);
return _Airports.Value.Where(c => c.Location.GetDistanceTo(loc) < distInMiles * 1609.344);
}
}
你可以这样做:
--SELECT Points closer than @radius
select * from #Points p
WHERE power(p.x - @locX, 2) + POWER(p.y - @locY, 2) < POWER(@radius,2)
(这已无耻地从http://www.sqlservercentral.com/Forums/Topic1228111-8-1.aspx#bm1229043中删除,通过 Google Search for SQL + Pyhtagoras 找到)。
如果您的机场位于点 0,0,则半径 30 英里内的所有机场都应在一个圆圈内。要测试点是否在圆内,您需要测试每个平方方程: sqrt(X*X + Y*Y) < R,其中 X, Y - 每个位置的位置,R = 100 英里
这是“乌鸦飞过两点之间的距离”的公式:Haversine
formula: a = sin²(Δφ/2) + cos(φ1).cos(φ2).sin²(Δλ/2)
c = 2.atan2(√a, √(1−a))
d = R.c
其中 φ 是纬度,λ 是经度,R 是地球半径(平均半径 = 6,371 公里)请注意,角度需要以弧度为单位才能传递给三角函数!
你可以把这段代码翻译成 SQL
JavaScript:
var R = 6371; // km
var dLat = (lat2-lat1).toRad();
var dLon = (lon2-lon1).toRad();
var lat1 = lat1.toRad();
var lat2 = lat2.toRad();
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
这是数学函数的 T-SQL 页面的链接:http: //msdn.microsoft.com/en-us/library/ms188919.aspx