Common area of circles

Shashwat Anand anand.shashwat at gmail.com
Fri Feb 5 09:49:02 CET 2010


Here is my approach:
# input circles, remove duplicates, store them
# check whether all circle intersect:
    if no: print '0.0'
    if yes:
# calculate intersection points of two circles.
# check if that point lies in rest all circles
    if yes: store it as polygon-coordinates (hull)
    calculate area of curve from the given two points
# calculate final area : net area of curve + area of polygon
Here is my final code :
It's still Buggy (the logic I believe is correct, The implementation is
Buggy I guess
<Code>

import math

def catch_point(x, y):
    # checks for points which lie inside all the circles
    # stores all such point in hull
    kount = True
    for i in range(n):
        if (x - circle[i][0])**2 + (y - circle[i][1])**2 - 1.0 > 0:
            kount = False
    if kount == True:
        hull.append((x, y))

def curve_area(x0, y0, x1, y1, x2, y2):
    k = math.sqrt((x1 - x2)**2 + (y1 - y2)**2)
    area_c = math.pi * (math.degrees(math.acos(1.0 - k*k/2.0))/360) #TODO
Verify
    area_t = 0.5 * ( x0*(y1 - y2) - x1*(y0 - y2) + x2*(y0 - y1) )
    if area_t < 0:  area_t = -area_t
    area = area_c - area_t
    #print area
    return area

def polygon_area(p):
    # calculate area of the polygon given the co-ordinates
    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]])

def intersect_circles(l):
    # check whether all circle intersects or not
    for i in l:
        for j in l:
            if (i[0] - j[0])**2 + (i[1] - j[1])**2 >= 4.0:
                sol = 0.0
                return sol
                break
    return 1.0

def intersect_coordinates(l):
    sol = 0.0   # initialisation of final result
    for i in range(n):
        for j in range(n):
            # find all intersecting co-ordinates for each circle
            xa, xb = circle[i][0], circle[j][0]
            ya, yb = circle[i][1], circle[j][1]
            d = math.sqrt((xa - xb)**2 + (ya - yb)**2)
            if d == 0:  continue
            x1 = 0.5*(xa + xb) + 0.5*(yb - ya)*math.sqrt(4 - d*d) / d
            y1 = 0.5*(yb + ya) - 0.5*(xb - xa)*math.sqrt(4 - d*d) / d
            catch_point(x1, y1) # first intersection point
            x2 = 0.5*(xa + xb) - 0.5*(yb - ya)*math.sqrt(4 - d*d) / d
            y2 = 0.5*(yb + ya) + 0.5*(xb - xa)*math.sqrt(4 - d*d) / d
            catch_point(x2, y2) # second intersection point
        sol += curve_area(circle[i][0], circle[i][1], hull[-1][0],
hull[-1][1], hull[-2][0], hull[-2][1])
        # add up the value of curves
    return sol

t = int(raw_input())        # total no. of test cases
for test in range(t):
    n = int(raw_input())    # total no. of circles
    circle = []             # a blank list which will contain center of
circles
    hull = []               # a blank list which will consist of points on
convex polygon
    for i in range(n):
        x,y = [float(i) for i in raw_input().split()]
        circle.append((x,y))    # storing the value

    circle = list(set(circle))  # removing duplicates
    n = len(circle)             # calculating no. of non-duplicate circle
    sol = intersect_circles(circle)     #intersect_circles() check whether
all circle intersect
    if sol == 0.0:          # if sol == 0.0 means all circle do not
intersect
        print "0.000000"    # solution = 0.000000 in this case
    elif n == 1:            # if only 1 circle present, the solution is PI
        print "%.6f" %(math.pi)
    else:
        sol = intersect_coordinates(circle)        # for rest cases we need
to calculate intersection co-ordinates of circle
        print "%.6f" %(sol + polygon_area(hull))   # final solution

</Code>

sample output :
4
2
0 0
1 0
1.228370
3
0 0
0 0
0 0
3.141593
3
0 0
0 1
10 12
0.000000
3
0 0
1 0
0 1
0.192972

Either there is a redundency or there is some issue with this line : sol +=
curve_area(circle[i][0], circle[i][1], hull[-1][0], hull[-1][1],
hull[-2][0], hull[-2][1])

Still trying to fix it.
~l0nwlf

On Fri, Feb 5, 2010 at 11:48 AM, John Nagle <nagle at animats.com> wrote:

> Chris Rebert wrote:
>
>> On Thu, Feb 4, 2010 at 2:39 AM, Shashwat Anand <anand.shashwat at gmail.com>
>> wrote:
>>
>>> Given 'n' circles and the co-ordinates of their center, and the radius of
>>> all being equal i.e. 'one', How can I take out the intersection of their
>>> area.
>>>
>>
>> How is this at all specific to Python?
>>
>> This also sounds suspiciously like homework, which you should know
>> this list is unlikely to give direct answers to, though you might be
>> able to get a few pointers or some general suggestions.
>>
>
>    Good point.
>
>    This is actually a problem in what's called "constructive geometry".
> Usually, this is a 3D problem, for which the term "constructive solid
> geometry", or CSG, is used.  That's where to look for algorithms.
>
>    Yes, there are efficient algorithms and near-exact solutions.
> The basic idea is that you find all the points at which circles
> intersect, sort those by one coordinate, and advance across that
> coordinate, from one value of interest to the next.  Between any
> two values of interest you're dealing with areas bounded by arcs
> and lines, so the areas can be calculated analytically.  It's a
> lot like a rasterized polygon fill algorithm.
>
>    (I used to do stuff like this back when I did physics engines
> with efficient 3D collision detection.)
>
>                                John Nagle
> --
> http://mail.python.org/mailman/listinfo/python-list
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20100205/871aca2e/attachment.html>


More information about the Python-list mailing list