Square made these super cool shirts for Pride 2015 that filled in the negative space around the Square logo with rainbow bands of circles. This project is one way to automate that process.
This isn't really the sphere packing problem in the pure, mathematical sense. The actual sphere packing problem aims to find an optimal solution, filling a region with the greatest number of spheres of some size possible. Instead, we only want to make a patch of circles that is relatively dense in the middle and decreases in density as you approach the edge, while avoiding the areas blocked by an image (which we represent with a 2d numpy array).
For "packing" the circles, we'll use the "growing circles" method described here. Basically, we create circles that grow until they cannot grow any more, iteratively adding tiny circles to the canvas:
block_mask := input image mapped to a 2d boolean matrixTo make the patch centrally dense, we take the following two measures:
Without further ado, some results:
Of course, we can't do all this without reproducing the original!
The final step of this would be to make it shirt-able. The version below is segmented into 7 colors (using a simple mod operation) with entropy inversely proportional to circle size, producing a slightly more gradient look than the simple segmentation step allows for.