Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GeoDjango, what SRID to use for PointField interfacing with Google Maps V3 API?

I am a bit confused, what should I set my SRID value to in my GeoDjango PointField to stay accurate in the context of addresses being geocoded via google maps api into coordinates and distances being queried via django-postgis?

Im getting mixed opinions reading the threads around the net and stackover flow and am unsure what to do. As you can see my application is using geopy with google maps api to geocode an address. Right now my coordinates field doesn't have an SRID set which defaults to 4326 which is (EPSG: 4326). Now apparently this sees the earth as a globe, not a flat surface.

According to the answer in the following question things such as google maps use (EPSG 3857) which apparently has an SRID of 900913. https://gis.stackexchange.com/questions/48949/epsg-3857-or-4326-for-googlemaps-openstreetmap-and-leaflet

So does this mean I should set my SRID to 900913? All my restaurant model's coordinates are saved in the same method seen below using the geocoder. I would assume so.

Now this is where I get thrown off, the following tutorial http://invisibleroads.com/tutorials/geodjango-googlemaps-build.html uses a pointfield with their SRID set to 4326 (default) and their marker points appear perfectly on google maps.

Currently my queries are decently accurate but still feels seems a bit off.

Help is appreciated, thanks!

from geopy.geocoders import GoogleV3
from django.contrib.gis.geos import *
from django.contrib.gis.measure import D

geo = GoogleV3()

def home_page(request):
  distance = 3680
  address, coordinates = geo.geocode('Swanston Street, Melbourne Australia')
  ref_location = Point(coordinates)
  
  query = Restaurant.objects.filter(restaurant_location__distance_lte=(ref_location, D(m=distance))).distance(ref_location).order_by('distance')

  return render(request, 'swings/home.html', {'restaurants': query})

Restaurant Model

class Restaurant(models.Model):
    name = models.CharField(max_length=25, blank=False)
    user = models.ForeignKey(User)
    address = models.CharField(max_length=50, blank=False)
    restaurant_location = models.PointField(null=False, blank=False)
    objects = models.GeoManager()

    def __str__(self):
        return self.name
like image 493
user3739703 Avatar asked Jul 02 '14 08:07

user3739703


1 Answers

You should use 4326 (which means latitude and longitude, using the WGS84 datum and spheroid to model the globe's shape) to add points to Google Maps. Devices, such as GPS, which record your position on the globe, will save data in 4326, which will then be projected internally within Google Maps to 3857 (which is in meters). If you look at the example for loading GeoJSON you will see that the points are in 4326.

900913 (which is just GOOGLE in calculator writing) has caused a lot of confusion and arose out of the fact that initially the EPSG was very sniffy about what they regard as an inaccurate projection, mostly because it assumes the world to be a sphere. It became popular anyway because of Google's global prominence and for its mathematical tractability. Subsequently, the EPSG gave it a new official designation of 3857 (well technically there was another one too, 3587, just to cause yet more confusion). So, while people still talk about 900913, officially you should use 3587. 3587 is projected in meters and used to generate tiles for display in Google Maps, but should not be used to add point sources to it, where you definitely want to use 4326.

There is a good article here if you want to know any more about the history of this: http://alastaira.wordpress.com/2011/01/23/the-google-maps-bing-maps-spherical-mercator-projection/

like image 167
John Powell Avatar answered Oct 23 '22 12:10

John Powell