给定两个 lat/longs,我如何判断它们之间的距离是否在 1 英里以内?
Given two lat/longs, how can I tell if they are within 1 mile of each other?
我正在尝试实施一种非常有效的检查,以查看两点之间是否在一英里以内。
我只关心它们是否在一英里之内——关于距离的其他事情对我来说都不重要。
由于关注范围狭窄,我不是寻找通用的“how far apart are these points”函数。
我目前的方法是计算 Haversine distance,然后检查它是否小于一英里。
在这种情况下效率很重要,因为我必须为大型记录集计算此 yes/no 标志。
那么,判断两个 lat/long 点是否在彼此一英里以内的最有效方法是什么?
我正在 T-SQL 中进行此检查,但这并不重要。
我当前的 haversine 计算如下。
CREATE FUNCTION dbo.USR_UFN_HAVERSINE_DISTANCE
(
@LAT1 FLOAT(18)
,@LONG1 FLOAT(18)
,@LAT2 FLOAT(18)
,@LONG2 FLOAT(18)
,@UnitOfMeasure NVARCHAR(10) = 'KILOMETERS'
)
RETURNS FLOAT(18)
AS
BEGIN
DECLARE
@R FLOAT(8)
,@DLAT FLOAT(18)
,@DLON FLOAT(18)
,@A FLOAT(18)
,@C FLOAT(18)
,@D FLOAT(18)
;
SET @R =
CASE @UnitOfMeasure
WHEN 'MILES' THEN 3956.55
WHEN 'KILOMETERS' THEN 6367.45
WHEN 'FEET' THEN 20890584
WHEN 'METERS' THEN 6367450
ELSE 6367.45 --km
END
SET @DLAT = RADIANS(@LAT2 - @LAT1);
SET @DLON = RADIANS(@LONG2 - @LONG1);
SET @A = SIN(@DLAT / 2)
* SIN(@DLAT / 2)
+ COS(RADIANS(@LAT1))
* COS(RADIANS(@LAT2))
* SIN(@DLON / 2)
* SIN(@DLON / 2);
SET @C = 2 * ASIN(MIN(SQRT(@A)));
SET @D = @R * @C;
RETURN @D;
END;
DECLARE
@pt1 geography,
@pt2 geography;
SET @pt1 = geography::Point(45.65100, -120.34900, 4326);
SET @pt2 = geography::Point(44.65100, -120.37654, 4326);
SELECT @pt1.STDistance(@pt2);
-return 值以米为单位,但您可以通过更改 SRID 指定 return。
-SRID 列表可在此处获得
Select * from sys.spatial_reference_systems
由于您指定需要 运行 对大型数据集执行此操作,因此我建议使用 table 值函数。如果您可以预先计算地理点,那就更好了,但这一切都是内联的。
create function dbo.fn_areWithinOneMile(@long1 float, @lat1 float, @long2 float, @lat2 float)
returns table
as
return
select cast(
case when
geography::Point(@lat1, @long1, 4236).STDistance(geography::Point(@lat2, @long2, 4236)) > 1609.34 then 0
else 1
end as bit) as [withinOneMile?]
go
with cte as (select * from (values
(42, 42),
(43, 43),
(44, 44)
) as x(lat, long)
), j as (
select long, lat, lag(long, 1) over (order by lat) as long2, lag(lat, 1) over (order by lat) as lat2
from cte
)
select *
from j
cross apply dbo.fn_areWithinOneMile(long, lat, long2, lat2) as o
where long2 is not null;
我正在尝试实施一种非常有效的检查,以查看两点之间是否在一英里以内。
我只关心它们是否在一英里之内——关于距离的其他事情对我来说都不重要。
由于关注范围狭窄,我不是寻找通用的“how far apart are these points”函数。
我目前的方法是计算 Haversine distance,然后检查它是否小于一英里。
在这种情况下效率很重要,因为我必须为大型记录集计算此 yes/no 标志。
那么,判断两个 lat/long 点是否在彼此一英里以内的最有效方法是什么?
我正在 T-SQL 中进行此检查,但这并不重要。 我当前的 haversine 计算如下。
CREATE FUNCTION dbo.USR_UFN_HAVERSINE_DISTANCE
(
@LAT1 FLOAT(18)
,@LONG1 FLOAT(18)
,@LAT2 FLOAT(18)
,@LONG2 FLOAT(18)
,@UnitOfMeasure NVARCHAR(10) = 'KILOMETERS'
)
RETURNS FLOAT(18)
AS
BEGIN
DECLARE
@R FLOAT(8)
,@DLAT FLOAT(18)
,@DLON FLOAT(18)
,@A FLOAT(18)
,@C FLOAT(18)
,@D FLOAT(18)
;
SET @R =
CASE @UnitOfMeasure
WHEN 'MILES' THEN 3956.55
WHEN 'KILOMETERS' THEN 6367.45
WHEN 'FEET' THEN 20890584
WHEN 'METERS' THEN 6367450
ELSE 6367.45 --km
END
SET @DLAT = RADIANS(@LAT2 - @LAT1);
SET @DLON = RADIANS(@LONG2 - @LONG1);
SET @A = SIN(@DLAT / 2)
* SIN(@DLAT / 2)
+ COS(RADIANS(@LAT1))
* COS(RADIANS(@LAT2))
* SIN(@DLON / 2)
* SIN(@DLON / 2);
SET @C = 2 * ASIN(MIN(SQRT(@A)));
SET @D = @R * @C;
RETURN @D;
END;
DECLARE
@pt1 geography,
@pt2 geography;
SET @pt1 = geography::Point(45.65100, -120.34900, 4326);
SET @pt2 = geography::Point(44.65100, -120.37654, 4326);
SELECT @pt1.STDistance(@pt2);
-return 值以米为单位,但您可以通过更改 SRID 指定 return。
-SRID 列表可在此处获得
Select * from sys.spatial_reference_systems
由于您指定需要 运行 对大型数据集执行此操作,因此我建议使用 table 值函数。如果您可以预先计算地理点,那就更好了,但这一切都是内联的。
create function dbo.fn_areWithinOneMile(@long1 float, @lat1 float, @long2 float, @lat2 float)
returns table
as
return
select cast(
case when
geography::Point(@lat1, @long1, 4236).STDistance(geography::Point(@lat2, @long2, 4236)) > 1609.34 then 0
else 1
end as bit) as [withinOneMile?]
go
with cte as (select * from (values
(42, 42),
(43, 43),
(44, 44)
) as x(lat, long)
), j as (
select long, lat, lag(long, 1) over (order by lat) as long2, lag(lat, 1) over (order by lat) as lat2
from cte
)
select *
from j
cross apply dbo.fn_areWithinOneMile(long, lat, long2, lat2) as o
where long2 is not null;