Common area of circles
davea at ieee.org
Thu Feb 4 18:27:16 CET 2010
Shashwat Anand wrote:
> I want to calculate areas.
> like for two circles (0, 0) and (0, 1) : the output is '1.228370'
> similarly my aim is to take 'n' co-ordinates, all of radius '1' and
> calculate the area common to all.
> The best I got was monte-carlo methods which is inefficient. Is there any
> other approach possible.
You start with a list of circles, each having center (a,b), and radius
(r). As you stated the problem, r is always 1, but I'll keep the
This is untested, and probably contains typos, at least.
I would do it with successively smaller squares. A square can be
described using center coordinates (x,y) , and length (s) of a side.
Each square can have three states: not included, partially included,
and fully included.
You build a list of squares, starting with one, the bounding square for
the first circle.
For each square in the list, you go through all the circles (each with
center a,b, and radius r), and for each circle decide if the square is
entirely within the circle, or partially. If it's fully included in all
of them, you add its area to the the accumulator, and drop it from your
list. if it's not included at all in one of them, you just drop it
from the list. (Note, be careful about modifying a list you're
iterating through -- make a copy)
After a pass through the list, the accumulator is a lower-bound for the
area, and the accumulator plus the areas of all the squares is an upper
bound. If these are close enough together, you terminate.
Otherwise you take the remaining squares in the list, split each into
four pieces, and end up with a list 4 times as long. And repeat the
loop, checking each square against each circle.
The only remaining question is how you decide for a given circle and a
given square which of the three states it's in. And it turns out you
can be pretty approximate in this, and it'll still converge. So you can
take a distance between (a,b) and (x,y), and compare it to r-s/2 and to
r+(s*0.707106781187). If it's greater than r+s*0.707106781187, no
intersection. If it's less than r-s/2, then the square's entirely inside.
Note that I used 0.707106781187 above, but you'd actually use sqr(0.5)
to whatever precision you needed. And if it's convenient to round it,
round it upwards; again it won't affect the result. I doubt if it
would matter in Python code, but you could even do the whole thing in
integers (avoiding the sqrt for distance calc), if you were careful
about the bounding formulas. That's premature optimization, however.
More information about the Python-list