ST_DWithin takes parameter as degree , not meters , why?

smallufo picture smallufo · Dec 9, 2011 · Viewed 12.2k times · Source

The ST_DWithin document says , the third parameter(distance) is in meters. But when I execute some query , it seems it takes the 3rd parameter as 'degree' ?

Here is my simplified table structure :

> \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

All points are stored with SRID=4326.

And this is the query :

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

It takes the 3rd parameter (100) as 'degree' , so it returns all data , I have to narrow down to 0.001 to find nearby points.

But how do I directly pass meters as 3rd parameter (I don't want to do meter/degree transformation ) ? What's wrong with my query ? why postgreSQL doesn't take it as meters as document says ?

Environments :

> 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

If it is the SRID that causes this problem , what SRID directly makes use of 'meter' as the unit ? (I tried transforming to SRID=2163 , but still in degree) Thanks.

Answer

radek picture radek · Dec 9, 2011

From the docs:

For Geometries: The distance is specified in units defined by the spatial reference system of the geometries.

If your data is in SRID=4326 the distance you are specifying is in degrees.

You either have to use ST_Transform and meter based coordinate system, or one of the two functions: ST_Distance_Sphere (faster, less accurate) or ST_Distance_Spheroid.