Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calculating area enclosed by arbitrary polygon on Earth's surface

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.

like image 288
Paul A. Hoadley Avatar asked Aug 27 '09 10:08

Paul A. Hoadley


People also ask

How do you find the area of an enclosed 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))}].

What is the command name to calculate the surface area of a sphere?

area = areaint(lat,lon) calculates the spherical surface area of the polygon specified by the input vectors lat and lon .


3 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.

like image 136
tom10 Avatar answered Sep 22 '22 13:09

tom10


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); } 
like image 37
user2548538 Avatar answered Sep 21 '22 13:09

user2548538


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.

like image 28
James Schek Avatar answered Sep 25 '22 13:09

James Schek