코딩
파이썬으로 크리스마스 트리 만들기 / Python - How to make Christmas tree
구름위의공룡
2020. 12. 28. 11:15
코로나때문에 집에서 보내는 크리스마스였는데 심심해서 만들어보았다.
2D로 만든 코드들은 많았는데 3D로 만든 것이 없어서 Numpy 모델로 구현해보았다.
만들면서 numpy와 matplotlib.pyplot의 3D scatter에 대한 여러 함수들을 다뤄볼 수 있다.
There are many 2D tree but no 3D tree, so I made christmas tree 3D model by using Numpy library. We can learn how to use numpy and matplotlib library for 3D scatter.
#!/usr/bin/env python
# coding: utf-8
import numpy as np
import matplotlib.pyplot as plt
n = 1800
vmin, vmax, zmin, zmax = -30, 30, -1, 2
# green leaves
tree = []
colors = []
r = 30
for i in range(19):
color = np.array([(i*0.1) * np.random.random_sample() + 0.1*i for i in range(int(vmax-vmin)*20)])
colors.append(color)
zmin += 3
zmax += 3
length = np.random.uniform(0, r, size=int(vmax-vmin)*20)
angle = np.pi * np.random.uniform(0, 2, size=int(vmax-vmin)*20)
xt = length * np.cos(angle)
yt = length * np.sin(angle)
zt = np.random.uniform(zmin, zmax, size=int(vmax-vmin)*20)
tree.append([xt, yt, zt])
r -= 1.5
# brown stem
tree2 = []
z2max, z2min = 0, -2
for j in range(15):
length = np.sqrt(np.random.uniform(9, 100, size=100))
angle = np.pi * np.random.uniform(0, 2, size=100)
x = length * np.cos(angle)
y = length * np.sin(angle)
zs = np.random.uniform(z2min, z2max, size=(100))
z2min -= 1.5
z2max -= 1.5
tree2.append([x, y, zs])
# background snow
snow = []
z3min = -21
z3max = -19
snow_colors = []
for j in range(10):
xs = np.random.uniform(-40, 40, size=2000)
ys = np.random.uniform(-40, 40, size=2000)
zs = np.random.uniform(z3min, z3max, size=(2000))
z3max -= 1.5
z3min -= 1.5
snow.append([xs, ys, zs])
color = np.array([(i*0.1) * np.random.random_sample() + 0.1*i for i in range(2000)])
snow_colors.append(colors)
# function for falling snow
n = 250
def randrange(n, vmin, vmax):
'''
Helper function to make an array of random numbers having shape (n, )
with each number distributed Uniform(vmin, vmax).
'''
return (vmax - vmin)*np.random.rand(n) + vmin
fig = plt.figure(figsize=(15, 15))
ax = plt.axes(projection='3d')
fig.set_facecolor('black')
ax.set_facecolor('black')
# set 3D axes and its background color as black
ax.w_xaxis.pane.fill = False
ax.w_yaxis.pane.fill = False
ax.w_zaxis.pane.fill = False
# remove axis line silhouette
ax.set_xlabel('$Merry\ Christmas$', fontsize=20, c='white') # Message 1
ax.set_ylabel('$2020$', fontsize=20, c='white') # Message 2
# put message as axis label. message form is Latex
ax.w_xaxis.set_pane_color((0.0, 0.0, 0.0, 0.0))
ax.w_yaxis.set_pane_color((0.0, 0.0, 0.0, 0.0))
ax.w_zaxis.set_pane_color((0.0, 0.0, 0.0, 0.0))
# set axis wall color as black
ax.grid(False)
ax.view_init(elev=10., azim=30)
# set angle of view
#scatter leaves, stem, snow
for i in range(10):
ax.scatter(snow[i][0], snow[i][1], snow[i][2], c='#ffffe4', marker='*', s=12, cmap='Greys')
for i in range(15):
ax.scatter(tree2[i][0], tree2[i][1], tree2[i][2], c='#8c564b', marker='o', s=15)
for i in range(19):
ax.scatter(tree[i][0], tree[i][1], tree[i][2], c=colors[i], marker='o', s=10, cmap='Greens')
for m, zlow, zhigh in [('*', -15, 60)]:
xs = randrange(n, -40, 40)
ys = randrange(n, -40, 40)
zs = randrange(n, zlow, zhigh)
ax.scatter(xs, ys, zs, c='#ffffe4', marker=m, s=10)
# scatter decoration.
r = 28.5
z = 2
color = ['red', 'yellow', 'orange']
for i in range(20):
theta = np.linspace(-2* np.pi, 2 * np.pi, 21 - i)
for j in range(len(theta)):
x = r * np.sin(theta[j])*np.sqrt(1.69)
y = r * np.cos(theta[j])
ax.scatter(x, y, z, c=color[j%len(color)], marker='D', s=15)
z += 3
r -= 1.5
r = 22
z = 20
for i in range(10):
theta = np.linspace(-2* np.pi, 2 * np.pi, 21 - i)
for j in range(len(theta)):
x = r * np.sin(theta[j])*np.sqrt(1.69)
y = r * np.cos(theta[j])
ax.scatter(x, y, z, c=color[j%len(color)], marker='^', s=15)
z += 3
r -= 1.4
plt.show()
결과