Guest User

Untitled

a guest
Oct 10th, 2020
3,841
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 34.70 KB | None | 0 0
  1. from manimlib.imports import *
  2.  
  3. # _ _ _ _
  4. # / \ | |__ ___| |_ _ __ __ _ ___| |_
  5. # / _ \ | '_ \/ __| __| '__/ _` |/ __| __|
  6. # / ___ \| |_) \__ \ |_| | | (_| | (__| |_
  7. # /_/ \_\_.__/|___/\__|_| \__,_|\___|\__|
  8. # ____
  9. # / ___| ___ ___ _ __ ___ ___
  10. # \___ \ / __/ _ \ '_ \ / _ \/ __|
  11. # ___) | (_| __/ | | | __/\__ \
  12. # |____/ \___\___|_| |_|\___||___/
  13. ########################################################################################
  14.  
  15.  
  16. class FourierCirclesScene(ZoomedScene):
  17. CONFIG = {
  18. "n_vectors": 10,
  19. "big_radius": 2,
  20. "colors": [
  21. BLUE_D,
  22. BLUE_C,
  23. BLUE_E,
  24. GREY_BROWN,
  25. ],
  26. "vector_config": {
  27. "buff": 0,
  28. "max_tip_length_to_length_ratio": 0.25,
  29. "tip_length": 0.15,
  30. "max_stroke_width_to_length_ratio": 10,
  31. "stroke_width": 1.7,
  32. },
  33. "circle_config": {
  34. "stroke_width": 1,
  35. },
  36. "base_frequency": 1,
  37. "slow_factor": 0.5,
  38. "center_point": ORIGIN,
  39. "parametric_function_step_size": 0.001,
  40. "drawn_path_color": YELLOW,
  41. "drawn_path_stroke_width": 2,
  42. "interpolate_config": [0, 1],
  43. # Zoom config
  44. "include_zoom_camera": False,
  45. "scale_zoom_camera_to_full_screen": False,
  46. "scale_zoom_camera_to_full_screen_at": 4,
  47. "zoom_factor": 0.3,
  48. "zoomed_display_height": 3,
  49. "zoomed_display_width": 4,
  50. "image_frame_stroke_width": 1,
  51. "zoomed_camera_config": {
  52. "default_frame_stroke_width": 3,
  53. "cairo_line_width_multiple": 0.05,
  54. },
  55. "zoom_position": lambda mob: mob.move_to(ORIGIN),
  56. "zoom_camera_to_full_screen_config": {
  57. "run_time": 3,
  58. "func": there_and_back_with_pause,
  59. "velocity_factor": 1
  60. },
  61. "wait_before_start": None
  62. }
  63.  
  64. def setup(self):
  65. ZoomedScene.setup(self)
  66. self.slow_factor_tracker = ValueTracker(
  67. self.slow_factor
  68. )
  69. self.vector_clock = ValueTracker(0)
  70. self.add(self.vector_clock)
  71.  
  72. def add_vector_clock(self):
  73. self.vector_clock.add_updater(
  74. lambda m, dt: m.increment_value(
  75. self.get_slow_factor() * dt
  76. )
  77. )
  78.  
  79. def get_slow_factor(self):
  80. return self.slow_factor_tracker.get_value()
  81.  
  82. def get_vector_time(self):
  83. return self.vector_clock.get_value()
  84.  
  85. def get_freqs(self):
  86. n = self.n_vectors
  87. all_freqs = list(range(n // 2, -n // 2, -1))
  88. all_freqs.sort(key=abs)
  89. return all_freqs
  90.  
  91. def get_coefficients(self):
  92. return [complex(0) for _ in range(self.n_vectors)]
  93.  
  94. def get_color_iterator(self):
  95. return it.cycle(self.colors)
  96.  
  97. def get_rotating_vectors(self, freqs=None, coefficients=None):
  98. vectors = VGroup()
  99. self.center_tracker = VectorizedPoint(self.center_point)
  100.  
  101. if freqs is None:
  102. freqs = self.get_freqs()
  103. if coefficients is None:
  104. coefficients = self.get_coefficients()
  105.  
  106. last_vector = None
  107. for freq, coefficient in zip(freqs, coefficients):
  108. if last_vector:
  109. center_func = last_vector.get_end
  110. else:
  111. center_func = self.center_tracker.get_location
  112. vector = self.get_rotating_vector(
  113. coefficient=coefficient,
  114. freq=freq,
  115. center_func=center_func,
  116. )
  117. vectors.add(vector)
  118. last_vector = vector
  119. return vectors
  120.  
  121. def get_rotating_vector(self, coefficient, freq, center_func):
  122. vector = Vector(RIGHT, **self.vector_config)
  123. vector.scale(abs(coefficient))
  124. if abs(coefficient) == 0:
  125. phase = 0
  126. else:
  127. phase = np.log(coefficient).imag
  128. vector.rotate(phase, about_point=ORIGIN)
  129. vector.freq = freq
  130. vector.coefficient = coefficient
  131. vector.center_func = center_func
  132. vector.add_updater(self.update_vector)
  133. return vector
  134.  
  135. def update_vector(self, vector, dt):
  136. time = self.get_vector_time()
  137. coef = vector.coefficient
  138. freq = vector.freq
  139. phase = np.log(coef).imag
  140.  
  141. vector.set_length(abs(coef))
  142. vector.set_angle(phase + time * freq * TAU)
  143. vector.shift(vector.center_func() - vector.get_start())
  144. return vector
  145.  
  146. def get_circles(self, vectors):
  147. return VGroup(*[
  148. self.get_circle(
  149. vector,
  150. color=color
  151. )
  152. for vector, color in zip(
  153. vectors,
  154. self.get_color_iterator()
  155. )
  156. ])
  157.  
  158. def get_circle(self, vector, color=BLUE):
  159. circle = Circle(color=color, **self.circle_config)
  160. circle.center_func = vector.get_start
  161. circle.radius_func = vector.get_length
  162. circle.add_updater(self.update_circle)
  163. return circle
  164.  
  165. def update_circle(self, circle):
  166. circle.set_width(2 * circle.radius_func())
  167. circle.move_to(circle.center_func())
  168. return circle
  169.  
  170. def get_vector_sum_path(self, vectors, color=YELLOW):
  171. coefs = [v.coefficient for v in vectors]
  172. freqs = [v.freq for v in vectors]
  173. center = vectors[0].get_start()
  174.  
  175. path = ParametricFunction(
  176. lambda t: center + reduce(op.add, [
  177. complex_to_R3(
  178. coef * np.exp(TAU * 1j * freq * t)
  179. )
  180. for coef, freq in zip(coefs, freqs)
  181. ]),
  182. t_min=0,
  183. t_max=1,
  184. color=color,
  185. step_size=self.parametric_function_step_size,
  186. )
  187. return path
  188.  
  189. def get_drawn_path_alpha(self):
  190. return self.get_vector_time()
  191.  
  192. def get_drawn_path(self, vectors, stroke_width=None, **kwargs):
  193. if stroke_width is None:
  194. stroke_width = self.drawn_path_stroke_width
  195. path = self.get_vector_sum_path(vectors, **kwargs)
  196. broken_path = CurvesAsSubmobjects(path)
  197. broken_path.curr_time = 0
  198. start, end = self.interpolate_config
  199.  
  200. def update_path(path, dt):
  201. alpha = self.get_drawn_path_alpha()
  202. n_curves = len(path)
  203. for a, sp in zip(np.linspace(0, 1, n_curves), path):
  204. b = (alpha - a)
  205. if b < 0:
  206. width = 0
  207. else:
  208. width = stroke_width * interpolate(start, end, (1 - (b % 1)))
  209. sp.set_stroke(width=width)
  210. path.curr_time += dt
  211. return path
  212.  
  213. broken_path.set_color(self.drawn_path_color)
  214. broken_path.add_updater(update_path)
  215. return broken_path
  216.  
  217. def get_y_component_wave(self,
  218. vectors,
  219. left_x=1,
  220. color=PINK,
  221. n_copies=2,
  222. right_shift_rate=5):
  223. path = self.get_vector_sum_path(vectors)
  224. wave = ParametricFunction(
  225. lambda t: op.add(
  226. right_shift_rate * t * LEFT,
  227. path.function(t)[1] * UP
  228. ),
  229. t_min=path.t_min,
  230. t_max=path.t_max,
  231. color=color,
  232. )
  233. wave_copies = VGroup(*[
  234. wave.copy()
  235. for x in range(n_copies)
  236. ])
  237. wave_copies.arrange(RIGHT, buff=0)
  238. top_point = wave_copies.get_top()
  239. wave.creation = ShowCreation(
  240. wave,
  241. run_time=(1 / self.get_slow_factor()),
  242. rate_func=linear,
  243. )
  244. cycle_animation(wave.creation)
  245. wave.add_updater(lambda m: m.shift(
  246. (m.get_left()[0] - left_x) * LEFT
  247. ))
  248.  
  249. def update_wave_copies(wcs):
  250. index = int(
  251. wave.creation.total_time * self.get_slow_factor()
  252. )
  253. wcs[:index].match_style(wave)
  254. wcs[index:].set_stroke(width=0)
  255. wcs.next_to(wave, RIGHT, buff=0)
  256. wcs.align_to(top_point, UP)
  257. wave_copies.add_updater(update_wave_copies)
  258.  
  259. return VGroup(wave, wave_copies)
  260.  
  261. def get_wave_y_line(self, vectors, wave):
  262. return DashedLine(
  263. vectors[-1].get_end(),
  264. wave[0].get_end(),
  265. stroke_width=1,
  266. dash_length=DEFAULT_DASH_LENGTH * 0.5,
  267. )
  268.  
  269. def get_coefficients_of_path(self, path, n_samples=10000, freqs=None):
  270. if freqs is None:
  271. freqs = self.get_freqs()
  272. dt = 1 / n_samples
  273. ts = np.arange(0, 1, dt)
  274. samples = np.array([
  275. path.point_from_proportion(t)
  276. for t in ts
  277. ])
  278. samples -= self.center_point
  279. complex_samples = samples[:, 0] + 1j * samples[:, 1]
  280.  
  281. return [
  282. np.array([
  283. np.exp(-TAU * 1j * freq * t) * cs
  284. for t, cs in zip(ts, complex_samples)
  285. ]).sum() * dt for freq in freqs
  286. ]
  287.  
  288. def zoom_config(self):
  289. # This is not in the original version of the code.
  290. self.activate_zooming(animate=False)
  291. self.zoom_position(self.zoomed_display)
  292. self.zoomed_camera.frame.add_updater(lambda mob: mob.move_to(self.vectors[-1].get_end()))
  293.  
  294. def scale_zoom_camera_to_full_screen_config(self):
  295. # This is not in the original version of the code.
  296. def fix_update(mob, dt, velocity_factor, dt_calculate):
  297. if dt == 0 and mob.counter == 0:
  298. rate = velocity_factor * dt_calculate
  299. mob.counter += 1
  300. else:
  301. rate = dt * velocity_factor
  302. if dt > 0:
  303. mob.counter = 0
  304. return rate
  305.  
  306. fps = 1 / self.camera.frame_rate
  307. mob = self.zoomed_display
  308. mob.counter = 0
  309. velocity_factor = self.zoom_camera_to_full_screen_config["velocity_factor"]
  310. mob.start_time = 0
  311. run_time = self.zoom_camera_to_full_screen_config["run_time"]
  312. run_time *= 2
  313. mob_height = mob.get_height()
  314. mob_width = mob.get_width()
  315. mob_center = mob.get_center()
  316. ctx = self.zoomed_camera.cairo_line_width_multiple
  317.  
  318. def update_camera(mob, dt):
  319. line = Line(
  320. mob_center,
  321. self.camera_frame.get_center()
  322. )
  323. mob.start_time += fix_update(mob, dt, velocity_factor, fps)
  324. if mob.start_time <= run_time:
  325. alpha = mob.start_time / run_time
  326. alpha_func = self.zoom_camera_to_full_screen_config["func"](alpha)
  327. coord = line.point_from_proportion(alpha_func)
  328. mob.set_height(
  329. interpolate(
  330. mob_height,
  331. self.camera_frame.get_height(),
  332. alpha_func
  333. ),
  334. stretch=True
  335. )
  336. mob.set_width(
  337. interpolate(
  338. mob_width,
  339. self.camera_frame.get_width(),
  340. alpha_func
  341. ),
  342. stretch=True
  343. )
  344. self.zoomed_camera.cairo_line_width_multiple = interpolate(
  345. ctx,
  346. self.camera.cairo_line_width_multiple,
  347. alpha_func
  348. )
  349. mob.move_to(coord)
  350. return mob
  351.  
  352. self.zoomed_display.add_updater(update_camera)
  353.  
  354.  
  355. class AbstractFourierOfTexSymbol(FourierCirclesScene):
  356. CONFIG = {
  357. "n_vectors": 50,
  358. "center_point": ORIGIN,
  359. "slow_factor": 0.05,
  360. "n_cycles": None,
  361. "run_time": 10,
  362. "tex": r"\rm M",
  363. "start_drawn": True,
  364. "path_custom_position": lambda mob: mob,
  365. "max_circle_stroke_width": 1,
  366. "tex_class": TexMobject,
  367. "tex_config": {
  368. "fill_opacity": 0,
  369. "stroke_width": 1,
  370. "stroke_color": WHITE
  371. },
  372. "include_zoom_camera": False,
  373. "scale_zoom_camera_to_full_screen": False,
  374. "scale_zoom_camera_to_full_screen_at": 1,
  375. "zoom_position": lambda mob: mob.scale(0.8).move_to(ORIGIN).to_edge(RIGHT)
  376. }
  377.  
  378. def construct(self):
  379. # This is not in the original version of the code.
  380. self.add_vectors_circles_path()
  381. if self.wait_before_start != None:
  382. self.wait(self.wait_before_start)
  383. self.add_vector_clock()
  384. self.add(self.vector_clock)
  385. if self.include_zoom_camera:
  386. self.zoom_config()
  387. if self.scale_zoom_camera_to_full_screen:
  388. self.run_time -= self.scale_zoom_camera_to_full_screen_at
  389. self.wait(self.scale_zoom_camera_to_full_screen_at)
  390. self.scale_zoom_camera_to_full_screen_config()
  391. if self.n_cycles != None:
  392. if not self.scale_zoom_camera_to_full_screen:
  393. for n in range(self.n_cycles):
  394. self.run_one_cycle()
  395. else:
  396. cycle = 1 / self.slow_factor
  397. total_time = cycle * self.n_cycles
  398. total_time -= self.scale_zoom_camera_to_full_screen_at
  399. self.wait(total_time)
  400. elif self.run_time != None:
  401. self.wait(self.run_time)
  402.  
  403. def add_vectors_circles_path(self):
  404. path = self.get_path()
  405. self.path_custom_position(path)
  406. coefs = self.get_coefficients_of_path(path)
  407. vectors = self.get_rotating_vectors(coefficients=coefs)
  408. circles = self.get_circles(vectors)
  409. self.set_decreasing_stroke_widths(circles)
  410. drawn_path = self.get_drawn_path(vectors)
  411. if self.start_drawn:
  412. self.vector_clock.increment_value(1)
  413. self.add(path)
  414. self.add(vectors)
  415. self.add(circles)
  416. self.add(drawn_path)
  417.  
  418. self.vectors = vectors
  419. self.circles = circles
  420. self.path = path
  421. self.drawn_path = drawn_path
  422.  
  423. def run_one_cycle(self):
  424. time = 1 / self.slow_factor
  425. self.wait(time)
  426.  
  427. def set_decreasing_stroke_widths(self, circles):
  428. mcsw = self.max_circle_stroke_width
  429. for k, circle in zip(it.count(1), circles):
  430. circle.set_stroke(width=max(
  431. mcsw / k,
  432. mcsw,
  433. ))
  434. return circles
  435.  
  436. def get_path(self):
  437. tex_mob = self.tex_class(self.tex, **self.tex_config)
  438. tex_mob.set_height(6)
  439. path = tex_mob.family_members_with_points()[0]
  440. return path
  441.  
  442.  
  443. class AbstractFourierFromSVG(AbstractFourierOfTexSymbol):
  444. CONFIG = {
  445. "n_vectors": 101,
  446. "run_time": 10,
  447. "start_drawn": True,
  448. "file_name": None,
  449. "svg_config": {
  450. "fill_opacity": 0,
  451. "stroke_color": WHITE,
  452. "stroke_width": 1,
  453. "height": 7
  454. }
  455. }
  456.  
  457. def get_shape(self):
  458. shape = SVGMobject(self.file_name, **self.svg_config)
  459. return shape
  460.  
  461. def get_path(self):
  462. shape = self.get_shape()
  463. path = shape.family_members_with_points()[0]
  464. return path
  465.  
  466.  
  467.  
  468. class FourierOfPaths(AbstractFourierOfTexSymbol):
  469. CONFIG = {
  470. "n_vectors": 100,
  471. "name_color": WHITE,
  472. "tex_class": TexMobject,
  473. "tex": None,
  474. "file_name": None,
  475. "tex_config": {
  476. "stroke_color": WHITE,
  477. "fill_opacity": 0,
  478. "stroke_width": 3,
  479. },
  480. "svg_config": {},
  481. "time_per_symbol": 5,
  482. "slow_factor": 1 / 5,
  483. "parametric_function_step_size": 0.01,
  484. "include_zoom_camera": False,
  485. "scale_zoom_camera_to_full_screen": False,
  486. }
  487.  
  488. def construct(self):
  489. self.add_vector_clock()
  490. if self.tex != None:
  491. name = self.tex_class(self.tex, **self.tex_config)
  492. elif self.file_name != None and self.tex == None:
  493. name = SVGMobject(self.file_name, **self.svg_config)
  494. max_width = FRAME_WIDTH - 2
  495. max_height = FRAME_HEIGHT - 2
  496. name.set_width(max_width)
  497. if name.get_height() > max_height:
  498. name.set_height(max_height)
  499.  
  500. frame = self.camera.frame
  501. frame.save_state()
  502.  
  503. vectors = VGroup(VectorizedPoint())
  504. circles = VGroup(VectorizedPoint())
  505. for path in name.family_members_with_points():
  506. for subpath in path.get_subpaths():
  507. sp_mob = VMobject()
  508. sp_mob.set_points(subpath)
  509. coefs = self.get_coefficients_of_path(sp_mob)
  510. new_vectors = self.get_rotating_vectors(
  511. coefficients=coefs
  512. )
  513. new_circles = self.get_circles(new_vectors)
  514. self.set_decreasing_stroke_widths(new_circles)
  515.  
  516. drawn_path = self.get_drawn_path(new_vectors)
  517. drawn_path.clear_updaters()
  518. drawn_path.set_style(**self.tex_config)
  519. drawn_path.set_style(**self.svg_config)
  520.  
  521. static_vectors = VMobject().become(new_vectors)
  522. static_circles = VMobject().become(new_circles)
  523.  
  524. self.play(
  525. Transform(vectors, static_vectors, remover=True),
  526. Transform(circles, static_circles, remover=True),
  527. frame.set_height, 1.5 * name.get_height(),
  528. frame.move_to, path,
  529. )
  530.  
  531. self.add(new_vectors, new_circles)
  532. self.vector_clock.set_value(0)
  533. self.play(
  534. ShowCreation(drawn_path),
  535. rate_func=linear,
  536. run_time=self.time_per_symbol
  537. )
  538. self.remove(new_vectors, new_circles)
  539. self.add(static_vectors, static_circles)
  540.  
  541. vectors = static_vectors
  542. circles = static_circles
  543. self.play(
  544. FadeOut(vectors),
  545. FadeOut(circles),
  546. Restore(frame),
  547. run_time=2
  548. )
  549. self.wait(3)
  550.  
  551. ########################################################################################
  552. ########################################################################################
  553. ########################################################################################
  554.  
  555. # ____ _ _ _____ _
  556. # / ___|(_)_ __ ___ _ __ | | ___ | ___|__ _ _ _ __(_) ___ _ __
  557. # \___ \| | '_ ` _ \| '_ \| |/ _ \ | |_ / _ \| | | | '__| |/ _ \ '__|
  558. # ___) | | | | | | | |_) | | __/ | _| (_) | |_| | | | | __/ |
  559. # |____/|_|_| |_| |_| .__/|_|\___| |_| \___/ \__,_|_| |_|\___|_|
  560. # |_|
  561. # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  562.  
  563.  
  564. # Using TexMobject or TextMobject
  565. class FourierOfTexSymbol(AbstractFourierOfTexSymbol):
  566. CONFIG = {
  567. # if start_draw = True the path start to draw
  568. "start_drawn": True,
  569. # Tex config
  570. "tex_class": TexMobject,
  571. "tex": r"\Sigma",
  572. "tex_config": {
  573. "fill_opacity": 0,
  574. "stroke_width": 1,
  575. "stroke_color": WHITE
  576. },
  577. # Draw config
  578. "drawn_path_color": YELLOW,
  579. "interpolate_config": [0, 1],
  580. "n_vectors": 50,
  581. "big_radius": 2,
  582. "drawn_path_stroke_width": 2,
  583. "center_point": ORIGIN,
  584. # Duration config
  585. "slow_factor": 0.1,
  586. "n_cycles": None,
  587. "run_time": 10,
  588. # colors of circles
  589. "colors": [
  590. BLUE_D,
  591. BLUE_C,
  592. BLUE_E,
  593. GREY_BROWN,
  594. ],
  595. # circles config
  596. "circle_config": {
  597. "stroke_width": 1,
  598. },
  599. # vector config
  600. "vector_config": {
  601. "buff": 0,
  602. "max_tip_length_to_length_ratio": 0.25,
  603. "tip_length": 0.15,
  604. "max_stroke_width_to_length_ratio": 10,
  605. "stroke_width": 1.7,
  606. },
  607. "base_frequency": 1,
  608. # definition of subpaths
  609. "parametric_function_step_size": 0.001,
  610. }
  611.  
  612. # Tex examples -------------------------------------------
  613. # n_vectors
  614. class Tsymbol20vectors(FourierOfTexSymbol):
  615. CONFIG = {
  616. "n_vectors": 20,
  617. "run_time": 10, # 10 seconds
  618. "tex_class": TextMobject,
  619. "tex": "T"
  620. }
  621.  
  622. class Tsymbol50vectors(FourierOfTexSymbol):
  623. CONFIG = {
  624. "n_vectors": 50,
  625. "run_time": 10, # 10 seconds
  626. "tex_class": TextMobject,
  627. "tex": "T"
  628. }
  629.  
  630. class Tsymbol150vectors(FourierOfTexSymbol):
  631. CONFIG = {
  632. "n_vectors": 150,
  633. "run_time": 10, # 10 seconds
  634. "tex_class": TextMobject,
  635. "tex": "T"
  636. }
  637.  
  638. class SigmaSymbol150vectors(FourierOfTexSymbol):
  639. CONFIG = {
  640. "n_vectors": 150,
  641. "run_time": 10, # 10 seconds
  642. "tex_class": TexMobject, # <-------- Default
  643. "tex": "\\Sigma"
  644. }
  645.  
  646. # slow_factor
  647. class SlowFactor0_1(FourierOfTexSymbol):
  648. CONFIG = {
  649. "n_vectors": 30,
  650. "run_time": 7,
  651. "tex_class": TexMobject,
  652. "tex": "\\Sigma",
  653. "slow_factor": 0.1, # <------------------ Default
  654. }
  655.  
  656. class SlowFactor0_3(FourierOfTexSymbol):
  657. CONFIG = {
  658. "n_vectors": 30,
  659. "run_time": 7,
  660. "tex_class": TexMobject,
  661. "tex": "\\Sigma",
  662. "slow_factor": 0.3, # <------------------
  663. }
  664.  
  665. class SlowFactor0_5(FourierOfTexSymbol):
  666. CONFIG = {
  667. "n_vectors": 30,
  668. "run_time": 7,
  669. "tex_class": TexMobject,
  670. "tex": "\\Sigma",
  671. "slow_factor": 0.5, # <------------------
  672. }
  673.  
  674. # start_drawn
  675. class StartDrawTrue(FourierOfTexSymbol):
  676. CONFIG = {
  677. "slow_factor": 0.05,
  678. "n_vectors": 30,
  679. "run_time": 15,
  680. "tex": "\\tau",
  681. "start_drawn": True # <------------------ Default
  682. }
  683.  
  684. class StartDrawFalse(FourierOfTexSymbol):
  685. CONFIG = {
  686. "slow_factor": 0.05,
  687. "n_vectors": 30,
  688. "run_time": 15,
  689. "tex": "\\tau",
  690. "start_drawn": False # <------------------
  691. }
  692.  
  693. # interpolate_config
  694. class InterpolateConfig0to1(FourierOfTexSymbol):
  695. CONFIG = {
  696. "slow_factor": 0.05,
  697. "n_vectors": 30,
  698. "run_time": 15,
  699. "tex": "\\tau",
  700. "interpolate_config": [0, 1] # <---------- Default
  701. }
  702.  
  703. class InterpolateConfig0_3to_1(FourierOfTexSymbol):
  704. CONFIG = {
  705. "slow_factor": 0.05,
  706. "n_vectors": 30,
  707. "run_time": 15,
  708. "tex": "\\tau",
  709. "interpolate_config": [0.3, 1] # <----------
  710. }
  711.  
  712. class InterpolateConfig1_to_1(FourierOfTexSymbol):
  713. CONFIG = {
  714. "slow_factor": 0.05,
  715. "n_vectors": 30,
  716. "run_time": 15,
  717. "tex": "\\tau",
  718. "interpolate_config": [1, 1] # <---------- # always write
  719. }
  720.  
  721. # n_cycles vs run_time
  722. class NCyclesVsRunTime(FourierOfTexSymbol):
  723. CONFIG = {
  724. "n_vectors": 30,
  725. "n_cycles": 3,
  726. "tex": "\\tau",
  727. }
  728.  
  729. # wait_before_start
  730. class WaitBeforeStart(FourierOfTexSymbol):
  731. CONFIG = {
  732. "n_vectors": 30,
  733. "n_cycles": 1,
  734. "tex": "\\tau",
  735. "wait_before_start": 2
  736. }
  737.  
  738. # center_point
  739. class CenterPoint(FourierOfTexSymbol):
  740. CONFIG = {
  741. "n_vectors": 30,
  742. "n_cycles": 1,
  743. "tex": "\\tau",
  744. "center_point": RIGHT*3
  745. }
  746.  
  747. # path_custom_position
  748. class CustomPosition(FourierOfTexSymbol):
  749. CONFIG = {
  750. "n_vectors": 30,
  751. "n_cycles": 1,
  752. "tex": "\\tau",
  753. "center_point": RIGHT*3,
  754. "path_custom_position": lambda mob: mob.to_edge(LEFT),
  755. "circle_config": {
  756. "stroke_opacity": 0,
  757. },
  758. }
  759.  
  760. # o x o x o x o x o x o x o x o x o x o x o x o x o x o x o x o x o x o x o x o x
  761. # SVG
  762. class FourierFromSVG(AbstractFourierFromSVG):
  763. CONFIG = {
  764. # if start_draw = True the path start to draw
  765. "start_drawn": True,
  766. # SVG file name
  767. "file_name": None,
  768. "svg_config": {
  769. "fill_opacity": 0,
  770. "stroke_color": WHITE,
  771. "stroke_width": 1,
  772. "height": 7
  773. },
  774. # Draw config
  775. "drawn_path_color": YELLOW,
  776. "interpolate_config": [0, 1],
  777. "n_vectors": 50,
  778. "big_radius": 2,
  779. "drawn_path_stroke_width": 2,
  780. "center_point": ORIGIN,
  781. # Duration config
  782. "slow_factor": 0.1,
  783. "n_cycles": None,
  784. "run_time": 10,
  785. # colors of circles
  786. "colors": [
  787. BLUE_D,
  788. BLUE_C,
  789. BLUE_E,
  790. GREY_BROWN,
  791. ],
  792. # circles config
  793. "circle_config": {
  794. "stroke_width": 1,
  795. },
  796. # vector config
  797. "vector_config": {
  798. "buff": 0,
  799. "max_tip_length_to_length_ratio": 0.25,
  800. "tip_length": 0.15,
  801. "max_stroke_width_to_length_ratio": 10,
  802. "stroke_width": 1.7,
  803. },
  804. "base_frequency": 1,
  805. # definition of subpaths
  806. "parametric_function_step_size": 0.001,
  807. }
  808.  
  809. # file_name
  810. class SVGDefault(FourierFromSVG):
  811. CONFIG = {
  812. "n_vectors": 100,
  813. "n_cycles": 1,
  814. "file_name": "c_clef", # in assets/svg_images/c_clef.svg
  815. }
  816.  
  817. # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  818. # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  819. # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  820.  
  821. # __ ___ _ _
  822. # \ \ / (_) |_| |__
  823. # \ \ /\ / /| | __| '_ \
  824. # \ V V / | | |_| | | |
  825. # \_/\_/ |_|\__|_| |_|
  826. # _____ _
  827. # |__ /___ ___ _ __ ___ ___ __| | ___ __ _ _ __ ___ ___ _ __ __ _
  828. # / // _ \ / _ \| '_ ` _ \ / _ \/ _` | / __/ _` | '_ ` _ \ / _ \ '__/ _` |
  829. # / /| (_) | (_) | | | | | | __/ (_| | | (_| (_| | | | | | | __/ | | (_| |
  830. # /____\___/ \___/|_| |_| |_|\___|\__,_| \___\__,_|_| |_| |_|\___|_| \__,_|
  831. # ---------------------------------------------------------------------------------------
  832. # The following works in both Tex and SVG
  833. # ---------------------------------------
  834. # ---------------------------
  835. # ----------------
  836.  
  837. # How activate it
  838. class ZoomedActivate(FourierFromSVG):
  839. CONFIG = {
  840. "slow_factor": 0.05,
  841. "n_vectors": 50,
  842. "n_cycles": 1,
  843. "file_name": "c_clef",
  844. "include_zoom_camera": True,
  845. "zoom_position": lambda zc: zc.to_corner(DR)
  846. }
  847.  
  848. # Zoomed camera: Moving camera
  849. # Zoomed display: Static camera
  850. # More info: https://github.com/Elteoremadebeethoven/AnimationsWithManim/blob/master/English/extra/faqs/faqs.md#zoomed-scene-example
  851. class ZoomedConfig(FourierFromSVG):
  852. CONFIG = {
  853. "slow_factor": 0.05,
  854. "n_vectors": 150,
  855. "n_cycles": 1,
  856. "file_name": "c_clef",
  857. "path_custom_position": lambda path: path.shift(LEFT*2),
  858. "center_point": LEFT*2,
  859. "circle_config": {
  860. "stroke_width": 0.5,
  861. "stroke_opacity": 0.2,
  862. },
  863. # Zoom config
  864. "include_zoom_camera": True,
  865. "zoom_position": lambda zc: zc.to_edge(RIGHT).set_y(0),
  866. "zoom_factor": 0.5,
  867. "zoomed_display_height": 5,
  868. "zoomed_display_width": 5,
  869. "zoomed_camera_config": {
  870. "default_frame_stroke_width": 3,
  871. "cairo_line_width_multiple": 0.05,
  872. # What is cairo_line_width_multiple?
  873. # See here: https://stackoverflow.com/questions/60765530/manim-zoom-not-preserving-line-thickness
  874. },
  875. }
  876.  
  877. # Move Zoomed display to full screen
  878. class ZoomedDisplayToFullScreen(FourierOfTexSymbol):
  879. CONFIG = {
  880. "slow_factor": 0.05,
  881. "n_vectors": 30,
  882. "run_time": 16,
  883. "tex": "\\tau",
  884. # Zoom config
  885. "include_zoom_camera": True,
  886. "zoom_position": lambda zc: zc.to_corner(DR),
  887. # Zoomed display to Full screen config
  888. "scale_zoom_camera_to_full_screen": True,
  889. "scale_zoom_camera_to_full_screen_at": 4, # Move the camera at 4 seconds
  890. "zoom_camera_to_full_screen_config": {
  891. "run_time": 3,
  892. "func": smooth,
  893. "velocity_factor": 1
  894. },
  895. }
  896.  
  897. class ZoomedDisplayToFullScreenWithRestore(ZoomedDisplayToFullScreen):
  898. CONFIG = {
  899. "run_time": 20,
  900. "zoom_camera_to_full_screen_config": {
  901. "run_time": 12,
  902. "func": lambda t: there_and_back_with_pause(t, 1/10),
  903. # learn more: manimlib/utils/rate_functions.py
  904. },
  905. }
  906.  
  907.  
  908. # ---------------------------------------------------------------------------------------
  909. # ---------------------------------------------------------------------------------------
  910. # ---------------------------------------------------------------------------------------
  911.  
  912. # ____ _ _
  913. # | _ \ _ __ __ ___ __ _ __ __ _| |_| |__
  914. # | | | | '__/ _` \ \ /\ / / | '_ \ / _` | __| '_ \
  915. # | |_| | | | (_| |\ V V / | |_) | (_| | |_| | | |
  916. # |____/|_| \__,_| \_/\_/ | .__/ \__,_|\__|_| |_|
  917. # |_|
  918.  
  919. # //////////////////////////////////////////////////////////////////////////////////////////
  920.  
  921. class FourierOfPathsTB(FourierOfPaths):
  922. CONFIG = {
  923. "n_vectors": 100,
  924. "tex_class": TextMobject,
  925. "tex": "TB",
  926. "tex_config": {
  927. "stroke_color": RED,
  928. },
  929. "time_per_symbol": 5,
  930. "slow_factor": 1 / 5,
  931. }
  932.  
  933.  
  934. # Convert objects to paths
  935. # Inkscape example: [ToolBar] Path > Object to path
  936. class FourierOfPathsSVG(FourierOfPaths):
  937. CONFIG = {
  938. "n_vectors": 100,
  939. "file_name": "music_symbols",
  940. "svg_config": {
  941. "stroke_color": RED,
  942. },
  943. "time_per_symbol": 5,
  944. "slow_factor": 1 / 5,
  945. }
  946.  
  947. # //////////////////////////////////////////////////////////////////////////////////////////
  948. # //////////////////////////////////////////////////////////////////////////////////////////
  949. # //////////////////////////////////////////////////////////////////////////////////////////
  950.  
  951. # ____ _
  952. # / ___| _ ___| |_ ___ _ __ ___
  953. # | | | | | / __| __/ _ \| '_ ` _ \
  954. # | |__| |_| \__ \ || (_) | | | | | |
  955. # \____\__,_|___/\__\___/|_| |_| |_|
  956.  
  957. # _ _ _ _
  958. # / \ _ __ (_)_ __ ___ __ _| |_(_) ___ _ __ ___
  959. # / _ \ | '_ \| | '_ ` _ \ / _` | __| |/ _ \| '_ \/ __|
  960. # / ___ \| | | | | | | | | | (_| | |_| | (_) | | | \__ \
  961. # /_/ \_\_| |_|_|_| |_| |_|\__,_|\__|_|\___/|_| |_|___/
  962. # x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-
  963.  
  964. class CustomAnimationExample(FourierCirclesScene):
  965. CONFIG = {
  966. "n_vectors": 200,
  967. "slow_factor": 0.2,
  968. "fourier_symbol_config": {
  969. "stroke_width": 0,
  970. "fill_opacity": 0,
  971. "height": 4,
  972. "fill_color": WHITE
  973. },
  974. "circle_config": {
  975. "stroke_width": 1,
  976. "stroke_opacity": 0.3,
  977. },
  978. }
  979. def construct(self):
  980. t_symbol = TextMobject("T", **self.fourier_symbol_config)
  981. c_clef_symbol = SVGMobject("c_clef", **self.fourier_symbol_config)
  982. c_clef_symbol.match_height(t_symbol)
  983. # set gradient
  984. for mob in [t_symbol,c_clef_symbol]:
  985. mob.set_sheen(0,UP)
  986. mob.set_color(color=[BLACK,GRAY,WHITE])
  987. group = VGroup(t_symbol,c_clef_symbol).arrange(RIGHT,buff=0.1)
  988. # set paths
  989. path1 = t_symbol.family_members_with_points()[0]
  990. path2 = c_clef_symbol.family_members_with_points()[0]
  991. # path 1 config
  992. coefs1 = self.get_coefficients_of_path(path1)
  993. vectors1 = self.get_rotating_vectors(coefficients=coefs1)
  994. circles1 = self.get_circles(vectors1)
  995. drawn_path1 = self.get_drawn_path(vectors1)
  996. # path 2 config
  997. coefs2 = self.get_coefficients_of_path(path2)
  998. vectors2 = self.get_rotating_vectors(coefficients=coefs2)
  999. circles2 = self.get_circles(vectors2)
  1000. drawn_path2= self.get_drawn_path(vectors2)
  1001. # text definition
  1002. text = TextMobject("Thanks for watch!")
  1003. text.scale(1.5)
  1004. text.next_to(group,DOWN)
  1005. # all elements toget
  1006. all_mobs = VGroup(group,text)
  1007. # set mobs to remove
  1008. vectors1_to_fade = vectors1.copy()
  1009. circles1_to_fade = circles1.copy()
  1010. vectors1_to_fade.clear_updaters()
  1011. circles1_to_fade.clear_updaters()
  1012. vectors2_to_fade = vectors2.copy()
  1013. circles2_to_fade = circles2.copy()
  1014. vectors2_to_fade.clear_updaters()
  1015. circles2_to_fade.clear_updaters()
  1016.  
  1017. self.play(
  1018. *[
  1019. GrowArrow(arrow)
  1020. for vg in [vectors1_to_fade, vectors2_to_fade]
  1021. for arrow in vg
  1022. ],
  1023. *[
  1024. ShowCreation(circle)
  1025. for cg in [circles1_to_fade, circles2_to_fade]
  1026. for circle in cg
  1027. ],
  1028. run_time=2.5,
  1029. )
  1030. self.remove(
  1031. *vectors1_to_fade,
  1032. *circles1_to_fade,
  1033. *vectors2_to_fade,
  1034. *circles2_to_fade,
  1035. )
  1036. self.add(
  1037. vectors1,
  1038. circles1,
  1039. drawn_path1.set_color(RED),
  1040. vectors2,
  1041. circles2,
  1042. drawn_path2.set_color(BLUE),
  1043. )
  1044. self.add_vector_clock()
  1045.  
  1046. # wait one cycle
  1047. self.wait( 1 / self.slow_factor)
  1048. self.bring_to_back(t_symbol,c_clef_symbol)
  1049. self.play(
  1050. t_symbol.set_fill,None,1,
  1051. c_clef_symbol.set_fill,None,1,
  1052. run_time=3
  1053. )
  1054. self.wait()
  1055. # move camera
  1056. self.play(
  1057. self.camera_frame.set_height, all_mobs.get_height()*1.2,
  1058. self.camera_frame.move_to, all_mobs.get_center()
  1059. )
  1060. self.wait(0.5)
  1061. self.play(
  1062. Write(text)
  1063. )
  1064. self.wait(10)
  1065.  
  1066. # x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-
  1067. # x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-
  1068. # x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-
Advertisement
Add Comment
Please, Sign In to add comment