如何获得以米为单位的距离

Posted

技术标签:

【中文标题】如何获得以米为单位的距离【英文标题】:how to get distance in meter 【发布时间】:2017-02-01 07:09:01 【问题描述】:

我有下面的存储程序我想检查我的汽车纬度经度的距离,如果距离以米为单位小于 500,则最近的地理围栏显示地理围栏 id 哪个地理围栏 id 最近的汽车纬度经度。如果汽车纬度经度最近的多边形显示多边形 ID,如果矩形显示矩形 id 我是 sql server 的新手,所以我在这里请专业人士帮助我,我非常感谢你,演示表在共享链接中,

question and demo table is here

CREATE TABLE CarDistance 
(
ID int IDENTITY(1,1) PRIMARY KEY,
car_id int,
latitude float,
longitude float

)
insert into CarDistance values(1234, '52.582191','-2.878418')

CREATE TABLE tblgeofencing2  
(
ID int IDENTITY(1,1) PRIMARY KEY,
car_id int,
ShapeType  varchar(255),
PolygonLatLng  varchar(max),
minlatitude [float] NULL,
    [minlongitude] [float] NULL,
    [maxlatitude] [float] NULL,
    [maxlongitude] [float] NULL,
)

insert into tblgeofencing2 values(123, 'polygon','24.835300590037598 67.06858277320862,24.835933468801272 67.06929624080658,24.83532979989791 67.07035303115845,24.83454113125045 67.0697683095932,24.835300590037598 67.06858277320862',NULL,NULL,NULL,NULL)
insert into tblgeofencing2 values(1234, 'rectangle','NULL','52.582191','-2.878418','52.233687','-2.702637')

Alter PROCEDURE [dbo].[Sp_CheckCarStatusMeter]  
 DECLARE @g GEOGRAPHY, 
         @ID INT,
     @curVal     INT, 
         @preVal     INT ,  
     @CarSuggested INT,  
     @carlatprevious VARCHAR(10), 
         @carlongprevious VARCHAR(10), 
    @AllLatitudeLongitude VARCHAR(255),     
         @pprevious GEOGRAPHY

 DECLARE SuggestCursor CURSOR  FOR
       SELECT TOP 100 rtha.car_id , rtha.latitude,  
           rtha.longitude 
     FROM   CarDistance rtha WHERE rtha.car_id = 123;
     OPEN SuggestCursor;  
     FETCH NEXT FROM SuggestCursor INTO @CarSuggestedID , @carlatprevious , @carlongprevious; 

     WHILE (@@FETCH_STATUS = 0)    
 BEGIN       

     DECLARE ShapeCursor CURSOR FOR  
  SELECT g.ID, @CarSuggestedID,  g.ShapeType  FROM   tblgeofencing AS g
         WHERE  car_id =@CarSuggestedID 
  FETCH NEXT FROM ShapeCursor INTO @ID , @CarIdx , @ShapeType; 

     WHILE (@@FETCH_STATUS = 0)
     BEGIN 
     IF (@ShapeType = 'polygon')
         BEGIN --Polygon IF 
             PRINT 'polygon if'; 
             SELECT @GeofenceIDnew = g.GeoFenceId,  @minY = g.PolygonLatLng ROM   tblgeofencing AS g
             WHERE  g.ID = =@CarSuggestedID 
             SET @g = geography ::STPolyFromText('POLYGON((' + @AllLatitudeLongitude + '))', 4326);           
             SET @pprevious = geography ::STPointFromText(
                     'POINT(' + @carlatprevious + ' ' + @carlongprevious +  ')',  4326   ); 
             SELECT @preVal = @g.STIntersects(@pprevious) 
             PRINT @preVal  
             IF @curVal = 1 AND @preVal = 0 
             BEGIN  
                PRINT 'Enter In GEOFENCE';  
                 SELECT @geofencename = geofenceName, 
                        @geofenceidforresult = ID  
                 FROM   tblgeofencing where ID = @CarSuggestedID;
                 INSERT INTO tblGeofenceCarStatus  
                 VALUES 
                   ( 
                     @CarSuggestedID,  @geofenceidforresult,@geofencename,  
                     @gpstime, @g.STDistance(@pprevious), 'Enter' ); 

             END  
        ELSE
BEGIN
Print Not in Geofence
END

         END; --- END POLYGON IF 
   FETCH NEXT FROM ShapeCursor INTO @ID , @CarIdx , @ShapeType;  



     END; --- END CHECK GEOFENCING RECTANGLE OR CIRCLE OR PLYGON 


      FETCH NEXT FROM SuggestCursor INTO @CarSuggestedID , @carlatprevious , @carlongprevious;  



       END;
     CLOSE ShapeCursor;  
      DEALLOCATE ShapeCursor;  
        CLOSE SuggestCursor;
       DEALLOCATE SuggestCursor; 
     SELECT * FROM   tblGeofenceCarStatus;    

 END;  

END; --- END SP BEGIN  STATEMENT

【问题讨论】:

【参考方案1】:

以下解决方案将:

确定每辆车的最近位置 识别每辆车的先前位置 根据多边形字符串或矩形坐标构建地理围栏多边形 识别当前位于地理围栏 500 米范围内(从外部)或位于地理围栏内的汽车 显示与之前位置的地理围栏的距离
;
WITH car_location_seq AS (
        SELECT   car_id
                ,ID
                ,latitude
                ,longitude
                ,ROW_NUMBER() OVER (PARTITION BY car_id ORDER BY ID DESC) AS Pos_Sequence
        FROM #CarDistance
),
car_location AS (
        SELECT   c1.car_id
                ,geography::Point(c1.longitude, c1.latitude,  4326) AS Geo_Point_Current
                ,CASE WHEN c2.car_id IS NOT NULL THEN geography::Point(c2.longitude, c2.latitude,  4326) END AS Geo_Point_Previous
        FROM car_location_seq c1 -- Most recent position
            LEFT JOIN car_location_seq c2 -- Previous position
                ON c1.car_id = c2.car_id
                AND c2.Pos_Sequence = 2
        WHERE c1.Pos_Sequence = 1
),
fences AS (
        SELECT   ID
                ,Car_ID
                ,CASE   WHEN ShapeType = 'polygon' THEN geography::STPolyFromText('POLYGON((' + PolygonLatLng + '))', 4326)
                        WHEN ShapeType = 'rectangle' THEN geography::STPolyFromText('POLYGON((' + 
                                CAST(maxlatitude AS VARCHAR(100)) + ' ' + CAST(minlongitude AS VARCHAR(100)) + ', ' + 
                                CAST(minlatitude AS VARCHAR(100)) + ' ' + CAST(minlongitude AS VARCHAR(100)) + ', ' + 
                                CAST(minlatitude AS VARCHAR(100)) + ' ' + CAST(maxlongitude AS VARCHAR(100)) + ', ' + 
                                CAST(maxlatitude AS VARCHAR(100)) + ' ' + CAST(maxlongitude AS VARCHAR(100)) + ', ' + 
                                CAST(maxlatitude AS VARCHAR(100)) + ' ' + CAST(minlongitude AS VARCHAR(100)) + 
                                '))', 4326)
                END AS Geo_Polygon
        FROM #tblgeofencing2
)

SELECT   f.ID AS Fence_ID
        ,c.car_id
        ,c.Geo_Point_Current
        --,c.Geo_Point_Current.STAsText()
        ,f.Geo_Polygon
        --,f.Geo_Polygon.STAsText()
        ,f.Geo_Polygon.STIntersects(c.Geo_Point_Current) AS Is_Inside_Fence_Current
        ,f.Geo_Polygon.STIntersects(c.Geo_Point_Previous) AS Is_Inside_Fence_Previous
        ,f.Geo_Polygon.STDistance(c.Geo_Point_Current) AS Distance_Current
        ,f.Geo_Polygon.STDistance(c.Geo_Point_Previous) AS Distance_Previous
--INTO #Relevant_Car_Positions
FROM fences f
    INNER JOIN car_location c
        ON f.car_id = c.car_id

WHERE f.Geo_Polygon.STDistance(c.Geo_Point_Current) < 500
;

样本输出:

您应该能够调整此代码以满足您的需要。例如,您可以首先通过取消注释INTO #Relevant_Car_Positions 将查询输出存储到临时表中。

【讨论】:

以上是关于如何获得以米为单位的距离的主要内容,如果未能解决你的问题,请参考以下文章

原始线要素类为地理坐标系,如何获取以米为单位的距离?

在MYSQL中用2个坐标以米为单位计算地球距离的最佳方法是啥?

如何在 iOS 应用程序中每 1/2 秒获取步行距离(以米为单位)和方向?

Postgis 中 2 点之间的距离,单位为 srid 4326,以米为单位

用给定的坐标和以米为单位的距离计算新坐标

golang Golang用于计算地球上长纬度点之间的距离(以米为单位)。