Kissing Circles

I’m playing around with ideas from the book Mathographics by Robert Dixon. On pages 190-192 he has images of what he calls Condensation drawings. I call them Kissing Circles because the circles all touch each other at just one point – hopefully.

Here is my attempt. If you want to see something cool set the drop count to 1 and then use the right-arrow key to increment the drop count by one over and over so that you can see one drop at a time being added.

view source

The author, Robert Dixon, doesn’t provide the code for his examples. Just the concept and how he would go about writing an algorithm to solve a particular problem. For this one he suggested that each circle gets pushed into an array. Then for each new circle – randomly placed – you loop through the array of existing circles to see if it overlaps with any of them. If not then you have a new circle to add to the display. Otherwise create a new circle in a random location and test again.

Code outline
My approach follows this general idea. I created a KissingCircles class that accepts 5 parameters:

  • width, height, // area that the center of the circles can occupy
  • circleCount, // number of circles to draw
  • seed, // number that is used to seed the random number generator
  • maxRadius

After drawing an initial circle to get things started I start looping through a while-loop that keeps track of the number of times through the loop – runs – and the number of circles that are successfully created – count.

Each time through the loop I use my PseudoRnd class to pick a random numbers for the x/y postion of a new circle. I then use the BitmapData.getPixel() method to find the color at that point. If it is white then I know that there is no circle at that point. ( The background is white. )

I’m using the PseudoRnd class because I want to be able to recreate a pattern. If the seed remains the same then the pattern will always be exactly the same for the same number of circles.

If the space it clear to draw a circle then I need to fit it up against the nearest circle to that point. To do so I loop through all of the existing circles to find the one that it is closest to. Once I have the nearest circle I check and see if it is further away than the maxRadius. If not then I’m done. The new circle will be drawn right up against the nearest one.

But if it is further away then I need to reposition the circle so that it has a radius equal to maxRadius and is right up against the nearest circle. This is where the Math.atan2( y, x ) method comes in handy. ( Check out my Math.atan2( y, x ) Explorer for an example of how it works. )

Now we have a new circle that has been placed right up against the nearest circle. Since the new circle has been moved we need to make sure that it didn’t get dropped on top of an existing circle so once more through the loop of all existing circles with the checkOverlap() method.

That pretty much does it.

Code evolved
This approach evolved over time. Initially I didn’t have a value for the maxRadius. So each new circle was exactly the radius it needed to be in order to just kiss up against the nearest circle. That’s fine but if the new circle is a long way from the nearest circle it means that this new circle will be huge. It could take up most of the available space.

If I were doing this over from scratch I might try picking a random circle from the array of all existing circles and then fit a new circle up against it. I think that might run a little faster because it would remove some of the looping that is needed to make sure that circles don’t overlap.

Interesting additions
I think it would be cool to let each circle animate from a point size up to its calculated radius over time. That might be a neat effect.

Do you have any suggestions for how to improve this?