106 votes

Calculer la distance entre deux points (Latitude, Longitude)

J'essaie de calculer la distance entre deux positions sur une carte. J'ai stocké dans mes données : Longitude, Latitude, X POS, Y POS.

J'ai déjà utilisé le code ci-dessous.

DECLARE @orig_lat DECIMAL
DECLARE @orig_lng DECIMAL
SET @orig_lat=53.381538 set @orig_lng=-1.463526
SELECT *,
    3956 * 2 * ASIN(
          SQRT( POWER(SIN((@orig_lat - abs(dest.Latitude)) * pi()/180 / 2), 2) 
              + COS(@orig_lng * pi()/180 ) * COS(abs(dest.Latitude) * pi()/180)  
              * POWER(SIN((@orig_lng - dest.Longitude) * pi()/180 / 2), 2) )) 
          AS distance
--INTO #includeDistances
FROM #orig dest

Je ne fais cependant pas confiance aux données qui en découlent, elles semblent donner des résultats légèrement inexacts.

Quelques exemples de données au cas où vous en auriez besoin

Latitude        Longitude     Distance 
53.429108       -2.500953     85.2981833133896

Quelqu'un pourrait-il m'aider avec mon code ? Cela ne me dérange pas si vous voulez corriger ce que j'ai déjà, mais si vous avez une nouvelle façon de le faire, ce serait génial.

Veuillez indiquer dans quelle unité de mesure vos résultats sont exprimés.

142voto

AakashM Points 32891

Puisque vous utilisez SQL Server 2008, vous avez le geography disponible, qui est conçu exactement pour ce type de données :

DECLARE @source geography = 'POINT(0 51.5)'
DECLARE @target geography = 'POINT(-3 56)'

SELECT @source.STDistance(@target)

Donne

----------------------
538404.100197555

(1 row(s) affected)

Il nous dit qu'il y a environ 538 km entre (près de) Londres et (près de) Edimbourg.

Naturellement, il y aura d'abord un certain apprentissage à faire, mais une fois que vous le connaissez, c'est beaucoup plus facile que d'implémenter votre propre calcul de Haversine ; de plus, vous obtenez BEAUCOUP de fonctionnalités.


Si vous voulez conserver votre structure de données existante, vous pouvez toujours utiliser STDistance en construisant des geography en utilisant l'option Point méthode :

DECLARE @orig_lat DECIMAL(12, 9)
DECLARE @orig_lng DECIMAL(12, 9)
SET @orig_lat=53.381538 set @orig_lng=-1.463526

DECLARE @orig geography = geography::Point(@orig_lat, @orig_lng, 4326);

SELECT *,
    @orig.STDistance(geography::Point(dest.Latitude, dest.Longitude, 4326)) 
       AS distance
--INTO #includeDistances
FROM #orig dest

48voto

HDA Points 2590

La fonction ci-dessous donne distance entre deux géocoordonnées en miles

create function [dbo].[fnCalcDistanceMiles] (@Lat1 decimal(8,4), @Long1 decimal(8,4), @Lat2 decimal(8,4), @Long2 decimal(8,4))
returns decimal (8,4) as
begin
declare @d decimal(28,10)
-- Convert to radians
set @Lat1 = @Lat1 / 57.2958
set @Long1 = @Long1 / 57.2958
set @Lat2 = @Lat2 / 57.2958
set @Long2 = @Long2 / 57.2958
-- Calc distance
set @d = (Sin(@Lat1) * Sin(@Lat2)) + (Cos(@Lat1) * Cos(@Lat2) * Cos(@Long2 - @Long1))
-- Convert to miles
if @d <> 0
begin
set @d = 3958.75 * Atan(Sqrt(1 - power(@d, 2)) / @d);
end
return @d
end 

La fonction ci-dessous donne distance entre deux géocoordonnées en kilomètres

CREATE FUNCTION dbo.fnCalcDistanceKM(@lat1 FLOAT, @lat2 FLOAT, @lon1 FLOAT, @lon2 FLOAT)
RETURNS FLOAT 
AS
BEGIN

    RETURN ACOS(SIN(PI()*@lat1/180.0)*SIN(PI()*@lat2/180.0)+COS(PI()*@lat1/180.0)*COS(PI()*@lat2/180.0)*COS(PI()*@lon2/180.0-PI()*@lon1/180.0))*6371
END

La fonction ci-dessous donne distance entre deux géocoordonnées en kilomètres en utilisant Géographie type de données qui a été introduit dans sql server 2008

DECLARE @g geography;
DECLARE @h geography;
SET @g = geography::STGeomFromText('LINESTRING(-122.360 47.656, -122.343 47.656)', 4326);
SET @h = geography::STGeomFromText('POINT(-122.34900 47.65100)', 4326);
SELECT @g.STDistance(@h);

Utilisation :

select [dbo].[fnCalcDistanceKM](13.077085,80.262675,13.065701,80.258916)

Référence : Réf. 1 , Réf. 2

29voto

Stalinko Points 875

On dirait que Microsoft a envahi les cerveaux de tous les autres répondants et leur a fait écrire des solutions aussi compliquées que possible. Voici la solution la plus simple, sans fonctions ni déclarations supplémentaires :

SELECT geography::Point(LATITUDE_1, LONGITUDE_1, 4326).STDistance(geography::Point(LATITUDE_2, LONGITUDE_2, 4326))

Il suffit de remplacer vos données par LATITUDE_1 , LONGITUDE_1 , LATITUDE_2 , LONGITUDE_2 par exemple :

SELECT geography::Point(53.429108, -2.500953, 4326).STDistance(geography::Point(c.Latitude, c.Longitude, 4326))
from coordinates c

8voto

Fatih K. Points 328
Create Function [dbo].[DistanceKM] 
( 
      @Lat1 Float(18),  
      @Lat2 Float(18), 
      @Long1 Float(18), 
      @Long2 Float(18)
)
Returns Float(18)
AS
Begin
      Declare @R Float(8); 
      Declare @dLat Float(18); 
      Declare @dLon Float(18); 
      Declare @a Float(18); 
      Declare @c Float(18); 
      Declare @d Float(18);
      Set @R =  6367.45
            --Miles 3956.55  
            --Kilometers 6367.45 
            --Feet 20890584 
            --Meters 6367450 

      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
GO

Utilisation :

select dbo.DistanceKM(37.848832506474, 37.848732506474, 27.83935546875, 27.83905546875)

Sorties :

0,02849639

Vous pouvez modifier le paramètre @R avec des flottants commentés.

4voto

AdaTheDev Points 53358

Si vous utilisez SQL 2008 ou une version plus récente, je vous recommande de consulter la page GÉOGRAPHIE type de données. SQL a un support intégré pour les requêtes géospatiales.

Par exemple, vous auriez une colonne dans votre table de type GEOGRAPHY qui serait remplie avec une représentation géospatiale des coordonnées (consultez la référence MSDN liée ci-dessus pour des exemples). Ce type de données expose ensuite des méthodes vous permettant d'effectuer toute une série de requêtes géospatiales (par exemple, trouver la distance entre deux points).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X