Tuesday, May 30, 2023

Sphere Cluster

We can generate 3D clusters in a similar way to the previous post, but using a hyperbolic regular polyhedron tiling instead of a hyperbolic regular polygon tiling. We can continue to use this 2D diagram as a guide:

We define the outer green circle as radius 1, and the offset green circle l2 has its centre at a distance L=sqrt(1+R^2) where R is the solution to:

 R/theta = sqrt(1+R^2)/sin(pi/2 + pi/m)

where theta is the angle from the polyhedron centre to the nearest face edge and m is the number of polyhedrons that meet at each edge. There are two good polyhedrons to use here, the dodecahedron and the icosahedron, their values and resulting formula are: 

 Dodecahedron: 

  • theta = atan2(phi+2, 2phi + 2 + 1/phi)
  • m      = 4
  • R      = sqrt(2)/sqrt(-2 + cosec^2(theta))
Icosahedron:
  • theta = atan2(phi, 1+2phi)
  • m      = 3
  • R      = 2/sqrt(-4 + cosec^2(theta))
Where phi is the golden ratio, and the inner red circle has radius r=L-R.

To render in 3D we want to do something better than just an inside-outside test, we want to approximate the distance to the nearest surface. It goes roughly like this... invert each query point p around the red radius r sphere then:

  1. rotate the point to a be radially in one single polyhedron face*
  2. if it is inside l2 you invert it around l2
  3. if its magnitude is less than rk (plus a skin width) then divide by rk and then invert around l4 = sqrt(r), sending the red sphere to the outer green unit sphere
  4. once you are out of iterations return the distance to the centre sphere rk, multiplier by a scale factor that is initialised to 1 and grows in proportion to all transformations of p in the above steps
* this is a bit harder in 3D than 2D. The simplest I can think of is to fold the point around the planes defined by the origin and each edge of the chosen face. For the dodecahedron the chosen face has vertices in order: (1/phi,0,phi), (1,-1,1), (phi, -1/phi,0), (phi,1/phi,0), (1,1,1). For the icosahedron the three vertices are (0,1,phi), (0,1,-phi), (phi,0,1). The planes can be generated using the cross product of adjacent vertices. I found that for the dodecahedron you just need to fold around each edge twice to guarantee the point ends up radially in the specified face, and for the icosahedron you need to do it three times. 

The direction to the l2 sphere centre is then the direction to this face centre, which is the mean of the above vertices.

The resulting approximate signed distance function to the shape's surface is sampled in Fragmentarium in order to generate a rendering of the shape with lighting and shadows. 

Here is the result for the dodecahedral cluster, with k values from 0.7 up to 1:





Here against a black background, a close up of k=0.7:
and k=0.8:
and k=0.1:

For the icosahedral cluster, here are k values of 0.7 up to 1:




Both the decahedral and the icosahedral become cluster-sponges at k=1, and are very spikey and visually less rough. We can make the shape less spikey at higher k by alternating between the dodecahedral and the icosahedral clusters. Since they are duals of each other, we should expect that to do the opposite of lining up subclusters. 

There are two versions depending on which shape you start with. Here starting with the dodecahedral with k from 0.8 up to 1:




a close up at k=1:

Here we start with the icosahedral shape, k = 0.7 to 1:





It is a bit hard to render this fractal for k>=1, but if you replace the final distance calculation with a slightly smaller sphere distance then it makes no difference to the limit set, and avoids some rendering artifacts for k>1, which is when the shape changes from a cluster to a sponge.

So here is the icosahedral fractal for k=1 and k=1.3:




and the dodecahedral from k=1 up to k=1.6:



If you toggle between icosahedral and dodecahedral, it is a bit more organic looking:

k=1.1 starting dodecahedral:
k=1.2


Starting icosahedral, k=1.1:
k=1.16
k=1.17

Sunday, May 28, 2023

Disk Cluster 2

 In a previous post I was making cluster fractals because these are quite rarely found in fractal examples. Moreover, I was making clusters that are nowhere differentiable (from the outside), which is the purest sort of fractal boundary because everywhere has the same fractal property, with no smooth regions. 

The only problem with these clusters is that they were a little too heavily constructed, and so don't transfer to 3D in any obvious or simple way. 

This post however constructs the cluster based on a very small number of symmetries. It uses two different sphere inversions, octagonal symmetry and a single scale factor k. As such, it makes a proper Kleinian group limit set. To describe it I borrow from figure 6 of this Kajino paper:

We define the outer green circle as radius 1, and the offset green circle l2 is at a distance L=sqrt(1+R^2) where R is its radius: R=2/sqrt(-4 + cosec^2(pi/n)), and n is the polygon number of sides, here it is n=8. The inner red circle has radius r=L-R.

To test if a point is inside or outside the cluster, first you invert the point around the purple circle then:

  1. rotate the point to the first octant (in line with the circle l2)
  2. if it is inside l2 you invert it around l2
  3. if its magnitude is less than rk then divide by rk and then invert around l4 = sqrt(r), sending the red circle to the outer green unit circle
repeat until its magnitude is > 1 (black) or you run out of repetitions (white).

For k=0.9 we get:
For k=1 we get:

and for k=1.1 we get:
Actually this last picture uses slightly less than 1.1 as we need to tweak the value for circles to match properly. I don't have the exact analytic value for k here, but it is very close to k=1.0985.

In terms of fractal classes these are a cluster, a cluster-sponge and a cluster-foam respectively. The first differs from the previous cluster in that the subclusters closer to the centre don't form a uniform pattern, and because it is a proper Kleinian group it generalises cleanly to the two other structures pictured above.

The value of n doesn't have to be 8 but it needs to be more than 6, so here are clusters for n=7 and n=9, both for k=0.8:

Here are the cluster-sponge versions (k=1):

One thing to note about these cluster-sponges it that they are very spikey. That is because the sub-cluster orientation lines up with its parent, causing a cascade of disks all in a row. 

We can avoid that by rotating each point by pi/n in step 3, here for n=8 for comparison with the first three images:

This latter image is again slightly away from k=1.1, at approximately k=1.096. Here's a high resolution close up:


Notice that these are all less spikey, and the k=1 case is no longer a cluster-sponge, so can have larger sub-clusters before touching. In the n=7 case the touch point happens around k=1.064:

For fun here's the prior n=8 image coloured by iteration depth:


The next step is to bring this formulation across to three dimensions. I cover this in the next post, but as a quick preview:

There are basically two ways to do this, we can use a hyperbolic tiling of an icosahedron or a dodecahedron. Here I'm using an icosahedron, which give 20 subclusters (one for each face).

The above image is a sphere at each icosahedron in a hyperbolic tiling, only the tiling has been sphere inverted, sending all radii r to 1/r. We use a value of k of roughly 0.5 above.

We then need to recurse inside each sphere, like so:


For larger k, around 0.8:
and k=1

Here's close up around k=0.8: