Removing MC Escher from the projective plane

MC Escher in Cylindrical Coordinates

The goal of this project is to take a few of MC Escher's Circle Limit images, and look at them in a different model of the hyperbolic plane. I've selected the cylindrical version we've seen in class, which we were told is an area- preserving map.

Methods

I wrote the program to do this using Python 3, and manipulating the images as they are contained in files was done through the Pillow library.

To do this, I crafted a short computer program to take an image in the Poincaré model (which is the model Escher used to fashion his images), and attempt to place them in the cyindrical model we saw. Mapping each individual pixel in the image in the Poincaré model to a pixel on the cylinder would likely leave too many pixels in a small place near one end and leave the other mostly empty, so I decided to consider a grid of pixels on the cylinder, and for each pixel on the cylinder, I find which point on the Poincaré disc maps to that point on the cylinder.

Getting from the cylinder to the hyperboloid is a relatively simple matter. We consider cylinder coordinates to be given by an ordered pair \((\theta, h)\), where \(\theta\) is the angle and \(h\) is the height. We can get a triple \((x,y,z)\) on the cylinder from this pair by considering \((\cos{\theta},\sin{\theta},h)\).

Now, to get from the cylinder to the hyperboloid, we have a very simple mapping. We take the point \((\theta,h)\) to the point \((r\cos{\theta},r\sin{\theta},h)\), where \(r\) is given by \(\sqrt{t^2-1}\). We get this formula because we know that on the hyperboloid we must satisfy the equation \(x^2+y^2-t^2=-1\), which we rearrange to get \(x^2+y^2=t^2-1\), and we already have an \(x\) and \(y\), so we can find our \(t\) easily enough.

The next step has us find the point on the Poincaré disc. This is easy enough, as we've done this in class. Given \((x,y,t)\) on the hyperboloid, we project through the point \((0,0,-1)\), which once the algebra is done, takes \((x,y,t)\) to the point \((\frac{x}{t+1},\frac{y}{t+1})\) on the Poincaré disc.

Thus, we can write the entire transformation as something that takes \[ (\theta,h) \mapsto (x,y,h) \mapsto (x,y,t) \mapsto (x,y) \] which we write in full as \[ (\theta,h) \mapsto (\frac{\sqrt{h^2-1}\cos\theta}{h+1},\frac{\sqrt{h^2-1}\sin\theta}{h+1}) \]

Results

Some of the images are just the images as I found them on the internet and their projected forms, and others have been altered to give a better idea of what certain things map to. A couple images were created by me just to see what happens!

cli.png clo.png

These are the first images I attempted to do this to. The left is Escher's Circle Limit I, and the right is the result after transformation.

circle.png clo2.png

This is Escher's Circle Limit IV, before and after.

circle2.png clo4.png

Here, I colored a few of the bats from Circle Limit IV so that we can see exactly what maps to what.

circle3.png clo5.png

Next, I colored some vertical bats, so that we can really get a better idea of how things change

cli.png closh.png

In this, I decided to consider the projection starting not from the bottom of the hyperbola, but from a point higher up, so that more of the higher parts can be seen.

closh.png

This is the same image above, but stretched out horizontally and shrunk vertically. You can begin to see that the scrambled mess at the top really does represent the fish here.

orth.png ortho.png

For this one, I wanted to see what an arbitrary line in the Poincaré model mapped to.

base.png clo6.png

Here, I wanted to just play with an image and see what happened. It's pretty neat! We see a beautiful red pattern along the border because the black border circle (in the first image) was originally red, and the recoloring missed a few pixels along the inner border.

Caveats

It's pretty hard to see whether this projection really preserves areas (or whether Escher made a correct image) because each of the pixels is selected by the closest pixel on the Poincaré disc to the point mapped to by the cylinder. So, some regions are a pixel or two larger than they should be, others are a pixel or two smaller. This is also highly dependent on the resolutions of the images both going in and coming out. It's probably possible to create an arbitrary-precision version of this program, but that is beyond what I can reasonably accomplish in a few weeks of playing with this.

Another slight caveat is that the images must be square images where the Poincaré disc is the circle centered at the center of the image. It's a little tricky to make such an image but fortunately some other people have done so and posted their results on the internet.

Code

You can grab the script I used here