EDIT: (my conclusion and thank you note) I want to thank you all guys for this unexpected intellectual and artistic journey. Hope you had fun and enjoyed it the same as I did.
I would like to generate a circle pack
that mimics this: (don't pay attention on numbers, and colors at all, at the moment I am interested in circle positions and radii only)
or this:
I am new in Mathematica, could you give me some guidance? Thnx.
EDIT: The question was strictly for planar case (and remains so), however I see @Jacob Akkerboom in his answer added a solution for 3D generalization (thanks!), and, speaking of that, I just want here to bring to your attention this picture:
EDIT 2: There are some applications of circle packing in irregular shapes, like this: (author Jerome St Claire, handpainted)
... and a font called Dotted: (author Maggie Janssen)
... and some logos:
... garden design:
... infographics:
... and these hypnotic images: (from percolatorapp)
Answer
replacing RandomReal
function in István's code with
u = RandomVariate[UniformDistribution[{0,1 - ((1 - 2 min)/(max - min) (r - min) + 2 min)}]]
leads to non-uniform distribution
Randomization for the angle can also be non-uniform:
randomPoint =
Compile[{{r, _Real}},
Module[{u =
RandomVariate[
UniformDistribution[{0,
1 - (-((1 - 2 min)/(max - min)) (r - min) + 1)}]],
a = RandomVariate[
UniformDistribution[{π/(max - min)^(1/10) (r - min)^(1/10),
2 π - π/(max - min)^(1/10) (r - min)^(
1/10)}]]}, {Sqrt@u*Cos[a 2 Pi], Sqrt@u*Sin[a 2 Pi]}],
Parallelization -> True, CompilationTarget -> "C",
RuntimeOptions -> "Speed"];
The same applies to color. I think that after playing for long enough with these distributions you may even get some beautiful shapes. The real challenge would be to build new compilable distributions based on some graphics, like the figures in your example, or even some edge-detected pictures.
Edit (thanks to Simon Woods). The same idea may be implemented much easier using Simon's approach. We just have to make the radius choice dependent on the distance to the border. Inside the main loop replace the definition of r
:
r = Min[max, d, m Exp[-(d/m)^0.2]]
This way the code respects fine details of the shape. You can see the the elephant's tail is drawn in small circles, which is common sense.
And it takes about 40 seconds to render all the zigs and zags of Norway's shoreline (set imagesize
to 500, max=10
, min=0.5
, pad=0.2
).
Further, changing Simon's definition of m
by adding a background value we can create distinguishable shapes in a pool of small circles:
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 = 20;(*largest disk radius*)
min = 0.5;(*smallest disk radius *)
pad = 1;(*padding between disks*)
color = ColorData["DeepSeaColors"];
timeconstraint = 10;
shape = Binarize@ColorNegate@ImageCrop@Rasterize@Style["A", FontSize -> 1000];
centers = radii = {};
Module[{dim, dt, pt, m, d, r},
dim = ImageDimensions[shape];
dt = DistanceTransform[shape];
TimeConstrained[While[True,
While[
While[
pt = RandomReal[{1, #}] & /@ dim;
(m = 3 + ImageValue[dt, pt]) < min];
(d = Min[distance[pt, centers, radii]] - pad) < min];
r = Min[max, d, m];
centers = Join[centers, {pt}];
radii = Join[radii, {r}]
], timeconstraint]]
Graphics[{color@RandomReal[], #} & /@ MapThread[Disk, {centers, radii}]]
And after that we can finally get to coloring (again, this is a modification of Simon's code):
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 = 8;(*largest disk radius*)
min = 2;(*smallest disk radius*)
pad = 1.5;(*padding between disks*)
color1 = ColorData["Aquamarine"];
color2 = ColorData["SunsetColors"];
timeconstraint = 10;
background = 7;
shape = Binarize@ColorNegate@Rasterize@Style["74", Bold, Italic, FontFamily -> "PT Serif", FontSize -> 250];
centers = radii = colors = {};
Module[{dim, dt, pt, m, d, r}, dim = ImageDimensions[shape];
dt = DistanceTransform[shape];
TimeConstrained[
While[True, While[While[pt = RandomReal[{1, #}] & /@ (2 dim);
(m = If[Norm[pt - dim] < 200, background, 0] + If[pt[[1]] < dim[[1]] 3/2 && pt[[1]] > dim[[1]]/2 && pt[[2]] < dim[[2]] 3/2 && pt[[2]] > dim[[2]]/2, ImageValue[dt, pt - dim/2], 0]) < min];
(d = Min[distance[pt, centers, radii]] - pad) < min];
r = Min[max, d, m ];
centers = Join[centers, {pt}];
radii = Join[radii, {r}];
colors =Join[colors, {Blend[{color2@RandomReal[{0.4, 0.7}], color1@RandomReal[{0.4, 0.7}]}, Piecewise[{{1/max*(m - background), m < background + max/2}, {1, m >= background + max/2}}]]}]];, timeconstraint]]
Graphics[MapThread[{#1, Disk[#2, #3]} &, {colors, centers, radii}]]
Comments
Post a Comment