programing

두 점 사이의 거리 계산(위도, 경도)

batch 2023. 4. 16. 14:47
반응형

두 점 사이의 거리 계산(위도, 경도)

지도상의 두 위치 사이의 거리를 계산하려고 합니다.데이터: 경도, 위도, X POS, Y POS에 저장했습니다.

저는 이전에 아래의 스니펫을 사용하고 있었습니다.

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

하지만 여기서 나오는 데이터는 믿을 수 없습니다만, 결과가 약간 부정확한 것 같습니다.

필요한 경우 샘플 데이터

Latitude        Longitude     Distance 
53.429108       -2.500953     85.2981833133896

누가 내 코드를 좀 도와줄 수 있나요? 만약 당신이 이것을 할 수 있는 새로운 방법이 있다면 제가 가지고 있는 것을 고치고 싶어도 상관없습니다.

결과가 어떤 측정 단위에 속하는지 명시해 주십시오.

SQL Server 2008을 사용하고 있기 때문에 다음과 같은 종류의 데이터를 위해 설계된 데이터 유형을 사용할 수 있는 데이터 유형은 다음과 같습니다.

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

SELECT @source.STDistance(@target)

주다

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

(1 row(s) affected)

런던에서 에딘버러까지는 약 538km라고 말해 준다.

물론, 우선은 많은 것을 배울 수 있지만, 일단 이것이 자신의 Haversine 계산을 구현하는 것보다 훨씬 쉽다는 것을 알게 되면, 많은 기능을 얻을 수 있습니다.


기존 데이터 구조를 유지하려면STDistance적절한 구성을 통해geography다음 메서드를 사용하는 인스턴스:

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

아래 함수는 두 위치 사이의 거리(마일)를 제공합니다.

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 

아래 함수는 두 측지 좌표 사이의 거리(km)를 제공합니다.

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

아래 함수는 sql server 2008에서 도입된 지리 데이터 유형을 사용하여 2개의 지리 좌표 사이의 거리(km)를 나타냅니다.

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

사용방법:

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

레퍼런스: Ref1, Ref2

마이크로소프트는 다른 모든 응답자들의 뇌를 침범하여 가능한 한 복잡한 해결책을 쓰게 한 것으로 보인다.다음은 추가 함수/선언문을 사용하지 않는 가장 간단한 방법입니다.

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

단순히 데이터를 대체하여LATITUDE_1,LONGITUDE_1,LATITUDE_2,LONGITUDE_2예:

SELECT geography::Point(53.429108, -2.500953, 4326).STDistance(geography::Point(c.Latitude, c.Longitude, 4326))
from coordinates c
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

사용방법:

dbo를 선택합니다.DistanceKM(37.84883250647, 37.84873250647, 27.83935546875, 27.83905546875)

출력:

0,02849639

주석이 달린 플로트를 사용하여 @R 파라미터를 변경할 수 있습니다.

SQL 2008 이후를 사용하는 경우 지리 데이터 유형을 확인하는 것이 좋습니다.SQL은 지리 공간 쿼리를 기본적으로 지원합니다.

예를 들어, GIGRATION 유형의 테이블에 좌표의 지리 공간적 표현으로 채워지는 열이 있을 것입니다(위에 링크된 MSDN 참조 참조 참조 참조).그런 다음 이 데이터 유형은 지리 공간 쿼리 전체 호스트(예: 두 점 사이의 거리 찾기)를 수행할 수 있는 방법을 제공합니다.

위의 답변과 더불어 SELECT 내부의 거리를 계산하는 방법이 있습니다.

CREATE FUNCTION Get_Distance
(   
    @La1 float , @Lo1 float , @La2 float, @Lo2 float
)
RETURNS TABLE 
AS
RETURN 
    -- Distance in Meters
    SELECT GEOGRAPHY::Point(@La1, @Lo1, 4326).STDistance(GEOGRAPHY::Point(@La2, @Lo2, 4326))
    AS Distance
GO

사용방법:

select Distance
from Place P1,
     Place P2,
outer apply dbo.Get_Distance(P1.latitude, P1.longitude, P2.latitude, P2.longitude)

스칼라 함수도 작동하지만 대량의 데이터를 계산할 때 매우 비효율적입니다.

이게 도움이 됐으면 좋겠어요.

언급URL : https://stackoverflow.com/questions/13026675/calculating-distance-between-two-points-latitude-longitude

반응형