Message Boards Message Boards

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

Voronoi cells of stereographically projected pattern

Caught

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:

Stereo[p_] := p[[;; -2]]/(1 - p[[-1]])

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},
   Table[
    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"}},
 Manipulate[
  VoronoiMesh[
   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]]]},
   ImageSize -> 540, Background -> cols[[-1]]],
  {?, 0, ?}
  ]
 ]
4 Replies
Posted 7 years 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.

POSTED BY: J. M.
Posted 7 years 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! :)

POSTED BY: J. M.

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.

enter image description here - Congratulations! This post is now a Staff Pick as distinguished by a badge on your profile! Thank you, keep it coming!

POSTED BY: EDITORIAL BOARD
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract