Say I have an arbitrary set of latitude and longitude pairs representing points on some simple, closed curve. In Cartesian space I could easily calculate the area enclosed by such a curve using Green's Theorem. What is the analogous approach to calculating the area on the surface of a sphere? I guess what I am after is (even some approximation of) the algorithm behind Matlab's areaint
function.

- 1,518
- 1
- 13
- 17
6 Answers
There several ways to do this.
1) Integrate the contributions from latitudinal strips. Here the area of each strip will be (Rcos(A)(B1-B0))(RdA), where A is the latitude, B1 and B0 are the starting and ending longitudes, and all angles are in radians.
2) Break the surface into spherical triangles, and calculate the area using Girard's Theorem, and add these up.
3) As suggested here by James Schek, in GIS work they use an area preserving projection onto a flat space and calculate the area in there.
From the description of your data, in sounds like the first method might be the easiest. (Of course, there may be other easier methods I don't know of.)
Edit – comparing these two methods:
On first inspection, it may seem that the spherical triangle approach is easiest, but, in general, this is not the case. The problem is that one not only needs to break the region up into triangles, but into spherical triangles, that is, triangles whose sides are great circle arcs. For example, latitudinal boundaries don't qualify, so these boundaries need to be broken up into edges that better approximate great circle arcs. And this becomes more difficult to do for arbitrary edges where the great circles require specific combinations of spherical angles. Consider, for example, how one would break up a middle band around a sphere, say all the area between lat 0 and 45deg into spherical triangles.
In the end, if one is to do this properly with similar errors for each method, method 2 will give fewer triangles, but they will be harder to determine. Method 1 gives more strips, but they are trivial to determine. Therefore, I suggest method 1 as the better approach.

- 67,082
- 10
- 127
- 137
-
My answer is an elaboration of your (2). Computationally, vector math is going to be much less expensive than integration, and quite possibly easier to code. Note that all the vector operations can be done with spherical-coordinate vectors, which latitude/longitude essentially are. – Cascabel Aug 27 '09 at 17:59
-
@Jefromi: I think your comment is incorrect and I've edited my answer to address this. – tom10 Aug 27 '09 at 21:40
-
Thanks Tom. I _assume_ the Matlab function does something like your (1). I will see if I can get hold of that paper. Regarding your objection to spherical triangles, my question may not have been completely clear on this point, but all I have are vertices—an ordered set of latitude/longitude pairs. The edges are just implied, so we may as well assume that they are great circles for the purposes of any calculations. – Paul A. Hoadley Aug 27 '09 at 23:04
-
Paul... this makes sense, especially if you points are close together. – tom10 Aug 27 '09 at 23:13
-
I managed to track down that paper. And, rather amazingly since the FTP server mentioned in the article is gone, the associated code. So I'll brush up my Fortran skills and check it out. – Paul A. Hoadley Aug 29 '09 at 00:20
-
Paul - just curious how they do the calculation in the paper (though I'm not sure whether you were able to get the paper or just the code). Oh, Fortran, those were the days... – tom10 Aug 31 '09 at 18:32
-
@tom10 link broken for paper. Can you please fix it ? – gansub Sep 16 '18 at 10:20
-
@gansub: I think the paper is no longer available on the site. I can't find it either. As i recall, and it was a long time ago, the paper wasn't very useful anyway. – tom10 Sep 18 '18 at 00:39
I rewrote the MATLAB's "areaint" function in java, which has exactly the same result. "areaint" calculates the "suface per unit", so I multiplied the answer by Earth's Surface Area (5.10072e14 sq m).
private double area(ArrayList<Double> lats,ArrayList<Double> lons)
{
double sum=0;
double prevcolat=0;
double prevaz=0;
double colat0=0;
double az0=0;
for (int i=0;i<lats.size();i++)
{
double colat=2*Math.atan2(Math.sqrt(Math.pow(Math.sin(lats.get(i)*Math.PI/180/2), 2)+ Math.cos(lats.get(i)*Math.PI/180)*Math.pow(Math.sin(lons.get(i)*Math.PI/180/2), 2)),Math.sqrt(1- Math.pow(Math.sin(lats.get(i)*Math.PI/180/2), 2)- Math.cos(lats.get(i)*Math.PI/180)*Math.pow(Math.sin(lons.get(i)*Math.PI/180/2), 2)));
double az=0;
if (lats.get(i)>=90)
{
az=0;
}
else if (lats.get(i)<=-90)
{
az=Math.PI;
}
else
{
az=Math.atan2(Math.cos(lats.get(i)*Math.PI/180) * Math.sin(lons.get(i)*Math.PI/180),Math.sin(lats.get(i)*Math.PI/180))% (2*Math.PI);
}
if(i==0)
{
colat0=colat;
az0=az;
}
if(i>0 && i<lats.size())
{
sum=sum+(1-Math.cos(prevcolat + (colat-prevcolat)/2))*Math.PI*((Math.abs(az-prevaz)/Math.PI)-2*Math.ceil(((Math.abs(az-prevaz)/Math.PI)-1)/2))* Math.signum(az-prevaz);
}
prevcolat=colat;
prevaz=az;
}
sum=sum+(1-Math.cos(prevcolat + (colat0-prevcolat)/2))*(az0-prevaz);
return 5.10072E14* Math.min(Math.abs(sum)/4/Math.PI,1-Math.abs(sum)/4/Math.PI);
}

- 869
- 1
- 8
- 14
-
I need the same thing but in PHP but the code seems to be too complex for me to understand. Can you help me with that? – arsal khan Jun 10 '20 at 19:49
You mention "geography" in one of your tags so I can only assume you are after the area of a polygon on the surface of a geoid. Normally, this is done using a projected coordinate system rather than a geographic coordinate system (i.e. lon/lat). If you were to do it in lon/lat, then I would assume the unit-of-measure returned would be percent of sphere surface.
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.
If you needed to do many polygons in a geographic area, there are likely other projections that will work (or will be close enough). UTM, for example, is an excellent approximation if all of your polygons are clustered around a single meridian.
I am not sure if any of this has anything to do with how Matlab's areaint function works.

- 17,844
- 7
- 51
- 64
-
Thanks James. I had wondered whether projecting the polygon into a plane first was feasible. I see that projection preserves area, so maybe that would be ideal. – Paul A. Hoadley Aug 29 '09 at 00:17
-
+1... right, talking to a friend who also does a lot of GIS work, she told me this is how they do it. Is there a reason for this approach? – tom10 Aug 30 '09 at 01:16
-
@Paul--you may already know this, but be careful which projection you select. Some projections preserve area, others don't. The common Web Mercator used on most maps only preserves shape. – James Schek Aug 31 '09 at 15:01
-
@tom Not sure why... My guess is that it's easier to work with cartesian/planar systems. If you need to do more than calculate the area of a polygon, then having a planar representation makes life easier. Plus--USGS, among others, provides "reference" implementations of most major projection techniques. – James Schek Aug 31 '09 at 15:04
-
@James: from the computational perspective: which of the equal-area projections would be the cheapest to use for calculating the area? I mean which projection has the simplest transformation formula? – Igor Brejc Jan 29 '10 at 05:35
-
@Igor: Unfortunately, I don't know the specifics of the projection algorithms--it's all a black box to me. I'll ask around and see if I can find a definitive answer. – James Schek Feb 01 '10 at 15:48
I don't know anything about Matlab's function, but here we go. Consider splitting your spherical polygon into spherical triangles, say by drawing diagonals from a vertex. The surface area of a spherical triangle is given by
R^2 * ( A + B + C - \pi)
where R
is the radius of the sphere, and A
, B
, and C
are the interior angles of the triangle (in radians). The quantity in the parentheses is known as the "spherical excess".
Your n
-sided polygon will be split into n-2
triangles. Summing over all the triangles, extracting the common factor of R^2
, and bringing all of the \pi
together, the area of your polygon is
R^2 * ( S - (n-2)\pi )
where S
is the angle sum of your polygon. The quantity in parentheses is again the spherical excess of the polygon.
[edit] This is true whether or not the polygon is convex. All that matters is that it can be dissected into triangles.
You can determine the angles from a bit of vector math. Suppose you have three vertices A
,B
,C
and are interested in the angle at B
. We must therefore find two tangent vectors (their magnitudes are irrelevant) to the sphere from point B
along the great circle segments (the polygon edges). Let's work it out for BA
. The great circle lies in the plane defined by OA
and OB
, where O
is the center of the sphere, so it should be perpendicular to the normal vector OA x OB
. It should also be perpendicular to OB
since it's tangent there. Such a vector is therefore given by OB x (OA x OB)
. You can use the right-hand rule to verify that this is in the appropriate direction. Note also that this simplifies to OA * (OB.OB) - OB * (OB.OA) = OA * |OB| - OB * (OB.OA)
.
You can then use the good ol' dot product to find the angle between sides: BA'.BC' = |BA'|*|BC'|*cos(B)
, where BA'
and BC'
are the tangent vectors from B
along sides to A
and C
.
[edited to be clear that these are tangent vectors, not literal between the points]

- 479,068
- 72
- 370
- 318
-
The proof of Girard's Theorem is very elegant - if you have any desire to fully understand what you're doing here, have a look at http://math.rice.edu/~pcmi/sphere/gos3.html and http://math.rice.edu/~pcmi/sphere/gos4.html – Cascabel Aug 27 '09 at 18:11
-
Does the second equation (the one involving S) require that the polygon is convex? – Justin Aug 27 '09 at 21:53
-
Thanks Jefromi. A non-convex polygon would also complicate the initial splitting into spherical triangles. Is there a well-known algorithm to achieve that? – Paul A. Hoadley Aug 27 '09 at 22:55
-
Wait, why are we trying to decompose it? The area formula is still valid! The proof didn't depend on convexity. The area of the polygon is still the sum of the area of the triangles, no matter how you cut it up. – Cascabel Aug 27 '09 at 23:22
-
Sorry, I wasn't questioning the proof, but the cutting up itself. At some point I want to be able to do this programmatically, and obviously drawing diagonals from a vertex only works for a convex polygon. What I'm asking is whether there's another algorithm for the splitting which doesn't get stumped by a non-convex shape. – Paul A. Hoadley Aug 28 '09 at 02:01
-
@Paul - Call the little strip of area inside the triangle that's parallel to the edge furthest from the central vertex the "far edge". Then if you go around the perimeter and add the triangle area when the far edge is inside your mapped area, and subtract it when it's outside, I think this spherical triangle algorithm will work on both concave and convex (and even disconnected) shapes. – tom10 Aug 28 '09 at 03:03
-
The proof gives you a formula for the area of the polygon which you can simply use. You do not have to split it into triangles. That's just how I proved the formula works. – Cascabel Aug 28 '09 at 13:50
-
Certainly the proof does depend on convexity, it's just not explicit; but it's implicit when you do the sum and assume that the entire area of the triangle is within the map area. – tom10 Aug 28 '09 at 20:02
-
Yes, there's an implicit step. No, it's not a problem, as long as the polygon doesn't have holes. You can further subdivide as necessary without affecting the angle excess. It's just way more casework than was appropriate here. – Cascabel Aug 28 '09 at 20:22
-
As a final nail in the coffin, look here. The formula's simply printed. I just thought it was worth seeing why it worked. http://mathworld.wolfram.com/SphericalPolygon.html – Cascabel Aug 28 '09 at 20:24
-
Yes, it seems that this is valid. As for being "way more casework", it seems to me if you just say over and over that we should all look at your proof, your proof should probably cover the case in question. To find this out, I had to look it up elsewhere. Here's an example of a good link to it. http://books.google.com/books?id=CCqzMm_-WucC&lpg=PA132&ots=mrkr1aGLen&dq=concave%20%22spherical%20polygon%22%20area&pg=PA132#v=onepage&q=concave%20%22spherical%20polygon%22%20area&f=false – tom10 Aug 28 '09 at 20:41
Here is a Python 3 implementation, loosely inspired by the above answers:
def polygon_area(lats, lons, algorithm = 0, radius = 6378137):
"""
Computes area of spherical polygon, assuming spherical Earth.
Returns result in ratio of the sphere's area if the radius is specified.
Otherwise, in the units of provided radius.
lats and lons are in degrees.
"""
from numpy import arctan2, cos, sin, sqrt, pi, power, append, diff, deg2rad
lats = np.deg2rad(lats)
lons = np.deg2rad(lons)
# Line integral based on Green's Theorem, assumes spherical Earth
#close polygon
if lats[0]!=lats[-1]:
lats = append(lats, lats[0])
lons = append(lons, lons[0])
#colatitudes relative to (0,0)
a = sin(lats/2)**2 + cos(lats)* sin(lons/2)**2
colat = 2*arctan2( sqrt(a), sqrt(1-a) )
#azimuths relative to (0,0)
az = arctan2(cos(lats) * sin(lons), sin(lats)) % (2*pi)
# Calculate diffs
# daz = diff(az) % (2*pi)
daz = diff(az)
daz = (daz + pi) % (2 * pi) - pi
deltas=diff(colat)/2
colat=colat[0:-1]+deltas
# Perform integral
integrands = (1-cos(colat)) * daz
# Integrate
area = abs(sum(integrands))/(4*pi)
area = min(area,1-area)
if radius is not None: #return in units of radius
return area * 4*pi*radius**2
else: #return in ratio of sphere total area
return area
Please find a somewhat more explicit version (and with many more references and TODOs...) here.

- 693
- 4
- 14