Расчет расстояния между двумя точками (Широта, Долгота)
Я пытаюсь рассчитать расстояние между двумя позициями на карте.
Я сохранил в своих данных: долготу, широту, 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
Может кто-нибудь помочь мне с моим кодом, я не возражаю, если вы хотите исправить то, что у меня уже есть, если у вас есть новый способ достижения этого, это будет здорово.
Укажите, в какой единице измерения ваши результаты.
Ответы
Ответ 1
Поскольку вы используете SQL Server 2008, у вас есть тип данных geography
, который предназначен именно для такого рода данных:
DECLARE @source geography = 'POINT(0 51.5)'
DECLARE @target geography = 'POINT(-3 56)'
SELECT @source.STDistance(@target)
дает
----------------------
538404.100197555
(1 row(s) affected)
Расскажите нам, что это примерно 538 км от (рядом) Лондона до (рядом) Эдинбурга.
Естественно, что сначала будет учиться, но как только вы это знаете, это намного проще, чем реализация собственного расчета Haversine; плюс вы получаете много функциональности.
Если вы хотите сохранить существующую структуру данных, вы все равно можете использовать STDistance
, построив подходящие экземпляры geography
, используя метод Point
:
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
Ответ 2
Функция ниже дает расстояние между двумя геокоординатами в милях
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
Эта функция дает расстояние между двумя геокоординатами в километрах
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
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
Ответ 3
Поскольку вы используете SQL 2008 или новее, я бы рекомендовал проверить тип данных GEOGRAPHY. SQL построил поддержку геопространственных запросов.
например. у вас будет столбец в вашей таблице типа GEOGRAPHY, который будет заполнен геопространственным представлением координат (посмотрите примеры ссылок MSDN, приведенные выше для примеров). Затем этот тип данных предоставляет методы, позволяющие выполнять целый комплекс геопространственных запросов (например, нахождение расстояния между двумя точками)
Ответ 4
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.848832506474, 37.848732506474, 27.83935546875, 27.83905546875)
Выходы:
0,02849639
Вы можете изменить параметр @R с комментариями float.