Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Computing circle intersections in O( (n+s) log n)

I'm trying to figure out how to design an algorithm that can complete this task with a O((n+s) log n) complexity. s being the amount of intersections. I've tried searching on the internet, yet couldn't really find something.

Anyway, I realise having a good data structure is key here. I am using a Red Black Tree implementation in java: TreeMap. I also use the famous(?) sweep-line algorithm to help me deal with my problem.

Let me explain my setup first.

I have a Scheduler. This is a PriorityQueue with my circles ordered(ascending) based on their most left coordinate. scheduler.next() basically polls the PriorityQueue, returning the next most left circle.

public Circle next()
{ return this.pq.poll();    }

I also have an array with 4n event points in here. Granting every circle has 2 event points: most left x and most right x. The scheduler has a method sweepline() to get the next event point.

public Double sweepline()
{ return this.schedule[pointer++];    }

I also have a Status. The sweep-line status to be more precise. According to the theory, the status contains the circles that are eligible to be compared to each other. The point of having the sweep line in this whole story is that you're able to rule out a lot of candidates because they simply are not within the radius of current circles.

I implemented the Status with a TreeMap<Double, Circle>. Double being the circle.getMostLeftCoord().

This TreeMap guarantees O(log n) for inserting/removing/finding.

The algorithm itself is implemented like so:

Double sweepLine = scheduler.sweepline();
Circle c = null;
while (notDone){
    while((!scheduler.isEmpty()) && (c = scheduler.next()).getMostLeftCoord() >= sweepLine)
        status.add(c);


    /*
     * Delete the oldest circles that the sweepline has left behind
     */
    while(status.oldestCircle().getMostRightCoord() < sweepLine)
        status.deleteOldest();

    Circle otherCircle;
    for(Map.Entry<Double, Circle> entry: status.keys()){
        otherCircle = entry.getValue();
        if(!c.equals(otherCircle)){
            Intersection[] is = Solver.findIntersection(c, otherCircle);
            if(is != null)
                for(Intersection intersection: is)
                    intersections.add(intersection);
        }
    }

    sweepLine = scheduler.sweepline();
}

EDIT: Solver.findIntersection(c, otherCircle); returns max 2 intersection points. Overlapping circles are not considered to have any intersections.

The code of the SweepLineStatus

public class BetterSweepLineStatus {

TreeMap<Double, Circle> status = new TreeMap<Double, Circle>();

public void add(Circle c)
{ this.status.put(c.getMostLeftCoord(), c);     }

public void deleteOldest()
{ this.status.remove(status.firstKey());    }

public TreeMap<Double, Circle> circles()
{ return this.status;       }

public Set<Entry<Double, Circle>> keys()
{ return this.status.entrySet();    }

public Circle oldestCircle()
{ return this.status.get(this.status.firstKey());   }

I tested my program, and I clearly had O(n^2) complexity. What am I missing here? Any input you guys might be able to provide is more than welcome.

Thanks in advance!

like image 686
xrdty Avatar asked May 08 '14 17:05

xrdty


People also ask

How do you solve for intersection of a circle?

To do this, you need to work out the radius and the centre of each circle. If the sum of the radii and the distance between the centres are equal, then the circles touch externally. If the difference between the radii and the distance between the centres are equal, then the circles touch internally.

What is the intersection of a circle?

Two circles may intersect in two imaginary points, a single degenerate point, or two distinct points. The intersections of two circles determine a line known as the radical line.

How many intersections can a circle have?

Similarly for each pair of circle can at the max intersect at 2 points. Therefore if you have m circles there can be mC2 pairs of circles each with 2 intersections. So the total number of intersections will be 2*mC2.


2 Answers

You can not find all intersection points of n circles in the plane in O(n log n) time because every pair of circles can have up to two distinct intersection points and therefore n circles can have up to n² - n distinct intersection points and hence they can not be enumerated in O(n log n) time.

One way to obtain the maximum number of n² - n intersection points is to place the centers of n circles of equal radius r at mutually different points of a line of length l < 2r.

Intersecting circles

like image 118
Daniel Brückner Avatar answered Sep 22 '22 00:09

Daniel Brückner


N circles with the same centre and radius will have N(N-1)/2 pairs of intersecting circles, while by using large enough circles so that their boundaries are almost straight lines you can draw a grid with N/2 lines intersecting each of N/2 lines, which is again N^2. I would look and see how many entries are typically present in your map when you add a new circle.

You might try using bounding squares for your circles and keeping an index on the pending squares so that you can find only squares which have y co-ordinates that intersect your query square (assuming that the sweep line is parallel to the y axis). This would mean that - if your data was friendly, you could hold a lot of pending squares and only check a few of them for possible intersections of the circles within the squares. Data unfriendly enough to cause real N^2 intersections is always going to be a problem.

like image 25
mcdowella Avatar answered Sep 22 '22 00:09

mcdowella