Message Boards Message Boards


[GIF] Caught (Voronoi cells of stereographically projected pattern)

Posted 1 year ago
4 Replies
6 Total Likes

Voronoi cells of stereographically projected pattern


Continuing with the stereographic projection theme. This time, I generated a bunch of points arranged in spirals on the sphere, like so:

Points on the sphere

Then I stereographically project the points to the plane and compute the Voronoi diagram of the resulting points. Throw in a rotation of the sphere and you get the above animation.

As for the code, first of all we need the stereographic projection map:


Next, we need to define the points. It turned out that without throwing in some noise in the definition of the points, VoronoiMesh[] would occasionally fail, which is why I put in the RandomVariate[] business in both cylindrical coordinates:

pts = With[{n = 20},
    CoordinateTransformData["Cylindrical" -> "Cartesian", "Mapping"]
     [{Sqrt[1 - (z + #)^2], θ + RandomVariate[UniformDistribution[{-.00001, .00001}]] 
         + (z + # + 2)/2 * π/2, z + #}
       &[RandomVariate[UniformDistribution[{-.00001, .00001}]]]
    {z, -.9, .9, 2/n}, {θ, 0, 2 π - 2 π/n, 2 π/n}]

Finally, then, here's the animation:

With[{cols = RGBColor /@ {"#F5841A", "#03002C"}},
   Stereo[RotationMatrix[θ, {1., 0, 0}].#] & /@ Flatten[pts, 1],
   {{-4.1, 4.1}, {-4.1, 4.1}}, PlotTheme -> "Lines", PlotRange -> 4, 
   MeshCellStyle -> {{1, All} -> Directive[Thickness[.005], cols[[1]]]},
  {θ, 0, π}
4 Replies
Posted 1 year ago

Yes, the implementation in my reply is intended for en masse application of the stereographic transformation. If I were implementing Stereo[], I would maintain both implementations, and use an argument check so that the applicable method is used.

That is: Stereo[pt_?VectorQ] := (* stuff *) would be the one-point case, corresponding to your implementation, and Stereo[pt_?MatrixQ] := (* stuff *) would be the many-point case, corresponding to my implementation.


Ah, that's a good point! Even after all these years, I think I still have a bit of a mental block about representations of vectors in Mathematica, but of course you're quite right that a list of vectors can be interpreted as a matrix whose rows are the given vectors.

I don't like your redefinition of Stereo[] as much: with your definition I can't apply it to a single point, only to a list of points. Of course, in this particular example I am applying to to a list of points, but this is a function that I reuse constantly, including in circumstances when I want to apply it to single points.

Posted 1 year ago

Here are some quick tips for your future artwork:

  1. The operation RotationMatrix[θ, {1, 0, 0}].# & /@ pts can be recast into a more efficient form with a little linear algebra. Briefly, if you are mapping a premultiplication by a matrix over a list of points, this is equivalent to postmultiplying the list of points by the transpose of the matrix. That is, A.# & /@ list is just the same as list.Transpose[A].

In this case, it is very fortuitous that the transpose of RotationMatrix[] takes on a very convenient form. To sum up, the compact version of this operation is pts.RotationMatrix[-θ, {1, 0, 0}].

  1. You can redefine your function Stereo[] so that it acts on a list of points en masse, instead of you having to map it over each point:

    Stereo[pts_?MatrixQ] := Drop[pts, None, -1]/(1 - pts[[All, -1]])

With these considerations, we can redo the heart of your code as

Stereo[Flatten[pts, 1].RotationMatrix[-θ, {1, 0, 0}]]

with Stereo[] defined for a list of points.

Anyway, nice artwork, as always! :)



Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
or Discard

Group Abstract Group Abstract