ポアンカレの円板をPythonで描画する

　ネットにあるかと思って探してみたけどなかったので自分で書く。

#ポアンカレの円板とは

　エッシャーのアレで有名なやつです。

　これから説明が長くなるので、Pythonで実装したものとソースコードが以下になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288125/391adda3-e68a-d570-c1b8-fc7a84f0cc4f.png)

```python
import numpy as np
import matplotlib.pyplot as plt

theta = np.linspace(0,2*np.pi,100)
colorlist = ["r","g","b","c","m","y"]

t = list(range(0,6))
for n in t:
    n2 = np.power(2,n)
    for phi in np.linspace(0,2*np.pi,2*n2+1):
        x = np.cos(theta)*np.tan(np.pi/n2) + np.cos(phi)/np.cos(np.pi/n2)
        y = np.sin(theta)*np.tan(np.pi/n2) + np.sin(phi)/np.cos(np.pi/n2)
        plt.plot(x,y,lw=0.5,color=colorlist[n-2])

for phi in np.linspace(0,2*np.pi,9):
    t = np.linspace(-2,2,100)
    x = t*np.cos(phi)
    y = t*np.sin(phi)
    plt.plot(x,y,lw=0.5,color='y')

plt.plot(np.cos(theta),np.sin(theta),color='black')
plt.xlim(-1,1)
plt.ylim(-1,1)
plt.show()
```

　これは無限に広がる双曲空間を1つの円板に閉じ込めたものと言われますが、これだけでは説明は不十分で、「平坦な空間」ではなく「双曲空間」を閉じ込めているのがミソかなと思います。

#双曲空間

　双曲空間とは直線が双曲線のようになる空間です。そもそも今目の前に見えている空間がまっすぐだからって、それが永遠にまっすぐ続くとは限らない訳です。地球だって丸いし。地表にある直線は惑星スケールで見ればすべて正円（正確には回転楕円体）なので、地球はすべての直線が円になる空間であると言えます。反対に、すべての直線が双曲線になってしまう空間があってもよいはずです。表にすると以下のようになります。

|空間の種類|三角形の内角の和|平行でない直線|平行な直線*|
|---|---|---|---|
|球面|＞180度|2点で交わる|交わらない|
|平面|=180度|1点で交わる|交わらない|
|双曲面|＜180度|1点で交わるか交わらない|交わらない|
*……まったく同じ直線である場合を除く

　ユークリッド平面（格子座標）上のグリッドが双曲線であるような空間を考えれば以下の条件を満たします。ユークリッド座標に転写するのと以下のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288125/84c4e9a0-fc27-0e59-7452-59030c15a630.png)

　端の方にある四角形が明らかに尖っているのがわかると思います。これでも角度を正しく反映していますが、全体像が見づらいので円板に**無理矢理**圧縮するとします。適当に無限遠$=1$としましょう。

ユークリッド平面$U$　→　双曲面$H$への垂直投影　→　原点への中心投影

　という手順によりこの圧縮はわりと自然に行うことができます。計算式も単純な相似で算出できます。変換後の座標系を$D$とします。

```math
U:[x_U,y_U] \longmapsto H:[x_H,y_H,z_H]\\
x_H = x_U\\
y_H = y_U\\
z_H = \sqrt{x_U^{2}+y_U^{2}+1}\\
```
```math
H:[x_H,y_H,z_H] \longmapsto D:[x_D,y_D,1]\\
x_D = \frac{x_H}{z_H}\\
y_D = \frac{y_H}{z_H}\\
```

　結果が以下：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288125/93b6988b-5aca-b763-6391-0d96ca9255b8.png)
※実際は無限本の直線がありますが、横41本縦41本に留めています

　見やすい！　このようなモデルを**クラインの円板**と言います。これは双曲線の漸近線と無限遠の交点を直線でつないでおり、ユークリッド的な感覚での位置関係はわかりやすいですが、各直線の角度を正確に反映していないというデメリットがあります（本来は90度以下で交わっている所も直角に見える）。

　そこで、今度は直線同士の角度を保ったまま円板に圧縮する操作をします。これによって得られるものが**ポアンカレ円板**と呼ばれるもので、以下の操作になります。

```math
D:[x_D,y_D,1] \longmapsto P:[x_P,y_P,0]\\
x_P = \frac{x_D}{1+\sqrt{1-x_D^{2}-y_D^{2}}}\\
y_P = \frac{y_D}{1+\sqrt{1-x_D^{2}-y_D^{2}}}\\
```

　結果が以下：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288125/789e005f-6843-71e2-ef57-bdf40f0d951e.png)

　各直線と無限遠（円周）の交点が直角になっていること、また直線同士の角度はユークリッド座標のそれと同一に保たれていることがわかります。

#グリッド以外への適用

　今までは双曲空間の説明のためグリッド（のように並んだ双曲線）がそのまま変換されたものを出していましたが、それ以外のものも変換してみます。以下のような双曲線の集合を考えてみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288125/17ab3653-8cc5-c427-c2b6-598e3a6e4f2a.png)

　いきなりサイケになりましたが、すべての線は双曲線なので落ち着いてください。

　これをクラインの円板上に変換すると、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288125/e3f99d91-d7f8-4376-3248-03111d915c7c.png)

　ポアンカレの円板上に変換すると、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288125/80e02caa-b359-dc73-4eb7-35642216f00a.png)

　こうなります。こうして最初に出した図形が描かれました。

　これらすべての図において、各直線で囲まれた図形の**辺の数・位置関係**といった位相的な関係は変わっていないことに注目ください。

##補足

　冒頭のソースコードでは、上のような煩雑な計算を経ずに円を描くことでポアンカレの円板を実現しています。もちろん双曲線に上のような変換を施すことでも結果的に円になり、ポアンカレの円板を作成できます。