4

I've just used osm2pgsql to import osm data to a PostGIS database, using lat/long option to store it in WGS84 projection. I would like to use ST_DWithin to select nodes close to a random point. When I try that directly on the WGS84 data it returns wrong results but works if I reproject it in Web Mercator. What am i missing to avoid the reprojection?

SELECT ST_AsText(way),
       ST_X(ST_AsText(way)) as X,
       ST_Y(ST_AsText(way)) as Y,
       railway
  FROM planet_osm_point
 WHERE railway IS NOT NULL AND
       ST_DWithin(ST_Transform(way, 3785),
                  ST_Transform(ST_SetSRID(ST_MakePoint(-1.631560, 48.107485), 4326), 3785),
                  500)
 LIMIT 1000;

Mercator projection output

SELECT ST_AsText(way),
       ST_X(ST_AsText(way)) as X, 
       ST_Y(ST_AsText(way)) as Y,
       railway
  FROM planet_osm_point 
 WHERE railway IS NOT NULL AND
       ST_DWithin(way, ST_SetSRID(ST_MakePoint(-1.631560, 48.107485), 4326), 500)
 LIMIT 1000;

WGS84 projection output

As you can see the outputs from WGS84 projection aren't even close to the point I'm lookin at and I can't figure out why when I am using the same geometry type for ST_DWithin. Is there a step I'm missing? (also I am not showing all of the results here, the Web Mercator projection gets me about 154 results, while WGS84 projection goes beyond 1000)

4
  • Can you try ST_SetSRID(way, 4326) ensure it thinks they are in the same CRS?
    – Mintx
    Commented Apr 20, 2022 at 17:06
  • On a side note web Mercator is 3857
    – JGH
    Commented Apr 20, 2022 at 18:15
  • Make sure you have a spatial index in place ON planet_osm_point USING GIST (ST_Transform(way, 3857));, or, in conjunction with the correct answer below, ON planet_osm_point USING GIST ((way::GEOGRAPHY)); to benefit from index lookup performance!
    – geozelot
    Commented Apr 21, 2022 at 8:30
  • Web Mercator should not ever be used for distance or area calculations, as the poles are infinitely far away from the Equator. Even locations close to the Equator have wrong distances, but far away locations have very wrong distance/area values.
    – Vince
    Commented Apr 21, 2022 at 11:39

1 Answer 1

8

The problem is that you are using ST_DWithin on GEOMETRY objects with coordinates in WGS84. Therefore, your function call is requesting all features within 500 degrees (i.e., everything on the planet). https://postgis.net/docs/ST_DWithin.html

To calculate the distance in metres, cast the geometries to geography data type:

SELECT ST_AsText(way),
       ST_X(ST_AsText(way)) as X, 
       ST_Y(ST_AsText(way)) as Y,
       railway
  FROM planet_osm_point 
 WHERE railway IS NOT NULL AND
       ST_DWithin(way::geography,
                  ST_SetSRID(ST_MakePoint(-1.631560, 48.107485), 4326)::geography,
                  500)
 LIMIT 1000;

This will return slightly different distances compared to when you project to EPSG:3857 (Web Mercator) because that projection does not maintain distances to scale. Casting to geography will provide more accurate results by calculating distances using ellipsoid calculations, by default.

2
  • Hello, thank you very much for your answer, i have used it instead and looked up for some info on difference between geography and geometry type, i would put you as an aswer to my question but i'm not sure how Commented Apr 25, 2022 at 14:59
  • @Bad_deepLearner Glad to hear this worked for you. To see how to accept an answer, see this question on GIS.SE meta.
    – hgb
    Commented Apr 25, 2022 at 18:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.