[comp.graphics] Area of polygon with arc edges

DSeal@acorn.co.uk (10/17/89)

To determine the area of an arbitrary "polygon", the sides of which may be
straight line segments, arcs or other curves, I would suggest the following
approach:

Suppose that the vertices are (x(i),y(i)), i=1 to N, and set x(0)=x(N),
y(0)=y(N). Express the curve from (x(i-1),y(i-1)) to (x(i),y(i)) either in
non-parametric form

    y=f_i(x), for x running from x(i-1) to x(i),

or in parametric form

    x=g_i(t), y=h_i(t), for t running from 0 to 1,

whichever seems suitable for the type of curve. (If a non-parametric form
seems suitable, it may be necessary to split the curves at vertical tangents
to make certain the non-parametric form exists for each curve.)

The idea is to sum the signed areas of "quadrilaterals" of the following
form:

    (x(i-1),y(i-1))
         *
         |\
         | -_              (x(i),y(i))
         |   --__              _*
         |       ----______---- |
         |                      |
         |                      |
         |                      |
         *----------------------*
     (x(i-1),0)              (x(i),0)

E.g. Consider the diagram:

                __-------__
             A *           * B
               |\         /|
               | \       / |
               |  \     /  |
               |   \   /   |
               |    \ /    |
               |   C *     |
               |     |     |
               |     |     |
               |     |     |
             D *-----*-----* E
                     F

The area of the polygon ABC is equal to area(ABED)-area(BCFE)-area(CADF).
(The signs are determined by whether X increases or decreases as we go along
the edge.)

The signed areas required are in fact simply integrals. In the case of a
non-parametric curve, the integral required is:

      / x(i)
     |
     | f_i(x)dx.
     |
    / x=x(i-1)

In the case of a parametric curve, it is:

      / 1       / 1
     |         |
     | ydx  =  | h_i(t)g_i'(t)dt,
     |         |
    / t=0     / t=0

where g_i'(t) is the derivative of g_i(t).

I can't be much more specific than this without knowing what exactly the
curves used are and how they are specified. A simple example is when the
curve is simply a straight line segment. This is most easily dealt with
using a parametric form, namely x=g_i(t)=(1-t)*x(i-1)+t*x(i),
y=h_i(t)=(1-t)*y(i-1)+t*y(i). This gives g_i'(t)=x(i)-x(i-1), and hence a
signed area of

      / 1
     |
     | ((1-t)*y(i-1)+t*y(i))*(x(i)-x(i-1))dt
     |
    / t=0

                       / 1
                      |
    = (x(i)-x(i-1)) * | (y(i-1) + (y(i)-y(i-1))*t)dt
                      |
                     / t=0

                      [                                  ] 1
    = (x(i)-x(i-1)) * [ (y(i-1)*t + (y(i)-y(i-1))*t*t/2) ]
                      [                                  ] t=0

    = (x(i)-x(i-1)) * ( y(i-1) + (y(i)-y(i-1))/2 )

    = (x(i)-x(i-1)) * (y(i-1)+y(i))/2.

This gives the area of a straight-edged polygon as:

    SUM (i=1..N) (x(i)-x(i-1))*(y(i)+y(i-1))/2

    = SUM (i=1..N) (x(i)*y(i-1)-x(i-1)*y(i))/2

(by cancelling out the +x(i)*y(i) from each term with the
-x((i+1)-1)*y((i+1)-1) from the next term).

These are of course the formulae that various people have given before.

If the edges are more complicated curves, the mathematics becomes
correspondingly more complicated. For instance, if the edge is a Bezier
curve, g_i and h_i will both be third degree polynomials and so the function
h_i(t)g_i'(t) will be a fifth degree polynomial. This is essentially easy,
but involves more mathematics than I want to type!

I have not worked out the details of circular arcs - the best way to do the
integration may well depend on how you are specifying the arc. But the
technique above should work.

Finally, areas obtained by this technique will have the same properties as
those given by the SUM (i=1..N) (x(i)*y(i-1)-x(i-1)*y(i))/2 formula. E.g.
they are positive if the polygon is traversed clockwise, negative if
anti-clockwise; for self-intersecting polygons, they will be SUM (components
of polygon) ((area of component)*(winding number of polygon around
component)).

David Seal

Acorn Computers Ltd.,
Fulbourn Road,
Cambridge CB1 4JN,
U.K.

<insert standard disclaimers>