Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 STDistance (geography Data Type мать её)  [new]
Bryk_Alien
Guest
Цель - определить расстояние по географическим координатам
Берём пример из MSDN, чуть меняем его:
DECLARE @g geography;  
DECLARE @h geography;  
SET @g = geography::STGeomFromText('POINT(55.000000 33.000000)', 4326);  
SET @h = geography::STGeomFromText('POINT(55.000000 34.000000)', 4326);  
SELECT @g.STDistance(@h) AS STDistance;  
-- Моя рукописная функция, см. спойлер
SELECT [dbo].[fnAddressGeoDist](55.000000, 33.000000, 55.000000, 34.000000) AS AddressGeoDist

Получаем:
STDistance AddressGeoDist
110913.39893372463778

Яндекс карты, мат. формулы, глобус и здравый смысл подсказывают, что длина параллели на широте 55 град = 63995 метров
Так какого хрена STDistance выдаёт чёрт знает что?!
:(
первый час ночи...
+ fnAddressGeoDist
/*ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
	Функция определяет расстояние между точками 1 и 2 по их координатам.
	X - Широта, Y - Долгота, 6371000 - радиус земли в метрах
	31.03.2015
*/
ALTER FUNCTION [dbo].[fnAddressGeoDist] ( @Pos1X DECIMAL(9,6), 
					  @Pos1Y DECIMAL(9,6), 
					  @Pos2X DECIMAL(9,6), 
					  @Pos2Y DECIMAL(9,6)
) RETURNS int
AS
BEGIN
	DECLARE @Dist int
/*
	cos(d) = sin(φА)·sin(φB) + cos(φА)·cos(φB)·cos(λА − λB),
		где φА и φB — широты, λА, λB — долготы данных пунктов, d — расстояние между пунктами, измеряемое в радианах длиной дуги большого круга земного шара. 
	Расстояние между пунктами, измеряемое в километрах, определяется по формуле:
		L = d·R, где R = 6371 км — средний радиус земного шара.
*/
	SET @Dist = 6371000 * 2 * ASIN(SQRT(
      POWER(SIN((@Pos1X - ABS(@Pos2X)) * PI()/180 / 2), 2) +
      COS(@Pos1X * PI()/180) *
      COS(ABS(@Pos2X) * PI()/180) *
      POWER(SIN((@Pos1Y - @Pos2Y) * PI()/180 / 2), 2)
    ))
	RETURN @Dist
END
12 окт 16, 00:52    [19771526]     Ответить | Цитировать Сообщить модератору
 Re: STDistance (geography Data Type мать её)  [new]
Bryk_Alien
Guest
Всё бл.!!
Пол часа писал, нажал "отправить" и осенило!
Надо поменять координаты широты и долготы местами
ска
12 окт 16, 00:55    [19771530]     Ответить | Цитировать Сообщить модератору
 Re: STDistance (geography Data Type мать её)  [new]
iap
Member

Откуда: Москва
Сообщений: 46977
Bryk_Alien
Всё бл.!!
Пол часа писал, нажал "отправить" и осенило!
Надо поменять координаты широты и долготы местами
ска
Надо ещё учесть, что Земля не шар.
MSSQL использует модель в виде эллипсоида вращения.

Это я на вычисления в спойлере посмотрел.
12 окт 16, 11:08    [19772337]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: STDistance (geography Data Type мать её)  [new]
Cat2
Member

Откуда: Petroskoi, Karjala
Сообщений: 145699
iap
Bryk_Alien
Всё бл.!!
Пол часа писал, нажал "отправить" и осенило!
Надо поменять координаты широты и долготы местами
ска
Надо ещё учесть, что Земля не шар.
MSSQL использует модель в виде эллипсоида вращения.

Это я на вычисления в спойлере посмотрел. Картинка с другого сайта.

Не надо ничего учитывать, можно пользоваться STDistance. Все уже там учтено, кроме того, что Микрософт опять пошла своим путем. Если во всем мире принято, что геокоординаты задаются в формате Широта-Долгота, то она использует Долгота-Широта.

declare @SRID int = 4326 -- идентификатор пространственной ссылки, который определяет в том числе среднюю  длину меридиана
--Точки на экваторе
DECLARE @g0 geography = geography::STPointFromText('POINT(0 0)', @SRID) -- Долгота - Гринвич, градус = 0, широта - экватор (0)
DECLARE @h0 geography = geography::STPointFromText('POINT(1 0)', @SRID) -- Долгота - Гринвич, градус = 1, широта - экватор (0)
SELECT @h0.STDistance(@g0) / 60,  @g0.Lat as Lat0, @g0.Long as Long0, @h0.Lat as Lat1, @h0.Long as long1
--Точки на 45 широте
DECLARE @g45 geography  = geography::STPointFromText('POINT(0 45)', @SRID) -- Долгота - Гринвич, градус = 0, широта - 45-ая
DECLARE @h45 geography = geography::STPointFromText('POINT(1 45)', @SRID)  -- Долгота - Гринвич, градус = 1, широта - 45-ая
SELECT  @h45.STDistance(@g45) /60 as Distance, @g45.Lat as Lat0, @g45.Long as Long0, @h45.Lat as Lat1, @h45.Long as long1

Первый select, как и положено, дает морскую милю, которая примерно равна одной градусной минуте меридиана и экватора. Второй, как и положено - меньше

Distance Lat0 Long0 Lat1 long1
1855,32484559809 0 0 0 1


Distance Lat0 Long0 Lat1 long1
1314,10557844484 45 0 45 1

Несколько часов бился, пока понял в чем причина Картинка с другого сайта.
Может поможет кому, а то в интернетах самые фантастические предположения, что надо SRID другой использовать или то, что результат выдается в градусах
24 дек 18, 21:06    [21772477]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить