[GIS] Why is the Google Maps circle shape not matching to the distance calculated with PostgreSQL

coordinate systemgoogle-maps-apipostgis

I am running a PostgreSQL 9.1 Database with PostGIS 1.5 extension. Several coordinates are stored in there with type GEOMETRY (SRID 4326).
I'm building a web-application with Google Maps Javascript API v3 to display those points. For any point on the map and a definable distance, I now want to highlight markers if they are within the radius of that point.

This query returns the IDs of all those points:

WITH chosen AS (SELECT * FROM ST_SetSRID (ST_MakePoint ($1, $2), 4326))
SELECT mypoints.id FROM mypoints, chosen
WHERE ST_DWithin (mypoints.location::geography, chosen.ST_SetSRID::geography, $3);

The ::geography casts are needed here to use meters as measurement unit instead of degrees. $1,$2 is lon,lat, $3 is the chosen distance in meters.

Clientside, only the markers resulting from the query receive full opacity and I also display a google.maps.Circle with the chosen distance as radius. As you can see on the picture below, some markers that should be highlighted if you trust the red circle are not returned by my query. The difference also only seems to occur on the X-axis.



Now what is wrong here?

Is the circle shape from the GMaps JS API inaccurate for my region (Germany)?

Or am I missing something in my query?


So far, i really think that martin_f is right about the distortion. There are multiple coordinate systems involved here: https://stackoverflow.com/questions/15015946/google-map-api-v3-projection

Can anybody confirm that every Shape I draw in Google Maps Javascript API is in SRID 3857 and every Marker I add with Lat/Lon Values in SRID 4326 are internally converted to 3857 before they are shown on the map?

Best Answer

I suspect the issue relates to the very real difference existing between geometry objects, existing on a plane map surface, and geography objects, existing on a curved globe surface.

It is always more accurate (but slower) to do calculations with geography types on a globe. Projecting features from a globe onto a plane always incurs distortion.

Looking at your SQL code, on the 3rd line you do cast to geography but for the "incomplete" reasons. You do it to use meters instead of degrees for the distance measure, and that is good. You should also do it because you get more accurate results.

Now, in the 1st line of your SQL code, you make a point out of coordinate parameters, but it is by default a geometry and so you end up not comparing like with like. Try casting the point you make to geography and see what happens.

Like this, i think:

ST_SetSRID(ST_MakePoint($1, $2),4326)::geography

If you draw circles using GMaps, they are probably not representing true circles on the globe. If "GMaps" (not sure what you mean, exactly) uses the Web Mercator projection, then a drawn circle really represents an "egg" shape on the globe, with the pointed end up north. That's how the Mercator projection distorts things -- things get hugely stretched as one moves away from the equator.