7
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Posted at

#見てみたいよね?
三角関数、対数関数、サイクロイド…数えたらきりがないほどにこの世界ではいろんな関数や図形、グラフがあります。
そんなグラフを3Dで見てみたいですよね?
#で一体どうするってのさ?
今回はBlenderとExcelを使ってやっていきたいと思います。
Excelファイルに座標のデータを入れてそれを基にBlenderでオブジェクトを生成します。
image.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
こんな感じで表に入っていたらOKです。
ちなみにグラフにするとこんな感じです。
・ x軸y軸を分けたもの
image.png  
・ x軸y軸を合わせたもの
image.png

##Blenderでグラフを作る
まずはBlenderをダウンロードしましょう。
Blenderをダウンロード
ダウンロードできたら起動して、pythonエディターを開きましょう。
↓ここですね
image.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

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

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ライブラリを使えるようにしときましょう。

入れ方についての詳しい説明

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

先程作ったファイルを実行するためにBlenderをScriptモードにします。
これでも行けます。
image.png
そうしたらfunction_3Dgraph.pyを開いて実行してください。
image.png

グラフが出てきたら成功です!
image.png
(Blenderの1mは小さいので分かりづらいですがちゃんと振幅が1のsin波になっています。振幅を10にすると分かりやすくなります。)
 
 
 

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

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

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

 \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は任意の定数)$と三次元の直線もできるわけです。
…ここまでは直行形式のグラフの話です。では極形式の時はどうしましょう?
たとえばこんな式があったとします。

r=f(θ)

image.png

この式で表されている直線を横軸(x軸)と縦軸(y軸)にそれぞれ分解します。
image.png

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

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

じゃ何故使ったのかというと、例えば…
image.png

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

image.png
やや縮んでる気がしますがまぁ大丈夫でしょう。値をとるときにn倍にすれば問題ないですし…
#あとがき
今回はExcelを使ってBlenderで3Dグラフを作ってみました。次はこのグラフをアニメみたいに動かしてみたいですね。

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?