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

Posted 1 year ago
2121 Views
|
4 Replies
|
6 Total Likes
|
 CaughtContinuing with the stereographic projection theme. This time, I generated a bunch of points arranged in spirals on the sphere, like so: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
Sort By:
Posted 11 months ago
 - Congratulations! This post is now a Staff Pick as distinguished by a badge on your profile! Thank you, keep it coming!
Posted 11 months ago
 Here are some quick tips for your future artwork: 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}]. 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 11 months ago
 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 11 months 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.
Community posts can be styled and formatted using the Markdown syntax.