2016-03-25 2 views
0

Ich versuche, eine sehr effiziente Überprüfung zu implementieren, um zu sehen, ob zwei Punkte innerhalb einer Meile voneinander entfernt sind.Bei zwei Lat/Longs, wie kann ich feststellen, ob sie innerhalb von 1 Meile voneinander sind?

ich nur Pflege, ob sie innerhalb einer Meile sind - sonst nichts über die Entfernung ist mir wichtig.

Wegen dieser engen Fokus bin ich nicht auf der Suche nach einem allgemeinen Zweck "how far apart are these points" -Funktion.

Mein aktueller Ansatz ist es, die Haversine distance, zu berechnen und dann überprüfen, um zu sehen, ob es weniger ist als eine Meile.

Effizienz ist in diesem Fall wichtig, weil ich diese Ja/Nein-Flag für große Datensätze berechnen muss.

Also, was ist der effizienteste Weg, zu sagen, ob zwei lat/long Punkte innerhalb einer Meile voneinander?

Ich mache diese Überprüfung in T-SQL, nicht, dass es viel ausmacht. Meine aktuelle hairsine Berechnung ist unten.

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; 
+0

Mögliche Duplikat [schnellste Weg, Abstand zu finden zwischen zwei Breite/Länge Points] (http://stackoverflow.com/questions/1006654/fastest-way-to-find-distance-between-two-lat -Punkte) –

+0

@ KenY-N Danke, dass du mich da gezeigt hast. Ich habe bereits eine allgemeine Funktion, um die Entfernung zwischen zwei Punkten zu erhalten. Da es mir in diesem Fall nur wichtig ist, ob die Entfernung innerhalb einer Meile liegt oder nicht, hoffe ich, dass es einen schnelleren Weg gibt, ohne die gesamte Entfernung berechnen zu müssen. Ich habe die Frage bearbeitet, um diese Unterscheidung zu verdeutlichen. – JosephStyons

+0

Überprüfen Sie die zweite Antwort zu dieser verknüpften Frage? Es scheint so zu sein, dass du auf das kommst, was du willst ... –

Antwort

1

Da Sie angeben, dass Sie diese über große Datenmengen ausgeführt werden müssen, würde ich eine Tabellenwertfunktion vor. Besser, wenn Sie die Geographie-Punkte vorberechnen können, aber das macht alles inline.

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; 
1
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); 

-Der Rückgabewert in Metern, obwohl Sie die Rückgabe auch durch Änderung der SRID angeben.

-Die Liste der SRID die sind hier verfügbar

Select * from sys.spatial_reference_systems 
Verwandte Themen