Search code examples
postgresqlpostgissrid

Get metric distance between two points via a PostgreSQL/PostGIS request


I have a question about the use of postgreSQL/postGIS.

I would like to display markers on a map (stored in a database) which are some distance away from the user (coordinates given to the request).

The type of the field of the markers is POINT (I store lat/long). The user position is detetermined by the Google Map API.

Here is the actual request :

SELECT * FROM geo_points WHERE ST_distance(ST_SetSRID(geo_points.coords::geometry,4326),ST_GeomFromEWKT('SRID=4326;POINT(45.0653944 4.859764599999996)')) > 65

I know (after some research on internet) that the function ST_distance gives me the distance in degree between markers and the user position and that I test the distance in km.

I think I have to use the function ST_tranform to transform the points in metric coordinates.

So my questions are : - what is the SRID for France - how can I make this dynamically for the entire world according to the user position ?

I also kow that the function ST_within exists and that could do this. But I anticipate the fact that later, I could need the distance.

Any help would be greatly appreciated

ps: there are maybe solutions in other post, but all the answers I have found during my researches were not really meeting my needs.


Solution

  • Firstly, pay attention to the axis order of coordinates used by PostGIS, it should be long/lat. Currently you are searching in Somalia. Swapping to the coordinates, you would be searching in France.

    You can use a geodesic calculation with the geography type, or use geodesic functions like ST_Distance_Spheroid. With the geography type, you may want to use ST_DWithin for higher performance.

    Here are geo_points 65 m away or less from the point of interest in France (not Somalia):

    SELECT * FROM geo_points
    WHERE ST_Distance_Spheroid(
        ST_Transform(geo_points.coords::geometry, 4326),
        ST_SetSRID(ST_MakePoint(4.859764599999996, 45.0653944), 4326),
        'SPHEROID["WGS 84",6378137,298.257223563]') < 65.0;
    

    However, it will be very slow, since it needs to find the distance to every geo_points, so only do this if you don't care about performance and have less than a few thousand points.

    If you change and transform geo_points.coords to store lon/lat (WGS84) as a geography type:

    SELECT * FROM geo_points
    WHERE ST_DWithin(
        geo_points::geography,
        ST_SetSRID(ST_MakePoint(4.859764599999996, 45.0653944), 4326)::geography,
        65.0);