A simple algorithm that measures the distance of existing disks from a new, candidate disk, while decreasing radius size.

The following two functions generate a random point in the unit disk and measures the distance to all existing disks.

```
randomPoint = Compile[{{r, _Real}}, Module[
{u = RandomReal@{0, 1 - 2 r}, a = RandomReal@{0, 2 Pi}},
{Sqrt@u*Cos[a 2 Pi], Sqrt@u*Sin[a 2 Pi]}],
Parallelization -> True, CompilationTarget -> "C", RuntimeOptions -> "Speed"];
distance = Compile[{{pt, _Real, 1}, {centers, _Real, 2}, {radii, _Real, 1}},
(Sqrt[Abs[First@# - First@pt]^2 + Abs[Last@# - Last@pt]^2] & /@ centers) - radii,
Parallelization -> True, CompilationTarget -> "C", RuntimeOptions -> "Speed"];
max = .08; (* largest disk radius *)
min = 0.005; (* smallest disk radius and step size *)
pad = 0.005; (* padding between disks *)
tolerance = 1000; (* wait this many rejections before decreasing radius *)
color = ColorData["BlueGreenYellow"];
centers = radii = {};
Do[failed = 0;
While[failed < tolerance,
pt = randomPoint@r;
dist = distance[pt, centers, radii];
If[Min@dist > r + pad,
centers = Join[centers, {pt}];
radii = Join[radii, {r}];,
failed++;
]];, {r, max, min, -min}]
Graphics[{color@RandomReal[], #} & /@ MapThread[Disk, {centers, radii}],
AspectRatio -> 1, Frame -> False, PlotRange -> {{-1, 1}, {-1, 1}},
PlotRangePadding -> Scaled@.02, Axes -> False, ImageSize -> 400]
```

By increasing tolerance one can achieve more dense packings, using of course more time. With various min/max radius values and paddings, I got the following packings:

**Concerning other, possibly irregular shapes**

Since OP requested other shapes, here is my solution for any, possibly irregular polygon. While the `distance`

function remains intact, this approach requires a new `randomPoint`

function that draws random points from the $(x, y)$ range of the polygon coordinates from inside the shape (thanks to rm -rf).

The function `randomPoint`

expects a single polygon (with no holes) or a list of polygons (where the first is the outer boundary shape and the rest are the holes):

```
randomPoint[r_, {in_Polygon, ex___Polygon}] := Module[{p, range},
range = {Min@#, Max@#} & /@ Transpose@First@in;
While[(p = RandomReal /@ range; Not@And[
Graphics`Mesh`InPolygonQ[in, p],
And @@ (Not@Graphics`Mesh`InPolygonQ[#, p] & /@ {ex})]
),]; p];
randomPoint[r_, poly_Polygon] := randomPoint[r, {poly}];
max = 1; (* largest disk radius *)
d = 0.01; (* smallest disk radius and step size *)
pad = 0; (* padding between disks *)
tolerance = 300; (* wait for this many rejections before decreasing radius *)
color = ColorData@"BlueGreenYellow";
shape = Polygon@N@(First@First@CountryData["Australia", "SchematicPolygon"]);
centers = radii = {};
Do[failed = 0;
While[failed < tolerance,
pt = randomPoint[r, shape];
dist = distance[pt, centers, radii];
If[Min@dist > r + pad,
centers = Join[centers, {pt}];
radii = Join[radii, {r}];,
failed++;
]];, {r, max, d, -d}];
{
Graphics[{EdgeForm@Gray, FaceForm@White, shape}, ImageSize -> 300],
Graphics[{color@RandomReal[], #} & /@ MapThread[Disk, {centers, radii}],
ImageSize -> 300]}
```

For shapes with holes, I used Szabolcs's conversion to polygons:

```
shape = Block[{fun, g, xmin, xmax, ymin, ymax},
fun = ListInterpolation@
Rasterize[Style[Rotate["β", -Pi/2], FontSize -> 24,
FontFamily -> "Times"], "Data", ImageSize -> 300][[All, All, 1]];
{{xmin, xmax}, {ymin, ymax}} = fun@"Domain";
g = RegionPlot[fun[x, y] < 128, {x, xmin, xmax}, {y, ymin, ymax},
PlotPoints -> 50, AspectRatio -> Automatic];
Cases[Normal@g, Line[x___] :> Polygon@x, Infinity]
];
```

Result with `{max = 3, d = .05}`

is:

4

You can take a look here and here as a start.

– Öskå – 2014-01-13T13:00:57.6938

Somewhat related is a word cloud. Functions used there could be easily adapted to disks.

– István Zachar – 2014-01-13T13:27:29.9331randomly place the largest circles, then place successively smaller ones where they can fit. Its quite straigntforward, and really this feels like a "give me some code" question.. – george2079 – 2014-01-13T13:49:33.207

4Thanks for links above, I'll try to find some ideas there. @george2079, no, its not that straightforward. I have a version in another language that is my test bed, it produces a solid output, but I want a little intellectual stimulation from other people here, in order to create a working and beautiful solution at the end. – VividD – 2014-01-13T14:09:26.807

I'm not sure the irregular shapes and fonts are not hand-made... – István Zachar – 2014-01-14T08:41:23.570

Shapes are handmade. They are paintings sold like any other paintings. The author says he needs around 4 hours to make one (if I remember well, maybe I am mistaken). – VividD – 2014-01-14T11:05:56.443

1

Off-topic here admittedly, but I'm posting this Gist just in case anyone finds this page when looking for a JS solution to the same problem (as I did). This script loads an SVG shape and generates the circles to fit within it. https://gist.github.com/gouldingken/8d0b7a05b0b0156da3b8

– goulding – 2015-07-03T14:09:14.010@goulding I have seen javascript snippets on this site before a few times, and generally such a comparison is appreciated. I downloaded your files, but simply opening index.html in a browser did not display anything for me. I changed the path js/main.js to circlePackShape.js but that didnt work. Maybe this is really basic stuff, but still it would be nice for our users if you could make it easier to run for a js novice. If you don't want to put a readme on the github because you also have other audiences in mind, perhaps you can post an answer here. <temporary message> – Jacob Akkerboom – 2015-07-05T10:14:17.853

don't pay attention on numbers, and colors at allWhat numbers and colors are you talking about? :o) – hftf – 2015-09-29T20:10:01.723