Pythonでトーラス結び目を描画(3Dグラフィックス)

投稿者: | 2022年4月3日

Pythonでトーラスの結び目を描画

Pythonでトーラスの結び目を描画


Pythonでトーラスの結び目を描画する際のPythonコードを作成してみました。トーラスの結び目の回転動画を出力するPythonのソースも作成しました。トーラス結び目の3d画像を出力します。静止画像と回転動画のソースサンプルを用意しています。

Pythonでのソースコード


import matplotlib.pyplot as plt
import numpy as np

#パラメータ設定
u=np.linspace(0,2*np.pi,360)
v=np.linspace(0,2*np.pi,360)
u,v=np.meshgrid(u,v)

#描画数式設定
X = (10 - np.cos(u)+2*np.sin(5*v)) * np.cos(2*v)
Y = (10 - np.cos(u)+2*np.sin(5*v)) * np.sin(2*v)
Z = 20 * np.cos(5*v)+2*np.sin(u)

#座標軸設定
fig = plt.figure(figsize=(50,50),dpi=100)
ax = fig.add_subplot(projection='3d')
ax.set_xlabel('x axis')
ax.set_ylabel('y axis')
ax.set_zlabel('z axis')
ax.set_xlim(-10,10)
ax.set_ylim(-10,10)
ax.set_zlim(-20,20)
ax.set_box_aspect((3,3,1))

#描画処理
ax.plot_surface(
                X, Y, Z
                , rcount=500
                , ccount=50
                , alpha=1.0
                ,antialiased=True
                ,cmap='viridis'
                )

#画像表示
plt.subplots_adjust(left=0.0,
                    bottom=0.0,
                    right=1.0,
                    top=1.0,
                    wspace=0.0,
                    hspace=0.0)
plt.show()

下記設定にて、メッシュの粒度を設定します。

, rcount=500
, ccount=50

下記設定にて、軸座標表示を非表示にすることも可能です。

[boax.axis("off")

カラー設定パターンを複数出力


トーラス結び目のカラー設定パターンを複数出力するソースサンプルです。

#******************************************************************************
# トーラス結び目
#******************************************************************************
import matplotlib.pyplot as plt
import numpy as np
from sympy.logic.boolalg import false
import time
import datetime

#------------------------------------------------------------------------------
#パラメータ設定、数式設定
#------------------------------------------------------------------------------
#パラメータ設定
u=np.linspace(0,2*np.pi,1800)
v=np.linspace(0,2*np.pi,1800)
u,v=np.meshgrid(u,v)

#描画数式設定

#結び目(3,1)
X = (10 - np.cos(u)+2*np.sin(3*v)) * np.cos(1*v)
Y = (10 - np.cos(u)+2*np.sin(3*v)) * np.sin(1*v)
Z = 20 * np.cos(3*v)+2*np.sin(u)

'''
#結び目(5,3)
X = (10 - np.cos(u)+2*np.sin(23*v)) * np.cos(2*v)
Y = (10 - np.cos(u)+2*np.sin(23*v)) * np.sin(2*v)
Z = 20 * np.cos(23*v)+2*np.sin(u)
'''

"""
#結び目(5,2)
X = (10 - np.cos(u)+2*np.sin(5*v)) * np.cos(2*v)
Y = (10 - np.cos(u)+2*np.sin(5*v)) * np.sin(2*v)
Z = 20 * np.cos(5*v)+2*np.sin(u)
"""

"""
#結び目(3,2)
X = (10 - np.cos(u)+3*np.sin(3*v)) * np.cos(2*v)
Y = (10 - np.cos(u)+3*np.sin(3*v)) * np.sin(2*v)
Z = 20 * np.cos(3*v)+3*np.sin(u)
"""

"""
#結び目(5,2)
X = (10 - np.cos(u)+3*np.sin(5*v)) * np.cos(2*v)
Y = (10 - np.cos(u)+3*np.sin(5*v)) * np.sin(2*v)
Z = 15 * np.cos(5*v)+3*np.sin(u)
"""

#結び目(7,2)
"""
X = (10 - np.cos(u)+3*np.sin(7*v)) * np.cos(2*v)
Y = (10 - np.cos(u)+3*np.sin(7*v)) * np.sin(2*v)
Z = 15 * np.cos(7*v)+3*np.sin(u)
"""

"""
#結び目(9,2)
X = (10 - np.cos(u)+3*np.sin(9*v)) * np.cos(2*v)
Y = (10 - np.cos(u)+3*np.sin(9*v)) * np.sin(2*v)
Z = 15 * np.cos(9*v)+3*np.sin(u)
"""

"""
X = (10 +1*np.cos(3*u)) * np.cos(2*v)
Y = (10 +1*np.cos(3*u)) * np.sin(2*v)
Z = 1*np.sin(3*u)
"""

#------------------------------------------------------------------------------
# トーラス結び目描画
#------------------------------------------------------------------------------
def plot_3d(cmapType):

    #---------------------------------------------------------------------------
    #処理開始
    #---------------------------------------------------------------------------
    print("描画開始(" + cmapType + ")")
    dt_now = datetime.datetime.now()
    print(dt_now.strftime('%Y/%m/%d %H:%M:%S'))
    start = time.time()

    #---------------------------------------------------------------------------
    #座標軸設定
    #---------------------------------------------------------------------------
    fig = plt.figure(figsize=(16,9),dpi=256)
    ax = fig.add_subplot(projection='3d')
    ax.set_xlabel('x axis')
    ax.set_ylabel('y axis')
    ax.set_zlabel('z axis')
    ax.set_xlim(-10,10)
    ax.set_ylim(-10,10)
    ax.set_zlim(-20,20)
    ax.set_box_aspect((1,1,1))
    ax.view_init(elev=90, azim=0)
    ax.axis("off")

    #---------------------------------------------------------------------------
    #描画処理
    #---------------------------------------------------------------------------
    ax.plot_surface(
                    X, Y, Z
                    , rcount=3000
                    , ccount=3000
                    , alpha=1.0
                    ,antialiased=false
                    ,cmap=cmapType
                    )

    plt.subplots_adjust(left=0.0,
                        bottom=0.0,
                        right=1.0,
                        top=1.0,
                        wspace=0.0,
                        hspace=0.0)

    #---------------------------------------------------------------------------
    #画像表示
    #---------------------------------------------------------------------------
    #plt.show()

    #---------------------------------------------------------------------------
    #画像を保存
    #---------------------------------------------------------------------------
    plt.savefig("torus_node_" + cmapType + ".png", format="png",dpi=256)
    plt.clf()
    plt.close()

    #---------------------------------------------------------------------------
    #処理終了
    #---------------------------------------------------------------------------
    print (time.time()-start)
    dt_now = datetime.datetime.now()
    print(dt_now.strftime('%Y/%m/%d %H:%M:%S'))
    print("描画終了(" + cmapType + ")")

#------------------------------------------------------------------------------
#カラー設定
#------------------------------------------------------------------------------
cmap_list= [
    'viridis', 'plasma', 'inferno', 'magma', 'cividis',
    'Greys', 'Purples', 'Blues', 'Greens', 'Oranges', 'Reds',
    'YlOrBr', 'YlOrRd', 'OrRd', 'PuRd', 'RdPu', 'BuPu',
    'GnBu', 'PuBu', 'YlGnBu', 'PuBuGn', 'BuGn', 'YlGn',
    'binary', 'gist_yarg', 'gist_gray', 'gray', 'bone',
    'pink', 'spring', 'summer', 'autumn', 'winter', 'cool',
    'Wistia', 'hot', 'afmhot', 'gist_heat', 'copper',
    'PiYG', 'PRGn', 'BrBG', 'PuOr', 'RdGy', 'RdBu', 'RdYlBu',
    'RdYlGn', 'Spectral', 'coolwarm', 'bwr', 'seismic',
    'twilight', 'twilight_shifted', 'hsv',
    'Pastel1', 'Pastel2', 'Paired', 'Accent', 'Dark2',
    'Set1', 'Set2', 'Set3', 'tab10', 'tab20', 'tab20b',
    'tab20c',
    'flag', 'prism', 'ocean', 'gist_earth', 'terrain',
    'gist_stern', 'gnuplot', 'gnuplot2', 'CMRmap',
    'cubehelix', 'brg', 'gist_rainbow', 'rainbow', 'jet',
    'turbo', 'nipy_spectral', 'gist_ncar'
    ]

#------------------------------------------------------------------------------
#Main処理
#------------------------------------------------------------------------------
if __name__ == "__main__":
    print("描画開始")
    for name in cmap_list:
        plot_3d(name)
    print("描画終了")

出力画像


アニメーション


トーラスの結び目の回転動画を出力するPythonのソースです。

#******************************************************************************
# トーラスのノードの回転動画出力
#******************************************************************************
import matplotlib.pyplot as plt
import numpy as np
from IPython.display import HTML
import matplotlib.animation as animation

#==============================================================================
#処理開始
#==============================================================================
print("描画開始")

#------------------------------------------------------------------------------
#パラメータ設定、数式設定
#------------------------------------------------------------------------------
#トーラスノード
#パラメータ設定
u=np.linspace(0,2*np.pi,360)
v=np.linspace(0,2*np.pi,360)
u,v=np.meshgrid(u,v)

#描画数式設定
x = (10 - np.cos(u)+2*np.sin(5*v)) * np.cos(2*v)
y = (10 - np.cos(u)+2*np.sin(5*v)) * np.sin(2*v)
z = 20 * np.cos(5*v)+2*np.sin(u)

#------------------------------------------------------------------------------
#animation
#------------------------------------------------------------------------------
#画像サイズ設定
fig = plt.figure(figsize=(16, 9), dpi=256)
ax = fig.gca(projection='3d')
ax.plot_surface(
                x, y, z
                , rcount=500
                , ccount=50
                , alpha=1.0
                ,antialiased=True
                ,cmap='viridis'
                )
ax.set_box_aspect((2,2,1))
plt.axis('off')

#表示軸回転設定
def animate(i):
    ax.view_init(elev=30., azim=-60 +3.6*i)
    return fig,

#動画保存
#frames:描画フレーム数
#interval:描画間隔(ミリセカンド)
ani = animation.FuncAnimation(fig, animate , frames=500, interval=100, blit=True)
ani.save('rotate_3d_torus_node.mp4', writer="ffmpeg",dpi=256)
HTML(ani.to_html5_video())

#=========================================================================
#終了処理
#=========================================================================
#numpy_version
print("numpy_version:" + np.__version__)
import matplotlib as mpl
#version
print("matplotlib_version:" + mpl.__version__)
#終了メッセージ
print("描画終了")

出力結果

座標軸を表示した版は以下となります。

高画質販売


Pixtaにてトーラス結び目の高画質画像を販売しています。

写真素材のピクスタ

写真・イラストに関する記事は、下記サイトを見てください。
https://www.photo.jazzbluessea.yokohama/

関連記事





最近の投稿

管理者が運営している関連サイト