I'm using geodjango + postgres to display polygons from tigerline on a map. Pretty simple stuff so far.

My issue is that when I use the GPolygon object: django.contrib.gis.maps.google.GPolygon there is a considerable slowdown. (see below for the code I'm using)

locations = Location.objects.filter(mpoly__contains=point)
polygons = []
for location in locations :
    for poly in location.mpoly :
        gpoly = GPolygon(poly, \
            stroke_color = location.location_type.stroke_color,\
            stroke_weight = location.location_type.stroke_weight,
            stroke_opacity  = location.location_type.stroke_opacity,\
            fill_color = location.location_type.fill_color,\
            fill_opacity = location.location_type.fill_opacity)
        gpoly.location = location.id
        #raise Exception(gpoly)
# Google Map Abstraction
#raise Exception(len(polygons))
the_map = GoogleMap(polygons=polygons)
  • all of my location's mpoly are MultiPolygons
  • there are only 84 polygons total when I raise Exception(len(polygons))
  • this tiny block of code is incurring a 10 sec load time on localhost w/ 4gig ram and an i5 proc... I'm not resource locked

Does anybody have any idea what GPolygon is doing? Is GPolygon not ideal for production? is it just for prototyping?


I'm now setting up my GPolygon like so:

gpoly = GPolygon(poly.simplify(float(get_tolerance(poly.num_points))), \
    stroke_color = location.location_type.stroke_color,\
    stroke_weight = location.location_type.stroke_weight,
    stroke_opacity  = location.location_type.stroke_opacity,\
    fill_color = location.location_type.fill_color,\
    fill_opacity = location.location_type.fill_opacity)

using the function:

def get_tolerance(num_points) :
    """figure out a good tolerance"""
    tolerance = 0
    if num_points <= 500:
        tolerance = 0
    elif num_points <= 750: 
        tolerance = .001
    elif num_points <= 1000: 
        tolerance = .002
    elif num_points > 2000: 
        tolerance = .007

    return tolerance

which sets a tolerance for the simplify geos function based on the total number of points (I noticed that for things like florida where the keys(islands) are separate polygons that the ones with fewer points broke with a high tolerance, while the big main landmass polygons are too huge without simplifying to a large degree.

This has made my program a magnitude faster BUT I still think there is tons of room for improvement.

Which leads me to my newest questions:

  • Is there a better way to guess acceptable tolerances?
  • What other possible speed gains could I explore?


Something i did was pass all of the polygons to the view as geojson objects and use JS to build the polygon objects which is way faster than django.contrib.gis.maps.google.GPolygon.

Server side python:

def get_location_polygons(request):
    """Returns a civic location name from a geodetic point"""
    response_data = {'ack':None,'data':None,'messages':[]}
    if request.method == 'POST':
        #try :
        # Get the location
        location = Location.objects.get(pk=request.POST['location_id'])

        # Build the polygons
        response_data['ack']            = True
        response_data['messages'] = _(u'OK')            
        response_data['data']           = {
            'stroke_color'      : location.location_type.stroke_color,
            'stroke_weight'     : location.location_type.stroke_weight,
            'stroke_opacity'    : location.location_type.stroke_opacity,
            'fill_color'            : location.location_type.fill_color,
            'fill_opacity'      : location.location_type.fill_opacity,
            'polygons'              : location.mpoly.geojson,
            'title'                     : location.title
        #except :
        #   # Fetch failed
        #   response_data['ack']            = False
        #   response_data['messages'] = [_(u'Polygon for location could not be fetched.')]
        response_data['ack']            = False
        response_data['messages'] = [_(u'HTTP Method must be POST')]

    return HttpResponse(json.dumps(response_data), mimetype="application/json")

Client side JS:

poly = JSON.parse(data.data['polygons'])
var paths = coord_to_paths(poly.coordinates, bucket, location_id);
polygons[bucket][location_id] = new google.maps.Polygon({ 
    paths                   : paths, 
    strokeColor     : data.data.stroke_color, 
    strokeOpacity   : data.data.stroke_opacity, 
    strokeWeight    : data.data.stroke_weight, 
    fillColor           : data.data.fill_color, 
    fillOpacity     : data.data.fill_opacity
function coord_to_paths(coords, bucket, location_id)
    var paths = []; 
    poly_bounds[bucket][location_id] = new google.maps.LatLngBounds();
    for (var i = 0; i < coords.length; i++)
        for (var j = 0; j < coords[i].length; j++)
            var path = []; 
            for (var k = 0; k < coords[i][j].length; k++)
                var ll = new google.maps.LatLng(coords[i][j][k][1], coords[i][j][k][0]);

    return paths;       
  • Thanks for migrating this question over. I may leave it open for a while and see if anyone has a better solution than what I came up with. Thanks for taking interest. Jun 12, 2012 at 17:43

1 Answer 1


Reducing fidelity (i.e removing the number of nodes) will help since there is less data to pass to Google Maps.

Nevertheless, I would hope you are not doing this for every request directly in the view and that this is something that you are doing only once (during the first save), or through some asynchronous queue mechanism like Celery.

You can always have a shape that you use for analysis (with the full vertex count) and another one that you use for display.

  • I figured reducing the number of vertices would be key, however, choosing the simplification factor for each polygon seems not as straight forward. any idea on a good algorithm for that? my get_tolerance(num_points) function sometimes breaks if it tries to simplify a poly too much. Thanks for responding Jun 15, 2012 at 14:57
  • get_tolerance should not be a function based on the number of nodes, you should just pick a number and stick with it. The tolerance value determines the degree of simplification and it uses the units of the underlying spatial reference. It is not exactly that, but you can think of it as the minimum distance before two nodes are close enough that they become one. Jun 15, 2012 at 16:23
  • that is interesting, I think the simplify function in geodjango may be buggy then. On smaller polygons I noticed that If i specified a tolerance too high that the polygon would break (not validate as a geos polygon) I figured that had to do with oversimplification and that I should adjust the simplification level based on the number of nodes (which worked to a degree, but seemed error prone) Jun 15, 2012 at 18:12
  • I doubt is a bug in geodjango. Probably you are using values that are too high. Remember that in order to be a valid polygon, you need to have at least 3 points. If your value is too high then you can run into cases where too many nodes snap to each other and you end up with less than three nodes. Many nodes does not mean bigger feature necessarily, it just means higher fidelity / density. I can create a super small polygon with 1000 nodes that will blow up when you use 0.02 of tolerance - no bug in geodjango required. Jun 15, 2012 at 19:14
  • in that case I'm back to my original question, how do you determine programatically the correct tolerance? Jun 15, 2012 at 19:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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