ST_DWithin принимает параметр как степень, а не метры, почему?

В документе ST_DWithin третий параметр (расстояние) находится в метрах. Но когда я выполняю какой-либо запрос, кажется, что он принимает третий параметр как "степень"?

Вот моя упрощенная структура таблицы:

> \d+ theuser;
                         Table "public.theuser"
  Column  |          Type          | Modifiers | Storage  | Description 
----------+------------------------+-----------+----------+-------------
 id       | bigint                 | not null  | plain    | 
 point    | geometry               |           | main     | 
Indexes:
    "theuser_pkey" PRIMARY KEY, btree (id)
    "point_index" gist (point)
Referenced by:
    ...
Has OIDs: no

Все точки хранятся вместе с SRID = 4326.

И это запрос:

> select * from theuser where ST_DWithin(point , ST_GeomFromText('POINT(120.9982 24.788)',4326) , 100 );

Он принимает третий параметр (100) как "степень", поэтому он возвращает все данные, я должен сузить до 0,001, чтобы найти близлежащие точки.

Но как я могу напрямую передавать счетчики в качестве третьего параметра (я не хочу делать преобразование метра/градуса)? Что случилось с моим запросом? почему postgreSQL не воспринимает это как метры, как говорит документ?

Среды:

> select version();
                                                  version                                                  
-----------------------------------------------------------------------------------------------------------
 PostgreSQL 8.4.9 on i486-pc-linux-gnu, compiled by GCC gcc-4.4.real (Ubuntu 4.4.3-4ubuntu5) 4.4.3, 32-bit

> SELECT postgis_lib_version();
 postgis_lib_version 
---------------------
 1.4.0

Если это проблема с SRID, то какой SRID непосредственно использует "метр" в качестве единицы? (Я попытался преобразовать в SRID = 2163, но все еще в степени) Спасибо.

Ответы

Ответ 1

Из docs:

Для геометрий: расстояние указано в единицах, определенных пространственная система координат геометрии.

Если ваши данные находятся в SRID = 4326, заданное расстояние находится в градусах.

Вам либо нужно использовать ST_Transform, либо систему координат на основе счетчика, либо одну из двух функций: ST_Distance_Sphere (быстрее, менее точный) или ST_Distance_Spheroid.

Ответ 2

Если и только если ваша геометрия находится в WGS84, то есть srid 4326, вы можете отбросить геометрии к географии

select * from theuser where ST_DWithin(point::geography , ST_GeomFromText('POINT(120.9982 24.788)',4326)::geography , 100 )

Ответ 3

Я бы не рекомендовал вам преобразовываться в счетчики каждый раз, когда вы хотите использовать DWithin, кстати, если вам нужны метры, вам нужна проекция с равной площадью, например Albers (их много), почему бы вам не попробовать ST_Buffer (точка, градусы) и посмотреть, что он делает на земле Google, принять меры и найти нужный вам номер, обычно вам нужны предопределенные диапазоны, что-то вроде очень близко = 0,00008, около = 0,0005, далеко = 0,001, действительно далеко = 0,01, действительно очень далеко = 0,1 и т.д. (все в градусах).

В предыдущем вопросе вы просили максимально быстрый путь, вы находитесь в правильном направлении.

Ответ 4

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

select * from theuser where ST_DWithin(point , ST_GeomFromText('POINT(120.9982 24.788)',4326) , 0.1/111.325 );

Здесь 0,1 = 100 метров.

Ответ 5

Моя реализация преобразования метров в градусы.

DROP FUNCTION IF EXISTS meters_to_decimal_degrees(double precision);

CREATE FUNCTION meters_to_decimal_degrees(meters double precision)
RETURNS double precision AS
$BODY$
SELECT (($1 * 180.0) / pi()) / 6378137.0
$BODY$
LANGUAGE sql IMMUTABLE SECURITY DEFINER;

Использование:

ST_DWithin(same.geometry, place.geometry, meters_to_decimal_degrees(20000))