I think the main problem is that ArcTan
runs from $-\pi$ to $\pi$, but the DataRange
in the x
direction runs from 0
to 1
, so you're actually using 6 and a bit copies of the original image to cover the whole circle. This is easily fixed by specifying explicit values for DataRange
, i.e.
Manipulate[
With[{sectors = 8},
ImageTransformation[
ImagePad[im, {{-x, x}, {-x, x}}, Padding -> "Reversed"],
Function[{pt}, {ArcTan[-#2, #1] & @@ (pt), Norm[pt]}], 250,
DataRange -> {Pi/sectors {-1, 1}, {0, 1}},
PlotRange -> {{-2, 2}, {-2, 2}}, Padding -> "Reversed"]], {x, 0,
100, 5}]

Here, sectors
is the number of sectors in the transformed image.
Edit
Note that while ImageTransformation
works it isn't very fast. If you are using Mathematica 8 you could use for example ParametricPlot
in combination with TextureCoordinateFunction
to get a similar but faster result.
First, we need a source image for the Texture
. To get the right tiling where two neighbouring images are each other's reflection, I'm using the following:
imReflected = ImageAssemble[{
{ImageReflect[im, Bottom], ImageRotate[im, Pi]},
{im, ImageReflect[im, Left]}}]

Next, we need a TextureCoordinateFunction
. To get the reflections of the shifted image in the circles r=a
and the radial lines t=b
where a
and b
are integers I'm using a triangle wave with period 2 and amplitude 1/2 which is vertically shifted by some offset corresponding to x
in the solution above.
func[p_, x_] := x + TriangleWave[{0., 1/2.}, p/2 - 1/4]
The transformed image can then be plotted according to
Manipulate[
ParametricPlot[{r Cos[2 Pi/sectors t], r Sin[2 Pi/sectors t]},
{r, 0, 3}, {t, 0, sectors},
Mesh -> None, BoundaryStyle -> None,
Axes -> False,
PlotStyle -> {Opacity[1], Texture[imReflected]},
TextureCoordinateFunction -> ({func[#4, x], func[#3, x]} &),
TextureCoordinateScaling -> False,
PerformanceGoal -> "Quality",
PlotPoints -> {4, 1 + Round[40, sectors]},
PlotRange -> {{-2, 2}, {-2, 2}}],
{x, 0, 1},
{{sectors, 6}, 4, 10, 2}]

Note that for the best result the number of plot points in the r
and t
direction should be one plus a multiple of the number of rings and sectors, respectively.
Edit
Inspired by faleichik's answer below, I've decided to implement his solution using textured triangles. There are basically two different triangles in the tessellation, one being the mirror image of the other. The other triangles are rotated and/or translated copies of either of these triangles which can be constructed from the base triangles using Rotate
and Translate
. Therefore, one way to get the tessellation is as follows:
Manipulate[
DynamicModule[{texcrds, base, hex, im},
im = ImageResize[ExampleData[{"TestImage", "Mandrill"}], 100];
texcrds = offset + {{0, 0}, {1, 0}, {1/2, Sqrt[3]/2}};
base = {Polygon[{{0, 0}, {1, 0}, {1/2, Sqrt[3]/2}},
VertexTextureCoordinates -> texcrds],
Polygon[{{0, 0}, {1, 0}, {1/2, -Sqrt[3]/2}},
VertexTextureCoordinates -> texcrds]};
hex = Rotate[base, #, {0, 0}] & /@ {0, 2 Pi/3, -2 Pi/3};
Graphics[{Texture[im],
Translate[Translate[hex, {{0, 0}, {3/2, -Sqrt[3]/2}}],
Tuples[{3 Range[0, n/2], Range[0, n] Sqrt[3]}]]},
PlotRange -> {{-1/2, 3 n/2 + 1/2}, {-Sqrt[3]/2, n Sqrt[3]}}]],
{{n, 3, "resolution"}, 1, 5, 1},
{{offset, 0}, 0, 2}]
