Братец Кролик ждет каникул

Братец Кролик ждет каникул, чтобы отдохнуть. Ему хочется то скорейшее наступление зимних каникул, то летних. И пока он ждет, ему приходят разные идеи поздравительных открыток, которые он может сделать. Однако он был бы скучным кроликом, если бы рисовал их вручную. Поэтому он изобретает способы рисования при помощи математических функций.

Например, он придумал, как рисовать цветок, используя тела вращения для празднования наступления лета.

Кролик

Пример кода для рисования цветка:


from matplotlib import pyplot as plt
from math import sqrt, pi, cos, sin
import numpy as np

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

t_grid = np.linspace(-1 - sqrt(7), -1 + sqrt(7), 50)
s_grid = np.linspace(-1, 1, 50)
T, S = np.meshgrid(t_grid, s_grid)
theta_fun = lambda t, s: 0.2 * pi * (t + 1 + sqrt(7)) / sqrt(7) - 0.4 * pi + 0.1
phi_fun = lambda t, s: pi * s / (4 * sqrt(2)) * sqrt(max(2 - t ** 2 / abs(t - 3), 0))
for k in range(1, 16):
  phi0 = 0.4 * pi * k
  r = 14 - 0.8 * k
  x_fun = lambda t, s: r * cos(phi0 + phi_fun(t, s)) * cos(theta_fun(t, s))
  y_fun = lambda t, s: r * sin(phi0 + phi_fun(t, s)) * cos(theta_fun(t, s))
  z_fun = lambda t, s: r * sin(theta_fun(t, s))
  X = np.array(list(map(x_fun, T.flatten(), S.flatten()))).reshape((50, 50))
  Y = np.array(list(map(y_fun, T.flatten(), S.flatten()))).reshape((50, 50))
  Z = np.array(list(map(z_fun, T.flatten(), S.flatten()))).reshape((50, 50))
  ax.plot_surface(X, Y, Z, cmap='Reds')
z = np.linspace(-25, -10, 50)
p = np.linspace(0, 2 * pi, 50)
Z, P = np.meshgrid(z, p)
X = np.cos(P)
Y = np.sin(P)
ax.plot_surface(X, Y, Z, cmap='Greens')
ax.set_box_aspect(aspect=(1, 1, 1.5))
plt.show()
    
Цветок

Однако он не против порисовать что-то и к следующему новому году. Беда лишь в том, что он придумал, как нарисовать ёлку, но не может "нарядить" её елочными шарами. Помогите братцу кролику придумать алгоритмический способ "нарядить" елку.

Пример кода для рисования ёлки:


from matplotlib import pyplot as plt
from math import pi, cos, sin

def plot_segment(x1, y1, z1, x2, y2, z2):
  plt.plot([x1, x2], [y1, y2], [z1, z2], 'g', linewidth=1.5)

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

n = 20
m = 10
dr = [0.5 + i / n for i in range(n)]
dz = [-1 + i / n for i in range(n)]
z = [3.5 * (1 - i / n) for i in range(n)]
phi = [[2 * pi * (i / n + j / m) for j in range(m)] for i in range(n)]
dx = [[dr[i] * cos(phi[i][j]) for j in range(m)] for i in range(n)]
dy = [[dr[i] * sin(phi[i][j]) for j in range(m)] for i in range(n)]

for i in range(n):
  for j in range(m):
    plot_segment(0, 0, z[i], dx[i][j], dy[i][j], z[i] + dz[i])

ax.set_box_aspect(aspect=(1, 1, 1.5))
plt.show()
    
Ёлка

Благодарность за идею задания сердечно благодарю коллегу Юлия Лапкина: математические элементы