Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to calculate the area of a polygon on the earth's surface using python?

The title basically says it all. I need to calculate the area inside a polygon on the Earth's surface using Python. Calculating area enclosed by arbitrary polygon on Earth's surface says something about it, but remains vague on the technical details:

If you want to do this with a more "GIS" flavor, then you need to select an unit-of-measure for your area and find an appropriate projection that preserves area (not all do). Since you are talking about calculating an arbitrary polygon, I would use something like a Lambert Azimuthal Equal Area projection. Set the origin/center of the projection to be the center of your polygon, project the polygon to the new coordinate system, then calculate the area using standard planar techniques.

So, how do I do this in Python?

like image 944
andreas-h Avatar asked Jan 13 '11 15:01

andreas-h


People also ask

How do you find the area of a polygon with coordinates?

If the points are (x1, y1), (x2, y2), ..., (x4, y4), then here's the formula: 2A = (x1y2 - x2y1) + (x2y3 - x3y2) + (x3y4 - x4y3) + (x4y1 - x1y4) (Notice the formula is for 2 times the area - to get the area, calculate the number on the right and divide by 2.)

How do you find the surface of a polygon?

The formula to calculate the area of a regular polygon is, Area = (number of sides × length of one side × apothem)/2, where the value of apothem can be calculated using the formula, Apothem = [(length of one side)/{2 ×(tan(180/number of sides))}].


2 Answers

Let's say you have a representation of the state of Colorado in GeoJSON format

{"type": "Polygon",   "coordinates": [[    [-102.05, 41.0],     [-102.05, 37.0],     [-109.05, 37.0],     [-109.05, 41.0]  ]]} 

All coordinates are longitude, latitude. You can use pyproj to project the coordinates and Shapely to find the area of any projected polygon:

co = {"type": "Polygon", "coordinates": [     [(-102.05, 41.0),      (-102.05, 37.0),      (-109.05, 37.0),      (-109.05, 41.0)]]} lon, lat = zip(*co['coordinates'][0]) from pyproj import Proj pa = Proj("+proj=aea +lat_1=37.0 +lat_2=41.0 +lat_0=39.0 +lon_0=-106.55") 

That's an equal area projection centered on and bracketing the area of interest. Now make new projected GeoJSON representation, turn into a Shapely geometric object, and take the area:

x, y = pa(lon, lat) cop = {"type": "Polygon", "coordinates": [zip(x, y)]} from shapely.geometry import shape shape(cop).area  # 268952044107.43506 

It's a very close approximation to the surveyed area. For more complex features, you'll need to sample along the edges, between the vertices, to get accurate values. All caveats above about datelines, etc, apply. If you're only interested in area, you can translate your feature away from the dateline before projecting.

like image 70
sgillies Avatar answered Sep 19 '22 07:09

sgillies


The easiest way to do this (in my opinion), is to project things into (a very simple) equal-area projection and use one of the usual planar techniques for calculating area.

First off, I'm going to assume that a spherical earth is close enough for your purposes, if you're asking this question. If not, then you need to reproject your data using an appropriate ellipsoid, in which case you're going to want to use an actual projection library (everything uses proj4 behind the scenes, these days) such as the python bindings to GDAL/OGR or (the much more friendly) pyproj.

However, if you're okay with a spherical earth, it quite simple to do this without any specialized libraries.

The simplest equal-area projection to calculate is a sinusoidal projection. Basically, you just multiply the latitude by the length of one degree of latitude, and the longitude by the length of a degree of latitude and the cosine of the latitude.

def reproject(latitude, longitude):     """Returns the x & y coordinates in meters using a sinusoidal projection"""     from math import pi, cos, radians     earth_radius = 6371009 # in meters     lat_dist = pi * earth_radius / 180.0      y = [lat * lat_dist for lat in latitude]     x = [long * lat_dist * cos(radians(lat))                  for lat, long in zip(latitude, longitude)]     return x, y 

Okay... Now all we have to do is to calculate the area of an arbitrary polygon in a plane.

There are a number of ways to do this. I'm going to use what is probably the most common one here.

def area_of_polygon(x, y):     """Calculates the area of an arbitrary polygon given its verticies"""     area = 0.0     for i in range(-1, len(x)-1):         area += x[i] * (y[i+1] - y[i-1])     return abs(area) / 2.0 

Hopefully that will point you in the right direction, anyway...

like image 40
Joe Kington Avatar answered Sep 18 '22 07:09

Joe Kington