views:

3289

answers:

12

Assuming a series of points in 2d space that do not self-intersect, what is an efficient method of determining the surface area of the resulting polygon?

As a side note, this is not homework and I am not looking for code. I am looking for a description I can use to implement my own method. I have my ideas about pulling a sequence of triangles from the list of points, but I know there are a bunch of edge cases regarding convex and concave polygons that I probably won't catch.

+6  A: 

Step 1 = triangulate the polygon.

Step 2 = find the area of each triangle.

Step 3 = add up the areas from Step 2.

Step 1 is the difficult part.

Marcin
step 1: http://en.wikipedia.org/wiki/Convex_hull
Jimmy
He didn't specify it's guaranteed to be convex :(
Marcin
You don't need a full triangulation, or a convex polygon/hull. Just pick any vertex as common to all triangles, and walk the edge of the polygon, treating "negative" triangles as negative area (this is roughly equivalent to most of the other answers here)
comingstorm
A: 

My inclination would be to simply start slicing off triangles. I don't see how anything else could avoid being awfully hairy.

Take three sequential points that comprise the polygon. Ensure the angle is less than 180. You now have a new triangle which should be no problem to calculate, delete the middle point from the polygon's list of points. Repeat until you have only three points left.

Loren Pechtel
+1  A: 

One way to do it would be to decompose the polygon into triangles, compute the area of the triangles, and take the sum as the area of the polygon.

MattK
+1  A: 
  1. Set a base point (the most convex point). This will be your pivot point of the triangles.
  2. Calculate the most-left point (arbitrary), other than your base point.
  3. Calculate the 2nd-most-left point to complete your triangle.
  4. Save this triangulated area.
  5. Shift over one point to the right each iteration.
  6. Sum the triangulated areas
Joe Philllips
Make sure you negate the triangle area if the next point is moving "backwards".
recursive
A: 

Lazy: Render it and count pixels. The bigger the rendered image the more exact is this method.

Georg
+1  A: 

Or do a contour integral. Stokes' Theorem allows you to express an area integral as a contour integral. A little Gauss quadrature and Bob's your uncle.

duffymo
+4  A: 

A set of points without any other constraints don't necessarily uniquely define a polygon.

So, first you have to decide what polygon to build from these points - perhaps the convex hull? http://en.wikipedia.org/wiki/Convex_hull

Then triangulate and calculate area. http://www.mathopenref.com/polygonirregulararea.html

mbeckish
+25  A: 

Here is the standard method, AFAIK. Basically sum the cross products around each vertex. Much simpler than triangulation.

Python code, given a polygon represented as a list of (x,y) vertex coordinates, implicitly wrapping around from the last vertex to the first:

def area(p):
    return 0.5 * abs(sum(x0*y1 - x1*y0
                         for ((x0, y0), (x1, y1)) in segments(p)))

def segments(p):
    return zip(p, p[1:] + [p[0]])

David Lehavi comments: It is worth mentioning why this algorithm works: It is an application of Green's theorem for the functions -y and x; exactly in the way a planimeter works. More specifically:

Formula above =
integral_over_perimeter(-y dx + x dy) =
integral_over_area((-(-dy)/dy+dx/dx) dy dx) =
2 Area

Darius Bacon
ARGH! One minute ahead!MSN
MSN
It is worth mentioning why this algorithm works:It is an application of Green's theorem for the functions -y and x; exactly in the way a planimeter works.More specifically:Formula above = integral_permieter(-y dx + x dy) =integral_area((-(-dy)/dy+dx/dx)dydyx = 2 Area
David Lehavi
+4  A: 

To expand on the triangulate and sum triangle areas, those work if you happen to have a convex polygon OR you happen to pick a point that doesn't generate lines to every other point that intersect the polygon.

For a general non-intersecting polygon, you need to sum the cross product of the vectors (reference point, point a), (reference point, point b) where a and b are "next" to each other.

Assuming you have a list of points that define the polygon in order (order being points i and i+1 form a line of the polygon):

Sum(cross product ((point 0, point i), (point 0, point i + 1)) for i = 1 to n - 1.

Take the magnitude of that cross product and you have the surface area.

This will handle concave polygons without having to worry about picking a good reference point; any three points that generate a triangle that is not inside the polygon will have a cross product that points in the opposite direction of any triangle that is inside the polygon, so the areas get summed correctly.

MSN

MSN
+3  A: 

Here is a good explanation that hasn't been linked yet: http://www.wikihow.com/Calculate-the-Area-of-a-Polygon

Mongo
A: 

Better than summing triangles is summing trapezoids in the Cartesian space:

area = 0;
for (i = 0; i < n; i++) {
  i1 = (i + 1) % n;
  area += (vertex[i].y + vertex[i1].y) * (vertex[i1].x - vertex[i].x) / 2.0;
}
David Hanak
A: 

The cross product is a classic.

If you have zillion of such computation to do, try the following optimized version that requires half less multiplications:

area = 0;
for( i = 0; i < N; i += 2 )
   area += x[i+1]*(y[i+2]-y[i]) + y[i+1]*(x[i]-x[i+2]);
area /= 2;

I use array subscript for clarity. It is more efficient to use pointers. Though good compilers will do it for you.

The polygon is assumed to be "closed", which means you copy the first point as point with subscript N. It also assume the polygon has an even number of points. Append an additional copy of the first point if N is not even.

The algorithm is obtained by unrolling and combining two successive iterations of the classic cross product algorithm.

I'm not so sure how the two algorithms compare regarding numerical precision. My impression is that the above algorithm is better than the classic one because the multiplication tend to restore the loss of precision of the subtraction. When constrained to use floats, as with GPU, this can make a significant difference.

EDIT: "Area of Triangles and Polygons 2D & 3D" describes an even more efficient method

// "close" polygon
x[N] = x[0];
x[N+1] = x[1];
y[N] = y[0];
y[N+1] = y[1];

// compute area
area = 0;
for( size_t i = 1; i <= N; ++i )
  area += x[i]*( y[i+1] - y[i-1] );
area /= 2;
chmike