GeoDjango: Determine the area of a polygon
Asked Answered
I

4

5

In my model I have a polygon field defined via

polygon = models.PolygonField(srid=4326, geography=True, null=True, blank=True)

When I want to determine the area of the polygon, I call

area_square_degrees = object.polygon.area

But how can I convert the result in square degrees into m2 with GeoDjango? This answer does not work, since area does not have a method sq_m. Is there any built-in conversion?

Icebreaker answered 10/11, 2013 at 17:47 Comment(1)
Did you find a django native solution that can also save the area in the database upon the object creation?Whiffler
A
7

You need to transform your data to the correct spatial reference system.

area_square_local_units = object.polygon.transform(srid, clone=False).area

In the UK you might use the British National Grid SRID of 27700 which uses meters.

area_square_meters = object.polygon.transform(27700, clone=False).area

You may or may not want to clone the geometry depending on whether or not you need to do anything else with it in its untransformed state.

Docs are here https://docs.djangoproject.com/en/1.8/ref/contrib/gis/geos/

Adur answered 23/8, 2015 at 20:43 Comment(2)
Note that Guillaume's answer below is a better solution when using 4326 & geography type in your model geometry field.Adur
In order for this to work with the current version, you have to set clone=True. With clone=False, nothing is returned, and you try to get .area on NULL.Bogart
R
4

I have struggled a lot with this, since i could'nt find a clean solution. The trick is you have to use the postgis capabilities (and and thus its only working with postgis..):

from django.contrib.gis.db.models.functions import Area
loc_obj = Location.objects.annotate(area_=Area("poly")).get(pk=??)  
# put the primary key of the object

print(loc_obj.area_)  # distance object, result should be in meters, but you can change to the unit you want, e.g  .mi for miles etc..

The models.py:

class Location(models.Model):
    poly = gis_models.PolygonField(srid=4326, geography=True)

It's i think the best way to do it if you have to deal with geographic coordinates instead of projections. It does handle the curve calculation of the earth, and the result is precise even with big distance/area

Ramberg answered 1/9, 2017 at 9:43 Comment(2)
Is there a way to make the area calculation upon the object creation or at least make the calculation for one row instead of the whole table?Whiffler
I guess it something like Location.objects.filter(pk=XXX) .annotate(area_=Area("poly")). Then calculations are made only on the subset of the table.Ramberg
M
2

I needed an application to get the area of poligons around the globe and if I used an invalid country/region projection I got the error OGRException: OGR failure

I ended using an OpenLayers implementation using the 4326 projection (is the default projection) to avoid concerning about every country/region specific projection. Here is my code:

import math

def getCoordsM2(coordinates):
    d2r = 0.017453292519943295  # Degrees to radiant
    area = 0.0
    for coord in range(0, len(coordinates)):
        point_1 = coordinates[coord]
        point_2 = coordinates[(coord + 1) % len(coordinates)]
        area += ((point_2[0] - point_1[0]) * d2r) *\
            (2 + math.sin(point_1[1] * d2r) + math.sin(point_2[1] * d2r))
    area = area * 6378137.0 * 6378137.0 / 2.0
    return math.fabs(area)

def getGeometryM2(geometry):
    area = 0.0
    if geometry.num_coords > 2:
        # Outer ring
        area += getCoordsM2(geometry.coords[0])
        # Inner rings
        for counter, coordinates in enumerate(geometry.coords):
            if counter > 0:
                area -= getCoordsM2(coordinates)
    return area

Simply pass your geometry to getGeometryM2 function and you are done! I use this function in my GeoDjango model as a property. Hope it helps!

Morales answered 16/11, 2015 at 18:2 Comment(0)
N
-4

If Its earths surface area that you are talking about, 1 square degree has 12,365.1613 square km. So multiple your square degree and multiply by 10^6 to convert to meters.

Nicolnicola answered 22/1, 2014 at 9:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.