Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / STDistance (geography Data Type мать её) / 4 сообщений из 4, страница 1 из 1
12.10.2016, 00:52
    #39324929
Bryk_Alien
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
STDistance (geography Data Type мать её)
Цель - определить расстояние по географическим координатам
Берём пример из MSDN , чуть меняем его:
Код: sql
1.
2.
3.
4.
5.
6.
7.
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 AddressGeoDist110913.39893372463778
Яндекс карты, мат. формулы, глобус и здравый смысл подсказывают, что длина параллели на широте 55 град = 63995 метров
Так какого хрена STDistance выдаёт чёрт знает что?!
:(
первый час ночи...
fnAddressGeoDist
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
/*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

...
Рейтинг: 0 / 0
12.10.2016, 00:55
    #39324931
Bryk_Alien
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
STDistance (geography Data Type мать её)
Всё бл.!!
Пол часа писал, нажал "отправить" и осенило!
Надо поменять координаты широты и долготы местами
ска
...
Рейтинг: 0 / 0
12.10.2016, 11:08
    #39325116
iap
iap
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
STDistance (geography Data Type мать её)
Bryk_AlienВсё бл.!!
Пол часа писал, нажал "отправить" и осенило!
Надо поменять координаты широты и долготы местами
скаНадо ещё учесть, что Земля не шар.
MSSQL использует модель в виде эллипсоида вращения.

Это я на вычисления в спойлере посмотрел.
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
24.12.2018, 21:06
    #39752507
Cat2
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
STDistance (geography Data Type мать её)
iapBryk_AlienВсё бл.!!
Пол часа писал, нажал "отправить" и осенило!
Надо поменять координаты широты и долготы местами
скаНадо ещё учесть, что Земля не шар.
MSSQL использует модель в виде эллипсоида вращения.

Это я на вычисления в спойлере посмотрел.

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

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
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 long11855,32484559809 0 0 0 1

Distance Lat0 Long0 Lat1 long11314,10557844484 45 0 45 1
Несколько часов бился, пока понял в чем причина

Может поможет кому, а то в интернетах самые фантастические предположения, что надо SRID другой использовать или то, что результат выдается в градусах
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / STDistance (geography Data Type мать её) / 4 сообщений из 4, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]