0

I am building a web service with GeoDjango which involves user submitted events including a location. I created a model field for my location using django.contrib.gis.db:

location = models.PointField(srid=900913)

I chose to specify 900913 as I read that this is the projection used by Google Maps and I am getting the location by placing a marker on a Google map. The coordinate is presented to me in lat/lng form. I am storing this point in a PostGIS DB using GEOS:

location = geos.Point(data['lng'], data['lat'], srid=900913)

If I want to view this point on a map, I get the lat and lng from my DB (e.g. lat = location.coords[1]) and use them to centre my map and this works fine.

When I want to browse a map and display events from DB which lie inside the map bounds I use GeoDjango's within query and the maps bounds (in lat/lng format):

    bounds = geos.Polygon.from_bbox((swLng, swLat, neLng, neLat))
    events = Event.objects.filter(location__within=bounds)

This appears to work fine and I display pins on the map corresponding to the lat/lng of these events.

So far nothing would suggest that anything is going wrong, however I am completely new to this stuff and I want to ensure that I'm getting it right for when I inevitably want to use my location data in more complex ways. The reason I'm suspicious is that my Django admin pane does not display the location correctly on the OpenStreetMap. It shows a point which appears to correspond to the (0,0) point shown here. The displayed text version of the location field is SRID=900913;POINT(-1.277482509613037 50.874104373286066), which is clearly still in lat/lng. As I move my mouse around the admin map I can see the displayed coords in the bottom right corner are in 900913 format, and not in lat/lng.

Please can you explain how I can store my location points in the correct format, and what advantages this has over simply using lat/lng (my guess is that if I want to specify say a distance in km for lookups, I can't use my lat/lng locations).

7
  • You may want to look at using EPSG:3857. This is a standard projection for webmaps. If you look at the projection of Google Maps from Open Layers (in QGIS), this is the projection that is used. Commented May 27, 2014 at 17:36
  • As far as I can tell this is the same projection as 900913. I find all these codes so confusing, e.g. what do all the 'codes' on this page mean? wiki.openstreetmap.org/wiki/EPSG:3857 So if I decided to use EPSG:3857 or stick with 900913, how do I store and use my coordinates in this format with GeoDjango?
    – Ferguzz
    Commented May 28, 2014 at 9:30
  • Check out spatialreferencing.org it has the projections and Moore information about them. It is a good resource to use Commented May 28, 2014 at 12:07
  • I have checked this out. In fact there's a link to it in my question. However I find that this is purely reference material and doesn't provide any insight into how to actually go about using the projections. It certainly doesn't give any information relating to GeoDjango/Geos etc.
    – Ferguzz
    Commented May 28, 2014 at 12:27
  • Well that is no the purpose of the website. It was created as a reference, not a tool to answer specific questions related to technology or software products. Commented May 28, 2014 at 13:29

1 Answer 1

4

The points being returned to you by Google Maps are in lat/lng, which almost always these days means SRID=4326. So change your geometry SRID in your PostGIS table to that:

location = geos.Point(data['lng'], data['lat'], srid=4326)

Then, when displaying points on a web map the projection of the map is commonly set to the Spherical Mercator coordinate system, because it seems to look better. Coordinates in this projection are in meters from an origin, not lat/lng. Set your web map to EPSG:3857 (the same definition as 900913, which has been deprecated). You will need to reproject any geometry (your points) into this projection - fortunately, web map APIs do this pretty simply and effeciently. The way you do it is slightly different in each web map API, but you should set the map projection when you create it (OpenLayers example):

 var mOptions = {
   projection: new OpenLayers.Projection("EPSG:3857"),
   displayProjection: new OpenLayers.Projection("EPSG:4326"),
   units: "m",
   numZoomLevels: 18,
   maxResolution: 156543.0339,
   maxExtent: new OpenLayers.Bounds(-20037508, -20037508, 20037508, 20037508)
   };
   map = new OpenLayers.Map("map", mOptions);

Then when you add your points to the map transform them from lat/lng to the map coordinate system:

 var geojson_format = new OpenLayers.Format.GeoJSON({
    'internalProjection': new OpenLayers.Projection('EPSG:3857'),
    'externalProjection': new OpenLayers.Projection('EPSG:4326')
    });
 var theFeature = geojson_format.read(json[i].geometry);

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.