如何获得以米为单位的距离
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 秒获取步行距离(以米为单位)和方向?