I have a graphic picture which is an annulus and I need to map it conformally onto a cylinder.
The real math problem is to map a punched plane onto a cylinder conformally. I am given a part of a plane near the origin. The origin is removed. So, I take a bigger disc around the origin and remove another tiny disc around the origin. Then I am left with the annulus. Now I want to map this annulus onto a cylinder. I tried Texture but the best I could do is to wrap a square around a cylinder. I ether need to cut the annulus, map it conformally onto a square first and then use Texture. Here I got stuck with conformal mapping. How to map conformally a cut annulus on a square? Is there a better way how to do this mapping/texture directly? Thank you!

  • $\begingroup$ Can you post the code you've tried? $\endgroup$ Oct 5, 2017 at 9:58

1 Answer 1


Here is what I tried to get a conformal parameterization from an annulus to a cylinder with Mathematica.

First I make an ansatz, transforming polar coordinates to cylindrical ones, where I use the offset function h in the axial direction as degree of freedom.

zz = {z[[1]], z[[2]]};
f = z \[Function] Evaluate[Module[{r, \[Phi]},
     {r, \[Phi]} = ToPolarCoordinates[zz];
     {R Cos[\[Phi]], R Sin[\[Phi]], h[r]}]

Next, I compute the Riemannian metric that is generated via pullback along the ansatz f.

metric = D[f[zz], {zz, 1}]\[Transpose].D[f[zz], {zz, 1}] /. Power[zz.zz, p_] :> r^(2 p) // Simplify;

The map f is conformal if and only if metric is a diagonal matrix with both entries on the diagonal being equal. Hence, I try to find h by letting the off-diagonal entries vanish (note that metric is symmetric, so that metric[[1, 2]] and metric[[2, 1]] coincide):

sol = Solve[metric[[1, 2]] == 0 /. z[[1]]^2 -> r^2 - z[[2]]^2, Derivative[1][h][r]];
dsol = DSolve[Equal @@ #, h[r], r] & /@ sol[[All, 1]] /. r -> Sqrt[z[[1]]^2 + z[[2]]^2];
f1 = z \[Function] Evaluate[f[zz] /. dsol[[1, 1]] // Simplify]
f2 = z \[Function] Evaluate[f[zz] /. dsol[[2, 1]] // Simplify]

(* Function[z, {(R z[[1]])/Sqrt[z[[1]]^2 + z[[2]]^2], (R z[[2]])/Sqrt[z[[1]]^2 + z[[2]]^2], C[1] - 1/2 R Log[z[[1]]^2 + z[[2]]^2]}] *)
(* Function[z, {(R z[[1]])/Sqrt[z[[1]]^2 + z[[2]]^2], (R z[[2]])/Sqrt[z[[1]]^2 + z[[2]]^2], C[1] + 1/2 R Log[z[[1]]^2 + z[[2]]^2]}] *)

Aha, this seems to work. Let's test the results:

D[f1[zz], {zz, 1}]\[Transpose].D[f1[zz], {zz, 1}] // Simplify
D[f2[zz], {zz, 1}]\[Transpose].D[f2[zz], {zz, 1}] // Simplify

(* {{R^2/(z[[1]]^2 + z[[2]]^2), 0}, {0, R^2/(z[[1]]^2 + z[[2]]^2)}} *)
(* {{R^2/(z[[1]]^2 + z[[2]]^2), 0}, {0, R^2/(z[[1]]^2 + z[[2]]^2)}} *)

That's it! Note that we have only one integration constant C[1]. This tells us that the ratio of inner to outer radius of the annulus must correspond in some way to the aspect ratio of the cylinder.

This is how it can be used in practice:

texcoordfun =  X \[Function] Evaluate[{1/2, 1/2} + 1/11 zz /. Solve[f1[zz] == {X[[1]], X[[2]], X[[3]]}, {z[[1]], z[[2]], R}][[4]] /. C[1] -> 1];
tex = Texture[ExampleData[{"TestImage", "Apples"}]];
gr = RevolutionPlot3D[{1, 0, t}, {t, 0, 1}, Mesh -> None, PlotStyle -> White];
gc3D = Cases[gr, _GraphicsComplex][[1]];
texcoords = texcoordfun /@ gc3D[[1]];
AppendTo[gc3D, VertexTextureCoordinates -> texcoords];
gc2D = gc3D;
gc2D[[1]] = texcoords;
Graphics[{tex, gc2D}]
Graphics3D[{tex, gc3D}]

enter image description here

enter image description here

  • $\begingroup$ Thank you so much! It works! I'll post my attempt to write such a code and ask few more details later. $\endgroup$
    – Masha
    Oct 6, 2017 at 18:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.