pythonとBlenderで完全自作プラネタリウムを作る

#はじめに
高校生という生き物はいつだって欲望に忠実である。
「星が見たい！」と言い出したのはいつ頃だったか。
よーしわかった。プラネタリウムを作ろう。

#目標
高校生が可能な範囲内でそれなりに良いものを作る。
作るものはプラネタリウムのドームと，恒星球と呼ばれる星の投影機。

#準備するもの
####恒星球
* PC（winでもmacでも，pythonとblenderが使えればよい）
* 厚紙
* 針
* のり
* 豆電球

####ドーム
* 段ボール
* ロール紙
* ガムテープ

#制作手順
####恒星球
ネット上にはいろいろな人がプラネタリウムを制作している様子をアップロードしているが，恒星球は[市販のもの](https://www.amazon.co.jp/%E3%83%94%E3%83%B3%E3%83%9B%E3%83%BC%E3%83%AB%E5%BC%8F-%E3%83%97%E3%83%A9%E3%83%8D%E3%82%BF%E3%83%AA%E3%82%A6%E3%83%A0-%E5%A4%A7%E4%BA%BA%E3%81%AE%E7%A7%91%E5%AD%A6%E3%83%9E%E3%82%AC%E3%82%B8%E3%83%B3%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-BESTSELECTION-%E5%A4%A7%E5%B9%B3%E8%B2%B4%E4%B9%8B/dp/4057002405/ref=sr_1_1?adgrpid=117887960524&dchild=1&hvadid=536131972069&hvdev=c&hvqmt=e&hvtargid=kwd-347352904514&hydadcr=27488_14464591&jp-ad-ap=0&keywords=%E3%83%97%E3%83%A9%E3%83%8D%E3%82%BF%E3%83%AA%E3%82%A6%E3%83%A0+%E5%A4%A7%E4%BA%BA%E3%81%AE%E7%A7%91%E5%AD%A6&qid=1627967154&sr=8-1)を使っているケースが多い。
だが，自分たちで作るからこそ価値があるというものだろう。

#####pythonの準備
最初にPCにpython3系をインストールする。
（分からない場合は[こちら](https://qiita.com/New_enpitsu_15/items/ee95bde0858e9f77acf0)）

ちゃんとpythonがPCで使えるようになっているか確認。
「win + r」でファイル名を指定して実行を立ち上げ，そこにcmdと打ち込むと黒い画面が出てくる。
そこに，pythonと入力

```terminal:cmd
C:\Users\user>python
```

enter。
python3系が立ち上がり

```:cmd
>>>
```

のようなものがでればOK。

:::note warn
出ない場合は恐らくPATHが通っていないので，環境変数を確認。
:::

次にmatplotlibをインストールする。
さきほどの黒い画面に

```:cmd
>>>exit()
```

と入力してpythonの対話モードを終了。
そのまま，

```terminal:cmd
C:\Users\user>python -m pip install matplotlib
```

と入力すれば，matplotlibがインストールできる。

#####atom上でpythonを実行する
次に，実際にpythonのプログラムを組むための環境を作っていく。
私のおすすめのエディタはatomなので，これを使うと想定しながら進める。

まず，[こちら](https://atom.io/)からatomをダウンロードする。
インストールが完了したら，atomを立ち上げ，左上のファイル，設定，インストールと進んでいく。
そうすると検索ボックスが出てくるので，そこに，atom-runnerと入力し，インストール。
これで，atom上でpythonを実行できるようになる。

ためしに新しいファイルtest.pyを作成し，以下のように入力してみる。

```python:test.py
print("Hello, World!!!!!")
```

そのまま，「Alt + r」で実行してみると，下のほうに

Hello, World!!!!!

と表示されるだろう。

#####二次元座標系への星のプロット
プログラムを組めるようにはなったが，星のデータがなければなにもできない。
今回は[ヒッパルコス星表](http://astronomy.webcrow.jp/hip/)に含まれる3215個分の星のデータを使用した。
ページに飛んでダウンロードを押すと，なんかよくわからない数字がたくさん出てくるとおもう。
これをすべてコピーして，atomに戻り，新しいファイルstar_plot.txtを作成してそこにペースト，保存する。

ここからは実際にプログラムを組んでいく。
まずは，先ほど保存した星の位置データを二次元座標系にプロットした画像データを作る。
実際に組んだものがこちら。

```python:star_plot.py
# -*- coding: utf-8 -*-

#各種ライブラリのインポート
import matplotlib.pyplot as plt
import math
import sys

#ヒッパルコス星表の入力は
# 0 HIP番号
# 1 赤経時
# 2 赤経分
# 3 赤経秒
# 4 赤緯符号
# 5 赤緯度
# 6 赤緯分
# 7 赤緯秒
# 8 等級
#となっている

#星の数
N = 3215
plot_data = []

#ヒッパルコス星表のデータを開く
with open('star_plot.txt', 'r', encoding='utf-8') as star:
    star_data = star.readlines()
    for i in range(N):
        #「,」でそれぞれのデータが区切られているため，「,」でデータを分割してリストに入れなおす
        star_data[i] = star_data[i].split(',')
        #赤経と赤緯で表されているデータを度に変換する
        a = float(float(star_data[i][1])*15 + float(star_data[i][2])*0.25 + float(star_data[i][3])*0.0042)
        b = float(float(star_data[i][5]) + float(star_data[i][6])/60 + float(star_data[i][7])/3600)
        #等級は小数点以下まで書かれているが，今回は整数値に丸めた
        c = int(round(float(star_data[i][8]), 0))
        #赤緯の符号がマイナス（0）のとき，
        if star_data[i][4] == "0":
            b = -b
        #等級が5以下の星だけを集める
        if c <= 5:
            plot_data.append([a,b,c,i])
star.close()

x = []
y = []
blt = []

for i in range(len(plot_data)):
    x_ = round(float(plot_data[i][0]), 1)
    y_ = round(float(plot_data[i][1]), 1)
    blt_ = plot_data[i][2]

    x.append(x_)
    y.append(y_)
    blt.append(blt_)

#matplotlibのグラフの設定
plt.figure(figsize=(36, 9), dpi=300)
plt.xlim(0, 360)
plt.ylim(-90, 90)
plt.axis("on")

#星の等級ごとに，プロットする点の色と大きさを変更する。
for i in range(len(plot_data)):
    s_ = (6 - blt[i])**3
    plt.scatter(x[i], y[i], s=s_, c=s_, cmap='spring', vmin=-50, vmax=343)
#png形式の画像として保存
plt.savefig("star_fig.png")

```


プログラムを「Alt + r」で実行すれば，以下のような画像ファイルができる。
![star_fig.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275927/b641cc64-d6d0-9532-13f0-902d09ce5957.png)


画像の左上からsinカーブに沿って，星が密集している部分があると思うが，これが天の川である。
また，x座標70，y座標0の付近にオリオン座が見える。
気づいた人もいるかもしれないが，この画像は実際の星と比べて左右が反転している。
しかし，丸める際にこの印刷面を球の表にすれば，スクリーンに映るときは実際の星空の向きになるので問題ない。

#####Blenderを用いて正多面体上に星をプロット
しかし，二次元座標上に星をプロットしただけでは，完成ではない。
例えば，メルカトル図法で描かれた地球を丸めても，球体の地球にはならない。

そこで今回は，正多面体の展開図にこの二次元座標で描かれた星をリプロットする方法をとった。
このリプロットに関してだが，しっかり計算すれば星が正しい位置に来る展開図を作成できると思う。しかし，私はその方法をうまく実装することができなかった（うまく計算できた方はぜひやり方を教えていただきたい）。

私がとった方法は，3DCGソフトのBlenderを用いて正多面体をUV展開し，その展開図を作成した画像に合わせて，ペーパークラフト作成用のアドオンを用いて展開図を作るというものである（友人の[KN](https://qiita.com/knagasawa11/lgtms)にこのアイデアを頂き，Blenderの使い方まで教えてもらった。感謝）。

まずは，Blenderを[ここ](https://www.blender.org/download/)からインストールする。
Blenderを立ち上げ，新規ファイル，全般を選ぶと，以下のような画面になる。
![blender1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275927/a5e1b71a-4c48-ffe1-e520-c0a2fdfc5384.png)

この真ん中にある物体を右クリックして，削除。
「Shift + a」でメッシュ，ico球を選択すると，次はこんなものが出てくる。
![blender2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275927/60782d60-dcd7-4a6a-2de5-2cc5ef52e9c0.png)

これで正多面体が用意できた。

:::note info
ここでおまじないとして，右上の「オプション」の下にある球のアイコンのうち，右から二番目を選択しておく（画像では右から三番目が選択された状態となっている）。
:::

次に，画面を２分割し，どちらかの画面でUV展開を行う（今回は左の画面）。
左上にあるBlenderマークから少し左下にカーソルを動かすと，カーソルが十字型になる場所があるので，そこから右へドラッグすれば，２画面に分割することができる。
次に，Blenderマークのすぐ下にある井戸の井の字とボールのマークをクリックすると，ドロップダウンが開くため，そこからUVエディターを選択する。
そうするとこのような画面になる。
![blender2-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275927/4e807d4c-8df6-1834-8ee9-60c476a0b85a.png)

できたら，右の画面に戻り，先ほどの井戸とボールのマークの下にある「オブジェクト」をクリックし，編集に変更する。すると，
![blender2-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275927/3c3ece85-1319-8b4e-69a4-1febecf75ebd.png)


この展開図ではいささか問題があるので，展開図を変更する。
右の正多面体にカーソルを合わせ，「a」を押し，その後，「u」を押すと，UV展開の方法がいくつか出てくる。
そこで円筒状投影を選択すれば，
![blender3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275927/8e608899-248f-5873-affe-464f4af59f89.png)
こうなる。

できたら，左の画面の「開く」というところから，pythonで作成したstar_fig.pngを開く。
![blender4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275927/4c260151-d866-f577-0a42-698edcf80772.png)

左の画面の1つ1つの三角形が右の正多面体の面を表している。
このままではすべての面がうまく画像に合っていないので，点をうまいこと動かして画像の枠内にピッタリと収まるように変形していく。

:::note info
Blenderを用いた方法で誤差が生じるのはココの操作である。
そのため，なるべく誤差を少なくするために，スケール変換で大まかな形は合わせてしまったほうが良い。

ショートカットキー
a：全選択，s：スケール変換，s->x：横軸のみスケール変換，s->y：縦軸のみスケール変換，g：移動
:::

ピッタリ合わせた後のものがこちら。
![blender5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275927/2cda620d-a507-9c26-f2e5-2d45d6bce18a.png)
見るとよくわかると思うが，てっぺん付近や左右の端っこはかなりゆがんでしまっている。
簡単にやろうと思うとここら辺が限界。

次に，またBlenderマークの左下にカーソルを合わせて，十字型のカーソルを出した後，下にドラッグして３画面にする。
同様に，Blenderマークの下のアイコンをクリック，今度はシェーダーエディターを選択。
![blender6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275927/eef40b47-b00b-499e-b5b2-e5cf5b960969.png)
できたら，今出したウィンドウの右上あたりにある新規をクリックする。

次に，シェーダーエディターの追加ボタンを押して，「UVマップ」と「画像テクスチャ」の２つを追加する。
![blender7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275927/3d7a03cc-ddd2-5f48-3a38-cbd75acd9de4.png)
画面テクスチャの「開く」からstar_fig.pngを開く。
UVマップのUVの右にある青い点を，画像テクスチャのベクトルの左にある青い点にドラッグ＆ドロップ。
また，画像テクスチャの右のカラーからプリンシプルBSDFのベースカラーにドラッグ＆ドロップ。

ここまで完了すれば，一番最初のICO球を用意した画面に恒星球の完成形が映し出されているだろう。
![blender8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275927/2b1dcb5e-bc5f-84db-9b90-4b292356a33c.png)

:::note warn
ICO球に画像が映らない場合は「おまじない」がしてあるか確認する。
:::

#####正多面体の展開図を作る
恒星球はできたので，この展開図を作っていく。
参考にしたのは[こちら](https://qiita.com/atskimura/items/056b4d904dd140589cf3)
この記事で解説されているので詳しいことは書かないが，アドオンが見つからない場合はgithubからインストールしなければならない場合があることと，シームの付け方を注意しないとペーパークラフトができないことがあるので注意。


完成したものがこちら。
![blender9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275927/4153d58e-4866-2998-ef0e-182fd53ef7ab.png)

#####ピンホール式プラネタリウム
完成したものを印刷して，光を通さない厚紙等にのりで貼り付ける。
組み立てる前に星の部分に針で穴を空けていく。
この時，星の等級によって穴の大きさを変えるのだが，思ったより大きく空けた方が良い。
その後，下の方の一面をはさみで切り取ってから，のりしろを組み合わせて正多面体をクラフトする。
これで恒星球は完成。

####ドーム
今回はJAXAの[ダンボールドームプロジェクト](https://www.kaguya.jaxa.jp/ja/document/DomeProject.htm)を参考にした。
やり方はすべて書いてあるので，ここでは実際に作ってみて感じたことを書いていこうと思う。
まず，組み立てる時にはそれなりの人数が必要になってくる点。
寸法通り作るとかなりでかいものとなる。教室に入れるために土台となるA8は半分の450mmの高さとしたが，それでも5人くらいはいないと難しい。

また，JAXAの手順では紙を貼るときにスプレーのりを使用しているが，今回は予算的に厳しかったため，紙を折り返してガムテープで貼り付けた。そうするとかなり安く抑えることができたのだが，ドームの見た目が少し残念なことになってしまった。

最後に，ダンボールの状態。
今回は家電量販店のごみをリユースしたのだが，そうすると折り目がついた部品が出てきてしまい，ドームの耐久性に少し不安が残る形となった。

余談だが，2020年に制作したときは，竹を使ってドームを制作した（方法は[こちら](https://stardome.jp/how.html)）。
そのドームに白のカーテンを掛けてスクリーンとしたのだが，どうしても内部の竹が邪魔で投影できない星が出てきてしまった。
ただ，制作時間的には圧倒的に短く終えられるので，時間がない場合はこちらでも良いだろう。


#上映
完成したら正多面体の面がない部分から豆電球を入れて，光らせる。

うまくできていれば，こんな風に映るはず。
![PXL_20210730_073445498.MP.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275927/91b5a52b-2143-b502-1131-ed5b8426b6a4.jpeg)

:::note info
私たちが今回用いた豆電球は3.8V，0.5Aのもの。
なるべく明るい方が良いが，今回のようなピンホール式の場合，星の形がフィラメントの形になってしまうため，フィラメントはなるべく短い方が良い。
明るさとフィラメントの長さは相反するものであるが，ドームの遮光性を高めることができれば，明るさはある程度犠牲にしてもうまく映る。
:::

#最後に
ぶっちゃけ高校生が自力でここまでできるのかは疑問が残るところだが，部分的にでもプラネタリウムを作るときの参考にして頂ければ大変嬉しく思っている。
また，小中学生のお父さんお母さんが夏休みの自由研究を行う時の参考にしてもらってもいいだろう（誰の自由研究？）。

実際にドームの中で恒星球を光らせてみるとかなりの感動ものである。
こればっかりは体験してみないと分からないので，興味が湧いた方はぜひ作ってみてほしい。