2013-02-06 40 views
1

有沒有一種方法可以在SQL Server 2008 R2中瞭解另一點的南端,東端等?確定點之間的基數(指南針)方向

例如,我有一個起源point(lat1,lng1),我想知道在哪裏point(lat2,lng2)是從原點位於:北部,西部等..

我試圖構建一個風玫瑰圖,這可能對我有用。

+0

如果第二點的經度比第一點時,第二點是更北,否則南如果第二點的經度低於第一點。 如果第二點的格點大於第一個點,則第二個點爲更多東部,否則爲西部(如果第二個點的格點小於第一個點)。 – elvis

回答

3

爲了計算兩個座標之間的軸承,同時使用SQL Server 2008 R2的地理類型,您可以使用此功能:

CREATE FUNCTION [dbo].[CalculateBearing] 
(
    @pointA as geography 
    ,@pointB as geography 
) 

RETURNS decimal(18,12) 

AS 

    BEGIN 

    -- Declare the return variable 
    DECLARE @bearing decimal(18,12) 

    -- Declare the local variables 
    DECLARE @x decimal(18,12) 
    DECLARE @y decimal(18,12) 
    DECLARE @dLat decimal(18,12) 
    DECLARE @dLong decimal(18,12) 
    DECLARE @rLat1 decimal(18,12) 
    DECLARE @rLat2 decimal(18,12) 

    IF(@pointA.STIsEmpty() = 1 OR @pointB.STIsEmpty() = 1) 
     set @bearing = null 
    ELSE 
     BEGIN 

     -- Calculate delta between coordinates 
     SET @dLat = RADIANS(@pointB.Lat - @pointA.Lat) 
     SET @dLong = RADIANS(@pointB.Long - @pointA.Long) 

     -- Calculate latitude as radians 
     SET @rLat1 = RADIANS(@pointA.Lat) 
     SET @rLat2 = RADIANS(@pointB.Lat) 

     SET @y = SIN(@dLong)*COS(@rLat2) 
     SET @x = COS(@rLat1)*SIN(@rLat2)-SIN(@rLat1)*COS(@rlat2)*COS(@dLong) 

     IF (@x = 0 and @y = 0) 
      SET @bearing = null 
     ELSE 
      BEGIN 
       SET @bearing = CAST((DEGREES(ATN2(@y,@x)) + 360) as decimal(18,12)) % 360 
      END 
    END 

    -- Return the result of the function 
    RETURN @bearing 

END 

GO 

並在此之後,你可以使用這個功能是這樣的:

DECLARE @pointA as geography 
DECLARE @pointB as geography 

SET @pointA = geography::STGeomFromText('POINT(3 45)', 4326) 
SET @pointB = geography::STGeomFromText('POINT(4 47)', 4326) 

SELECT [dbo].[CalculateBearing](@pointA, @pointB) 

UPDATE:將架構

Bearing explanation

+0

嗨,謝謝你的回答,但我不得不說,我不知道如何閱讀..或理解結果,對於這些座標函數返回數字18.795229754601,這是什麼意思?,謝謝。 – user1848515

+0

它給了北方的方向。因此,它是由北點A - 點B(NAB)描述的角度,所以如果使用模90,則可以確定點B位於點A的北,東,南或西側。 –

2

我想出了一種使用相當直接的標準SQL函數來計算方位的方法。 ATAN功能完成大部分實際工作;兩個CASE語句只是特殊情況下的更正。 1是來源,2是目的地。

atan(([Longitude2]-[Longitude1])/(10e-10+[Latitude2]-[Latitude1]))*360/pi()/2 
+case when [Latitude2]<[Latitude1] then 180 else 0 end 
+case when [Longitude2]<[Longitude1] and [Latitude2]>[Latitude1] then 360 else 0 end 
+0

比其他解決方案要容易得多。很棒。謝謝。 – user3308241

+1

只是一個提示。在某些情況下,這個數字是正確的,但是是負數。我將abs()函數添加到查詢中,每次結果似乎都是正確的。 – user3308241

2

今天早上我需要這個功能來爲用戶在我們的系統中搜索附近的訂單時提供範圍和基本方向。我在這裏找到了尼古拉斯的回答,它讓我走了大部分路。我創建了第二個函數,它使用Nicolas's爲我的UI創建了一個縮寫的主要方向(N,NE,E等)。

使用從https://en.wikipedia.org/wiki/Points_of_the_compass此處提供結合值尼古拉斯的方位計算,以確定每個主方向範圍,

CREATE FUNCTION [dbo].[CalculateCardinalDirection] 
(
    @pointA as geography 
    ,@pointB as geography 
) 

RETURNS varchar(2) 

AS 
BEGIN 
    DECLARE @bearing decimal(18,12) 
    -- Bearing calculation provided by http://stackoverflow.com/a/14781032/4142441 
    SELECT @bearing = dbo.CalculateBearing(@pointA, @pointB) 

    RETURN CASE WHEN @bearing BETWEEN 0 AND 22.5 THEN 'N' 
       WHEN @bearing BETWEEN 22.5 AND 67.5 THEN 'NE' 
       WHEN @bearing BETWEEN 67.5 AND 112.5 THEN 'E' 
       WHEN @bearing BETWEEN 112.5 AND 157.5 THEN 'SE' 
       WHEN @bearing BETWEEN 157.5 AND 202.5 THEN 'S' 
       WHEN @bearing BETWEEN 202.5 AND 247.5 THEN 'SW' 
       WHEN @bearing BETWEEN 247.5 AND 292.5 THEN 'W' 
       WHEN @bearing BETWEEN 292.5 AND 337.5 THEN 'NW' 
       ELSE 'N' -- Catches NULL bearings and the 337.5 to 360.0 range 
      END 
END 
GO 
+0

不錯,這很有用!我將更新我的代碼以在一個項目中添加一列。謝謝 –