1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
from manim import *
from manim.mobject.opengl.opengl_surface import OpenGLSurface
from manim.mobject.opengl.opengl_three_dimensions import OpenGLSurfaceMesh
import numpy as np
from scipy.special import sph_harm
# configure style
config.background_color = '#202020'
config.tex_template.add_to_preamble(
r"\usepackage[p,osf]{scholax}"
r"\usepackage{amsmath}"
r"\usepackage[scaled=1.075,ncf,vvarbb]{newtxmath}"
)
class FourierOnS1(ThreeDScene):
@staticmethod
def harmonic_cos(m, n, theta, phi):
# get only the cos() part
r = np.real(sph_harm(m, n, theta, phi)) * 5 # Y_n^m
# coordinates transformation
x = r * np.cos(theta) * np.sin(phi)
y = r * np.sin(phi) * np.sin(theta)
z = r * np.cos(phi)
return [x, y, z]
@staticmethod
def harmonic_surf(m, n):
surf = Surface(lambda u, v: FourierOnS1.harmonic_cos(m, n, u, v),
u_range=[0, 2 * PI], v_range=[-PI, PI], resolution=[50, 50],
fill_opacity=.8, checkerboard_colors=[BLUE_D, BLUE_E])
return surf
def construct(self):
axes = ThreeDAxes(x_range=[-1, 1], y_range=[-1, 1])
self.add(axes)
self.set_camera_orientation(theta=30 * DEGREES, phi=75 * DEGREES)
self.begin_ambient_camera_rotation(rate=.1)
last_surf = None
last_label = None
for n in range(0, 5):
for m in range(0, n):
surf = FourierOnS1.harmonic_surf(m, n)
label = MathTex(r"Y_{%d}^{%d}(\theta, \phi)" % (n, m))
if last_surf is not None:
self.play(ReplacementTransform(last_surf, surf))
if last_label is not None:
self.remove(last_label)
self.play(Create(surf))
self.add_fixed_in_frame_mobjects(label)
label.to_corner(UL)
last_surf = surf
last_label = label
self.wait()
self.wait(5)
|