グラフを3Dで見てみたい！そんな夢かなえます。

#見てみたいよね?
三角関数、対数関数、サイクロイド…数えたらきりがないほどにこの世界ではいろんな関数や図形、グラフがあります。
そんなグラフを3Dで見てみたいですよね？
#で一体どうするってのさ?
今回はBlenderとExcelを使ってやっていきたいと思います。
Excelファイルに座標のデータを入れてそれを基にBlenderでオブジェクトを生成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542948/a498a537-85c3-535f-da8a-6b82680e910d.png)

では仕組みが分かったところで…
#早速作ってくか
##開発環境
windows 10
python 3.7
Blender 2.8
pip 20.2.1
##Excelでデータを作成する
まずはExcelファイルをいじいじするライブラリをインストールしましょう。

```
$pip install openpyxl
```


コードはまぁざっとこんな感じですね

```function_3Dgraph.py
import openpyxl
import math

class funcdate():
    def create_wb(self,wb_name):
        new_file=openpyxl.Workbook() #Excelファイルのデータを作成します。
        new_file.save(wb_name+'.xlsx') #いったん保存します。
        print('Excelファイルが出来ました')
        return new_file
    
    def write_wb(self,cell_name,cell_value,file_name):
        file=openpyxl.load_workbook(file_name+'.xlsx',data_only=True) #Excelファイルを読み込みます。
        new_wb=file.active #シートを読み込みます。
        new_wb[cell_name]=cell_value #cell_mane(例えばA1)セルに値を入れます。

    def write_func(self,t,file_name):
        file=openpyxl.load_workbook(file_name+'.xlsx',data_only=True)
        new_wb=file.active
        print(new_wb)
        for i in range(1,t+1):
            if(i==0):
                i=1
            x=math.cos(i*math.pi/180) #ここの式は何でもいいです。
            y=math.sin(i*math.pi/180) #ここの式は何でもいいです。
            new_wb['A'+str(i)]=i #各座標にデータを入れていきます。
            new_wb['B'+str(i)]=x
            new_wb['C'+str(i)]=y
            print(new_wb['A'+str(i)].value,new_wb['B'+str(i)].value,new_wb['C'+str(i)].value)
            
        else:
            file.save(file_name+'.xlsx')
            print('記入出来ました')

    def get_func(self,file_name,t):
        file=openpyxl.load_workbook(file_name+'.xlsx',data_only=True)
        wb=file.active
        graph_t=wb['A'+str(t)].value #各座標にそれぞれのセルの値を入れます。
        graph_x=wb['B'+str(t)].value
        graph_y=wb['C'+str(t)].value
        a=[graph_t,graph_x,graph_y]
        return a

    
test=funcdate()
test.create_wb('test_function')
test.write_func(360,'test_function')
print(test.get_func('test_function',10))

```

ではさっそく実行してみましょう。

```
$python function_3Dgraph.py
```

実行したらExcelファイルが出来上がってるはずなので、開いてみてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542948/11cd1e44-a325-0bba-138d-3dfc2c1090f4.png)
こんな感じで表に入っていたらOKです。
ちなみにグラフにするとこんな感じです。
・ x軸y軸を分けたもの
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542948/cb31aa4c-38f7-45c0-ba03-17563d48e39b.png)　　
・ x軸y軸を合わせたもの
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542948/7eb4d0cc-e2b1-47f3-1d71-f9289a242de6.png)


##Blenderでグラフを作る
まずはBlenderをダウンロードしましょう。
[Blenderをダウンロード](https://www.blender.org/)
ダウンロードできたら起動して、pythonエディターを開きましょう。
↓ここですね
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542948/ab618ed8-4b53-70b2-211c-d1f3f4da54f2.png)
そうしたら下のコードを打ってみてください。最初に生成されているキューブを削除(xキー)しとくと見やすいですね。

```
$import bpy
$bpy.ops.mesh.primitive_uv_sphere_add(segments=32, ring_count=16, radius=1.0, calc_uvs=True, enter_editmode=False, align='WORLD', location=(0.0, 0.0, 0.0), rotation=(0.0, 0.0, 0.0))
```

座標(0.0,0.0,0.0)に球が出てきたら成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542948/21246b3a-4132-cb87-aa59-15599057f64c.png)

ではさっそく追記しましょう

```function_3Dgraph.py
import openpyxl
import math
import bpy

class funcdate():
    def create_wb(self,wb_name):
        new_file=openpyxl.Workbook()
        new_file.save(wb_name+'.xlsx')
        print('Excelファイルが出来ました')
        return new_file
    
    def write_wb(self,cell_name,cell_value,file_name):
        file=openpyxl.load_workbook(file_name+'.xlsx',data_only=True)
        new_wb=file.active
        new_wb[cell_name]=cell_value

    def write_func(self,t,file_name):
        file=openpyxl.load_workbook(file_name+'.xlsx',data_only=True)
        new_wb=file.active
        print(new_wb)
        for i in range(1,t+1):
            if(i==0):
                i=1
            x=math.cos(i*math.pi/180)
            y=math.sin(i*math.pi/180)
            new_wb['A'+str(i)]=i
            new_wb['B'+str(i)]=x
            new_wb['C'+str(i)]=y
            print(new_wb['A'+str(i)].value,new_wb['B'+str(i)].value,new_wb['C'+str(i)].value)
            
        else:
            file.save(file_name+'.xlsx')
            print('記入出来ました')

    def get_func(self,file_name,t):
        file=openpyxl.load_workbook(file_name+'.xlsx',data_only=True)
        wb=file.active
        graph_t=wb['A'+str(t)].value
        graph_x=wb['B'+str(t)].value
        graph_y=wb['C'+str(t)].value
        a=[graph_t,graph_x,graph_y]
        return a

    
test=funcdate()
test.create_wb('test_function')
test.write_func(360,'test_function')
for i in range(1,360):
     bpy.ops.mesh.primitive_uv_sphere_add(segments=32, ring_count=16, radius=1.0, calc_uvs=True, enter_editmode=False, align='WORLD', location=test.get_func('test_function',i), rotation=(0.0, 0.0, 0.0))


```

bpyライブラリはBlenderでしか使えないのでBlenderで実行します。

**とその前に**
Blenderでopenpyxlライブラリを使えるようにしときましょう。

[入れ方についての詳しい説明](https://codelabo.com/posts/20200228184408)

Blenderでopenpyxlを使うために管理者として起動してください。（権限ないと言われるので…）

先程作ったファイルを実行するためにBlenderをScriptモードにします。
これでも行けます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542948/0c880141-e6f8-e8eb-e4ce-60865c1a0b7a.png)
そうしたらfunction_3Dgraph.pyを開いて実行してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542948/e36f2015-431f-e423-5225-05fa844a4f6f.png)

グラフが出てきたら成功です!
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542948/29ed0bc4-d040-9f56-487e-e48f57ed0728.png)
(Blenderの1mは小さいので分かりづらいですがちゃんと振幅が1のsin波になっています。振幅を10にすると分かりやすくなります。)
　
　
　

とまぁこんな感じでグラフが完成しました。

ちなみにBlenderで作成したExcelファイルは C:\Program Files\Blender Foundation\Blender 2.83 に保存されます。

#余談
ここでちょっと数学的な話を…
今回は媒介変数tでxとyを表してグラフを作りました。式にするとこんな感じですね。

```math
 \left\{
\begin{array}{ll}
x=f(t) \\
y=g(t)
\end{array}
\right. 
```


これで$y=f(x)$の3Dのグラフが出来ます。また$t=z$とすれば、$ax=by=cz(a,b,cは任意の定数)$と三次元の直線もできるわけです。
…ここまでは直行形式のグラフの話です。では極形式の時はどうしましょう?
たとえばこんな式があったとします。

```math
r=f(θ)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542948/e26063f7-3f06-d0d2-9796-1af608609e8f.png)

この式で表されている直線を横軸(x軸)と縦軸(y軸)にそれぞれ分解します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542948/0e429501-2c70-3f7f-7aa4-f899f878e573.png)


```math
 \left\{
\begin{array}{ll}
x=f(θ) \cos(θ)\\
y=f(θ) \sin(θ)
\end{array}
\right. 
```

これで極形式のグラフが書けます。
　
　
　
実はここまでの事ならわざわざExcelファイルを使わく手もよいのです。~~何なら使わないほうがらk~~

じゃ何故使ったのかというと、例えば…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542948/328c2fd9-0305-b8a5-8932-d64cb963fd85.png)



このような式が分からないグラフの時に使います。Excelファイルに値が入ってる場合はそれを参考にしてグラフを作ればよいのです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542948/96bf9e34-f69a-db03-9a03-997323f1eaa4.png)
やや縮んでる気がしますがまぁ大丈夫でしょう。値をとるときにn倍にすれば問題ないですし…
#あとがき
今回はExcelを使ってBlenderで3Dグラフを作ってみました。次はこのグラフをアニメみたいに動かしてみたいですね。