Расчет расстояния PostGis

Я делаю приложение для навигации по внутренней карте прямо сейчас, и я пытаюсь создать базу данных точек карты в здании.

Все координаты, которые я использую, взяты из Google Map (что означает EPSG 3857). Теперь мне нужно найти расстояние в метрах, а также использовать D_Within в метрах.

Когда я пытаюсь извлечь расстояние между двумя точками:

SELECT ST_DISTANCE(
ST_GeomFromText('POINT(' || StartLon || ' ' || StartLat || ')',3857),
ST_GeomFromText('POINT(' || EndLon || ' ' || EndLat || ')',3857))
FROM i3_building.floordata;

Для первых 2 рядов с:

Start: 103.776047 1.292149; End: 103.77607 1.292212 (3 meters away)
Start: 103.776070 1.292212; End: 103.77554 1.292406 (50 meters away)

Полученный результат:

2.59422435413724e-005
4.11096095831604e-005

Хотя они и в радах, второй результат всего в два раза выше первого. Так что это меня смущает. Затем я пытаюсь вывести его в виде метров:

SELECT ST_DISTANCE(
    ST_GeographyFromText('POINT(' || StartLon || ' ' || StartLat || ')'),
    ST_GeographyFromText('POINT(' || EndLon || ' ' || EndLat || ')'))
FROM i3_building.floordata;

Результат для тех же строк:

2.872546829
4.572207435

Чего я тоже не ожидал. Я не очень хорошо знаком с PostGis и SRID, поэтому этот вопрос может показаться простым, но, пожалуйста, помогите мне, я застрял без @@


person Thomas Dang    schedule 08.07.2014    source источник


Ответы (2)


Ваша система отсчета координат (CRS) — 4326 широта/долгота. Это распространенный источник путаницы с Google Maps: 3857 — это CRS, используемая Google Maps для своих плиток, и это проецируемые метры на основе сферического земного шара. Векторные источники, которые добавляются в Google Maps (данные KML, дампы GPS и т. д.), как правило, имеют широту/долготу, 4326, что измеряется в градусах и преобразуется на лету.

Если вам нужно расстояние в метрах между двумя точками широты/долготы, используйте ST_Distance_Sphere. Например, для вашего первого набора баллов

SELECT ST_Distance_Sphere(ST_MakePoint(103.776047, 1.292149),ST_MakePoint(103.77607, 1.292212));

что дает 7,457 метра. Ваш второй набор точек находится на расстоянии 62,74 метра друг от друга на основе того же запроса.

Обратите внимание, что существует также ST_Distance_Spheroid, который принимает третий параметр, сфероид измерения , т. е. приближение к форме Земли. Это потенциально будет более точным, но, вероятно, несущественным на малых расстояниях.

ST_Distance дает расстояние в проекционных координатах, поэтому, вероятно, вы получили странные результаты, подставляя значения широты/долготы.

EDIT: Как отмечено в комментариях, начиная с Postgis 2.2, эта функция переименована в ST_DistanceSphere

person John Powell    schedule 08.07.2014
comment
Спасибо за ваш ответ. Я тоже попробовал 4326, но он не сильно отличается от 3857. Для расстояния первого комплекта он составляет 3 метра, так как он находится в моем офисе, поэтому я его хорошо знаю. Я также пытаюсь рассчитать это отсюда: boulter.com/gps/distance - тот же результат, 3 метров. - person Thomas Dang; 08.07.2014
comment
Что ты имеешь в виду под не сильно отличается? Я бы сказал, что 7,45 метра и 62,74 — это совсем разные. Однако проблема заключается в st_distance_sphere, так как он принимает ввод в широте/долготе, где st_distance принимает расстояние в проекционных координатах. 3857 и 4326 радикально отличаются, это метры и градусы соответственно, но вы должны подключить их к правильным функциям, чтобы получить правильные ответы :D - person John Powell; 08.07.2014
comment
Извините, просто пойдите и попробуйте измерить, около 7 метров вполне правильно. Спасибо за помощь :) - person Thomas Dang; 08.07.2014
comment
@ТомасДанг. Используйте st_distance_spheroid, если вы хотите быть действительно точным, но st_distance_sphere должен работать нормально для небольших расстояний. Я не знал, что Манила так близко к экватору. - person John Powell; 08.07.2014
comment
Имя функции «ST_Distance_Sphere» изменилось на «ST_DistanceSphere» (подчеркивание удалено) начиная с версии postgis 2.2.0. См.: postgis.net/docs/ST_DistanceSphere.html - person Abhishek Shah; 20.11.2020

Вот псевдокод

SELECT ST_Distance_Sphere(ST_MakePoint(lng1, lat1),ST_MakePoint(lng2, lat2));

Кроме того, для сферического расстояния новая функция ST_DistanceSphere использует следующее

SELECT ST_DistanceSphere(ST_MakePoint(lng1,lat1),ST_MakePoint(lng2,lat2)) 
person Amir Md Amiruzzaman    schedule 02.02.2021