368 Commits

Author SHA1 Message Date
鹤翔万里
f934bdc61e Merge pull request #1284 from niedong/typo-fix
fix typo docstring in scene_file_writer.py
2020-11-29 19:23:47 +08:00
niedong
ba405521ce fix typo docstring in scene_file_writer.py 2020-11-29 11:51:20 +08:00
鹤翔万里
0dc8e4389d Merge pull request #1268 from niedong/ci-fix
Change Ubuntu version to bionic in .travis.yml
2020-11-14 10:53:25 +08:00
niedong
34ec0f4795 Change Ubuntu version to bionic in .travis.yml
Remove redundant pycairo version
2020-11-09 23:09:38 +08:00
鹤翔万里
faa52d7dd4 Merge pull request #1264 from niedong/fix-ci
Specify pycairo version to 1.19.1
2020-11-08 13:49:35 +08:00
niedong
d797e5f1fe Specify pycairo version to 1.19.1 2020-11-04 18:38:10 +08:00
鹤翔万里
99952067c1 Merge pull request #1260 from Abdul1337/master
Fixed a typo in exapmle_scenes.py
2020-10-21 22:42:20 +08:00
Abdul Aziz
30ae89464e Fixed a typo in exapmle_scenes.py 2020-10-20 18:24:16 +05:30
鹤翔万里
1ecbbbbcd5 Merge pull request #1251 from italosestilon/master
fix iteration through a dictionary
2020-10-10 10:45:52 +08:00
鹤翔万里
186b86cb70 Merge pull request #1250 from amogh7joshi/patch-2
Fix typo in scene.py
2020-10-08 23:09:37 +08:00
Italos Estilon de Souza
4c42083ffc fix iteration through a dictionary 2020-10-07 11:52:05 -03:00
Amogh Joshi
dec753fc26 Update scene.py 2020-10-05 17:49:40 -04:00
鹤翔万里
08c90c272b Merge pull request #1216 from BERENGENITA/patch-1
Fixed typo in comment imports.py
2020-10-02 14:03:07 +08:00
Tony031218
be8b28dd9d update README.md 2020-10-01 10:32:01 +08:00
Tony031218
d0dc7ed301 remove an unnecessary file 2020-10-01 10:12:03 +08:00
鹤翔万里
abc24f2d52 Merge pull request #1147 from MeatBoyed/master
Pygments added to environment.yml
2020-09-30 23:33:08 +08:00
鹤翔万里
53756ea140 Merge pull request #1112 from vivek3141/patch-1
Add dot_color to BulletedList
2020-09-30 23:27:29 +08:00
鹤翔万里
dcb608f258 Merge pull request #1072 from Tony031218/change-coord-color
Allow Axes to change the color of coordinate labels
2020-09-30 23:26:59 +08:00
鹤翔万里
05acf31e47 Merge pull request #1064 from Erik-White/numberline
Correctly return get_unit_size
2020-09-30 23:21:56 +08:00
鹤翔万里
bc5c3968d9 Merge pull request #1043 from kuk0/get_merged_array
remove superfluous code
2020-09-30 23:21:05 +08:00
鹤翔万里
11c451c2e9 Merge pull request #1038 from peninha/patch-1
Corrected a bug in stretch_to_fit_depth function
2020-09-30 23:19:26 +08:00
鹤翔万里
52c5e32ba5 Merge pull request #975 from HappyFacade/patch-1
Update readme to reflect #571
2020-09-30 23:13:16 +08:00
dummy26
37efc93e9c Fix a typo in mobject.py (#847) 2020-09-30 23:03:57 +08:00
鹤翔万里
d63f61b903 Merge pull request #909 from Solara570/numberplane-fix
Small fix to NumberPlane construction
2020-09-30 23:01:49 +08:00
鹤翔万里
49d53d9a8f Merge pull request #836 from mavaras/master
#806 typo in WriteStuff
2020-09-30 22:57:30 +08:00
chaoxiaosu
79bf87754a A solution to 'Latex error converting to dvi' problem (#689) 2020-09-30 22:48:29 +08:00
鹤翔万里
e336cf5ddc Merge pull request #1217 from dor2727/patch-tobytes
fixed deprecation warning: tostring -> tobytes
2020-09-30 22:28:28 +08:00
鹤翔万里
e9638aee2e Merge pull request #1187 from Tony031218/master
A solution to xelatex error converting to xdv
2020-09-30 20:54:47 +08:00
Dor Harpaz
a42d9c6ecb fixed deprecation warning: tostring -> tobytes 2020-08-27 14:03:43 +03:00
BERENGENITA
9f945d9940 Fixed typo in comment imports.py
I have fixed a very simple typo and would like to commit it.
2020-08-27 12:17:43 +02:00
鹤翔万里
7556b99dc0 Update ctex_template.tex 2020-07-28 23:03:59 +08:00
Devin Neal
9174ec335c Update README.md 2020-07-18 09:07:34 -07:00
Charles
ea929d167f Pygments added to environment.yml 2020-06-22 13:06:21 +02:00
Vivek Verma
82d6ad0ef5 Add dot_color to BulletedList 2020-05-28 11:19:08 -07:00
Devin Neal
3c1a6bb8b1 Merge pull request #1091 from applemonkey496/patch-3
Add missing import to brace.py
2020-05-20 20:24:59 -07:00
Devin Neal
00ff47855e Merge pull request #1069 from applemonkey496/patch-1
Fix "itslef" to "itself"
2020-05-20 20:21:10 -07:00
applemonkey496
45c5ec7091 Add missing import to brace.py
Without `import copy` lines 128 to 131 will throw an error. I've tested this edit in my local version of the library and it fixes the bug.
2020-05-20 20:07:13 -07:00
Tony031218
4d78e0c63e fix changing coordinates color 2020-05-15 12:36:55 +08:00
Devin Neal
aff2d21bad Merge pull request #734 from zombie110year/master
latex can't recognize path seperator \\ in windows
2020-05-14 21:13:02 -07:00
applemonkey496
c82b1fc2c9 Fix "itslef" to "itself"
I know this is trivial, but I had to fix it.
2020-05-14 12:42:56 -07:00
Devin Neal
ca0b7a6b06 Merge pull request #1066 from 3b1b/remove-sanim
Remove sanim directory
2020-05-13 23:06:04 -07:00
Devin Neal
d31be357e5 Remove sanim directory 2020-05-13 23:04:31 -07:00
Aathish
a529a59abf Added DocStrings for all methods in Container, Scene, GraphScene, MovingCameraScene, SceneFileWriter, ThreeDScene, SpecialThreeDScene, ZoomedScene, VectorScene, and LinearTransformationScene. (#1040)
* Added DocStrings for methods in Container and Scene.
Removed 2 unused imports from scene.py.

* Added DocStrings for all methods in GraphScene, MovingCameraScene, SceneFileWriter, ThreeDScene, SpecialThreeDScene and ZoomedScene.

* Added DocStrings for all methods in `VectorScene` and LinearTransformationScene...
...except `position_x_coordinate` and `position_y_coordinate`

Co-authored-by: Aathish Sivasubrahmanian <aathishs@Aathishs-MacBook-Air.local>
2020-05-13 22:41:22 -07:00
NavpreetDevpuri
cf656e9c21 Code() in file Code_mobject.py to display code with color highlighted added Paragraph() and "exact_spaces" parameter to Text() (#1036) 2020-05-13 22:19:09 -07:00
NavpreetDevpuri
7f1a15b6ba Fixed ffmpeg 'Impossible to Open' and 'Protocol not found' (#1057) 2020-05-13 22:13:56 -07:00
Erik White
f3f9d0dfb7 Correctly return get_unit_size 2020-05-13 19:15:01 +03:00
Kubo Kovac
2f26a32f96 remove superfluous code 2020-05-10 14:58:01 +02:00
peninha
6a571262fd Corrected a bug in stretch_to_fit_depth function 2020-05-10 01:40:21 -03:00
Devin Neal
dbdd799696 Remove versions from requirements.txt 2020-05-07 11:31:54 -07:00
XiaoYoung
522a5b3c5f Fix space characters problem of Text (#1035)
* Fix Text wrong display

* Fix space characters problem of Text

* Fix a potential bug using height or width in Text

* Update Text

* Fix typo in text_mobject.py
2020-05-07 01:16:39 -07:00
鹤翔万里
3362f93964 Fix three bugs(shaders/stroke/size) of Text Class (text_mobject.py) (#1030)
* fix: remove the last M tag in svg files to make Text run in shaders branch

* fix: close the svg path manually to fix the bug of wrong stroke

* fix: remove Space mobjects in Text to fix the bug of TransformText

* feat: make Text and TextMobject equal in size

* this will lead to more bugs of setting color, so I delete it
2020-05-05 00:12:22 -07:00
Mike Magruder
af65c9d5d4 Performance improvement for most scenes (#974)
tl;dr: this is a significant performance improvement for many scenes. 1.7x - 2.6x improvement in animation it/s.

This is a small change to some of the hotest paths in rendering objects. The biggest win comes from not using np.allclose() to check if two points are close enough. In general, NumPy is awesome at operating on large arrays, but overkill for very tiny questions like this. Created a small function to determine if two points are close using the same algorithm, and limited it to 2D points since that's all we need in set_cairo_context_path().

A couple of other minor tweaks to reduce or eliminate other uses of NumPy in this path.

In general, it is better to avoid wrapping lists in np.array when a real NumPy array isn't actually needed.

Added a new file for performance test scenes, with a single scene from the end of a video I've been working on.

Data:

MacBook Pro (16-inch, 2019)
macOS Catalina 10.15.4
2.4 GHz 8-Core Intel Core i9
64 GB 2667 MHz DDR4
Python 3.7.3 (default, Mar  6 2020, 22:34:30)

Profiler: yappi under Pycharm.

Using the scene Perf1 from the included perf_scenes.py, averaged over 5 runs and rendered with:
manim.py perf_scenes.py Perf1 -pl --leave_progress_bars

Before:
Animation 0: FadeInTextMobject, etc.:               8.93it/s
Animation 1: ShowCreationParametricFunction, etc.: 84.66it/s

Profiler shows 48.5% of the run spent under Camera.set_cairo_context_path()

After
Animation 0: FadeInTextMobject, etc.:               23.45it/s  -- 2.63x improvement
Animation 1: ShowCreationParametricFunction, etc.: 149.62it/s  -- 1.77x improvement

Profiler shows 19.9% of the run spent under Camera.set_cairo_context_path()

Less improvement with production-quality renders, and percent improvement varies with scene of course. This appears to be a good win for every scene I'm working on though. I hope it will be for others, too.

NB: there are more perf improvements to be had, of course, but this is the best one I currently have.
2020-04-24 21:04:08 -07:00
XiaoYoung
f0cdcd90ba Fix Text wrong display (#889) 2020-04-23 20:36:57 -07:00
Devin Neal
19e3c97589 Revise config again (#987) 2020-04-17 02:51:25 -07:00
Devin Neal
811ee4d26b Merge pull request #986 from 3b1b/display-help
Display help if no input file is specified
2020-04-17 02:38:53 -07:00
Devin Neal
c847988e10 Display help if no input file is specified 2020-04-17 02:36:56 -07:00
Devin Neal
1bb2e8c237 Merge pull request #985 from 3b1b/remove-livestream
Remove livestream
2020-04-17 00:08:17 -07:00
Devin Neal
77ab3b8d3a Merge branch 'master' of github.com:3b1b/manim into dev 2020-04-17 00:00:36 -07:00
Devin Neal
87d8671995 Remove livestreaming option 2020-04-16 23:59:22 -07:00
Devin Neal
f0796055cc Update README.md 2020-04-15 20:08:02 -07:00
Happy
93ebd66853 Update readme to reflect #571 2020-04-12 13:07:40 -07:00
Devin Neal
48f2a1ec3c Re-add documentation link 2020-03-13 03:16:59 -07:00
Solara570
99519090fb Small fix to NumberPlane construction 2020-03-08 17:12:38 +08:00
Devin Neal
422e86e0da Remove dead documentation link 2020-02-21 20:28:43 -08:00
Devin Neal
c896f58bbd Merge pull request #877 from azarzadavila/master
Typo in super() 77acc99
2020-02-12 22:38:21 -08:00
azarzadavila
97a0a707d7 Typo in super() 77acc99 2020-02-09 11:31:54 +01:00
Grant Sanderson
30728879be Merge pull request #871 from 3b1b/bayes
Bayes
2020-02-03 09:16:21 -08:00
Grant Sanderson
77acc999cd Rename number_line_config to axis_config 2020-01-15 15:40:30 -08:00
Grant Sanderson
1279f040da Temporarily adding input_file_path to SceneFileWrite config. Not sure why this isn't there already, or if there are problems with setting a default, but it fixed a weird bug that had arisen 2020-01-11 17:14:02 -08:00
Grant Sanderson
0f71b0a408 Playing wiht logo 2020-01-11 17:13:02 -08:00
Grant Sanderson
ada09f1928 Editing old name animations 2020-01-11 17:12:44 -08:00
Grant Sanderson
839fb4ff58 Merge pull request #853 from 3b1b/bayes
Bayes
2020-01-06 09:43:06 -08:00
Grant Sanderson
24d077fbce Change referenced directory of 3b1b content in LICENSE and README 2020-01-06 09:39:33 -08:00
Grant Sanderson
16f8c025cd Small tweaks to old videos when revisiting their animations 2020-01-06 09:38:54 -08:00
Mario Varas
b5a75c3250 #806 typo in WriteStuff 2019-12-23 11:29:19 -05:00
Grant Sanderson
6fe082a5d8 Preliminary end to Bayes project 2019-12-19 19:42:50 -08:00
Grant Sanderson
0e92deddc4 Change ShowSubmobjectsOneByOne defaults 2019-12-19 19:42:28 -08:00
Grant Sanderson
fa2c831ef3 Support UTF8 tex 2019-12-19 19:42:06 -08:00
Grant Sanderson
2916990077 Change from old_projects to from from_3b1b.old 2019-12-17 10:07:37 -08:00
Grant Sanderson
ef6716625e Rename 3b1b_projects to from_3b1b 2019-12-17 09:45:07 -08:00
Grant Sanderson
a138cea3ed Pulled bayes.py into a folder for more bayes projects 2019-12-17 09:40:32 -08:00
Grant Sanderson
1387d88043 Preliminary end to bayes, part 1 2019-12-17 09:39:11 -08:00
Grant Sanderson
9deb2d3732 Change patron end screen 2019-12-17 09:38:18 -08:00
Grant Sanderson
a95318f1ab Fix print_family 2019-12-17 09:37:59 -08:00
Grant Sanderson
5ea6c0f525 Bayes scenes up to GlimpseOfNextVideo 2019-12-15 08:45:40 -08:00
Grant Sanderson
c74cfa3c5d Add error message for ApplyFunction 2019-12-15 08:44:57 -08:00
Grant Sanderson
5cce05fc46 Scenes up to IntroduceLynda 2019-12-12 14:40:42 -08:00
Grant Sanderson
c2838d78a2 Forgot to propagate kwargs in Underline 2019-12-12 14:40:08 -08:00
Grant Sanderson
ba2f2f8840 Merge pull request #829 from 3b1b/bayes
Bayes
2019-12-10 21:47:09 -08:00
Grant Sanderson
ebd4fbd1d2 Halfway through CreateFormulaFromDiagram 2019-12-10 21:36:58 -08:00
Grant Sanderson
b1d8d1081c Merge branch 'master' of github.com:3b1b/manim into bayes 2019-12-10 13:39:48 -08:00
Grant Sanderson
c579fb521e Up to WhenDoesBayesApply in bayes 2019-12-10 13:39:42 -08:00
Grant Sanderson
fc28375e42 Changed modification for tex mobjects that begin with a newline, which involved eliminating alignment when a TexMobject creates many SingleStringTexMobject to figure out how to divvy itself up 2019-12-10 13:39:25 -08:00
Grant Sanderson
f89bb3e125 Added Underline 2019-12-10 13:38:30 -08:00
Grant Sanderson
3628b61d75 Change default color and bubble creation for teacher student scenes 2019-12-10 13:38:18 -08:00
Devin Neal
0bddadea35 Merge pull request #816 from fresnik/master
Documentation typo in constants.rst
2019-12-07 17:52:36 -08:00
Grant Sanderson
cfc5ecc59c First couple scenes of bayes 2019-12-06 17:11:04 -08:00
Grant Sanderson
72006334f5 Added a small fix to the issue of Tex inputs starting with a new line 2019-12-06 17:10:51 -08:00
Grant Sanderson
94a3883880 Remove Mobject.print_family, as that is now in utils.debug 2019-12-06 17:10:26 -08:00
Grant Sanderson
84e7bdb2b1 Added a couple helpful debugging functions 2019-12-06 17:10:00 -08:00
Grant Sanderson
b7cb9aa938 Typo fix 2019-12-05 12:45:01 -08:00
Grant Sanderson
259007954b Merge pull request #820 from 3b1b/projects-reorg
Reorganized files for 3b1b videos into a 3b1b_projects folder
2019-12-05 12:43:06 -08:00
Grant Sanderson
a51a6ab489 Reorganized files for 3b1b videos into a 3b1b_projects folder 2019-12-05 12:41:00 -08:00
Grant Sanderson
e57f08f46e Merge pull request #819 from 3b1b/hyperdarts
Hyperdarts
2019-12-05 12:33:14 -08:00
Grant Sanderson
2e25c4c0a3 Fixed old snow scene 2019-12-05 12:32:20 -08:00
Grant Sanderson
bc593695f9 Fixed old confetti scene 2019-12-05 12:31:53 -08:00
Grant Sanderson
9811564f70 TODO stub 2019-12-05 12:31:23 -08:00
Grant Sanderson
32e4daaeba Typo fix to moduli 2019-12-05 12:31:06 -08:00
Grant Sanderson
aaff13a079 Merge branch 'master' of github.com:3b1b/manim into hyperdarts 2019-12-05 12:30:41 -08:00
Freyr Bergsteinsson
241030f916 Documentation typo in constants.rst, fixes issue #814 2019-12-05 00:23:34 +00:00
Devin Neal
2afa079b6a Merge pull request #780 from timgates42/bugfix/typo_installation
Fix simple typo: installtion -> installation
2019-11-27 23:10:48 -08:00
Devin Neal
637c48905a Merge pull request #805 from mavaras/master
#803 docs typo mistake
2019-11-27 22:56:21 -08:00
mavaras
43098a07e7 #803 docs typo mistake 2019-11-23 10:42:35 -05:00
Grant Sanderson
c37ece9007 Moved hyperdarts to old_projects 2019-11-18 09:29:21 -08:00
Grant Sanderson
aaebd8a5cf End of hyperdarts project 2019-11-18 09:28:58 -08:00
Grant Sanderson
6f70df0852 Animations for hyperdarts up to 7:00 2019-11-12 11:55:37 -08:00
Grant Sanderson
975c4dd03c Explicitly check for None, rather than truthiness, for Axes.get_coordinate_labels 2019-11-12 11:55:19 -08:00
Grant Sanderson
495ace2423 Merge pull request #790 from 3b1b/moduli
Moduli
2019-11-11 14:07:33 -08:00
Grant Sanderson
b651050dd0 Merge branch 'master' of github.com:3b1b/manim into moduli 2019-11-11 14:06:32 -08:00
Grant Sanderson
eb03a56dfc Finished triangle moduli space scene 2019-11-11 14:06:17 -08:00
Grant Sanderson
13193d209e Changed patron name ordering 2019-11-11 14:06:04 -08:00
Devin Neal
bcb8824e2c Merge pull request #698 from Elteoremadebeethoven/master_3b1b
Solve issue add sound in Windows 10
2019-11-06 16:21:58 -08:00
Devin Neal
1e3cf9fa78 Merge pull request #725 from Hammer7/master
Closes: #720
2019-11-06 16:21:23 -08:00
Tim Gates
b1b516e9c4 Fix simple typo: installtion -> installation 2019-10-31 22:38:41 +11:00
Grant Sanderson
0e1da5ef28 Merge pull request #777 from 3b1b/hyperdarts
Hyperdarts
2019-10-28 15:38:09 -07:00
Grant Sanderson
4df666e964 Merge branch 'master' of github.com:3b1b/manim into hyperdarts 2019-10-28 15:35:00 -07:00
Grant Sanderson
0729f2eb59 Retire spirals project 2019-10-28 15:34:55 -07:00
Grant Sanderson
c79474a57c Small changes to the ffmpeg args when writing video files 2019-10-28 14:40:46 -07:00
Devin Neal
ec9dd06d38 Merge pull request #748 from DzyubSpirit/fix-svg-width
Add default stroke width for the svg mobjects
2019-10-26 22:31:25 -07:00
Devin Neal
920d140e40 Merge pull request #776 from MathWhiz/patch-1
README.md fixes
2019-10-26 22:29:36 -07:00
Raymond Arndorfer
b163b1b685 Standardize README.md 2019-10-23 22:58:23 -05:00
Grant Sanderson
8c28017239 Small thumbnail change 2019-10-16 10:38:52 -07:00
Grant Sanderson
e1e66f3082 Merge pull request #752 from 3b1b/hyperdarts
Hyperdarts
2019-10-09 21:33:02 -07:00
Grant Sanderson
c4aefe9396 End of Prime Spiral video 2019-10-09 18:09:15 -07:00
Grant Sanderson
7674a9eaee Changed patreon end screen 2019-10-09 18:09:05 -07:00
DzyubSpirit
76c295a60b Add default stroke width for the svg mobjects
Closes: #747
2019-10-08 10:32:04 +03:00
Grant Sanderson
d80af64798 Many more scenes from the prime spirals video 2019-10-03 13:58:27 -07:00
Grant Sanderson
ccc51664f4 Still being dumb 2019-10-03 13:58:13 -07:00
Grant Sanderson
f66d6e4f97 Added AddTextWordByWord, but it's not yet working, presumably because of some bug in Succession. 2019-10-03 13:58:00 -07:00
Grant Sanderson
67f3d1584c A few filler scenes for spirals project 2019-09-30 12:06:35 -07:00
Grant Sanderson
c94aef8845 Have AnimationGroup initialize its runtime before begin is called. This way it can be composed 2019-09-30 12:06:17 -07:00
Grant Sanderson
4eb6c6fb5b Spiral animations Up to ExplainRays 2019-09-26 11:04:47 -07:00
Grant Sanderson
8e15846ec5 Tiny clean to spacing 2019-09-26 11:04:35 -07:00
Grant Sanderson
ff55e768c9 Spiral animations up to Label44Spirals 2019-09-24 14:40:39 -07:00
Grant Sanderson
557bbff36c Added PGroup 2019-09-24 14:40:21 -07:00
zombie110year
946367aa19 latex can't recognize path seperator \\ in windows
Modify path before transport it to system command
2019-09-24 22:12:22 +08:00
Grant Sanderson
2bb8afa9e0 Animations for the introduction of the prime spiral video 2019-09-19 13:39:02 -07:00
Grant Sanderson
42e0cd07ac Added support for changing and interpolating stroke_width on PMobjects 2019-09-19 13:38:46 -07:00
Grant Sanderson
307ac852a6 Added ShowSubmobjectsOneByOne 2019-09-19 13:38:03 -07:00
Grant Sanderson
ffecd03cb2 Begining of spirals video, which is my newfound distraction 2019-09-18 15:38:27 -07:00
Grant Sanderson
0f037651f3 Small modifications to some old name animations 2019-09-18 15:38:02 -07:00
Grant Sanderson
77797741a5 Small updates to hyperdarts scenes 2019-09-18 15:37:46 -07:00
Hlaing Min
a19a6317ec Closes: #720
Fix to interpret subsequent points of absolute MoveTo (M) command as absolute LineTo (L).
2019-09-13 01:51:22 +08:00
Grant Sanderson
85e5b20ede Small tweak to patron scroll 2019-09-10 13:27:18 -07:00
Grant Sanderson
f34a110d5b More hyperdarts scenes 2019-09-10 13:26:40 -07:00
Grant Sanderson
f54b2ac81a Don't add sound while skipping animations 2019-09-10 13:26:30 -07:00
Grant Sanderson
afbdb94bb3 Set basic functionality to show the hyperdarts game 2019-08-28 14:23:00 -07:00
Grant Sanderson
e85beb91dc Merge pull request #710 from 3b1b/windmill
Windmill
2019-08-27 19:07:23 -07:00
Grant Sanderson
2f2ef09c92 Merge branch 'master' of github.com:3b1b/manim into windmill 2019-08-27 19:05:27 -07:00
Grant Sanderson
a5641c8144 Changed EOC1 Thumbnail 2019-08-27 19:05:15 -07:00
Grant Sanderson
4391c9147b Tweaks to Fourier behavior 2019-08-27 19:05:05 -07:00
Grant Sanderson
308a3e23ad Retiring windmill project 2019-08-27 19:03:36 -07:00
Grant Sanderson
0ac7b420f2 End of windmill project 2019-08-27 19:02:04 -07:00
Alexander Vázquez
32abbb9371 Change way to remove sound_file_path 2019-08-20 01:34:13 -05:00
Devin Neal
b74e5ca254 Merge pull request #680 from xy-23/master
New Text Mobject
2019-08-16 00:58:58 -07:00
xy-23
9b3e60f5ce Update some Text Mobject changes 2019-08-16 15:53:36 +08:00
Devin Neal
f0cff687aa Merge pull request #663 from pranjaldhole/master
conda environment bug fix with pyreadline package, closes #662
2019-08-16 00:37:40 -07:00
Devin Neal
73fea6a197 Merge pull request #668 from jonatasscdc/patch-1
Update requirements.txt
2019-08-16 00:34:38 -07:00
Devin Neal
7e3dbf51fa Merge pull request #672 from omertuc/patch-1
Update requirements.txt to include pyreadline
2019-08-16 00:34:00 -07:00
xy-23
0983fa11be Update some Text Mobject changes 2019-08-12 14:40:42 +08:00
omertuc
d5dc0d4d5b Only install pyreadline on Windows
It's not required on Linux
2019-08-12 05:56:35 +03:00
xy-23
e9fa188d42 New Text Mobject 2019-08-12 09:35:05 +08:00
xy-23
fd3721e050 new Text mobject 2019-08-06 21:05:37 +08:00
omertuc
d61d540655 Update requirements.txt to include pyreadline
This solves #444
2019-08-06 08:19:46 +03:00
Devin Neal
e1c049bece Merge pull request #670 from 0xflotus/patch-1
fixed manim
2019-08-05 14:52:58 -07:00
0xflotus
e498077e6a fixed manim 2019-08-05 23:14:27 +02:00
xy-23
057a92f92c new Text mobject 2019-08-05 22:53:15 +08:00
jonatasscdc
cce2191eb6 Update requirements.txt
updated pycairo version for windows
2019-08-03 14:53:10 -03:00
Grant Sanderson
00b5aaeb26 Animations for windmill up to early draft publish 2019-08-01 10:40:44 -07:00
Pranjal Dhole
91580ed4a3 conda env bug fix- ffmpeg from conda 2019-08-01 17:04:29 +02:00
Pranjal Dhole
06f78bf28f conda environment bug fix with pyreadline package, closes #662 2019-08-01 15:43:30 +02:00
Grant Sanderson
502ad1a02a Further windmill animation, to the end of the problem solution 2019-07-30 16:37:21 -07:00
Devin Neal
49582c3591 Merge pull request #652 from xy-23/master
Fix tqdm display problem in windows
2019-07-29 16:53:17 -07:00
Grant Sanderson
f1413c7717 TryOutSimplestExamples for windmill 2019-07-29 09:54:11 -07:00
Grant Sanderson
55ece141e8 Up to IntroduceWindmill scene 2019-07-26 18:30:11 -07:00
xy-23
519f82f1e7 Fix tqdm display problem in windows 2019-07-26 16:45:52 +08:00
Devin Neal
930e059a16 Merge pull request #651 from xy-23/master
Add a feature
2019-07-26 00:10:22 -07:00
xy-23
82a1b05f28 Add a feature #650 2019-07-26 14:34:21 +08:00
Grant Sanderson
b467444ad3 Beginning of windmill project 2019-07-25 20:05:02 -07:00
Grant Sanderson
c7e6d9d474 Merge pull request #611 from 3b1b/diffyq
Diffyq
2019-07-24 20:38:48 -07:00
Grant Sanderson
d6876b995d tweaking some diffyq content 2019-07-24 20:37:07 -07:00
Grant Sanderson
61bb4944fa Remove borken save_as_gif lines 2019-07-24 20:36:44 -07:00
Devin Neal
9f761822e1 Merge pull request #648 from zavden/master
Fix the list of scenes.py
2019-07-24 16:10:05 -07:00
zavden
3cee3de94f Update extract_scene.py 2019-07-24 18:01:12 -05:00
Devin Neal
38432a73e7 Merge pull request #641 from AamodJ/master
Updated macOS installation
2019-07-20 14:14:00 -07:00
Xiao Young
71b71f2d65 Solution of text rendering problem (#628)
Prevent unwanted space added between TextMobjects
2019-07-20 14:13:23 -07:00
AamodJ
d400952acc Updated macOS installation 2019-07-20 00:49:08 +05:30
Devin Neal
43d28a8595 Merge pull request #632 from tcztzy/master
Arch Linux installation guild
2019-07-13 22:28:00 -07:00
Tang Ziya
17505673d6 remove redundant empty line 2019-07-14 13:11:02 +08:00
Tang Ziya
0fa3415cc0 Arch Linux installation section 2019-07-14 13:06:36 +08:00
Tang Ziya
b31a5fb421 Arch LInux installation guild
Related #629
2019-07-12 21:11:45 +08:00
Devin Neal
eb13def609 update numpy and scipy versions 2019-07-10 17:53:19 -07:00
Devin Neal
a721a19137 Merge pull request #630 from eitanlees/doc-link
DOC: update documentation link in readme
2019-07-10 14:11:19 -07:00
Eitan Lees
25a75f1876 DOC: update documentation link in readme 2019-07-10 13:20:06 -04:00
Devin Neal
b31a174ac6 Merge pull request #622 from npetrangelo/docs
Filled out making_a_scene in the docs
2019-07-07 22:42:08 -07:00
Nathan Petrangelo
612158277e Removed the joke 2019-07-08 01:33:07 -04:00
Nathan Petrangelo
c60dd05e33 Added one more sentence 2019-07-08 01:23:04 -04:00
Nathan Petrangelo
e5d7ebd978 Added code formatting 2019-07-08 01:18:10 -04:00
Nathan Petrangelo
0645bc6acc Filled out making_a_scene overview 2019-07-08 01:13:49 -04:00
Devin Neal
d01ca92120 remove extraneous newline 2019-07-07 21:46:59 -07:00
Devin Neal
61c963a8ae update documentation link again 2019-07-07 21:44:50 -07:00
Devin Neal
e83c69d968 udpate documentation link 2019-07-07 21:37:24 -07:00
Devin Neal
dfdceb1908 allow pycairo>=1.18.0 for windows 2019-07-07 10:11:33 -07:00
Grant Sanderson
36be369901 Beginning diffyq part 5 2019-07-03 11:09:05 -07:00
Grant Sanderson
b3673e93d7 Final animations for Fourier montage video 2019-07-03 11:08:39 -07:00
Grant Sanderson
985ef4518f Bug fix 2019-07-03 11:07:55 -07:00
Grant Sanderson
096f033954 Moved VIDEO_DIR initializations to after MEDIA_DIR 2019-07-01 12:51:48 -07:00
Grant Sanderson
92f4c0c001 Merge branch 'master' of github.com:3b1b/manim into diffyq 2019-06-29 15:21:00 -07:00
Grant Sanderson
10f2c105b1 Final animations for Fourier video 2019-06-29 15:20:52 -07:00
Grant Sanderson
34e343ec66 Changed endscreen default columns 2019-06-29 15:20:00 -07:00
Grant Sanderson
aec56c63be Added LIGHT_PINK 2019-06-29 15:19:43 -07:00
Grant Sanderson
c6d6e500fb Latest scenes for Fourier series video 2019-06-25 09:03:55 -07:00
Grant Sanderson
a3c1640fb7 NumberLine.default_numbers_to_display was not showing topmost number it should have 2019-06-25 09:03:33 -07:00
Grant Sanderson
0a695dd442 Changed Arrow default 2019-06-25 09:02:56 -07:00
Grant Sanderson
64c960041b Latest scenes for Fourier series, up to SimpleComplexExponentExample 2019-06-23 16:26:28 -07:00
Grant Sanderson
f3048eb574 Fixed bug with Bubble 2019-06-23 16:26:05 -07:00
Grant Sanderson
48f38b8940 Line.put_start_and_end_on should return self 2019-06-23 16:25:48 -07:00
Grant Sanderson
a535c6917e Added p2n and n2p abreviations for ComplexPlane 2019-06-23 16:25:22 -07:00
Devin Neal
41792fdb5f Merge pull request #607 from 3b1b/video_dir
Add --video_output_dir flag
2019-06-21 23:18:23 -07:00
Devin Neal
3ec231f0ca add video_output_dir flag 2019-06-21 22:52:16 -07:00
Grant Sanderson
0432514ccf Up to ShowInfiniteSum in diffyq part 4 animations 2019-06-21 17:56:42 -07:00
Grant Sanderson
a9baae4e98 Fixed(?) eye-tracking for PiCreatureScene 2019-06-20 20:23:48 -07:00
Grant Sanderson
0e44abe741 Latest changes for animations of video 4 of diffyq series 2019-06-20 13:26:43 -07:00
Grant Sanderson
40e44e6dd7 Parametric surface should remember what function created it 2019-06-20 13:26:22 -07:00
Grant Sanderson
02413d165a Change ode -> diffyq in imports 2019-06-19 16:24:44 -07:00
Grant Sanderson
7d596d0840 Merge pull request #606 from 3b1b/diffyq
Diffyq
2019-06-19 16:14:56 -07:00
Grant Sanderson
2e0e5cfb5e Rename ode folder to diffyq 2019-06-19 16:11:46 -07:00
Grant Sanderson
96e34b969c Changed ode folder to be named diffyq, since many of these are pde videos 2019-06-19 16:10:21 -07:00
Grant Sanderson
2f6be9a389 Some of the first scenes for diffyq part4 2019-06-19 16:08:46 -07:00
Grant Sanderson
2294cdea4f Allow Bubble to flip over any axis, which was unnecessarily restricted before 2019-06-19 16:08:14 -07:00
Grant Sanderson
8ce13875a3 Added Line.set_length 2019-06-19 16:07:22 -07:00
Grant Sanderson
7ac990119a frame_center was getting double-added, messing up MovingCameraScene 2019-06-19 16:07:07 -07:00
Devin Neal
43b643db6c Merge pull request #586 from Kolloom/install_doc
Install doc
2019-06-19 14:46:34 -07:00
Grant Sanderson
9da74cb657 Beginning chapter 4 animations 2019-06-18 20:40:41 -07:00
Grant Sanderson
2680a9c373 Change Fourier scene to center on vectors, not circles 2019-06-18 20:40:29 -07:00
Devin Neal
f908b68bed Merge pull request #597 from cclauss/patch-1
Travis CI: The sudo tag is now deprecated
2019-06-18 00:19:41 -07:00
Devin Neal
71f79530be Merge pull request #600 from red5h4d0w/master
Update tex_file_writing.py
2019-06-17 13:01:47 -07:00
red5h4d0w
e72390bfc4 Update tex_file_writing.py 2019-06-17 15:40:03 -04:00
cclauss
dc83cac5b4 Travis CI: The sudo tag is now deprecated
__sudo: required__ no longer is...  [Travis are now recommending removing the __sudo__ tag](https://blog.travis-ci.com/2018-11-19-required-linux-infrastructure-migration).

"_If you currently specify __sudo:__ in your __.travis.yml__, we recommend removing that configuration_"
2019-06-16 22:48:58 +02:00
Grant Sanderson
5a86ba08f4 Merge pull request #596 from 3b1b/diffyq
Diffyq
2019-06-16 12:53:02 -07:00
Grant Sanderson
e421d3689a Merge branch 'master' of github.com:3b1b/manim into diffyq 2019-06-16 12:51:46 -07:00
Grant Sanderson
dfeb11a2ab Final animations for diffyq chapter 3 2019-06-16 12:51:34 -07:00
Devin Neal
66f9ff29e4 update windows docs 2019-06-15 21:42:05 -07:00
Grant Sanderson
62c2772982 Nearly the final animations for diffyq part 3 2019-06-15 20:52:38 -07:00
Grant Sanderson
9e7619844f Latest animations for diffyq part 3 2019-06-15 12:22:37 -07:00
Grant Sanderson
6c2e7f4c2c interpolate_mobject should return self 2019-06-15 12:22:21 -07:00
Grant Sanderson
08eee147b3 Added TangentLine 2019-06-15 12:21:29 -07:00
Kolloom
43b4508b2c Fix wording. 2019-06-15 14:03:04 -05:00
Devin Neal
dade021eaa Merge pull request #592 from Grae-Drake/feature/docs-edits
Update link to Todd Zimmerman tutorial
2019-06-15 00:09:33 -07:00
Devin Neal
0041e3fd45 Merge pull request #585 from Kolloom/doc
Add documentation for the coordinate system
2019-06-14 23:15:01 -07:00
Grae Drake
d031e5735a Update tutorial description 2019-06-14 23:06:06 -07:00
Kolloom
e64a25bd40 Add a docker diagram to README.md 2019-06-15 00:51:22 -05:00
Kolloom
d7054e61f0 Change docker-compose to reflect README.md changes 2019-06-15 00:45:14 -05:00
Kolloom
6c1fb7ddca Change docker instructions on README.md
Change all refernces of INPUT_DIR to INPUT_PATH
change all references of OUTPUT_DIR to OUTPUT_PATH

change a paragraph
2019-06-15 00:43:32 -05:00
Grae Drake
7fab15abd4 Update link to Todd Zimmerman tutorial 2019-06-14 21:38:37 -07:00
Kolloom
6571b0d88e Mention VMobject for geometry 2019-06-14 23:34:56 -05:00
Kolloom
ee83d3bcec Update assets with medium preset 2019-06-14 23:26:40 -05:00
Kolloom
542ea68824 Fix wording 2019-06-14 23:08:03 -05:00
Kolloom
2a930ff702 Use monospace for asset annotation 2019-06-14 23:06:03 -05:00
Grant Sanderson
6f7e123b1a Discrete case scenes for diffyq part 3 2019-06-14 10:07:06 -07:00
Grant Sanderson
4196bb627e New scenes for diffyq part3 2019-06-13 16:16:42 -07:00
Grant Sanderson
2cbe19af7c Bug fix for the case when the media_dir has spaces 2019-06-13 16:15:43 -07:00
Grant Sanderson
2ccf83c0aa Change output folder heirarchy back to grouping files of similar types, rather grouping them as parts of the same scene 2019-06-13 16:15:02 -07:00
Grant Sanderson
cfbbff1bdf Default color of Vector should be white 2019-06-13 16:14:03 -07:00
Grant Sanderson
f10baa3fcd Change default media output directory to from 'video' to 'videos' 2019-06-13 16:13:42 -07:00
Grant Sanderson
34d1d27c56 Merge pull request #588 from 3b1b/diffyq
Diffyq
2019-06-13 09:34:25 -07:00
Grant Sanderson
cc08c090d1 Merge branch 'master' of github.com:3b1b/manim into diffyq 2019-06-13 09:29:57 -07:00
Grant Sanderson
caa4efdfa5 Latest scenes for diffyq part 3 2019-06-13 09:27:35 -07:00
Grant Sanderson
503b2bc896 For some reason stage_scenes still has a hardcoded input directory... 2019-06-13 09:27:19 -07:00
Grant Sanderson
542ddb9afd Make sure set_opacity changes background stroke as well 2019-06-13 09:26:34 -07:00
Grant Sanderson
6214ea7a01 Added TracedPath 2019-06-13 09:26:03 -07:00
Grant Sanderson
3b42f1f709 Added int_func to SHowIncreasingSubsets 2019-06-13 09:25:14 -07:00
Devin Neal
ab75015099 Merge pull request #582 from stephenwild/master
Documentation for TipableVMobject
2019-06-13 00:48:15 -07:00
Kolloom
e2eac0bd96 Minor edit 2019-06-11 00:59:36 -05:00
Kolloom
65c23d9e9f Fix docker install instruction
Env Var used in the compose.yml is INPUT_DIR and OUTPUT_DIR

Clarify the meaning of both variables and output message.
Note on -p not working.
2019-06-11 00:49:31 -05:00
Devin Neal
1322152391 Update README.md 2019-06-10 20:09:42 -07:00
Kolloom
b71e63a540 Add documentation for the coordinate system
Update index
Add 4 assets, one of which is an image

Image uses width 700
Videos uses 700x394
Those dimension are similar to how content is laid out
in sphinx
2019-06-10 16:23:49 -05:00
Stephen Wild
41539387a5 Documentation for TipableVMobject
Add an overview of TipableVMobject's functionality and a few comments, as well as grouping some methods by functionality (roughly).
2019-06-10 03:36:16 +08:00
Devin Neal
22b4c3578b Merge pull request #580 from Kolloom/pull_jarwin_patch-3
Update learning_by_example.rst
2019-06-08 16:37:54 -07:00
Kolloom
5535997356 Simple wording change 2019-06-08 18:32:42 -05:00
Devin Neal
3e2a312f51 Merge pull request #581 from Kolloom/link_fix
fix broken link due to misnamed file
2019-06-08 15:33:13 -07:00
Devin Neal
aad68a5503 Update docker install link 2019-06-08 15:28:25 -07:00
Kolloom
7f54ac9b3a fix broken link due to misnamed file 2019-06-08 14:17:59 -05:00
Kolloom
fb9cf93470 Minor changes 2019-06-08 14:00:59 -05:00
Kolloom
d1ada7a8aa Update mac install doc to include manim
also caution on python2 incompatibility
2019-06-08 13:44:10 -05:00
Kolloom
9ffe4a6839 Rewrite learning_by_example.py
Move embedded video to below example code.

Delete ``manim -h`` output. If user is able to run manim,
they should be able to use the help flag too.

Change wording on "instance" when it should be "classes"

Move info on flags to a note block

Add a note on transform only change apparances.

Move explanations to after code block

...
2019-06-08 13:32:27 -05:00
Devin Neal
f6dc1cb50f updated Compose file and update docker section of README.md 2019-06-08 00:40:23 -07:00
Devin Neal
a024916e66 Apply link fix from master 2019-06-08 00:32:43 -05:00
Kolloom
73a1d37785 Merging mac install doc from jarwin/patch-3 2019-06-08 00:19:31 -05:00
Purusharth Saxena
62206bc0e7 Update learning_by_example.rst
Updated getting started to accomodate manimlib (pip installation)
2019-06-08 00:19:31 -05:00
Devin Neal
57b96fdd07 fix documentation links 2019-06-06 20:40:11 -07:00
Devin Neal
de0d7c907d Merge branch 'master' of github.com:3b1b/manim 2019-06-04 21:10:37 -07:00
Devin Neal
8449bc3418 update documentation 2019-06-04 21:10:12 -07:00
Devin Neal
f81c275631 make media, tex, and video directories configurable via flags 2019-06-04 20:51:18 -07:00
Devin Neal
949bfaa0b4 Merge pull request #577 from Kolloom/master
Add animation documentation and asset folder
2019-06-04 20:38:15 -07:00
Kolloom
e1fb9f480b Add animation documentation and asset folder
Animation documentation is not yet complete.
Asset folder contains renders from code snipples.

Update constants.rst to include a ref tag
Update index to include the animation doc
2019-06-04 13:15:35 -05:00
Devin Neal
caa4577cd1 reorganize media file tree 2019-06-03 23:41:05 -07:00
Grant Sanderson
43b82f2c53 Scenes up to AnalyzeSineCurve for diffyq part 3 2019-06-03 11:33:39 -07:00
Devin Neal
c203f8e8c0 remove repeated latex package 2019-06-02 21:13:41 -07:00
Devin Neal
75996a618c install less latex 2019-06-02 21:10:45 -07:00
Devin Neal
ed24541de6 update dockerfile, add flag for high quality rendering (#573)
Allow rendering in 1080p by passing `--high_quality` and update the Dockerfile and Compose file to install Manim directly into the container.
2019-06-02 18:58:33 -07:00
Kolloom
22c8aa0eb8 Add documentation for constants.py (#572)
* Add documentation for constants.py

* Update documentation for constants.py

With suggestions from eulertour
2019-06-02 18:21:11 -07:00
Kierán Meinhardt
0590c153ef remove typographically incorrect punctuation from documentation headings (#567) 2019-06-02 13:54:03 -07:00
Charly
c42ae8a55b add option -i to save as gif (#529)
* add option -i to save as gif

* re-add -c command

* No longer needs to save mp4 first
2019-06-02 12:13:22 -07:00
Devin Neal
3632d97140 install pycairo conditionally based on platform identifier (#571) 2019-05-31 10:44:51 -07:00
quark67
e9fc2aa46c Correction of a bad alt description (#566) 2019-05-30 13:17:45 -07:00
Yoshi Askharoun
20590e6823 Remove duplicate usepackage (#554)
The textcomp package was imported twice in the ctex template
2019-05-29 20:25:51 -07:00
Grant Sanderson
8bb0b4f010 Merge branch 'master' of github.com:3b1b/manim into diffyq 2019-05-29 18:29:11 -07:00
Grant Sanderson
ab2318ff9d New scenes for diffyq part 3 2019-05-29 18:28:40 -07:00
Grant Sanderson
5dcb113996 Moving the frame_center of camera was not working. This fixes it, but I suspect there is a need for a deeper fix where everything is handled in transform_points_pre_display properly for the various camera classes 2019-05-29 18:28:28 -07:00
Devin Neal
68fb61a5b2 add information to docs (#563) 2019-05-28 21:28:01 -07:00
Devin Neal
2f37e3abf2 Merge pull request #562 from eulertour/master
add master_doc to conf.py
2019-05-28 21:07:40 -07:00
Devin Neal
aecf5b0b18 add master_doc to conf.py 2019-05-28 21:03:20 -07:00
Devin Neal
224d389522 Merge pull request #561 from Kolloom/master
Add Windows installation documentation
2019-05-28 19:08:34 -07:00
Grant Sanderson
52054571ab Merge branch 'master' of github.com:3b1b/manim into diffyq 2019-05-28 13:38:50 -07:00
Grant Sanderson
ddd7ce2f12 Animations up to the preview for the breakdown into sine curves for diffyq chapter 3 2019-05-28 13:38:45 -07:00
Kolloom
0b35d8e2ec Add Windows installation documentation
The installation is done with a Windows8 machine,
further testing are needed for windows10.
2019-05-28 15:22:20 -05:00
Devin Neal
47a4a1f2df Add social badges README 2019-05-28 01:39:06 -07:00
Devin Neal
486b28e4d2 Merge pull request #557 from Kolloom/master
Add installation documentation for ubuntu
2019-05-28 01:09:00 -07:00
Devin Neal
2ce766b3bf Update docs badge 2019-05-28 01:01:48 -07:00
Devin Neal
2deeeab509 Merge pull request #558 from eulertour/master
Testing a PR making a change to the docs
2019-05-28 00:44:07 -07:00
Devin Neal
e93ef301ce test pr on docs 2019-05-28 00:39:00 -07:00
Devin Neal
c7b5aa6e05 change docs to upstream 2019-05-28 00:36:13 -07:00
Devin Neal
0edb4edfd0 rebase onto upstream 2019-05-28 00:33:05 -07:00
Devin Neal
78448b4388 make build script executable 2019-05-28 00:21:10 -07:00
Devin Neal
969bcf4154 refactor and test doc deployment 2019-05-28 00:13:27 -07:00
Devin Neal
f3f0e3ba03 third attempt at deploying docs 2019-05-27 23:58:05 -07:00
Devin Neal
aa2734477a second attempt at deploying docs 2019-05-27 23:39:00 -07:00
Devin Neal
d0eb2a0ce8 Merge branch 'master' of github.com:3b1b/manim 2019-05-27 23:16:40 -07:00
Devin Neal
a4c8302c55 first attempt at deploying docs 2019-05-27 23:08:43 -07:00
Kolloom
5d4897bd50 Add installation documentation for ubuntu 2019-05-28 00:48:25 -05:00
Devin Neal
49d8276033 Merge pull request #555 from yoshiask/patch-3
Update pycairo requirement
2019-05-27 19:55:58 -07:00
Grant Sanderson
b7fcc68b55 Merge pull request #556 from 3b1b/diffyq
Diffyq
2019-05-27 19:51:21 -07:00
Grant Sanderson
4096fc28b8 Merge branch 'master' of github.com:3b1b/manim into diffyq 2019-05-27 19:49:00 -07:00
Grant Sanderson
e6eb4dd94f Beginning heat equation solution animations 2019-05-27 19:48:48 -07:00
Grant Sanderson
29424eb6b3 Added simple midpoint function 2019-05-27 19:48:33 -07:00
Grant Sanderson
d1e3e5ed20 Formatting correction 2019-05-27 19:48:14 -07:00
Grant Sanderson
828c3dcd7a Added c2p and p2c abbreviations to Axes 2019-05-27 19:47:57 -07:00
Yoshi Askharoun
17558a4bd5 Update pycairo requirement
Many issues, such as #535, stem from the odd installation procedure of cairo and pycairo on Windows. By changing the pycairo requirement in requirements.txt, pip will no longer attempt to uninstall the working version. This should have no effect on the functionality of manim, though new installations are likely to default to pycairo 1.18.0 now.
2019-05-27 19:00:48 -07:00
Devin Neal
304822fb8c Merge branch 'master' of github.com:3b1b/manim 2019-05-27 16:14:45 -07:00
Devin Neal
9fa350d906 clean up docs 2019-05-27 16:14:20 -07:00
kyarik
c62ba223b6 Fixed typo in the docs about page (#553) 2019-05-27 15:52:41 -07:00
Devin Neal
4447bbd016 add docs 2019-05-26 00:35:45 -07:00
Grant Sanderson
98696a29f8 Merge pull request #542 from kyarik/patch-1
Fixed typo in class name in example_scenes.py
2019-05-24 15:15:12 -07:00
Grant Sanderson
84514a1f6f Merge pull request #543 from kyarik/patch-2
Mentioned -r argument in example_scenes comment
2019-05-24 15:14:53 -07:00
Grant Sanderson
c21ea85ec9 Merge pull request #544 from kyarik/patch-3
Improved the "Using manim" section in the README
2019-05-24 15:14:21 -07:00
Grant Sanderson
cec7872f48 Merge pull request #547 from 3b1b/diffyq
Diffyq
2019-05-24 15:13:40 -07:00
Grant Sanderson
ce866e8222 Removed duplicate name_animations.py 2019-05-24 15:09:53 -07:00
Grant Sanderson
91b3abae4a Change big_ol_pile_of_imports to manimlib.imports 2019-05-24 15:08:02 -07:00
Grant Sanderson
6e6dd260da Merge branch 'master' of github.com:3b1b/manim into diffyq 2019-05-24 15:06:59 -07:00
Grant Sanderson
2d3493c3d5 Fourier series name animations 2019-05-24 15:06:52 -07:00
Grant Sanderson
c4449fdfb8 Small tweaks to Fourier series animations 2019-05-24 15:06:10 -07:00
Grant Sanderson
bf8f517b49 Changed SceneFileWriter.get_default_file_name 2019-05-24 15:05:20 -07:00
Grant Sanderson
b9822db5bf Changed thumbnail of nn1 2019-05-24 15:04:45 -07:00
kyarik
2ebcec4bbe Improved the "Using manim" section in the README
Improved the wording and presentation of the "Using manim" section in the README file.
2019-05-22 11:00:57 +02:00
kyarik
68961251a5 Mentioned -r argument in example_scenes comment
It is a good option to mention because the current default for a high quality 60fps video is 2560x1440.
So, if someone wants a 1920x1080 video, they should pass -r 1080.
2019-05-21 11:54:56 +02:00
kyarik
0f5cc33002 Fixed typo in class name in example_scenes.py
Changed UdatersExample to UpdatersExample.
2019-05-21 11:44:30 +02:00
Devin Neal
e59178dae7 copy docs 2019-05-12 23:40:41 -07:00
319 changed files with 37564 additions and 1049 deletions

4
.gitignore vendored
View File

@@ -7,11 +7,13 @@ cairo_test.py
mayavi_test.py
random_scenes/
files/
assets/
ben_playground.py
ben_cairo_test.py
.floo
.flooignore
.vscode
.vs
*.xml
*.iml
media
@@ -23,4 +25,4 @@ dist/
manim.egg-info/
primes.py
/media_dir.txt
/media_dir.txt

View File

@@ -1,9 +1,12 @@
language: python
sudo: required # required for Python 3.7 (travis-ci/travis-ci#9069)
dist: xenial # required for Python 3.7 (travis-ci/travis-ci#9069)
dist: bionic
python: "3.7"
cache: pip
addons:
apt:
packages:
- python3-sphinx
install:
- pip install --upgrade pip
- pip install -r requirements.txt
@@ -16,6 +19,8 @@ before_script:
script:
- python setup.py test
- python setup.py bdist_wheel
after_success:
- test $TRAVIS_BRANCH = "master" && test $TRAVIS_PULL_REQUEST = "false" && travis/build_docs.sh
deploy:
provider: pypi
user: eulertour

View File

@@ -3,12 +3,17 @@ RUN apt-get update \
&& apt-get install -qqy --no-install-recommends \
apt-utils \
ffmpeg \
texlive-latex-base \
texlive-full \
texlive-fonts-extra \
sox \
libcairo2-dev \
texlive \
texlive-fonts-extra \
texlive-latex-extra \
texlive-latex-recommended \
texlive-science \
tipa \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt requirements.txt
RUN python -m pip install -r requirements.txt && rm requirements.txt
COPY . /manim
RUN cd /manim \
&& python setup.py sdist \
&& python -m pip install dist/manimlib*
ENTRYPOINT ["/bin/bash"]

View File

@@ -1,5 +1,4 @@
All files of this project under the directories active_projects and old_projects
are copyright 3Blue1Brown LLC and used by permission for this project only.
All files of this project under the directory "from_3b1b" are copyright 3Blue1Brown LLC and used by permission for this project only.
Any other file of this project is available under the MIT license as follow:

View File

@@ -1,19 +1,24 @@
<img src="logo/cropped.png"/>
![logo](logo/cropped.png)
[![Documentation Status](https://readthedocs.org/projects/manim/badge/?version=latest)](https://manim.readthedocs.io/en/latest/?badge=latest)
[![Build Status](https://travis-ci.org/3b1b/manim.svg?branch=master)](https://travis-ci.org/3b1b/manim)
[![Documentation](https://img.shields.io/badge/docs-EulerTour-blue.svg)](https://www.eulertour.com/docs)
[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](http://choosealicense.com/licenses/mit/)
[![Manim Subreddit](https://img.shields.io/reddit/subreddit-subscribers/manim.svg?color=ff4301&label=reddit)](https://www.reddit.com/r/manim/)
[![Manim Discord](https://img.shields.io/discord/581738731934056449.svg?label=discord)](https://discord.gg/mMRrZQW)
Manim is an animation engine for explanatory math videos. It's used to create precise animations programmatically, as seen in the videos at [3Blue1Brown](https://www.3blue1brown.com/).
This repository contains the version of manim used by 3Blue1Brown. There is also a community maintained version at https://github.com/ManimCommunity/manim/.
To get help or to join the development effort, please join the [discord](https://discord.gg/mMRrZQW).
## Installation
Manim runs on python 3.7. You can install it from PyPI via pip
Manim runs on Python 3.6 or higher version. You can install it from PyPI via pip:
```sh
pip3 install manimlib
```
System requirements are [cairo](https://www.cairographics.org), [ffmpeg](https://www.ffmpeg.org), [sox](http://sox.sourceforge.net), [latex](https://www.latex-project.org) (optional, if you want to use LaTeX).
System requirements are [cairo](https://www.cairographics.org), [ffmpeg](https://www.ffmpeg.org), [sox](http://sox.sourceforge.net) (optional, if you want to play the prompt tone after running), [latex](https://www.latex-project.org) (optional, if you want to use LaTeX).
You can now use it via the `manim` command. For example:
@@ -21,7 +26,7 @@ You can now use it via the `manim` command. For example:
manim my_project.py MyScene
```
For more options, take a look at the Using manim sections further below.
For more options, take a look at the [Using manim](#using-manim) sections further below.
### Directly
@@ -32,12 +37,12 @@ If you want to hack on manimlib itself, clone this repository and in that direct
python3 -m pip install -r requirements.txt
# Try it out
python3 -m manim example_scenes.py SquareToCircle -pl
python3 ./manim.py example_scenes.py SquareToCircle -pl
```
### Directly (Windows)
1. [Install FFmpeg](https://www.wikihow.com/Install-FFmpeg-on-Windows).
2. Install Cairo. Download the wheel from https://www.lfd.uci.edu/~gohlke/pythonlibs/#pycairo. For most users, ``pycairo1.18.0cp37cp37mwin32.whl`` will do fine.
2. [Install Cairo](https://www.lfd.uci.edu/~gohlke/pythonlibs/#pycairo). For most users, ``pycairo1.18.0cp37cp37mwin32.whl`` will do fine (you can download it or other versions from [here](https://www.lfd.uci.edu/~gohlke/pythonlibs/#pycairo)).
```sh
pip3 install C:\path\to\wheel\pycairo1.18.0cp37cp37mwin32.whl
```
@@ -45,7 +50,7 @@ python3 -m manim example_scenes.py SquareToCircle -pl
4. [Install SoX](https://sourceforge.net/projects/sox/files/sox/).
5. Install the remaining Python packages. Make sure that ``pycairo==1.17.1`` is changed to ``pycairo==1.18.0`` in requirements.txt.
5. Install the remaining Python packages.
```sh
git clone https://github.com/3b1b/manim.git
cd manim
@@ -72,14 +77,29 @@ python3 -m manim example_scenes.py SquareToCircle -pl
### Using Docker
Since it's a bit tricky to get all the dependencies set up just right, there is a Dockerfile and Compose file provided in this repo as well as [a premade image on Docker Hub](https://hub.docker.com/r/eulertour/manim/tags/). The Dockerfile contains instructions on how to build a manim image, while the Compose file contains instructions on how to run the image.
The image does not contain a copy of the repo. This is intentional, as it allows you to either bind mount a repo that you've cloned locally or clone any fork/branch you want. In order to do this with the Compose file, you must set the `MANIM_PATH` environment variable to the absolute path to the manim repo.
The prebuilt container image has manim repository included.
`INPUT_PATH` is where the container looks for scene files. You must set the `INPUT_PATH`
environment variable to the absolute path containing your scene file and the
`OUTPUT_PATH` environment variable to the directory where you want media to be written.
1. [Install Docker](https://www.docker.com/products/overview)
1. [Install Docker](https://docs.docker.com)
2. [Install Docker Compose](https://docs.docker.com/compose/install/)
3. Render an animation
3. Render an animation:
```sh
MANIM_PATH=/absolute/path/to/manim/repo docker-compose run manim example_scenes.py SquareToCircle -l
INPUT_PATH=/path/to/dir/containing/source/code \
OUTPUT_PATH=/path/to/output/ \
docker-compose run manim example_scenes.py SquareToCircle -l
```
The command needs to be run as root if your username is not in the docker group.
You can replace `example.scenes.py` with any relative path from your `INPUT_PATH`.
![docker diagram](./manim_docker_diagram.png)
After running the output will say files ready at `/tmp/output/`, which refers to path inside the container. Your `OUTPUT_PATH` is bind mounted to this `/tmp/output` so any changes made by the container to `/tmp/output` will be mirrored on your `OUTPUT_PATH`. `/media/` will be created in `OUTPUT_PATH`.
`-p` won't work as manim would look for video player in the container system, which it does not have.
The first time you execute the above command, Docker will pull the image from Docker Hub and cache it. Any subsequent runs until the image is evicted will use the cached image.
Note that the image doesn't have any development tools installed and can't preview animations. Its purpose is building and testing only.
@@ -88,50 +108,31 @@ Try running the following:
```sh
python3 -m manim example_scenes.py SquareToCircle -pl
```
The -p is for previewing, meaning the video file will automatically open when it is done rendering.
Use -l for a faster rendering at a lower quality.
Use -s to skip to the end and just show the final frame.
Use -n (number) to skip ahead to the n'th animation of a scene.
Use -f to show the file in finder (for osx)
The `-p` flag in the command above is for previewing, meaning the video file will automatically open when it is done rendering. The `-l` flag is for a faster rendering at a lower quality.
Set MEDIA_DIR environment variable to determine where image and animation files will be written.
Some other useful flags include:
* `-s` to skip to the end and just show the final frame.
* `-n <number>` to skip ahead to the `n`'th animation of a scene.
* `-f` to show the file in finder (for OSX).
Look through the old_projects folder to see the code for previous 3b1b videos. Note, however, that developments are often made to the library without considering backwards compatibility on those old_projects. To run them with a guarantee that they will work, you will have to go back to the commit which complete that project.
Set `MEDIA_DIR` environment variable to specify where the image and animation files will be written.
While developing a scene, the `-sp` flags are helpful to just see what things look like at the end without having to generate the full animation. It can also be helpful to use the `-n` flag to skip over some number of animations.
Look through the `old_projects` folder to see the code for previous 3b1b videos. Note, however, that developments are often made to the library without considering backwards compatibility with those old projects. To run an old project with a guarantee that it will work, you will have to go back to the commit which completed that project.
While developing a scene, the `-sp` flags are helpful to just see what things look like at the end without having to generate the full animation. It can also be helpful to use the `-n` flag to skip over some number of animations.
### Documentation
Documentation is in progress at [manim.readthedocs.io](https://manim.readthedocs.io).
Documentation is in progress at [eulertour.com/docs](https://www.eulertour.com/docs/). And there is also an all-in-one documentation and tutorials maintained by **@manim-kindergarten**: [manim.ml](https://manim.ml/) (in Chinese).
### Walkthrough
Todd Zimmerman put together a [tutorial](https://talkingphysics.wordpress.com/2019/01/08/getting-started-animating-with-manim-and-python-3-7/) on getting started with manim, which has been updated to run on python 3.7.
### Live Streaming
To live stream your animations, simply run manim with the `--livestream` option.
```sh
> python -m manim --livestream
Writing to media/videos/scene/scene/1080p30/LiveStreamTemp.mp4
Manim is now running in streaming mode. Stream animations by passing
them to manim.play(), e.g.
>>> c = Circle()
>>> manim.play(ShowCreation(c))
>>>
```
It is also possible to stream directly to Twitch. To do that simply pass
--livestream and --to-twitch to manim and specify the stream key with
--with-key. Then when you follow the above example the stream will directly
start on your Twitch channel (with no audio support).
Todd Zimmerman put together a [tutorial](https://talkingphysics.wordpress.com/2019/01/08/getting-started-animating-with-manim-and-python-3-7/) on getting started with manim, which has been updated to run on Python 3.7.
[manim-kindergarten](https://github.com/manim-kindergarten/) wrote and collected some useful extra classes and some codes of videos in [manim_sandbox repo](https://github.com/manim-kindergarten/manim_sandbox).
## Contributing
Is always welcome. In particular, there is a dire need for tests and documentation.
Only accepts pull requests that fixes bugs / fixes typos / improves existing content (for more information, see [#1243](https://github.com/3b1b/manim/issues/1243)). Most pull requests should be directed to the [community version](https://github.com/ManimCommunity/manim/).
## License
All files in the directories active_projects and old_projects, which by and large generate the visuals for 3b1b videos, are copyright 3Blue1Brown.
All files in the directory `from_3b1b`, which by and large generate the visuals for 3b1b videos, are copyright 3Blue1Brown.
The general purpose animation code found in the remainder of the repository, on the other hand, is under the MIT license.

View File

@@ -6,13 +6,11 @@ services:
image: eulertour/manim:latest
# uncomment this line to build rather than pull the image
# build: .
volumes:
- ${MANIM_PATH:?MANIM_PATH environment variable isn't set}:/opt/manim
environment:
- PYTHONPATH=/opt/manim
working_dir: /opt/manim
entrypoint:
- python
- -m
- manim
- --media_dir=/tmp/output
volumes:
- ${INPUT_PATH:?INPUT_PATH environment variable isn't set}:/tmp/input
- ${OUTPUT_PATH:?OUTPUT_PATH environment variable isn't set}:/tmp/output
working_dir: /tmp/input
network_mode: "none"

19
docs/Makefile Normal file
View File

@@ -0,0 +1,19 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
SOURCEDIR = source
BUILDDIR = build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

35
docs/make.bat Normal file
View File

@@ -0,0 +1,35 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=source
set BUILDDIR=build
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
:end
popd

11
docs/source/about.rst Normal file
View File

@@ -0,0 +1,11 @@
About
=====
Animating technical concepts is traditionally pretty tedious, since it can be
difficult to make the animations precise enough to convey them accurately.
``Manim`` uses Python to generate animations programmatically, which makes it
possible to specify exactly how each one should run.
This project is still very much a work in progress, but I hope that the
information here will make it easier for newcomers to get started using
``Manim``.

210
docs/source/animation.rst Normal file
View File

@@ -0,0 +1,210 @@
Animation
=========
The simplest of which is ``Scene.add``. The object appears on the first frame
without any animation::
class NoAnimation(Scene):
def construct(self):
square = Square()
self.add(square))
Animation are used in conjunction with ``scene.Play``
Fade
----
.. raw:: html
<video width="560" height="315" controls>
<source src="_static/AnimationFadeIn.mp4" type="video/mp4">
</video>
.. code-block:: python
class AnimationFadeIn(Scene):
def construct(self):
square = Square()
anno = TextMobject("Fade In")
anno.shift(2 * DOWN)
self.add(anno)
self.play(FadeIn(square))
.. raw:: html
<video width="560" height="315" controls>
<source src="_static/AnimationFadeOut.mp4" type="video/mp4">
</video>
.. code-block:: python
class AnimationFadeOut(Scene):
def construct(self):
square = Square()
anno = TextMobject("Fade Out")
anno.shift(2 * DOWN)
self.add(anno)
self.add(square)
self.play(FadeOut(square))
.. raw:: html
<video width="560" height="315" controls>
<source src="_static/AnimationFadeInFrom.mp4" type="video/mp4">
</video>
.. code-block:: python
class AnimationFadeInFrom(Scene):
def construct(self):
square = Square()
for label, edge in zip(
["LEFT", "RIGHT", "UP", "DOWN"], [LEFT, RIGHT, UP, DOWN]
):
anno = TextMobject(f"Fade In from {label}")
anno.shift(2 * DOWN)
self.add(anno)
self.play(FadeInFrom(square, edge))
self.remove(anno, square)
.. raw:: html
<video width="560" height="315" controls>
<source src="_static/AnimationFadeOutAndShift.mp4" type="video/mp4">
</video>
.. code-block:: python
class AnimationFadeOutAndShift(Scene):
def construct(self):
square = Square()
for label, edge in zip(
["LEFT", "RIGHT", "UP", "DOWN"], [LEFT, RIGHT, UP, DOWN]
):
anno = TextMobject(f"Fade Out and shift {label}")
anno.shift(2 * DOWN)
self.add(anno)
self.play(FadeOutAndShift(square, edge))
self.remove(anno, square)
.. raw:: html
<video width="560" height="315" controls>
<source src="_static/AnimationFadeInFromLarge.mp4" type="video/mp4">
</video>
.. code-block:: python
class AnimationFadeInFromLarge(Scene):
def construct(self):
square = Square()
for factor in [0.1, 0.5, 0.8, 1, 2, 5]:
anno = TextMobject(f"Fade In from large scale\_factor={factor}")
anno.shift(2 * DOWN)
self.add(anno)
self.play(FadeInFromLarge(square, scale_factor=factor))
self.remove(anno, square)
.. raw:: html
<video width="560" height="315" controls>
<source src="_static/AnimationFadeInFromPoint.mp4" type="video/mp4">
</video>
.. code-block:: python
class AnimationFadeInFromPoint(Scene):
def construct(self):
square = Square()
for i in range(-6, 7, 2):
anno = TextMobject(f"Fade In from point {i}")
anno.shift(2 * DOWN)
self.add(anno)
self.play(FadeInFromPoint(square, point=i))
self.remove(anno, square)
Grow
----
.. raw:: html
<video width="560" height="315" controls>
<source src="_static/AnimationGrowFromEdge.mp4" type="video/mp4">
</video>
.. code-block:: python
class AnimationGrowFromEdge(Scene):
def construct(self):
for label, edge in zip(
["LEFT", "RIGHT", "UP", "DOWN"], [LEFT, RIGHT, UP, DOWN]
):
anno = TextMobject(f"Grow from {label} edge")
anno.shift(2 * DOWN)
self.add(anno)
square = Square()
self.play(GrowFromEdge(square, edge))
self.remove(anno, square)
.. raw:: html
<video width="560" height="315" controls>
<source src="_static/AnimationGrowFromCenter.mp4" type="video/mp4">
</video>
.. code-block:: python
class AnimationGrowFromCenter(Scene):
def construct(self):
square = Square()
anno = TextMobject("Grow from center")
anno.shift(2 * DOWN)
self.add(anno)
self.play(GrowFromCenter(square))
Diagonal Directions
-------------------
You can combine cardinal directions to form diagonal animations
.. raw:: html
<video width="560" height="315" controls>
<source src="_static/AnimationFadeInFromDiagonal.mp4" type="video/mp4">
</video>
.. code-block:: python
class AnimationFadeInFromDiagonal(Scene):
def construct(self):
square = Square()
for diag in [UP + LEFT, UP + RIGHT, DOWN + LEFT, DOWN + RIGHT]:
self.play(FadeInFrom(square, diag))
.. note::
You can also use the abbreviated forms like ``UL, UR, DL, DR``.
See :ref:`ref-directions`.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

53
docs/source/conf.py Normal file
View File

@@ -0,0 +1,53 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# http://www.sphinx-doc.org/en/master/config
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
# -- Project information -----------------------------------------------------
project = 'Manim'
copyright = '2019, EulerTour'
author = 'EulerTour'
# -- General configuration ---------------------------------------------------
master_doc = 'index'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = []
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['assets']

94
docs/source/constants.rst Normal file
View File

@@ -0,0 +1,94 @@
Manim Constants
===============
The ``constants.py`` under ``manimlib/`` contains variables that are used
during setup and running manim. Some variables are not documented here as they are
only used internally by manim.
Directories
-----------
MEDIA_DIR
The directory where ``VIDEO_DIR`` and ``TEX_DIR`` will be created,
if they aren't specified via flags.
VIDEO_DIR
Used to store the scenes rendered by Manim. When a scene is
finished rendering, it will be stored under
``VIDEO_DIR/module_name/scene_name/quality/scene_name.mp4``.
Created under ``MEDIA_DIR`` by default.
TEX_DIR
Files written by Latex are stored here. It also acts as a cache
so that the files aren't rewritten each time Latex is needed.
Those directories are created if they don't exist.
Tex
---
TEX_USE_CTEX
A boolean value. Change it to True if you need to use Chinese typesetting.
TEX_TEXT_TO_REPLACE
Placeholder text used by manim when generating tex files
TEMPLATE_TEX_FILE
By default ``manimlib/tex_template.tex`` is used. If ``TEX_USE_CTEX``
is set to True then ``manimlib/ctex_template.tex`` is used.
Numerical Constants
-------------------
PI
alias to ``numpy.pi``
TAU
PI * 2
DEGREES
TAU / 360
Camera Configuration
--------------------
Render setting presets
PRODUCTION_QUALITY_CAMERA_CONFIG
2560x1440 @ 60fps # This is the default when rendering a scene
HIGH_QUALITY_CAMERA_CONFIG
1920x1080 @ 60fps. # Used when the ``-h`` or ``--high_quality`` flag
is passed.
MEDIUM_QUALITY_CAMERA_CONFIG
1280x720 @ 30fps. # Used when the ``-m`` or ``--medium_quality``
flag is passed.
LOW_QUALITY_CAMERA_CONFIG
854x480 @ 15fps. # Used when the ``-l`` or ``--low_quality`` flag is
passed.
.. _ref-directions:
Coordinates
-----------
Used for 2d/3d animations and placements::
ORIGIN
UP
DOWN
RIGHT
LEFT
IN # 3d camera only, away from camera
OUT # 3d camera only, close to camera
UL = UP + LEFT # diagonal abbreviations. You can use either one
UR = UP + RIGHT
DL = DOWN + LEFT
DR = DOWN + RIGHT
TOP
BOTTOM
LEFT_SIDE
RIGHT_SIDE``
Colors
------
COLOR_MAP
A predefined color maps
PALETTE
A list of color hex strings, derived from COLOR_MAP

178
docs/source/coordinate.rst Normal file
View File

@@ -0,0 +1,178 @@
Coordinate
==========
By default, the scene in manim is made up by 8 x 14 grid. The grid is addressed using a numpy
array in the form of [x, y, z]. For 2D animations only the x and y axes are used.
.. code-block:: python
class DotMap(Scene):
def construct(self):
dots = dict()
annos = dict()
var_index = 0
for x in range(-7, 8):
for y in range(-4, 5):
annos[f"{x}{y}"] = TexMobject(f"({x}, {y})")
dots[f"{var_index}"] = Dot(np.array([x, y, 0]))
var_index = var_index + 1
for anno, dot in zip(annos.values(), dots.values()):
self.add(anno)
self.add(dot)
self.wait(0.2)
self.remove(anno)
.. raw:: html
<video width="700" height="394" controls>
<source src="_static/coordinate/DotMap.mp4" type="video/mp4">
</video>
.. note::
You can place objects outside this boundary, but it won't show up in the render.
Using Coordinates
-----------------
Coordinates are used for creating geometries (`VMobject` in manim) and animations.
Here coordinates are used to create this Polygon
.. code-block:: python
class CoorPolygon(Scene):
def construct(self):
for x in range(-7, 8):
for y in range(-4, 5):
self.add(Dot(np.array([x, y, 0]), color=DARK_GREY))
polygon = Polygon(
np.array([3, 2, 0]),
np.array([1, -1, 0]),
np.array([-5, -4, 0]),
np.array([-4, 4, 0]))
self.add(polygon)
.. Image:: assets/coordinate/CoorPolygon.png
:width: 700px
Coordinate Aliasing
-------------------
From some animations typing a ``np.array`` everytime you need a coordinate can be tedious.
Manim provides aliases to the most common coordinates::
UP == np.array([0, 1, 0])
DOWN == np.array([0, -1, 0])
LEFT == np.array([-1, 0, 0])
RIGHT == np.array([1, 0, 0])
UL == np.array([-1, 1, 0])
DL == np.array([-1, -1, 0])
UR == np.array([1, 1, 0])
DR == np.array([1, -1, 0])
Here coordinates are used for animations
.. code-block:: python
class CoorAlias(Scene):
def construct(self):
for x in range(-7, 8):
for y in range(-4, 5):
self.add(Dot(np.array([x, y, 0]), color=DARK_GREY))
aliases = {
"UP": UP,
"np.array([0,1,0])": np.array([0, 1, 0]),
"DOWN": DOWN,
"np.array([0,-1,0])": np.array([0, -1, 0]),
"LEFT": LEFT,
"np.array([-1,0,0])": np.array([-1, 0, 0]),
"RIGHT": RIGHT,
"np.array([1,0,0])": np.array([1, 0, 0]),
"UL": UL,
"np.array([-1,1,0])": np.array([-1, 1, 0]),
"DL": DL,
"np.array([-1,-1,0])": np.array([-1, -1, 0]),
"UR": UR,
"np.array([1,1,0])": np.array([1, 1, 0]),
"DR": DR,
"np.array([1,-1,0])": np.array([1, -1, 0])}
circle = Circle(color=RED, radius=0.5)
self.add(circle)
self.wait(0.5)
for text, aliase in aliases.items():
anno = TexMobject(f"\\texttt{{{text}}}")
self.play(Write(anno, run_time=0.2))
self.play(ApplyMethod(circle.shift, aliase))
self.wait(0.2)
self.play(FadeOut(anno, run_time=0.2))
.. raw:: html
<video width="700" height="394" controls>
<source src="_static/coordinate/CoorAlias.mp4" type="video/mp4">
</video>
Coordinate Arithmetic
---------------------
Numpy array allows arithmetic operations::
>>> numpy.array([2,2,0]) + 4
array([6, 6, 4])
>>> np.array([1, -3, 0]) + np.array([-4, 2, 0])
array([-3, -1, 0])
>>> np.array([2, 2, 0]) - np.array([3,6, 0])
array([-1, -4, 0])
>>> numpy.array([2,2,0]) - 3
array([-1, -1, -3])
>>> np.array([1, -3, 0]) * 3
array([ 3, -9, 0])
>>> numpy.array([2,2,0]) / 2
array([1., 1., 0.])
>>> numpy.array([2,2,0]) / numpy.array([1, 4, 0])
__main__:1: RuntimeWarning: invalid value encountered in true_divide
array([2. , 0.5, nan])
.. code-block:: python
class CoorArithmetic(Scene):
def construct(self):
for x in range(-7, 8):
for y in range(-4, 5):
self.add(Dot(np.array([x, y, 0]), color=DARK_GREY))
circle = Circle(color=RED, radius=0.5)
self.add(circle)
self.wait(0.5)
aliases = {
"LEFT * 3": LEFT * 3,
"UP + RIGHT / 2": UP + RIGHT / 2,
"DOWN + LEFT * 2": DOWN + LEFT * 2,
"RIGHT * 3.75 * DOWN": RIGHT * 3.75 * DOWN,
# certain arithmetic won't work as you expected
# In [4]: RIGHT * 3.75 * DOWN
# Out[4]: array([ 0., -0., 0.])
"RIGHT * 3.75 + DOWN": RIGHT * 3.75 + DOWN}
for text, aliase in aliases.items():
anno = TexMobject(f"\\texttt{{{text}}}")
self.play(Write(anno, run_time=0.2))
self.play(ApplyMethod(circle.shift, aliase))
self.wait(0.2)
self.play(FadeOut(anno, run_time=0.2))
.. raw:: html
<video width="700" height="394" controls>
<source src="_static/coordinate/CoorArithmetic.mp4" type="video/mp4">
</video>

View File

@@ -0,0 +1,4 @@
Animating Mobjects
==================
Learn about animations.

View File

@@ -0,0 +1,18 @@
Getting Started
===============
Todd Zimmerman put together `a very nice tutorial`_ on getting started with
``manim``, which has been updated to run on python 3.7. Note that you'll want
to change `from big_ol_pile_of_manim_imports import *` to `from
manimlib.imports import *` to work with the current codebase.
.. _a very nice tutorial: https://talkingphysics.wordpress.com/2019/01/08/getting-started-animating-with-manim-and-python-3-7/
.. toctree::
:caption: Contents
:maxdepth: 2
learning_by_example
mathematical_objects
animating_mobjects
making_a_scene

View File

@@ -0,0 +1,131 @@
Learning by Example
===================
SquareToCircle
--------------
``example_scenes.py`` contains simple examples that we can use to learn about manim.
Go ahead and try out the ``SquareToCircle`` scene by running it with ``$ manim example_scenes.py SquareToCircle -p``
in manim directory.
.. code-block:: python
:linenos:
from manimlib.imports import *
class SquareToCircle(Scene):
def construct(self):
circle = Circle()
square = Square()
square.flip(RIGHT)
square.rotate(-3 * TAU / 8)
circle.set_fill(PINK, opacity=0.5)
self.play(ShowCreation(square))
self.play(Transform(square, circle))
self.play(FadeOut(square))
.. raw:: html
<video width="560" height="315" controls>
<source src="../_static/SquareToCircle.mp4" type="video/mp4">
</video>
.. note::
The flag ``-p`` plays the rendered video with default video player.
Other frequently used flags are:
* ``-l`` for rendering video in lower resolution (which renders faster)
* ``-s`` to show the last frame of the video.
Run ``manim -h`` all the available flags (``python -m manim -h`` if you installed it to a venv)
Let's step through each line of ``SquareToCircle``
.. code-block:: python
:lineno-start: 3
class SquareToCircle(Scene):
You create videos in manim by writing :class:`~scene.scene.Scene` classes.
Each :class:`~scene.scene.Scene` in manim is self-contained. That means everything
you created under this scene does not exist outside the class.
.. code-block:: python
:lineno-start: 4
def construct(self):
:meth:`~scene.scene.Scene.construct` specifies what is displayed on the screen
when the :class:`~scene.scene.Scene` is rendered to video.
.. code-block:: python
:lineno-start: 5
circle = Circle()
square = Square()
``Circle()`` and ``Square()`` create :class:`~mobject.geometry.Circle` and :class:`~mobject.geometry.Square`.
Both of these are instances of :class:`~mobject.mobject.Mobject` subclasses, the base class for objects in manim. Note
that instantiating a :class:`~mobject.mobject.Mobject` does not add it to the
:class:`~scene.scene.Scene`, so you wouldn't see anything if you were to render
the :class:`~scene.scene.Scene` at this point.
.. code-block:: python
:lineno-start: 7
square.flip(RIGHT)
square.rotate(-3 * TAU / 8)
circle.set_fill(PINK, opacity=0.5)
``flip()`` ``rotate()`` ``set_fill()`` apply various modifications to the mobjects before animating
them. The call to :meth:`~mobject.mobject.Mobject.flip` flips the
:class:`~mobject.geometry.Square` across the RIGHT vector. This is equivalent
to a refection across the x-axis.
The call to :meth:`~mobject.mobject.Mobject.rotate` rotates the
:class:`~mobject.geometry.Square` 3/8ths of a full rotation counterclockwise.
The call to :meth:`~mobject.mobject.Mobject.set_fill` sets
the fill color for the :class:`~mobject.geometry.Circle` to pink, and its opacity to 0.5.
.. code-block:: python
:lineno-start: 11
self.play(ShowCreation(square))
self.play(Transform(square, circle))
self.play(FadeOut(square))
To generated animation, :class:`~animation.animation.Animation` classes are used.
Each :class:`~animation.animation.Animation` takes one or more :class:`~mobject.mobject.Mobject` instances as arguments, which it animates
when passed to :meth:`~scene.scene.Scene.play`. This is how video is typically
created in manim.
:class:`~mobject.mobject.Mobject` instances are automatically
added to the :class:`~scene.scene.Scene` when they are animated. You can add a
:class:`~mobject.mobject.Mobject` to the :class:`~scene.scene.Scene` manually
by passing it as an argument to :meth:`~scene.scene.Scene.add`.
:class:`~animation.creation.ShowCreation` draws a :class:`~mobject.mobject.Mobject` to the screen.
:class:`~animation.transform.Transform` morphs one :class:`~mobject.mobject.Mobject` into another.
:class:`~animation.creation.FadeOut` fades a :class:`~mobject.mobject.Mobject` out of the :class:`~scene.scene.Scene`.
.. note::
Only the first argument to :class:`~animation.transform.Transform` is modified,
the second is not added to the :class:`~scene.scene.Scene`. :class:`~animation.tranform.Transform`
only changes the appearance but not the underlying properties.
After the call to ``transform()`` ``square`` is still a :class:`~mobject.geometry.Square` instance
but with the shape of :class:`~mobject.geometry.Circle`.

View File

@@ -0,0 +1,15 @@
Making a Scene
==============
A scene is what renders when manim is executed. Each scene contains mobjects, which can then be animated as
previously explained. In code, a scene is a class that extends ``Scene`` and implements the ``construct``
function, like so. Manim will execute this function to render the scene.
.. code-block:: python
:linenos:
from manimlib.imports import *
class ExampleScene(Scene):
def construct(self):
# Add and animate mobjects here

View File

@@ -0,0 +1,13 @@
Mathematical Objects
====================
Everything that appears on screen in a manim video is a
:class:`~mobject.mobject.Mobject`, or Mathematical Object. A
:class:`~mobject.mobject.Mobject`'s appearance is determined by 3
factors:
* ``m.points``, an Nx3 ``numpy.array`` specifying how to draw ``m``
* ``m``'s style attributes, such as ``m.color``, ``m.stroke_width``, and
``m.fill_opacity``
* ``m.submobjects``, a list of :class:`~mobject.mobject.Mobject` instances that
are considered part of ``m``

30
docs/source/index.rst Normal file
View File

@@ -0,0 +1,30 @@
.. Manim documentation master file, created by
sphinx-quickstart on Mon May 27 14:19:19 2019.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to Manim's documentation!
=================================
These docs are generated from the master branch of the
`Manim repo <https://github.com/3b1b/manim>`_. You can contribute by submitting
a pull request there.
.. toctree::
:maxdepth: 2
:caption: Contents
about
installation/index
getting_started/index
coordinate
animation
constants
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View File

@@ -0,0 +1,12 @@
Installation
============
Instructions on installing Manim
.. toctree::
:maxdepth: 2
:caption: Contents
linux
mac
windows

View File

@@ -0,0 +1,64 @@
Linux
=====
Ubuntu
------
Install system libraries::
# apt install sox ffmpeg libcairo2 libcairo2-dev
Install Latex distribution::
# apt install texlive-full
Install manim via pypi::
# pip3 install manimlib
OR Install manim via the git repository with venv::
$ git clone https://github.com/3b1b/manim
$ cd manim
$ python3 -m venv ./
$ source bin/activate
$ pip3 install -r requirement.txt
To use manim in virtual environment you need to activate the environment with
the ``activate`` binary by doing ``source bin/activate``, to exit use the ``deactivate`` command.
.. note:: The git repository is updated first before the one on pypi. The git repository also
includes project files used to produce 3b1b videos. Some of the old projects might not
work as due to api changes.
.. note:: The required latex packages are dictated by
``manimlib/tex_template.tex`` which ``texlive-full`` will satisfy. The download size
can be quite large. If you wish to install only the packages required to use
manim, substitude ``texlive-full`` with::
texlive texlive-latex-extra texlive-fonts-extra
texlive-latex-recommended texlive-science texlive-fonts-extra tipa
Arch Linux
----------
Install system libraries::
# pacman -S cairo ffmpeg opencv sox
Install Latex distribution::
# pacman -S texlive-most
OR install python-manimlib_:sup:`AUR` package::
$ git clone https://aur.archlinux.org/python-manimlib.git
$ cd python-manimlib
$ makepkg -si
You can use AUR helpers such as yay_:sup:`AUR`::
$ yay -S python-manimlib
.. _python-manimlib: https://aur.archlinux.org/packages/python-manimlib/
.. _yay: https://aur.archlinux.org/packages/yay/

View File

@@ -0,0 +1,12 @@
Mac
===
The simplest way to install the system dependencies on Mac OS X is with Homebrew.
Mac come preinstalled with python2, but to use manim, python3 is required
1. Install python3 https://docs.python.org/3/using/mac.html
2. Install Cairo: ``brew install cairo``
3. Install Sox: ``brew install sox``
4. Install ffmpeg: ``brew install ffmpeg``
5. Install latex (MacTeX): ``brew cask install mactex``
6. Install manimlib ``pip install manimlib`` (or ``pip install --user manimlib`` to just yourself)

View File

@@ -0,0 +1,60 @@
Windows
=======
Install System Libraries
------------------------
Make sure you have *Python 3* for Windows installed first:
https://www.python.org/downloads/windows/
Install ffmpeg:
https://ffmpeg.org/download.html#build-windows
Install sox:
http://sox.sourceforge.net/Main/HomePage
Install a latex distribution. On Windows MikTex is commonly used:
https://miktex.org/howto/install-miktex
Path configuration
------------------
To invoke commandline without supplying path to the binary
the PATH environment needs to be configured. Below are template examples, please change
the path according to your username and specific python version. Assuming all the
softwares are installed with no alteration to the installation paths::
C:\Users\$username\AppData\local\Programs\Python\Python$version\
C:\Users\$username\AppData\local\Programs\Python\Python$version\Scripts\
C:\MikTex\miktex\bin\x64\
C:\ffmpeg\bin\
The path entries should be separated by semicolon.
Installing python packages and manim
------------------------------------
Make sure you can start pip using ``pip`` in your commandline. Then do
``pip install pyreadline`` for the ``readline`` package.
Grab the pycairo wheel binary ``pycairo1.18.0cp37cp37mwin32.whl`` from https://www.lfd.uci.edu/~gohlke/pythonlibs/#pycairo
and install it via ``python -m pip install C:\absolute\path\to\the\whl\file``
clone the manim repository if you have git ``git clone https://github.com/3b1b/manim`` or download the zip file from
the repository page with ``Clone or download`` button and unzip it.
Open the commandline within the manim directory with ``Shift + Right click`` on an empty space in the folder and select ``open command window here``
Install manim python dependencies with ``pip install -r requirements.txt``
Test the installation
---------------------
Type in ``python -m manim -h`` and if nothing went wrong during the installation process you should see the help text.
Use ``python -m manim example_scenes.py SquareToCircle -pl`` to render the example scene and the file should play after rendering. The movie file should be
in ``media/videos/example_scenes/480p15``

View File

@@ -5,7 +5,7 @@ channels:
dependencies:
- python=3.7
- cairo
- ffmpeg
- ffmpeg
- colour==0.1.5
- numpy==1.15.0
- pillow==5.2.0
@@ -14,4 +14,7 @@ dependencies:
- opencv==3.4.2
- pycairo==1.18.0
- pydub==0.23.0
- pyreadline
- ffmpeg
- pygments==2.6.1
- pip:
- pyreadline

View File

@@ -5,12 +5,14 @@ from manimlib.imports import *
# To watch one of these scenes, run the following:
# python -m manim example_scenes.py SquareToCircle -pl
#
# Use the flat -l for a faster rendering at a lower
# Use the flag -l for a faster rendering at a lower
# quality.
# Use -s to skip to the end and just save the final frame
# Use the -p to have the animation (or image, if -s was
# used) pop up once done.
# Use -n <number> to skip ahead to the n'th animation of a scene.
# Use -r <number> to specify a resolution (for example, -r 1080
# for a 1920x1080 video)
class OpeningManimExample(Scene):
@@ -96,7 +98,7 @@ class WarpSquare(Scene):
class WriteStuff(Scene):
def construct(self):
example_text = TextMobject(
"This is a some text",
"This is some text",
tex_to_color_map={"text": YELLOW}
)
example_tex = TexMobject(
@@ -111,7 +113,7 @@ class WriteStuff(Scene):
self.wait()
class UdatersExample(Scene):
class UpdatersExample(Scene):
def construct(self):
decimal = DecimalNumber(
0,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,10 @@
from active_projects.ode.part1.pendulum import *
from active_projects.ode.part1.staging import *
from active_projects.ode.part1.pi_scenes import *
from active_projects.ode.part1.phase_space import *
from active_projects.ode.part1.wordy_scenes import *
from active_projects.diffyq.part1.pendulum import *
from active_projects.diffyq.part1.staging import *
from active_projects.diffyq.part1.pi_scenes import *
from active_projects.diffyq.part1.phase_space import *
from active_projects.diffyq.part1.wordy_scenes import *
OUTPUT_DIRECTORY = "ode/part1"
OUTPUT_DIRECTORY = "diffyq/part1"
SCENES_IN_ORDER = [
WhenChangeIsEasier,
VectorFieldTest,

View File

@@ -1,10 +1,10 @@
from active_projects.ode.part2.staging import *
from active_projects.ode.part2.fourier_series import *
from active_projects.ode.part2.heat_equation import *
from active_projects.ode.part2.pi_scenes import *
from active_projects.ode.part2.wordy_scenes import *
from active_projects.diffyq.part2.staging import *
from active_projects.diffyq.part2.fourier_series import *
from active_projects.diffyq.part2.heat_equation import *
from active_projects.diffyq.part2.pi_scenes import *
from active_projects.diffyq.part2.wordy_scenes import *
OUTPUT_DIRECTORY = "ode/part2"
OUTPUT_DIRECTORY = "diffyq/part2"
SCENES_IN_ORDER = [
PartTwoOfTour,
HeatEquationIntroTitle,

View File

@@ -0,0 +1,70 @@
from active_projects.diffyq.part3.staging import *
from active_projects.diffyq.part3.temperature_graphs import *
from active_projects.diffyq.part3.pi_creature_scenes import *
from active_projects.diffyq.part3.wordy_scenes import *
from active_projects.diffyq.part3.discrete_case import *
OUTPUT_DIRECTORY = "diffyq/part3"
SCENES_IN_ORDER = [
LastChapterWrapper,
ThreeConstraints,
OceanOfPossibilities,
ThreeMainObservations,
SimpleCosExpGraph,
AddMultipleSolutions,
FourierSeriesIllustraiton,
BreakDownAFunction,
SineCurveIsUnrealistic,
AnalyzeSineCurve,
EquationAboveSineAnalysis,
ExponentialDecay,
InvestmentGrowth,
GrowingPileOfMoney,
CarbonDecayCurve,
CarbonDecayingInMammoth,
SineWaveScaledByExp,
ShowSinExpDerivatives,
IfOnly,
BoundaryConditionInterlude,
BoundaryConditionReference,
GiantCross,
SimulateRealSineCurve,
DerivativesOfLinearFunction,
StraightLine3DGraph,
SimulateLinearGraph,
EmphasizeBoundaryPoints,
ShowNewRuleAtDiscreteBoundary,
DiscreteEvolutionPoint25,
DiscreteEvolutionPoint1,
FlatEdgesForDiscreteEvolution,
FlatEdgesForDiscreteEvolutionTinySteps,
FlatEdgesContinuousEvolution,
FlatAtBoundaryWords,
SlopeToHeatFlow,
CloserLookAtStraightLine,
WriteOutBoundaryCondition,
SoWeGotNowhere,
ManipulateSinExpSurface,
HeatEquationFrame,
ShowFreq1CosExpDecay,
ShowFreq2CosExpDecay,
ShowFreq4CosExpDecay,
CompareFreqDecays1to2,
CompareFreqDecays1to4,
CompareFreqDecays2to4,
ShowHarmonics,
ShowHarmonicSurfaces,
# SimpleCosExpGraph,
# AddMultipleSolutions,
# IveHeardOfThis,
# FourierSeriesOfLineIllustration,
# InFouriersShoes,
]
PART_4_SCENES = [
FourierSeriesIllustraiton,
FourierNameIntro,
CircleAnimationOfF,
]

View File

@@ -0,0 +1,65 @@
from active_projects.diffyq.part4.staging import *
from active_projects.diffyq.part4.fourier_series_scenes import *
from active_projects.diffyq.part4.pi_creature_scenes import *
from active_projects.diffyq.part4.three_d_graphs import *
from active_projects.diffyq.part4.temperature_scenes import *
from active_projects.diffyq.part4.complex_functions import *
from active_projects.diffyq.part4.long_fourier_scenes import *
from active_projects.diffyq.part3.staging import *
OUTPUT_DIRECTORY = "diffyq/part4"
SCENES_IN_ORDER = [
ComplexFourierSeriesExample,
FourierOfFourier,
FourierOfFourierZoomedIn,
FourierOfFourier100xZoom,
FourierSeriesFormula,
RelationToOtherVideos,
WhyWouldYouCare,
ShowLinearity,
CombineSeveralSolutions,
FourierGainsImmortality,
SolveForWavesNothingElse,
CycleThroughManyLinearCombinations,
StepFunctionExample,
WhichWavesAreAvailable,
AlternateBoundaryConditions,
AskQuestionOfGraph,
CommentOnFouriersImmortality,
HangOnThere,
ShowInfiniteSum,
TechnicalNuances,
BreakDownStepFunction,
StepFunctionSolutionFormla,
# How to compute
FourierSeriesOfLineIllustration,
GeneralizeToComplexFunctions,
ClarifyInputAndOutput,
GraphForFlattenedPi,
PiFourierSeries,
RealValuedFunctionFourierSeries,
YouSaidThisWasEasier,
AskAboutComplexNotVector,
SimpleComplexExponentExample,
LooseWithLanguage,
DemonstrateAddingArrows,
TRangingFrom0To1,
LabelRotatingVectors,
IntegralTrick,
SwapIntegralAndSum,
FootnoteOnSwappingIntegralAndSum,
FormulaOutOfContext,
ShowRangeOfCnFormulas,
DescribeSVG,
# TODO
IncreaseOrderOfApproximation,
ShowStepFunctionIn2dView,
StepFunctionIntegral,
GeneralChallenge,
# Oldies
# FourierSeriesIllustraiton,
# FourierNameIntro,
# CircleAnimationOfF,
]

View File

@@ -0,0 +1,5 @@
from active_projects.diffyq.part5.staging import *
OUTPUT_DIRECTORY = "diffyq/part5"
SCENES_IN_ORDER = [
]

View File

@@ -0,0 +1,23 @@
from active_projects.diffyq.part4.long_fourier_scenes import *
OUTPUT_DIRECTORY = "diffyq/part4"
SCENES_IN_ORDER = [
ZoomedInFourierSeriesExample,
FourierSeriesExampleWithRectForZoom,
ZoomedInFourierSeriesExample100x,
FourierOfFourier100xZoom,
FourierOfFourierZoomedIn,
FourierOfFourier,
SigmaZoomedInFourierSeriesExample,
SigmaFourierSeriesExampleWithRectForZoom,
NailAndGearZoomedInFourierSeriesExample,
NailAndGearFourierSeriesExampleWithRectForZoom,
TrebleClefZoomedInFourierSeriesExample,
TrebleClefFourierSeriesExampleWithRectForZoom,
FourierOfSeattle,
FourierOfSeattleZoomedIn,
FourierOfBritain,
FourierOfBritainZoomedIn,
FourierOfHilbert,
FourierOfHilbertZoomedIn,
]

View File

@@ -1,5 +1,5 @@
from manimlib.imports import *
from active_projects.ode.part1.shared_constructs import *
from active_projects.diffyq.part1.shared_constructs import *
class Pendulum(VGroup):
@@ -254,7 +254,7 @@ class ThetaVsTAxes(Axes):
"tick_frequency": PI / 8,
"unit_size": 1.5,
},
"number_line_config": {
"axis_config": {
"color": "#EEEEEE",
"stroke_width": 2,
"include_tip": False,
@@ -371,7 +371,7 @@ class IntroducePendulum(PiCreatureScene, MovingCameraScene):
"tip_length": 0.3,
},
"x_max": 12,
"number_line_config": {
"axis_config": {
"stroke_width": 2,
}
},
@@ -750,7 +750,7 @@ class LowAnglePendulum(Scene):
"number_scale_val": 0.5,
},
"x_max": 25,
"number_line_config": {
"axis_config": {
"tip_length": 0.3,
"stroke_width": 2,
}
@@ -837,7 +837,7 @@ class MediumAnglePendulum(LowAnglePendulum):
"y_axis_config": {"unit_size": 0.75},
"y_max": PI / 2,
"y_min": -PI / 2,
"number_line_config": {
"axis_config": {
"tip_length": 0.3,
"stroke_width": 2,
}
@@ -867,7 +867,7 @@ class HighAnglePendulum(LowAnglePendulum):
"y_axis_config": {"unit_size": 0.5},
"y_max": PI,
"y_min": -PI,
"number_line_config": {
"axis_config": {
"tip_length": 0.3,
"stroke_width": 2,
}
@@ -888,7 +888,7 @@ class VeryLowAnglePendulum(LowAnglePendulum):
"y_axis_config": {"unit_size": 2},
"y_max": PI / 4,
"y_min": -PI / 4,
"number_line_config": {
"axis_config": {
"tip_length": 0.3,
"stroke_width": 2,
}

View File

@@ -1,6 +1,6 @@
from manimlib.imports import *
from active_projects.ode.part1.shared_constructs import *
from active_projects.ode.part1.pendulum import Pendulum
from active_projects.diffyq.part1.shared_constructs import *
from active_projects.diffyq.part1.pendulum import Pendulum
# TODO: Arguably separate the part showing many
@@ -2012,11 +2012,18 @@ class ManyStepsFromDifferentStartingPoints(TakeManyTinySteps):
class Thumbnail(IntroduceVectorField):
CONFIG = {
"vector_field_config": {
"delta_x": 0.5,
"delta_y": 0.5,
# "delta_x": 0.5,
# "delta_y": 0.5,
# "max_magnitude": 5,
# "length_func": lambda norm: 0.5 * sigmoid(norm),
"delta_x": 1,
"delta_y": 1,
"max_magnitude": 5,
"length_func": lambda norm: 0.5 * sigmoid(norm),
}
"length_func": lambda norm: 0.9 * sigmoid(norm),
},
"big_pendulum_config": {
"damping": 0.4,
},
}
def construct(self):
@@ -2027,7 +2034,7 @@ class Thumbnail(IntroduceVectorField):
field = self.vector_field
field.set_stroke(width=5)
for vector in field:
vector.set_stroke(width=3)
vector.set_stroke(width=8)
vector.tip.set_stroke(width=0)
vector.tip.scale(1.5, about_point=vector.get_last_point())
vector.set_opacity(1)
@@ -2063,17 +2070,43 @@ class Thumbnail(IntroduceVectorField):
new_mob.set_stroke(width=0)
black_parts.add(new_mob)
for vect in field:
for mob in title.family_members_with_points():
for p in [vect.get_start(), vect.get_end()]:
x, y = p[:2]
x0, y0 = mob.get_corner(DL)[:2]
x1, y1 = mob.get_corner(UR)[:2]
if x0 < x < x1 and y0 < y < y1:
vect.set_opacity(0.25)
vect.tip.set_stroke(width=0)
# for vect in field:
# for mob in title.family_members_with_points():
# for p in [vect.get_start(), vect.get_end()]:
# x, y = p[:2]
# x0, y0 = mob.get_corner(DL)[:2]
# x1, y1 = mob.get_corner(UR)[:2]
# if x0 < x < x1 and y0 < y < y1:
# vect.set_opacity(0.25)
# vect.tip.set_stroke(width=0)
self.add(self.plane)
self.add(field)
self.add(black_parts)
self.add(title)
# self.add(black_parts)
# self.add(title)
self.add_line(self.plane)
def add_line(self, axes):
func = self.vector_field_func
line = VMobject()
line.start_new_path(axes.c2p(-TAU, 3.5))
dt = 0.1
t = 0
total_time = 40
while t < total_time:
t += dt
last_point = line.get_last_point()
new_point = last_point + dt * func(last_point)
if new_point[0] > FRAME_WIDTH / 2:
new_point = last_point + FRAME_WIDTH * LEFT
line.start_new_path(new_point)
else:
line.add_smooth_curve_to(new_point)
line.set_stroke(WHITE, 6)
line.make_smooth()
self.add(line)

View File

@@ -1,5 +1,5 @@
from manimlib.imports import *
from active_projects.ode.part1.shared_constructs import *
from active_projects.diffyq.part1.shared_constructs import *
class SomeOfYouWatching(TeacherStudentsScene):

View File

@@ -1,10 +1,10 @@
from manimlib.imports import *
from active_projects.ode.part1.shared_constructs import *
from active_projects.ode.part1.pendulum import Pendulum
from active_projects.ode.part1.pendulum import ThetaVsTAxes
from active_projects.ode.part1.phase_space import IntroduceVectorField
from old_projects.div_curl import PhaseSpaceOfPopulationModel
from old_projects.div_curl import ShowTwoPopulations
from active_projects.diffyq.part1.shared_constructs import *
from active_projects.diffyq.part1.pendulum import Pendulum
from active_projects.diffyq.part1.pendulum import ThetaVsTAxes
from active_projects.diffyq.part1.phase_space import IntroduceVectorField
from from_3b1b.old.div_curl import PhaseSpaceOfPopulationModel
from from_3b1b.old.div_curl import ShowTwoPopulations
# Scenes

View File

@@ -1,5 +1,5 @@
from manimlib.imports import *
from active_projects.ode.part1.shared_constructs import *
from active_projects.diffyq.part1.shared_constructs import *
class SmallAngleApproximationTex(Scene):

View File

@@ -4,7 +4,7 @@ from manimlib.imports import *
class FourierCirclesScene(Scene):
CONFIG = {
"n_circles": 10,
"n_vectors": 10,
"big_radius": 2,
"colors": [
BLUE_D,
@@ -15,44 +15,57 @@ class FourierCirclesScene(Scene):
"circle_style": {
"stroke_width": 2,
},
"arrow_config": {
"vector_config": {
"buff": 0,
"max_tip_length_to_length_ratio": 0.35,
"tip_length": 0.15,
"max_stroke_width_to_length_ratio": 10,
"stroke_width": 2,
},
"use_vectors": True,
"circle_config": {
"stroke_width": 1,
},
"base_frequency": 1,
"slow_factor": 0.25,
"center_point": ORIGIN,
"parametric_function_step_size": 0.001,
"drawn_path_color": YELLOW,
"drawn_path_stroke_width": 2,
}
def setup(self):
self.slow_factor_tracker = ValueTracker(
self.slow_factor
)
self.vector_clock = ValueTracker(0)
self.vector_clock.add_updater(
lambda m, dt: m.increment_value(
self.get_slow_factor() * dt
)
)
self.add(self.vector_clock)
def get_slow_factor(self):
return self.slow_factor_tracker.get_value()
def get_vector_time(self):
return self.vector_clock.get_value()
#
def get_freqs(self):
n = self.n_circles
n = self.n_vectors
all_freqs = list(range(n // 2, -n // 2, -1))
all_freqs.sort(key=abs)
return all_freqs
def get_coefficients(self):
return [complex(0) for x in range(self.n_circles)]
return [complex(0) for x in range(self.n_vectors)]
def get_color_iterator(self):
return it.cycle(self.colors)
def get_circles(self, freqs=None, coefficients=None):
circles = VGroup()
color_iterator = self.get_color_iterator()
def get_rotating_vectors(self, freqs=None, coefficients=None):
vectors = VGroup()
self.center_tracker = VectorizedPoint(self.center_point)
if freqs is None:
@@ -60,80 +73,74 @@ class FourierCirclesScene(Scene):
if coefficients is None:
coefficients = self.get_coefficients()
last_circle = None
last_vector = None
for freq, coefficient in zip(freqs, coefficients):
if last_circle:
center_func = last_circle.get_start
if last_vector:
center_func = last_vector.get_end
else:
center_func = self.center_tracker.get_location
circle = self.get_circle(
vector = self.get_rotating_vector(
coefficient=coefficient,
freq=freq,
color=next(color_iterator),
center_func=center_func,
)
circles.add(circle)
last_circle = circle
return circles
vectors.add(vector)
last_vector = vector
return vectors
def get_circle(self, coefficient, freq, color, center_func):
radius = abs(coefficient)
phase = np.log(coefficient).imag
circle = Circle(
radius=radius,
color=color,
**self.circle_style,
)
line_points = (
circle.get_center(),
circle.get_start(),
)
if self.use_vectors:
circle.radial_line = Arrow(
*line_points,
**self.arrow_config,
)
def get_rotating_vector(self, coefficient, freq, center_func):
vector = Vector(RIGHT, **self.vector_config)
vector.scale(abs(coefficient))
if abs(coefficient) == 0:
phase = 0
else:
circle.radial_line = Line(
*line_points,
color=WHITE,
**self.circle_style,
phase = np.log(coefficient).imag
vector.rotate(phase, about_point=ORIGIN)
vector.freq = freq
vector.coefficient = coefficient
vector.center_func = center_func
vector.add_updater(self.update_vector)
return vector
def update_vector(self, vector, dt):
time = self.get_vector_time()
coef = vector.coefficient
freq = vector.freq
phase = np.log(coef).imag
vector.set_length(abs(coef))
vector.set_angle(phase + time * freq * TAU)
vector.shift(vector.center_func() - vector.get_start())
return vector
def get_circles(self, vectors):
return VGroup(*[
self.get_circle(
vector,
color=color
)
circle.add(circle.radial_line)
circle.freq = freq
circle.phase = phase
circle.rotate(phase)
circle.coefficient = coefficient
circle.center_func = center_func
for vector, color in zip(
vectors,
self.get_color_iterator()
)
])
def get_circle(self, vector, color=BLUE):
circle = Circle(color=color, **self.circle_config)
circle.center_func = vector.get_start
circle.radius_func = vector.get_length
circle.add_updater(self.update_circle)
return circle
def update_circle(self, circle, dt):
circle.rotate(
self.get_slow_factor() * circle.freq * dt * TAU
)
def update_circle(self, circle):
circle.set_width(2 * circle.radius_func())
circle.move_to(circle.center_func())
return circle
def get_rotating_vectors(self, circles):
return VGroup(*[
self.get_rotating_vector(circle)
for circle in circles
])
def get_rotating_vector(self, circle):
vector = Vector(RIGHT, color=WHITE)
vector.add_updater(lambda v, dt: v.put_start_and_end_on(
circle.get_center(),
circle.get_start(),
))
circle.vector = vector
return vector
def get_circle_end_path(self, circles, color=YELLOW):
coefs = [c.coefficient for c in circles]
freqs = [c.freq for c in circles]
center = circles[0].get_center()
def get_vector_sum_path(self, vectors, color=YELLOW):
coefs = [v.coefficient for v in vectors]
freqs = [v.freq for v in vectors]
center = vectors[0].get_start()
path = ParametricFunction(
lambda t: center + reduce(op.add, [
@@ -150,13 +157,19 @@ class FourierCirclesScene(Scene):
return path
# TODO, this should be a general animated mobect
def get_drawn_path(self, circles, stroke_width=2, **kwargs):
path = self.get_circle_end_path(circles, **kwargs)
def get_drawn_path_alpha(self):
return self.get_vector_time()
def get_drawn_path(self, vectors, stroke_width=None, **kwargs):
if stroke_width is None:
stroke_width = self.drawn_path_stroke_width
path = self.get_vector_sum_path(vectors, **kwargs)
broken_path = CurvesAsSubmobjects(path)
broken_path.curr_time = 0
def update_path(path, dt):
alpha = path.curr_time * self.get_slow_factor()
# alpha = path.curr_time * self.get_slow_factor()
alpha = self.get_drawn_path_alpha()
n_curves = len(path)
for a, sp in zip(np.linspace(0, 1, n_curves), path):
b = alpha - a
@@ -168,17 +181,17 @@ class FourierCirclesScene(Scene):
path.curr_time += dt
return path
broken_path.set_color(YELLOW)
broken_path.set_color(self.drawn_path_color)
broken_path.add_updater(update_path)
return broken_path
def get_y_component_wave(self,
circles,
vectors,
left_x=1,
color=PINK,
n_copies=2,
right_shift_rate=5):
path = self.get_circle_end_path(circles)
path = self.get_vector_sum_path(vectors)
wave = ParametricFunction(
lambda t: op.add(
right_shift_rate * t * LEFT,
@@ -216,15 +229,16 @@ class FourierCirclesScene(Scene):
return VGroup(wave, wave_copies)
def get_wave_y_line(self, circles, wave):
def get_wave_y_line(self, vectors, wave):
return DashedLine(
circles[-1].get_start(),
vectors[-1].get_end(),
wave[0].get_end(),
stroke_width=1,
dash_length=DEFAULT_DASH_LENGTH * 0.5,
)
# Computing Fourier series
# i.e. where all the math happens
def get_coefficients_of_path(self, path, n_samples=10000, freqs=None):
if freqs is None:
freqs = self.get_freqs()
@@ -250,7 +264,7 @@ class FourierCirclesScene(Scene):
class FourierSeriesIntroBackground4(FourierCirclesScene):
CONFIG = {
"n_circles": 4,
"n_vectors": 4,
"center_point": 4 * LEFT,
"run_time": 30,
"big_radius": 1.5,
@@ -271,7 +285,7 @@ class FourierSeriesIntroBackground4(FourierCirclesScene):
self.wait(self.run_time)
def get_ks(self):
return np.arange(1, 2 * self.n_circles + 1, 2)
return np.arange(1, 2 * self.n_vectors + 1, 2)
def get_freqs(self):
return self.base_frequency * self.get_ks()
@@ -282,52 +296,72 @@ class FourierSeriesIntroBackground4(FourierCirclesScene):
class FourierSeriesIntroBackground8(FourierSeriesIntroBackground4):
CONFIG = {
"n_circles": 8,
"n_vectors": 8,
}
class FourierSeriesIntroBackground12(FourierSeriesIntroBackground4):
CONFIG = {
"n_circles": 12,
"n_vectors": 12,
}
class FourierSeriesIntroBackground20(FourierSeriesIntroBackground4):
CONFIG = {
"n_circles": 20,
"n_vectors": 20,
}
class FourierOfPiSymbol(FourierCirclesScene):
CONFIG = {
"n_circles": 50,
"n_vectors": 51,
"center_point": ORIGIN,
"slow_factor": 0.1,
"run_time": 30,
"n_cycles": 1,
"tex": "\\pi",
"start_drawn": False,
"max_circle_stroke_width": 1,
}
def construct(self):
self.add_vectors_circles_path()
for n in range(self.n_cycles):
self.run_one_cycle()
def add_vectors_circles_path(self):
path = self.get_path()
coefs = self.get_coefficients_of_path(path)
circles = self.get_circles(coefficients=coefs)
for k, circle in zip(it.count(1), circles):
circle.set_stroke(width=max(
1 / np.sqrt(k),
1,
))
# approx_path = self.get_circle_end_path(circles)
drawn_path = self.get_drawn_path(circles)
vectors = self.get_rotating_vectors(coefficients=coefs)
circles = self.get_circles(vectors)
self.set_decreasing_stroke_widths(circles)
# approx_path = self.get_vector_sum_path(circles)
drawn_path = self.get_drawn_path(vectors)
if self.start_drawn:
drawn_path.curr_time = 1 / self.slow_factor
self.vector_clock.increment_value(1)
self.add(path)
self.add(vectors)
self.add(circles)
self.add(drawn_path)
self.wait(self.run_time)
self.vectors = vectors
self.circles = circles
self.path = path
self.drawn_path = drawn_path
def run_one_cycle(self):
time = 1 / self.slow_factor
self.wait(time)
def set_decreasing_stroke_widths(self, circles):
mcsw = self.max_circle_stroke_width
for k, circle in zip(it.count(1), circles):
circle.set_stroke(width=max(
# mcsw / np.sqrt(k),
mcsw / k,
mcsw,
))
return circles
def get_path(self):
tex_mob = TexMobject(self.tex)
@@ -338,16 +372,87 @@ class FourierOfPiSymbol(FourierCirclesScene):
return path
class FourierOfTexPaths(FourierOfPiSymbol, MovingCameraScene):
CONFIG = {
"n_vectors": 100,
"name_color": WHITE,
"animated_name": "Abc",
"time_per_symbol": 5,
"slow_factor": 1 / 5,
"parametric_function_step_size": 0.01,
}
def construct(self):
name = TextMobject(self.animated_name)
max_width = FRAME_WIDTH - 2
max_height = FRAME_HEIGHT - 2
name.set_width(max_width)
if name.get_height() > max_height:
name.set_height(max_height)
frame = self.camera.frame
frame.save_state()
vectors = VGroup(VectorizedPoint())
circles = VGroup(VectorizedPoint())
for path in name.family_members_with_points():
for subpath in path.get_subpaths():
sp_mob = VMobject()
sp_mob.set_points(subpath)
coefs = self.get_coefficients_of_path(sp_mob)
new_vectors = self.get_rotating_vectors(
coefficients=coefs
)
new_circles = self.get_circles(new_vectors)
self.set_decreasing_stroke_widths(new_circles)
drawn_path = self.get_drawn_path(new_vectors)
drawn_path.clear_updaters()
drawn_path.set_stroke(self.name_color, 3)
static_vectors = VMobject().become(new_vectors)
static_circles = VMobject().become(new_circles)
# static_circles = new_circles.deepcopy()
# static_vectors.clear_updaters()
# static_circles.clear_updaters()
self.play(
Transform(vectors, static_vectors, remover=True),
Transform(circles, static_circles, remover=True),
frame.set_height, 1.5 * name.get_height(),
frame.move_to, path,
)
self.add(new_vectors, new_circles)
self.vector_clock.set_value(0)
self.play(
ShowCreation(drawn_path),
rate_func=linear,
run_time=self.time_per_symbol
)
self.remove(new_vectors, new_circles)
self.add(static_vectors, static_circles)
vectors = static_vectors
circles = static_circles
self.play(
FadeOut(vectors),
Restore(frame),
run_time=2
)
self.wait(3)
class FourierOfPiSymbol5(FourierOfPiSymbol):
CONFIG = {
"n_circles": 5,
"n_vectors": 5,
"run_time": 10,
}
class FourierOfTrebleClef(FourierOfPiSymbol):
CONFIG = {
"n_circles": 100,
"n_vectors": 101,
"run_time": 10,
"start_drawn": True,
"file_name": "TrebleClef",
@@ -371,7 +476,7 @@ class FourierOfIP(FourierOfTrebleClef):
CONFIG = {
"file_name": "IP_logo2",
"height": 6,
"n_circles": 100,
"n_vectors": 100,
}
# def construct(self):
@@ -403,7 +508,7 @@ class FourierOfEighthNote(FourierOfTrebleClef):
class FourierOfN(FourierOfTrebleClef):
CONFIG = {
"height": 6,
"n_circles": 1000,
"n_vectors": 1000,
}
def get_shape(self):
@@ -413,7 +518,7 @@ class FourierOfN(FourierOfTrebleClef):
class FourierNailAndGear(FourierOfTrebleClef):
CONFIG = {
"height": 6,
"n_circles": 200,
"n_vectors": 200,
"run_time": 100,
"slow_factor": 0.01,
"parametric_function_step_size": 0.0001,
@@ -431,7 +536,7 @@ class FourierNailAndGear(FourierOfTrebleClef):
class FourierBatman(FourierOfTrebleClef):
CONFIG = {
"height": 4,
"n_circles": 100,
"n_vectors": 100,
"run_time": 10,
"arrow_config": {
"tip_length": 0.1,
@@ -447,7 +552,7 @@ class FourierBatman(FourierOfTrebleClef):
class FourierHeart(FourierOfTrebleClef):
CONFIG = {
"height": 4,
"n_circles": 100,
"n_vectors": 100,
"run_time": 10,
"arrow_config": {
"tip_length": 0.1,
@@ -469,7 +574,7 @@ class FourierHeart(FourierOfTrebleClef):
class FourierNDQ(FourierOfTrebleClef):
CONFIG = {
"height": 4,
"n_circles": 1000,
"n_vectors": 1000,
"run_time": 10,
"arrow_config": {
"tip_length": 0.1,
@@ -479,7 +584,7 @@ class FourierNDQ(FourierOfTrebleClef):
def get_shape(self):
path = VMobject()
shape = TexMobject("Hayley")
shape = TexMobject("NDQ")
for sp in shape.family_members_with_points():
path.append_points(sp.points)
return path
@@ -487,7 +592,7 @@ class FourierNDQ(FourierOfTrebleClef):
class FourierGoogleG(FourierOfTrebleClef):
CONFIG = {
"n_circles": 10,
"n_vectors": 10,
"height": 5,
"g_colors": [
"#4285F4",
@@ -522,7 +627,7 @@ class FourierGoogleG(FourierOfTrebleClef):
class ExplainCircleAnimations(FourierCirclesScene):
CONFIG = {
"n_circles": 100,
"n_vectors": 100,
"center_point": 2 * DOWN,
"n_top_circles": 9,
"path_height": 3,

View File

@@ -1,5 +1,5 @@
from manimlib.imports import *
from active_projects.ode.part2.shared_constructs import *
from active_projects.diffyq.part2.shared_constructs import *
class TwoDBodyWithManyTemperatures(ThreeDScene):
@@ -164,8 +164,12 @@ class BringTwoRodsTogether(Scene):
"tick_frequency": 10,
},
},
"y_labels": range(20, 100, 20),
"graph_x_min": 0,
"graph_x_max": 10,
"midpoint": 5,
"max_temp": 90,
"min_temp": 10,
"wait_time": 30,
"default_n_rod_pieces": 20,
"alpha": 1.0,
@@ -185,10 +189,9 @@ class BringTwoRodsTogether(Scene):
y_label = axes.get_y_axis_label("\\text{Temperature}")
y_label.to_edge(UP)
axes.y_axis.label = y_label
axes.y_axis.add(y_label)
axes.y_axis.add_numbers(
*range(20, 100, 20)
)
axes.y_axis.add_numbers(*self.y_labels)
self.axes = axes
self.y_label = y_label
@@ -199,7 +202,7 @@ class BringTwoRodsTogether(Scene):
x_min=self.graph_x_min,
x_max=self.graph_x_max,
step_size=self.step_size,
discontinuities=[5],
discontinuities=[self.midpoint],
)
graph.color_using_background_image("VerticalTempGradient")
@@ -314,22 +317,29 @@ class BringTwoRodsTogether(Scene):
rods.add_updater(self.update_rods)
self.play(
ClockPassesTime(
self.clock,
run_time=self.wait_time,
hours_passed=self.wait_time,
),
self.get_clock_anim(self.wait_time),
FadeOut(labels)
)
#
def initial_function(self, x):
if x <= 5:
return 90
else:
return 10
def get_clock_anim(self, time, **kwargs):
config = {
"run_time": time,
"hours_passed": time,
}
config.update(kwargs)
return ClockPassesTime(self.clock, **config)
def update_graph(self, graph, dt, alpha=None, n_mini_steps=100):
def initial_function(self, x):
epsilon = 1e-10
if x < self.midpoint - epsilon:
return self.max_temp
elif x > self.midpoint + epsilon:
return self.min_temp
else:
return (self.min_temp + self.max_temp) / 2
def update_graph(self, graph, dt, alpha=None, n_mini_steps=500):
if alpha is None:
alpha = self.alpha
points = np.append(
@@ -349,16 +359,16 @@ class BringTwoRodsTogether(Scene):
if (0 < i < len(points) - 1):
second_deriv = d2y / (dx**2)
else:
second_deriv = 0.5 * d2y / dx
second_deriv = 0
second_deriv = 2 * d2y / (dx**2)
# second_deriv = 0
y_change[i] = alpha * second_deriv * dt / n_mini_steps
# y_change[0] = y_change[1]
# y_change[-1] = y_change[-2]
y_change[0] = 0
y_change[-1] = 0
y_change -= np.mean(y_change)
# y_change[0] = 0
# y_change[-1] = 0
# y_change -= np.mean(y_change)
points[:, 1] += y_change
graph.set_points_smoothly(points)
return graph
@@ -374,8 +384,17 @@ class BringTwoRodsTogether(Scene):
)[1]
for alt_x in (x - dx, x, x + dx)
]
d2y = ry - 2 * y + ly
return d2y / (dx**2)
# At the boundary, don't return the second deriv,
# but instead something matching the Neumann
# boundary condition.
if x == x_max:
return (ly - y) / dx
elif x == x_min:
return (ry - y) / dx
else:
d2y = ry - 2 * y + ly
return d2y / (dx**2)
def get_rod(self, x_min, x_max, n_pieces=None):
if n_pieces is None:
@@ -407,7 +426,7 @@ class BringTwoRodsTogether(Scene):
self.rod_point_to_color(piece.get_right()),
])
def rod_point_to_color(self, point):
def rod_point_to_graph_y(self, point):
axes = self.axes
x = axes.x_axis.p2n(point)
@@ -417,11 +436,19 @@ class BringTwoRodsTogether(Scene):
self.graph_x_max,
x,
)
y = axes.y_axis.p2n(
return axes.y_axis.p2n(
graph.point_from_proportion(alpha)
)
return temperature_to_color(
(y - 45) / 45
def y_to_color(self, y):
y_max = self.max_temp
y_min = self.min_temp
alpha = inverse_interpolate(y_min, y_max, y)
return temperature_to_color(interpolate(-0.8, 0.8, alpha))
def rod_point_to_color(self, point):
return self.y_to_color(
self.rod_point_to_graph_y(point)
)
@@ -450,6 +477,7 @@ class ShowEvolvingTempGraphWithArrows(BringTwoRodsTogether):
self.add_clock()
self.add_rod()
self.add_arrows()
self.initialize_updaters()
self.let_play()
def add_axes(self):
@@ -467,7 +495,10 @@ class ShowEvolvingTempGraphWithArrows(BringTwoRodsTogether):
self.time_label.next_to(self.clock, DOWN)
def add_rod(self):
rod = self.rod = self.get_rod(0, 10)
rod = self.rod = self.get_rod(
self.graph_x_min,
self.graph_x_max,
)
self.add(rod)
def add_arrows(self):
@@ -504,24 +535,25 @@ class ShowEvolvingTempGraphWithArrows(BringTwoRodsTogether):
self.add(arrows)
self.arrows = arrows
def initialize_updaters(self):
if hasattr(self, "graph"):
self.graph.add_updater(self.update_graph)
if hasattr(self, "rod"):
self.rod.add_updater(self.color_rod_by_graph)
if hasattr(self, "time_label"):
self.time_label.add_updater(
lambda d, dt: d.increment_value(dt)
)
def let_play(self):
graph = self.graph
rod = self.rod
clock = self.clock
time_label = self.time_label
self.run_clock(self.wait_time)
graph.add_updater(self.update_graph)
time_label.add_updater(
lambda d, dt: d.increment_value(dt)
)
rod.add_updater(self.color_rod_by_graph)
# return
def run_clock(self, time):
self.play(
ClockPassesTime(
clock,
run_time=self.wait_time,
hours_passed=self.wait_time,
self.clock,
run_time=time,
hours_passed=time,
),
)

View File

@@ -1,5 +1,5 @@
from manimlib.imports import *
from active_projects.ode.part2.wordy_scenes import WriteHeatEquationTemplate
from active_projects.diffyq.part2.wordy_scenes import WriteHeatEquationTemplate
class ReactionsToInitialHeatEquation(PiCreatureScene):

View File

@@ -1,5 +1,5 @@
from manimlib.imports import *
from active_projects.ode.part1.staging import TourOfDifferentialEquations
from active_projects.diffyq.part1.staging import TourOfDifferentialEquations
class PartTwoOfTour(TourOfDifferentialEquations):
@@ -210,7 +210,7 @@ class BlackScholes(AltBrownianMotion):
self.wait(self.wait_time)
def add_title(self):
title = TextMobject("Black-Sholes equations")
title = TextMobject("Black-Scholes equations")
title.scale(1.5)
title.next_to(2 * UP, UP)
@@ -235,7 +235,7 @@ class BlackScholes(AltBrownianMotion):
x_max=20,
y_min=0,
y_max=10,
number_line_config={
axis_config={
"unit_size": 0.5,
},
)

View File

@@ -0,0 +1,303 @@
from manimlib.imports import *
from active_projects.diffyq.part2.heat_equation import *
class ShowNewRuleAtDiscreteBoundary(DiscreteSetup):
CONFIG = {
"axes_config": {
"x_min": 0,
"stroke_width": 1,
"x_axis_config": {
"include_tip": False,
},
},
"freq_amplitude_pairs": [
(1, 0.5),
(2, 1),
(3, 0.5),
(4, 0.3),
],
"v_line_class": DashedLine,
"v_line_config": {
},
"step_size": 1,
"wait_time": 15,
"alpha": 0.25,
}
def construct(self):
self.add_axes()
self.set_points()
self.show_boundary_point_influenced_by_neighbor()
self.add_clock()
self.let_evolve()
def set_points(self):
axes = self.axes
for mob in axes.family_members_with_points():
if isinstance(mob, Line):
mob.set_stroke(width=1)
step_size = self.step_size
xs = np.arange(
axes.x_min,
axes.x_max + step_size,
step_size
)
dots = self.dots = self.get_dots(axes, xs)
self.v_lines = self.get_v_lines(dots)
self.rod_pieces = self.get_rod_pieces(dots)
# rod_pieces
self.add(self.dots)
self.add(self.v_lines)
self.add(self.rod_pieces)
def show_boundary_point_influenced_by_neighbor(self):
dots = self.dots
ld = dots[0]
ld_in = dots[1]
rd = dots[-1]
rd_in = dots[-2]
v_len = 0.75
l_arrow = Vector(v_len * LEFT)
l_arrow.move_to(ld.get_left(), RIGHT)
r_arrow = Vector(v_len * RIGHT)
r_arrow.move_to(rd.get_right(), LEFT)
arrows = VGroup(l_arrow, r_arrow)
q_marks = VGroup(*[
TexMobject("?").scale(1.5).next_to(
arrow, arrow.get_vector()
)
for arrow in arrows
])
arrows.set_color(YELLOW)
q_marks.set_color(YELLOW)
blocking_rects = VGroup(*[
BackgroundRectangle(VGroup(
*dots[i:-i],
*self.rod_pieces[i:-i]
))
for i in [1, 2]
])
for rect in blocking_rects:
rect.stretch(1.1, dim=1, about_edge=UP)
self.play(FadeIn(blocking_rects[0]))
self.play(
LaggedStartMap(ShowCreation, arrows),
LaggedStart(*[
FadeInFrom(q_mark, -arrow.get_vector())
for q_mark, arrow in zip(q_marks, arrows)
]),
run_time=1.5
)
self.wait()
# Point to inward neighbor
new_arrows = VGroup(*[
Arrow(
d1.get_center(),
VGroup(d1, d2).get_center(),
buff=0,
).match_style(l_arrow)
for d1, d2 in [(ld, ld_in), (rd, rd_in)]
])
new_arrows.match_style(arrows)
l_brace = Brace(VGroup(ld, ld_in), DOWN)
r_brace = Brace(VGroup(rd, rd_in), DOWN)
braces = VGroup(l_brace, r_brace)
for brace in braces:
brace.align_to(
self.axes.x_axis.get_center(), UP
)
brace.shift(SMALL_BUFF * DOWN)
brace.add(brace.get_tex("\\Delta x"))
self.play(
ReplacementTransform(arrows, new_arrows),
FadeOut(q_marks),
ReplacementTransform(*blocking_rects)
)
self.wait()
self.play(FadeInFrom(braces, UP))
self.wait()
self.play(
FadeOut(new_arrows),
FadeOut(blocking_rects[1]),
FadeOut(braces),
)
def add_clock(self):
super().add_clock()
self.time_label.add_updater(
lambda d, dt: d.increment_value(dt)
)
VGroup(
self.clock,
self.time_label
).shift(2 * LEFT)
def let_evolve(self):
dots = self.dots
dots.add_updater(self.update_dots)
wait_time = self.wait_time
self.play(
ClockPassesTime(
self.clock,
run_time=wait_time,
hours_passed=wait_time,
),
)
#
def get_dots(self, axes, xs):
dots = VGroup(*[
Dot(axes.c2p(x, self.temp_func(x, 0)))
for x in xs
])
max_width = 0.8 * self.step_size
for dot in dots:
dot.add_updater(self.update_dot_color)
if dot.get_width() > max_width:
dot.set_width(max_width)
return dots
def get_v_lines(self, dots):
return always_redraw(lambda: VGroup(*[
self.get_v_line(dot)
for dot in dots
]))
def get_v_line(self, dot):
x_axis = self.axes.x_axis
bottom = dot.get_bottom()
x = x_axis.p2n(bottom)
proj_point = x_axis.n2p(x)
return self.v_line_class(
proj_point, bottom,
**self.v_line_config,
)
def get_rod_pieces(self, dots):
axis = self.axes.x_axis
factor = 1 - np.exp(-(0.8 / self.step_size)**2)
width = factor * self.step_size
pieces = VGroup()
for dot in dots:
piece = Line(ORIGIN, width * RIGHT)
piece.set_stroke(width=5)
piece.move_to(dot)
piece.set_y(axis.get_center()[1])
piece.dot = dot
piece.add_updater(
lambda p: p.match_color(p.dot)
)
pieces.add(piece)
return pieces
def update_dot_color(self, dot):
y = self.axes.y_axis.p2n(dot.get_center())
dot.set_color(self.y_to_color(y))
def update_dots(self, dots, dt):
for ds in zip(dots, dots[1:], dots[2:]):
points = [d.get_center() for d in ds]
x0, x1, x2 = [p[0] for p in points]
dx = x1 - x0
y0, y1, y2 = [p[1] for p in points]
self.update_dot(
dot=ds[1],
dt=dt,
mean_diff=0.5 * (y2 - 2 * y1 + y0) / dx
)
if ds[0] is dots[0]:
self.update_dot(
dot=ds[0],
dt=dt,
mean_diff=(y1 - y0) / dx
)
elif ds[-1] is dots[-1]:
self.update_dot(
dot=ds[-1],
dt=dt,
mean_diff=(y1 - y2) / dx
)
def update_dot(self, dot, dt, mean_diff):
dot.shift(mean_diff * self.alpha * dt * UP)
class DiscreteEvolutionPoint25(ShowNewRuleAtDiscreteBoundary):
CONFIG = {
"step_size": 0.25,
"alpha": 0.5,
"wait_time": 30,
}
def construct(self):
self.add_axes()
self.set_points()
self.add_clock()
self.let_evolve()
class DiscreteEvolutionPoint1(DiscreteEvolutionPoint25):
CONFIG = {
"step_size": 0.1,
"v_line_config": {
"stroke_width": 1,
},
"wait_time": 30,
}
class FlatEdgesForDiscreteEvolution(DiscreteEvolutionPoint1):
CONFIG = {
"wait_time": 20,
"step_size": 0.1,
}
def let_evolve(self):
lines = VGroup(*[
Line(LEFT, RIGHT)
for x in range(2)
])
lines.set_width(1.5)
lines.set_stroke(WHITE, 5, opacity=0.5)
lines.add_updater(self.update_lines)
turn_animation_into_updater(
ShowCreation(lines, run_time=2)
)
self.add(lines)
super().let_evolve()
def update_lines(self, lines):
dots = self.dots
for line, dot in zip(lines, [dots[0], dots[-1]]):
line.move_to(dot)
class FlatEdgesForDiscreteEvolutionTinySteps(FlatEdgesForDiscreteEvolution):
CONFIG = {
"step_size": 0.025,
"wait_time": 10,
"v_line_class": Line,
"v_line_config": {
"stroke_opacity": 0.5,
}
}

View File

@@ -0,0 +1,175 @@
from manimlib.imports import *
from active_projects.diffyq.part2.wordy_scenes import *
class IveHeardOfThis(TeacherStudentsScene):
def construct(self):
point = VectorizedPoint()
point.move_to(3 * RIGHT + 2 * UP)
self.student_says(
"I've heard\\\\", "of this!",
student_index=1,
target_mode="hooray",
bubble_kwargs={
"height": 3,
"width": 3,
"direction": RIGHT,
},
run_time=1,
)
self.change_student_modes(
"thinking", "hooray", "thinking",
look_at_arg=point,
added_anims=[self.teacher.change, "happy"]
)
self.wait(3)
self.student_says(
"But who\\\\", "cares?",
student_index=1,
target_mode="maybe",
bubble_kwargs={
"direction": RIGHT,
"width": 3,
"height": 3,
},
run_time=1,
)
self.change_student_modes(
"pondering", "maybe", "pondering",
look_at_arg=point,
added_anims=[self.teacher.change, "guilty"]
)
self.wait(5)
class InFouriersShoes(PiCreatureScene, WriteHeatEquationTemplate):
def construct(self):
randy = self.pi_creature
fourier = ImageMobject("Joseph Fourier")
fourier.set_height(4)
fourier.next_to(randy, RIGHT, LARGE_BUFF)
fourier.align_to(randy, DOWN)
equation = self.get_d1_equation()
equation.next_to(fourier, UP, MED_LARGE_BUFF)
decades = list(range(1740, 2040, 20))
time_line = NumberLine(
x_min=decades[0],
x_max=decades[-1],
tick_frequency=1,
tick_size=0.05,
longer_tick_multiple=4,
unit_size=0.2,
numbers_with_elongated_ticks=decades,
numbers_to_show=decades,
decimal_number_config={
"group_with_commas": False,
},
stroke_width=2,
)
time_line.add_numbers()
time_line.move_to(ORIGIN, RIGHT)
time_line.to_edge(UP)
triangle = ArrowTip(start_angle=-90 * DEGREES)
triangle.set_height(0.25)
triangle.move_to(time_line.n2p(2019), DOWN)
triangle.set_color(WHITE)
self.play(FadeInFrom(fourier, 2 * LEFT))
self.play(randy.change, "pondering")
self.wait()
self.play(
DrawBorderThenFill(triangle, run_time=1),
FadeInFromDown(equation),
FadeIn(time_line),
)
self.play(
Animation(triangle),
ApplyMethod(
time_line.shift,
time_line.n2p(2019) - time_line.n2p(1822),
run_time=5
),
)
self.wait()
class SineCurveIsUnrealistic(TeacherStudentsScene):
def construct(self):
self.student_says(
"But that would\\\\never happen!",
student_index=1,
bubble_kwargs={
"direction": RIGHT,
"height": 3,
"width": 4,
},
target_mode="angry"
)
self.change_student_modes(
"guilty", "angry", "hesitant",
added_anims=[
self.teacher.change, "tease"
]
)
self.wait(3)
self.play(
RemovePiCreatureBubble(self.students[1]),
self.teacher.change, "raise_right_hand"
)
self.change_all_student_modes(
"pondering",
look_at_arg=3 * UP,
)
self.wait(5)
class IfOnly(TeacherStudentsScene):
def construct(self):
self.teacher_says(
"If only!",
target_mode="angry"
)
self.change_all_student_modes(
"confused",
look_at_arg=self.screen
)
self.wait(3)
class SoWeGotNowhere(TeacherStudentsScene):
def construct(self):
self.student_says(
"So we've gotten\\\\nowhere!",
target_mode="angry",
added_anims=[
self.teacher.change, "guilty"
]
)
self.change_all_student_modes("angry")
self.wait()
text = TexMobject(
"&\\text{Actually,}\\\\",
"&\\sin\\left({x}\\right)"
"e^{-\\alpha {t}}\\\\",
"&\\text{isn't far off.}",
tex_to_color_map={
"{x}": GREEN,
"{t}": YELLOW,
}
)
text.scale(0.8)
self.teacher_says(
text,
content_introduction_class=FadeIn,
bubble_kwargs={
"width": 4,
"height": 3.5,
}
)
self.change_all_student_modes(
"pondering",
look_at_arg=self.screen
)
self.wait(3)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,919 @@
from manimlib.imports import *
from active_projects.diffyq.part2.wordy_scenes import *
class ThreeMainObservations(Scene):
def construct(self):
fourier = ImageMobject("Joseph Fourier")
name = TextMobject("Joseph Fourier")
name.match_width(fourier)
name.next_to(fourier, DOWN, SMALL_BUFF)
fourier.add(name)
fourier.set_height(5)
fourier.to_corner(DR)
fourier.shift(LEFT)
bubble = ThoughtBubble(
direction=RIGHT,
height=3,
width=4,
)
bubble.move_tip_to(fourier.get_corner(UL) + 0.5 * DR)
observations = VGroup(
TextMobject(
"1)",
"Sine = Nice",
),
TextMobject(
"2)",
"Linearity"
),
TextMobject(
"3)",
"Fourier series"
),
)
# heart = SuitSymbol("hearts")
# heart.replace(observations[0][2])
# observations[0][2].become(heart)
# observations[0][1].add(happiness)
# observations[2][2].align_to(
# observations[2][1], LEFT,
# )
observations.arrange(
DOWN,
aligned_edge=LEFT,
buff=2 * LARGE_BUFF,
)
observations.set_height(FRAME_HEIGHT - 2)
observations.to_corner(UL, buff=LARGE_BUFF)
self.add(fourier)
self.play(ShowCreation(bubble))
self.wait()
self.play(LaggedStart(*[
TransformFromCopy(bubble, observation[0])
for observation in observations
], lag_ratio=0.2))
self.play(
FadeOut(fourier),
FadeOut(bubble),
)
self.wait()
for obs in observations:
self.play(FadeInFrom(obs[1], LEFT))
self.wait()
class LastChapterWrapper(Scene):
def construct(self):
full_rect = FullScreenFadeRectangle(
fill_color=DARK_GREY,
fill_opacity=1,
)
rect = ScreenRectangle(height=6)
rect.set_stroke(WHITE, 2)
rect.set_fill(BLACK, 1)
title = TextMobject("Last chapter")
title.scale(2)
title.to_edge(UP)
rect.next_to(title, DOWN)
self.add(full_rect)
self.play(
FadeIn(rect),
Write(title, run_time=2),
)
self.wait()
class ThreeConstraints(WriteHeatEquationTemplate):
def construct(self):
self.cross_out_solving()
self.show_three_conditions()
def cross_out_solving(self):
equation = self.get_d1_equation()
words = TextMobject("Solve this equation")
words.to_edge(UP)
equation.next_to(words, DOWN)
cross = Cross(words)
self.add(words, equation)
self.wait()
self.play(ShowCreation(cross))
self.wait()
self.equation = equation
self.to_remove = VGroup(words, cross)
def show_three_conditions(self):
equation = self.equation
to_remove = self.to_remove
title = TexMobject(
"\\text{Constraints }"
"T({x}, {t})"
"\\text{ must satisfy:}",
**self.tex_mobject_config
)
title.to_edge(UP)
items = VGroup(
TextMobject("1)", "The PDE"),
TextMobject("2)", "Boundary condition"),
TextMobject("3)", "Initial condition"),
)
items.scale(0.7)
items.arrange(RIGHT, buff=LARGE_BUFF)
items.set_width(FRAME_WIDTH - 2)
items.next_to(title, DOWN, LARGE_BUFF)
items[1].set_color(MAROON_B)
items[2].set_color(RED)
bc_paren = TextMobject("(Explained soon)")
bc_paren.scale(0.7)
bc_paren.next_to(items[1], DOWN)
self.play(
FadeInFromDown(title),
FadeOutAndShift(to_remove, UP),
equation.scale, 0.6,
equation.next_to, items[0], DOWN,
equation.shift_onto_screen,
LaggedStartMap(FadeIn, [
items[0],
items[1][0],
items[2][0],
])
)
self.wait()
self.play(Write(items[1][1]))
bc_paren.match_y(equation)
self.play(FadeInFrom(bc_paren, UP))
self.wait(2)
self.play(Write(items[2][1]))
self.wait(2)
self.title = title
self.items = items
self.pde = equation
self.bc_paren = bc_paren
class RectAroundEquation(WriteHeatEquationTemplate):
def construct(self):
eq = self.get_d1_equation()
self.play(ShowCreationThenFadeAround(eq))
class BorderRect(Scene):
def construct(self):
rect = FullScreenFadeRectangle()
rect.set_stroke(WHITE, 3)
rect.set_fill(opacity=0)
self.add(rect)
class SeekIdealized(Scene):
def construct(self):
phrases = VGroup(*[
TextMobject(
"Seek", text, "problems",
tex_to_color_map={
"realistic": GREEN,
"{idealized}": YELLOW,
"over-idealized": YELLOW,
"general": BLUE,
}
)
for text in [
"realistic",
"{idealized}",
"over-idealized",
"general",
]
])
phrases.scale(2)
words = VGroup()
for phrase in phrases:
phrase.center()
word = phrase[1]
words.add(word)
phrase.remove(word)
arrow = Vector(DOWN)
arrow.set_stroke(WHITE, 6)
arrow.next_to(words[3], UP)
low_arrow = arrow.copy()
low_arrow.next_to(words[3], DOWN)
solutions = TextMobject("solutions")
solutions.scale(2)
solutions.move_to(phrases[3][1], UL)
models = TextMobject("models")
models.scale(2)
models.next_to(
words[0], RIGHT, buff=0.35,
aligned_edge=DOWN
)
phrases.center()
phrase = phrases[0]
self.add(phrase)
self.add(words[0])
self.wait()
words[0].save_state()
self.play(
words[0].to_edge, DOWN,
words[0].set_opacity, 0.5,
Transform(phrase, phrases[1]),
FadeInFrom(words[1], UP)
)
self.wait()
# self.play(
# words[1].move_to, words[2], RIGHT,
# FadeIn(words[2]),
# Transform(phrase, phrases[2])
# )
# self.wait()
self.play(
words[1].next_to, arrow, UP,
ShowCreation(arrow),
MaintainPositionRelativeTo(
phrase, words[1]
),
FadeInFrom(solutions, LEFT),
FadeIn(words[3]),
)
self.wait()
words[0].generate_target()
words[0].target.next_to(low_arrow, DOWN)
words[0].target.set_opacity(1)
models.shift(
words[0].target.get_center() -
words[0].saved_state.get_center()
)
self.play(
MoveToTarget(words[0]),
ShowCreation(low_arrow),
FadeInFrom(models, LEFT)
)
self.wait()
class SecondDerivativeOfSine(Scene):
def construct(self):
equation = TexMobject(
"{d^2 \\over d{x}^2}",
"\\cos\\left({x}\\right) =",
"-\\cos\\left({x}\\right)",
tex_to_color_map={
"{x}": GREEN,
}
)
self.add(equation)
class EquationAboveSineAnalysis(WriteHeatEquationTemplate):
def construct(self):
equation = self.get_d1_equation()
equation.to_edge(UP)
equation.shift(2 * LEFT)
eq_index = equation.index_of_part_by_tex("=")
lhs = equation[:eq_index]
eq = equation[eq_index]
rhs = equation[eq_index + 1:]
t_terms = equation.get_parts_by_tex("{t}")[1:]
t_terms.save_state()
zeros = VGroup(*[
TexMobject("0").replace(t, dim_to_match=1)
for t in t_terms
])
zeros.align_to(t_terms, DOWN)
new_rhs = TexMobject(
"=", "-\\alpha \\cdot {T}", "({x}, 0)",
**self.tex_mobject_config
)
# new_rhs.move_to(equation.get_right())
# new_rhs.next_to(equation, DOWN, MED_LARGE_BUFF)
# new_rhs.align_to(eq, LEFT)
new_rhs.next_to(equation, RIGHT)
new_rhs.shift(SMALL_BUFF * DOWN)
self.add(equation)
self.play(ShowCreationThenFadeAround(rhs))
self.wait()
self.play(
FadeOutAndShift(t_terms, UP),
FadeInFrom(zeros, DOWN),
)
t_terms.fade(1)
self.wait()
self.play(
# VGroup(equation, zeros).next_to,
# new_rhs, LEFT,
FadeIn(new_rhs),
)
self.wait()
self.play(
VGroup(
lhs[6:],
eq,
rhs,
new_rhs[0],
new_rhs[-3:],
zeros,
).fade, 0.5,
)
self.play(ShowCreationThenFadeAround(lhs[:6]))
self.play(ShowCreationThenFadeAround(new_rhs[1:-3]))
self.wait()
class ExpVideoWrapper(Scene):
def construct(self):
self.add(FullScreenFadeRectangle(
fill_color=DARKER_GREY,
fill_opacity=1,
))
screen = ImageMobject("eoc_chapter5_thumbnail")
screen.set_height(6)
rect = SurroundingRectangle(screen, buff=0)
rect.set_stroke(WHITE, 2)
screen.add(rect)
title = TextMobject("Need a refresher?")
title.scale(1.5)
title.to_edge(UP)
screen.next_to(title, DOWN)
screen.center()
self.play(
# FadeInFrom(title, LEFT),
FadeInFrom(screen, DOWN),
)
self.wait()
class ShowSinExpDerivatives(WriteHeatEquationTemplate):
CONFIG = {
"tex_mobject_config": {
"tex_to_color_map": {
"{0}": WHITE,
"\\partial": WHITE,
"=": WHITE,
}
}
}
def construct(self):
pde = self.get_d1_equation_without_inputs()
pde.to_edge(UP)
pde.generate_target()
new_rhs = TexMobject(
"=- \\alpha \\cdot T",
**self.tex_mobject_config,
)
new_rhs.next_to(pde, RIGHT)
new_rhs.align_to(pde.get_part_by_tex("alpha"), DOWN)
equation1 = TexMobject(
"T({x}, {0}) = \\sin\\left({x}\\right)",
**self.tex_mobject_config
)
equation2 = TexMobject(
"T({x}, {t}) = \\sin\\left({x}\\right)",
"e^{-\\alpha{t}}",
**self.tex_mobject_config
)
for eq in equation1, equation2:
eq.next_to(pde, DOWN, MED_LARGE_BUFF)
eq2_part1 = equation2[:len(equation1)]
eq2_part2 = equation2[len(equation1):]
# Rectangles
exp_rect = SurroundingRectangle(eq2_part2)
exp_rect.set_stroke(RED, 3)
sin_rect = SurroundingRectangle(
eq2_part1[-3:]
)
sin_rect.set_color(BLUE)
VGroup(pde.target, new_rhs).center().to_edge(UP)
# Show proposed solution
self.add(pde)
self.add(equation1)
self.wait()
self.play(
MoveToTarget(pde),
FadeInFrom(new_rhs, LEFT)
)
self.wait()
self.play(
ReplacementTransform(equation1, eq2_part1),
FadeIn(eq2_part2),
)
self.play(ShowCreation(exp_rect))
self.wait()
self.play(FadeOut(exp_rect))
# Take partial derivatives wrt x
q_mark = TexMobject("?")
q_mark.next_to(pde.get_part_by_tex("="), UP)
q_mark.set_color(RED)
arrow1 = Vector(3 * DOWN + 1 * RIGHT, color=WHITE)
arrow1.scale(1.2 / arrow1.get_length())
arrow1.next_to(
eq2_part2.get_corner(DL),
DOWN, MED_LARGE_BUFF
)
ddx_label1 = TexMobject(
"\\partial \\over \\partial {x}",
**self.tex_mobject_config,
)
ddx_label1.scale(0.7)
ddx_label1.next_to(
arrow1.point_from_proportion(0.8),
UR, SMALL_BUFF
)
pde_ddx = VGroup(
*pde.get_parts_by_tex("\\partial")[2:],
pde.get_parts_by_tex("\\over")[1],
pde.get_part_by_tex("{x}"),
)
pde_ddx_rect = SurroundingRectangle(pde_ddx)
pde_ddx_rect.set_color(GREEN)
eq2_part2_rect = SurroundingRectangle(eq2_part2)
dx = TexMobject(
"\\cos\\left({x}\\right)", "e^{-\\alpha {t}}",
**self.tex_mobject_config
)
ddx = TexMobject(
"-\\sin\\left({x}\\right)", "e^{-\\alpha {t}}",
**self.tex_mobject_config
)
dx.next_to(arrow1, DOWN)
dx.align_to(eq2_part2, RIGHT)
x_shift = arrow1.get_end()[0] - arrow1.get_start()[0]
x_shift *= 2
dx.shift(x_shift * RIGHT)
arrow2 = arrow1.copy()
arrow2.next_to(dx, DOWN)
arrow2.shift(MED_SMALL_BUFF * RIGHT)
dx_arrows = VGroup(arrow1, arrow2)
ddx_label2 = ddx_label1.copy()
ddx_label2.shift(
arrow2.get_center() - arrow1.get_center()
)
ddx.next_to(arrow2, DOWN)
ddx.align_to(eq2_part2, RIGHT)
ddx.shift(2 * x_shift * RIGHT)
rhs = equation2[-6:]
self.play(
FadeInFromDown(q_mark)
)
self.play(
ShowCreation(pde_ddx_rect)
)
self.wait()
self.play(
LaggedStart(
GrowArrow(arrow1),
GrowArrow(arrow2),
),
TransformFromCopy(
pde_ddx[0], ddx_label1
),
TransformFromCopy(
pde_ddx[0], ddx_label2
),
)
self.wait()
self.play(
TransformFromCopy(rhs, dx)
)
self.wait()
self.play(
FadeIn(eq2_part2_rect)
)
self.play(
Transform(
eq2_part2_rect,
SurroundingRectangle(dx[-3:])
)
)
self.play(
FadeOut(eq2_part2_rect)
)
self.wait()
self.play(
TransformFromCopy(dx, ddx)
)
self.play(
FadeIn(
SurroundingRectangle(ddx).match_style(
pde_ddx_rect
)
)
)
self.wait()
# Take partial derivative wrt t
pde_ddt = pde[:pde.index_of_part_by_tex("=") - 1]
pde_ddt_rect = SurroundingRectangle(pde_ddt)
dt_arrow = Arrow(
arrow1.get_start(),
arrow2.get_end() + RIGHT,
buff=0
)
dt_arrow.flip(UP)
dt_arrow.next_to(dx_arrows, LEFT, MED_LARGE_BUFF)
dt_label = TexMobject(
"\\partial \\over \\partial {t}",
**self.tex_mobject_config,
)
dt_label.scale(1)
dt_label.next_to(
dt_arrow.get_center(), UL,
SMALL_BUFF,
)
rhs_copy = rhs.copy()
rhs_copy.next_to(dt_arrow.get_end(), DOWN)
rhs_copy.shift(MED_LARGE_BUFF * LEFT)
rhs_copy.match_y(ddx)
minus_alpha_in_exp = rhs_copy[-3][1:].copy()
minus_alpha_in_exp.set_color(RED)
minus_alpha = TexMobject("-\\alpha")
minus_alpha.next_to(rhs_copy, LEFT)
minus_alpha.align_to(rhs_copy[0][0], DOWN)
dot = TexMobject("\\cdot")
dot.move_to(midpoint(
minus_alpha.get_right(),
rhs_copy.get_left(),
))
self.play(
TransformFromCopy(
pde_ddx_rect,
pde_ddt_rect,
)
)
self.play(
GrowArrow(dt_arrow),
TransformFromCopy(
pde_ddt,
dt_label,
)
)
self.wait()
self.play(TransformFromCopy(rhs, rhs_copy))
self.play(FadeIn(minus_alpha_in_exp))
self.play(
ApplyMethod(
minus_alpha_in_exp.replace, minus_alpha,
path_arc=TAU / 4
),
FadeIn(dot),
)
self.play(
FadeIn(minus_alpha),
FadeOut(minus_alpha_in_exp),
)
self.wait()
rhs_copy.add(minus_alpha, dot)
self.play(
FadeIn(SurroundingRectangle(rhs_copy))
)
self.wait()
#
checkmark = TexMobject("\\checkmark")
checkmark.set_color(GREEN)
checkmark.move_to(q_mark, DOWN)
self.play(
FadeInFromDown(checkmark),
FadeOutAndShift(q_mark, UP)
)
self.wait()
class DerivativesOfLinearFunction(WriteHeatEquationTemplate):
CONFIG = {
"tex_mobject_config": {
"tex_to_color_map": {
"{c}": WHITE,
}
}
}
def construct(self):
func = TexMobject(
"T({x}, {t}) = {c} \\cdot {x}",
**self.tex_mobject_config
)
dx_T = TexMobject("{c}", **self.tex_mobject_config)
ddx_T = TexMobject("0")
dt_T = TexMobject("0")
for mob in func, dx_T, ddx_T, dt_T:
mob.scale(1.5)
func.generate_target()
arrows = VGroup(*[
Vector(1.5 * RIGHT, color=WHITE)
for x in range(3)
])
dx_arrows = arrows[:2]
dt_arrow = arrows[2]
dt_arrow.rotate(-TAU / 4)
dx_group = VGroup(
func.target,
dx_arrows[0],
dx_T,
dx_arrows[1],
ddx_T,
)
dx_group.arrange(RIGHT)
for arrow, char, vect in zip(arrows, "xxt", [UP, UP, RIGHT]):
label = TexMobject(
"\\partial \\over \\partial {%s}" % char,
**self.tex_mobject_config
)
label.scale(0.7)
label.next_to(arrow.get_center(), vect)
arrow.add(label)
dt_arrow.shift(
func.target[-3:].get_bottom() + MED_SMALL_BUFF * DOWN -
dt_arrow.get_start(),
)
dt_T.next_to(dt_arrow.get_end(), DOWN)
self.play(FadeInFromDown(func))
self.wait()
self.play(
MoveToTarget(func),
LaggedStartMap(Write, dx_arrows),
run_time=1,
)
self.play(
TransformFromCopy(func[-3:], dx_T),
path_arc=-TAU / 4,
)
self.play(
TransformFromCopy(dx_T, ddx_T),
path_arc=-TAU / 4,
)
self.wait()
# dt
self.play(Write(dt_arrow))
self.play(
TransformFromCopy(func[-3:], dt_T)
)
self.wait()
class FlatAtBoundaryWords(Scene):
def construct(self):
words = self.get_bc_words()
self.play(Write(words))
self.wait()
def get_bc_words(self):
return TextMobject(
"Flat at boundary\\\\"
"for all", "${t}$", "$> 0$",
)
class WriteOutBoundaryCondition(FlatAtBoundaryWords, ThreeConstraints, MovingCameraScene):
def construct(self):
self.force_skipping()
ThreeConstraints.construct(self)
self.revert_to_original_skipping_status()
self.add_ic()
self.write_bc_words()
self.write_bc_equation()
def add_ic(self):
image = ImageMobject("temp_initial_condition_example")
image.set_width(3)
border = SurroundingRectangle(image, buff=SMALL_BUFF)
border.shift(SMALL_BUFF * UP)
border.set_stroke(WHITE, 2)
group = Group(image, border)
group.next_to(self.items[2], DOWN)
self.add(group)
def write_bc_words(self):
bc_paren = self.bc_paren
bc_words = self.get_bc_words()
bc_words.match_width(self.items[1][1])
bc_words.move_to(bc_paren, UP)
bc_words.set_color_by_tex("{t}", YELLOW)
self.play(ShowCreationThenFadeAround(
VGroup(self.items[0], self.pde)
))
self.play(
FadeOutAndShift(bc_paren, UP),
FadeInFrom(bc_words, DOWN),
)
self.wait()
self.bc_words = bc_words
def write_bc_equation(self):
bc_words = self.bc_words
equation = TexMobject(
"{\\partial {T} \\over \\partial {x}}(0, {t}) = ",
"{\\partial {T} \\over \\partial {x}}(L, {t}) = ",
"0",
**self.tex_mobject_config,
)
equation.next_to(bc_words, DOWN, MED_LARGE_BUFF)
self.play(
self.camera_frame.shift, 0.8 * DOWN,
)
self.play(FadeInFrom(equation, UP))
self.wait()
class HeatEquationFrame(WriteHeatEquationTemplate):
def construct(self):
equation = self.get_d1_equation()
equation.to_edge(UP, buff=MED_SMALL_BUFF)
ddx = equation[-11:]
dt = equation[:11]
full_rect = FullScreenFadeRectangle(
fill_color=DARK_GREY,
fill_opacity=1,
)
smaller_rect = ScreenRectangle(
height=6,
fill_color=BLACK,
fill_opacity=1,
stroke_color=WHITE,
stroke_width=2,
)
smaller_rect.next_to(equation, DOWN)
self.add(full_rect)
self.add(smaller_rect)
self.add(equation)
self.wait()
self.play(ShowCreationThenFadeAround(
ddx,
surrounding_rectangle_config={
"stroke_color": GREEN,
}
))
self.wait()
self.play(ShowCreationThenFadeAround(dt))
self.wait()
class CompareFreqDecays1to2(Scene):
CONFIG = {
"freqs": [1, 2]
}
def construct(self):
background = FullScreenFadeRectangle(
fill_color=DARKER_GREY,
fill_opacity=1,
)
screens = VGroup(*[
ScreenRectangle(
height=4,
fill_color=BLACK,
fill_opacity=1,
stroke_width=1,
stroke_color=WHITE,
)
for x in range(2)
])
screens.arrange(RIGHT)
screens.set_width(FRAME_WIDTH - 1)
formulas = VGroup(*[
self.get_formula(freq)
for freq in self.freqs
])
for formula, screen in zip(formulas, screens):
formula.next_to(screen, UP)
self.add(background)
self.add(screens)
self.add(formulas)
self.wait()
def get_formula(self, freq):
f_str = str(freq)
return TexMobject(
"\\cos\\left(%s \\cdot {x}\\right)" % f_str,
"e^{-\\alpha \\cdot %s^2 \\cdot {t}}" % f_str,
tex_to_color_map={
"{x}": GREEN,
"{t}": YELLOW,
f_str: MAROON_B,
}
)
class CompareFreqDecays1to4(CompareFreqDecays1to2):
CONFIG = {
"freqs": [1, 4],
}
class CompareFreqDecays2to4(CompareFreqDecays1to2):
CONFIG = {
"freqs": [2, 4],
}
class WorryAboutGenerality(TeacherStudentsScene, WriteHeatEquationTemplate):
def construct(self):
eq = self.get_d1_equation()
diffyq = self.get_diffyq_set()
is_in = TexMobject("\\in")
is_in.scale(2)
group = VGroup(eq, is_in, diffyq)
group.arrange(RIGHT, buff=MED_LARGE_BUFF)
group.to_edge(UP)
arrow = Vector(DOWN)
arrow.set_stroke(WHITE, 5)
arrow.next_to(eq, DOWN)
themes = TextMobject("Frequent themes")
themes.scale(1.5)
themes.next_to(arrow, DOWN)
self.play(
self.get_student_changes(
"sad", "tired", "pleading"
),
self.teacher.change, "raise_right_hand",
FadeInFromDown(eq)
)
self.play(Write(group[1:]))
self.wait(2)
self.play(
ShowCreation(arrow),
self.get_student_changes(*3 * ["pondering"]),
)
self.play(
FadeInFrom(themes, UP),
self.get_student_changes(*3 * ["thinking"]),
self.teacher.change, "happy"
)
self.wait(4)
# def get_d1_equation(self):
# result = super().get_d1_equation()
# lp, rp = parens = TexMobject("(", ")")
# parens.match_height(result)
# lp.next_to(result, LEFT, SMALL_BUFF)
# rp.next_to(result, RIGHT, SMALL_BUFF)
# result.add_to_back(lp)
# result.add(rp)
# return result
def get_diffyq_set(self):
words = TextMobject(
"Differential\\\\equations"
)
words.scale(1.5)
words.set_color(BLUE)
lb = Brace(words, LEFT)
rb = Brace(words, RIGHT)
return VGroup(lb, words, rb)

View File

@@ -0,0 +1,712 @@
from manimlib.imports import *
class GeneralizeToComplexFunctions(Scene):
CONFIG = {
"axes_config": {
"x_min": 0,
"x_max": 10,
"x_axis_config": {
"stroke_width": 2,
},
"y_min": -2.5,
"y_max": 2.5,
"y_axis_config": {
"tick_frequency": 0.25,
"unit_size": 1.5,
"include_tip": False,
"stroke_width": 2,
},
},
"complex_plane_config": {
"axis_config": {
"unit_size": 2
}
},
}
def construct(self):
self.show_cosine_wave()
self.transition_to_complex_plane()
self.add_rotating_vectors_making_cos()
def show_cosine_wave(self):
axes = Axes(**self.axes_config)
axes.shift(2 * LEFT - axes.c2p(0, 0))
y_axis = axes.y_axis
y_labels = y_axis.get_number_mobjects(
*range(-2, 3),
number_config={"num_decimal_places": 1},
)
t_tracker = ValueTracker(0)
t_tracker.add_updater(lambda t, dt: t.increment_value(dt))
get_t = t_tracker.get_value
def func(x):
return 2 * np.cos(x)
cos_x_max = 20
cos_wave = axes.get_graph(func, x_max=cos_x_max)
cos_wave.set_color(YELLOW)
shown_cos_wave = cos_wave.copy()
shown_cos_wave.add_updater(
lambda m: m.pointwise_become_partial(
cos_wave, 0,
np.clip(get_t() / cos_x_max, 0, 1),
),
)
dot = Dot()
dot.set_color(PINK)
dot.add_updater(lambda d: d.move_to(
y_axis.n2p(func(get_t())),
))
h_line = always_redraw(lambda: Line(
dot.get_right(),
shown_cos_wave.get_end(),
stroke_width=1,
))
real_words = TextMobject(
"Real number\\\\output"
)
real_words.to_edge(LEFT)
real_words.shift(2 * UP)
real_arrow = Arrow()
real_arrow.add_updater(
lambda m: m.put_start_and_end_on(
real_words.get_corner(DR),
dot.get_center(),
).scale(0.9),
)
self.add(t_tracker)
self.add(axes)
self.add(y_labels)
self.add(shown_cos_wave)
self.add(dot)
self.add(h_line)
self.wait(2)
self.play(
FadeInFrom(real_words, RIGHT),
FadeIn(real_arrow),
)
self.wait(5)
y_axis.generate_target()
y_axis.target.rotate(-90 * DEGREES)
y_axis.target.center()
y_axis.target.scale(2 / 1.5)
y_labels.generate_target()
for label in y_labels.target:
label.next_to(
y_axis.target.n2p(label.get_value()),
DOWN, MED_SMALL_BUFF,
)
self.play(
FadeOut(shown_cos_wave),
FadeOut(axes.x_axis),
FadeOut(h_line),
)
self.play(
MoveToTarget(y_axis),
MoveToTarget(y_labels),
real_words.shift, 2 * RIGHT + UP,
)
self.wait()
self.y_axis = y_axis
self.y_labels = y_labels
self.real_words = real_words
self.real_arrow = real_arrow
self.dot = dot
self.t_tracker = t_tracker
def transition_to_complex_plane(self):
y_axis = self.y_axis
y_labels = self.y_labels
plane = self.get_complex_plane()
plane_words = plane.label
self.add(plane, *self.get_mobjects())
self.play(
FadeOut(y_labels),
FadeOut(y_axis),
ShowCreation(plane),
)
self.play(Write(plane_words))
self.wait()
self.plane = plane
self.plane_words = plane_words
def add_rotating_vectors_making_cos(self):
plane = self.plane
real_words = self.real_words
real_arrow = self.real_arrow
t_tracker = self.t_tracker
get_t = t_tracker.get_value
v1 = Vector(2 * RIGHT)
v2 = Vector(2 * RIGHT)
v1.set_color(BLUE)
v2.set_color(interpolate_color(GREY_BROWN, WHITE, 0.5))
v1.add_updater(
lambda v: v.set_angle(get_t())
)
v2.add_updater(
lambda v: v.set_angle(-get_t())
)
v1.add_updater(
lambda v: v.shift(plane.n2p(0) - v.get_start())
)
# Change?
v2.add_updater(
lambda v: v.shift(plane.n2p(0) - v.get_start())
)
ghost_v1 = v1.copy()
ghost_v1.set_opacity(0.5)
ghost_v1.add_updater(
lambda v: v.shift(
v2.get_end() - v.get_start()
)
)
ghost_v2 = v2.copy()
ghost_v2.set_opacity(0.5)
ghost_v2.add_updater(
lambda v: v.shift(
v1.get_end() - v.get_start()
)
)
circle = Circle(color=GREY_BROWN)
circle.set_stroke(width=1)
circle.set_width(2 * v1.get_length())
circle.move_to(plane.n2p(0))
formula = TexMobject(
# "\\cos(x) ="
# "{1 \\over 2}e^{ix} +"
# "{1 \\over 2}e^{-ix}",
"2\\cos(x) =",
"e^{ix}", "+", "e^{-ix}",
tex_to_color_map={
"e^{ix}": v1.get_color(),
"e^{-ix}": v2.get_color(),
}
)
formula.next_to(ORIGIN, UP, buff=0.75)
# formula.add_background_rectangle()
formula.set_stroke(BLACK, 3, background=True)
formula.to_edge(LEFT, buff=MED_SMALL_BUFF)
formula_brace = Brace(formula[1:], UP)
formula_words = formula_brace.get_text(
"Sum of\\\\rotations"
)
formula_words.set_stroke(BLACK, 3, background=True)
randy = Randolph()
randy.to_corner(DL)
randy.look_at(formula)
self.play(
FadeOut(real_words),
FadeOut(real_arrow),
)
self.play(
FadeIn(v1),
FadeIn(v2),
FadeIn(circle),
FadeIn(ghost_v1),
FadeIn(ghost_v2),
)
self.wait(3)
self.play(FadeInFromDown(formula))
self.play(
GrowFromCenter(formula_brace),
FadeIn(formula_words),
)
self.wait(2)
self.play(FadeIn(randy))
self.play(randy.change, "pleading")
self.play(Blink(randy))
self.wait()
self.play(randy.change, "confused")
self.play(Blink(randy))
self.wait()
self.play(FadeOut(randy))
self.wait(20)
#
def get_complex_plane(self):
plane = ComplexPlane(**self.complex_plane_config)
plane.add_coordinates()
plane.label = TextMobject("Complex plane")
plane.label.scale(1.5)
plane.label.to_corner(UR, buff=MED_SMALL_BUFF)
return plane
class ClarifyInputAndOutput(GeneralizeToComplexFunctions):
CONFIG = {
"input_space_rect_config": {
"stroke_color": WHITE,
"stroke_width": 1,
"fill_color": DARKER_GREY,
"fill_opacity": 1,
"width": 6,
"height": 2,
},
}
def construct(self):
self.setup_plane()
self.setup_input_space()
self.setup_input_trackers()
self.describe_input()
self.describe_output()
def setup_plane(self):
plane = self.get_complex_plane()
plane.sublabel = TextMobject("(Output space)")
plane.sublabel.add_background_rectangle()
plane.sublabel.next_to(plane.label, DOWN)
self.add(plane, plane.label)
self.plane = plane
def setup_input_space(self):
rect = Rectangle(**self.input_space_rect_config)
rect.to_corner(UL, buff=SMALL_BUFF)
input_line = self.get_input_line(rect)
input_words = TextMobject("Input space")
input_words.next_to(
rect.get_bottom(), UP,
SMALL_BUFF,
)
self.add(rect)
self.add(input_line)
self.input_rect = rect
self.input_line = input_line
self.input_words = input_words
def setup_input_trackers(self):
plane = self.plane
input_line = self.input_line
input_tracker = ValueTracker(0)
get_input = input_tracker.get_value
input_dot = Dot()
input_dot.set_color(PINK)
f_always(
input_dot.move_to,
lambda: input_line.n2p(get_input())
)
input_decimal = DecimalNumber()
input_decimal.scale(0.7)
always(input_decimal.next_to, input_dot, UP)
f_always(input_decimal.set_value, get_input)
path = self.get_path()
def get_output_point():
return path.point_from_proportion(
get_input()
)
output_dot = Dot()
output_dot.match_style(input_dot)
f_always(output_dot.move_to, get_output_point)
output_vector = Vector()
output_vector.set_color(WHITE)
output_vector.add_updater(
lambda v: v.put_start_and_end_on(
plane.n2p(0),
get_output_point()
)
)
output_decimal = DecimalNumber()
output_decimal.scale(0.7)
always(output_decimal.next_to, output_dot, UR, SMALL_BUFF)
f_always(
output_decimal.set_value,
lambda: plane.p2n(get_output_point()),
)
self.input_tracker = input_tracker
self.input_dot = input_dot
self.input_decimal = input_decimal
self.path = path
self.output_dot = output_dot
self.output_vector = output_vector
self.output_decimal = output_decimal
def describe_input(self):
input_tracker = self.input_tracker
self.play(FadeInFrom(self.input_words, UP))
self.play(
FadeInFromLarge(self.input_dot),
FadeIn(self.input_decimal),
)
for value in 1, 0:
self.play(
input_tracker.set_value, value,
run_time=2
)
self.wait()
def describe_output(self):
path = self.path
output_dot = self.output_dot
output_decimal = self.output_decimal
input_dot = self.input_dot
input_tracker = self.input_tracker
plane = self.plane
real_line = plane.x_axis.copy()
real_line.set_stroke(RED, 4)
real_words = TextMobject("Real number line")
real_words.next_to(ORIGIN, UP)
real_words.to_edge(RIGHT)
traced_path = TracedPath(output_dot.get_center)
traced_path.match_style(path)
self.play(
ShowCreation(real_line),
FadeInFrom(real_words, DOWN)
)
self.play(
FadeOut(real_line),
FadeOut(real_words),
)
self.play(
FadeInFrom(plane.sublabel, UP)
)
self.play(
FadeIn(output_decimal),
TransformFromCopy(input_dot, output_dot),
)
kw = {
"run_time": 10,
"rate_func": lambda t: smooth(t, 1),
}
self.play(
ApplyMethod(input_tracker.set_value, 1, **kw),
ShowCreation(path.copy(), remover=True, **kw),
)
self.add(path)
self.add(output_dot)
self.wait()
# Flatten to 1d
real_function_word = TextMobject(
"Real-valued function"
)
real_function_word.next_to(ORIGIN, DOWN, MED_LARGE_BUFF)
path.generate_target()
path.target.stretch(0, 1)
path.target.move_to(plane.n2p(0))
self.play(
FadeIn(real_function_word),
MoveToTarget(path),
)
input_tracker.set_value(0)
self.play(
input_tracker.set_value, 1,
**kw
)
#
def get_input_line(self, input_rect):
input_line = UnitInterval()
input_line.move_to(input_rect)
input_line.shift(0.25 * UP)
input_line.set_width(
input_rect.get_width() - 1
)
input_line.add_numbers(0, 0.5, 1)
return input_line
def get_path(self):
# mob = SVGMobject("BatmanLogo")
mob = TexMobject("\\pi")
path = mob.family_members_with_points()[0]
path.set_height(3.5)
path.move_to(2 * DOWN, DOWN)
path.set_stroke(YELLOW, 2)
path.set_fill(opacity=0)
return path
class GraphForFlattenedPi(ClarifyInputAndOutput):
CONFIG = {
"camera_config": {"background_color": DARKER_GREY},
}
def construct(self):
self.setup_plane()
plane = self.plane
self.remove(plane, plane.label)
path = self.get_path()
axes = Axes(
x_min=0,
x_max=1,
x_axis_config={
"unit_size": 7,
"include_tip": False,
"tick_frequency": 0.1,
},
y_min=-1.5,
y_max=1.5,
y_axis_config={
"include_tip": False,
"unit_size": 2.5,
"tick_frequency": 0.5,
},
)
axes.set_width(FRAME_WIDTH - 1)
axes.set_height(FRAME_HEIGHT - 1, stretch=True)
axes.center()
axes.x_axis.add_numbers(
0.5, 1.0,
number_config={"num_decimal_places": 1},
)
axes.y_axis.add_numbers(
-1.0, 1.0,
number_config={"num_decimal_places": 1},
)
def func(t):
return plane.x_axis.p2n(
path.point_from_proportion(t)
)
graph = axes.get_graph(func)
graph.set_color(PINK)
v_line = always_redraw(lambda: Line(
axes.x_axis.n2p(axes.x_axis.p2n(graph.get_end())),
graph.get_end(),
stroke_width=1,
))
self.add(axes)
self.add(v_line)
kw = {
"run_time": 10,
"rate_func": lambda t: smooth(t, 1),
}
self.play(ShowCreation(graph, **kw))
self.wait()
class SimpleComplexExponentExample(ClarifyInputAndOutput):
CONFIG = {
"input_space_rect_config": {
"width": 14,
"height": 1.5,
},
"input_line_config": {
"unit_size": 0.5,
"x_min": 0,
"x_max": 25,
"stroke_width": 2,
},
"input_numbers": range(0, 30, 5),
"input_tex_args": ["t", "="],
}
def construct(self):
self.setup_plane()
self.setup_input_space()
self.setup_input_trackers()
self.setup_output_trackers()
# Testing
time = self.input_line.x_max
self.play(
self.input_tracker.set_value, time,
run_time=time,
rate_func=linear,
)
def setup_plane(self):
plane = ComplexPlane()
plane.scale(2)
plane.add_coordinates()
plane.shift(DOWN)
self.plane = plane
self.add(plane)
def setup_input_trackers(self):
input_line = self.input_line
input_tracker = ValueTracker(0)
get_input = input_tracker.get_value
input_tip = ArrowTip(start_angle=-TAU / 4)
input_tip.scale(0.5)
input_tip.set_color(PINK)
f_always(
input_tip.move_to,
lambda: input_line.n2p(get_input()),
lambda: DOWN,
)
input_label = VGroup(
TexMobject(*self.input_tex_args),
DecimalNumber(),
)
input_label[0].set_color_by_tex("t", PINK)
input_label.scale(0.7)
input_label.add_updater(
lambda m: m.arrange(RIGHT, buff=SMALL_BUFF)
)
input_label.add_updater(
lambda m: m[1].set_value(get_input())
)
input_label.add_updater(
lambda m: m.next_to(input_tip, UP, SMALL_BUFF)
)
self.input_tracker = input_tracker
self.input_tip = input_tip
self.input_label = input_label
self.add(input_tip, input_label)
def setup_output_trackers(self):
plane = self.plane
get_input = self.input_tracker.get_value
def get_output():
return np.exp(complex(0, get_input()))
def get_output_point():
return plane.n2p(get_output())
output_label, static_output_label = [
TexMobject(
"e^{i t}" + s,
tex_to_color_map={"t": PINK},
background_stroke_width=3,
)
for s in ["", "\\approx"]
]
output_label.scale(1.2)
output_label.add_updater(
lambda m: m.shift(
-m.get_bottom() +
get_output_point() +
rotate_vector(
0.35 * RIGHT,
get_input(),
)
)
)
output_vector = Vector()
output_vector.set_opacity(0.75)
output_vector.add_updater(
lambda m: m.put_start_and_end_on(
plane.n2p(0), get_output_point(),
)
)
t_max = 40
full_output_path = ParametricFunction(
lambda t: plane.n2p(np.exp(complex(0, t))),
t_min=0,
t_max=t_max
)
output_path = VMobject()
output_path.set_stroke(YELLOW, 2)
output_path.add_updater(
lambda m: m.pointwise_become_partial(
full_output_path,
0, get_input() / t_max,
)
)
static_output_label.next_to(plane.c2p(1, 1), UR)
output_decimal = DecimalNumber(
include_sign=True,
)
output_decimal.scale(0.8)
output_decimal.set_stroke(BLACK, 3, background=True)
output_decimal.add_updater(
lambda m: m.set_value(get_output())
)
output_decimal.add_updater(
lambda m: m.next_to(
static_output_label,
RIGHT, 2 * SMALL_BUFF,
aligned_edge=DOWN,
)
)
self.add(output_path)
self.add(output_vector)
self.add(output_label)
self.add(static_output_label)
self.add(BackgroundRectangle(output_decimal))
self.add(output_decimal)
#
def get_input_line(self, input_rect):
input_line = NumberLine(**self.input_line_config)
input_line.move_to(input_rect)
input_line.set_width(
input_rect.get_width() - 1.5,
stretch=True,
)
input_line.add_numbers(*self.input_numbers)
return input_line
class TRangingFrom0To1(SimpleComplexExponentExample):
CONFIG = {
"input_space_rect_config": {
"width": 6,
"height": 2,
},
}
def construct(self):
self.setup_input_space()
self.setup_input_trackers()
self.play(
self.input_tracker.set_value, 1,
run_time=10,
rate_func=linear
)
def get_input_line(self, rect):
result = ClarifyInputAndOutput.get_input_line(self, rect)
result.stretch(0.9, 0)
result.set_stroke(width=2)
for sm in result.get_family():
if isinstance(sm, DecimalNumber):
sm.stretch(1 / 0.9, 0)
sm.set_stroke(width=0)
return result

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,242 @@
from manimlib.imports import *
from active_projects.diffyq.part4.fourier_series_scenes import ComplexFourierSeriesExample
from manimlib.once_useful_constructs.fractals import HilbertCurve
class FourierSeriesExampleWithRectForZoom(ComplexFourierSeriesExample):
CONFIG = {
"n_vectors": 100,
"slow_factor": 0.01,
"rect_scale_factor": 0.1,
"start_drawn": True,
"drawing_height": 7,
"rect_stroke_width": 1,
}
def construct(self):
self.add_vectors_circles_path()
self.circles.set_stroke(opacity=0.5)
rect = self.rect = self.get_rect()
rect.set_height(self.rect_scale_factor * FRAME_HEIGHT)
rect.add_updater(lambda m: m.move_to(
self.get_rect_center()
))
self.add(rect)
self.run_one_cycle()
def get_rect_center(self):
return center_of_mass([
v.get_end()
for v in self.vectors
])
def get_rect(self):
return ScreenRectangle(
color=BLUE,
stroke_width=self.rect_stroke_width,
)
class ZoomedInFourierSeriesExample(FourierSeriesExampleWithRectForZoom, MovingCameraScene):
CONFIG = {
"vector_config": {
"max_tip_length_to_length_ratio": 0.15,
"tip_length": 0.05,
},
"parametric_function_step_size": 0.001,
}
def setup(self):
ComplexFourierSeriesExample.setup(self)
MovingCameraScene.setup(self)
def get_rect(self):
return self.camera_frame
def add_vectors_circles_path(self):
super().add_vectors_circles_path()
for v in self.vectors:
if v.get_stroke_width() < 1:
v.set_stroke(width=1)
class ZoomedInFourierSeriesExample100x(ZoomedInFourierSeriesExample):
CONFIG = {
"vector_config": {
"max_tip_length_to_length_ratio": 0.15 * 0.4,
"tip_length": 0.05 * 0.2,
"max_stroke_width_to_length_ratio": 80,
"stroke_width": 3,
},
"max_circle_stroke_width": 0.5,
"rect_scale_factor": 0.01,
# "parametric_function_step_size": 0.01,
}
def get_rect_center(self):
return self.vectors[-1].get_end()
# def get_drawn_path(self, vectors, stroke_width=2, **kwargs):
# return self.get_path_end(vectors, stroke_width, **kwargs)
class TrebleClefFourierSeriesExampleWithRectForZoom(FourierSeriesExampleWithRectForZoom):
CONFIG = {
"file_name": "TrebleClef",
"drawn_path_stroke_width": 10,
}
class TrebleClefZoomedInFourierSeriesExample(ZoomedInFourierSeriesExample):
CONFIG = {
"file_name": "TrebleClef",
}
class NailAndGearFourierSeriesExampleWithRectForZoom(FourierSeriesExampleWithRectForZoom):
CONFIG = {
"file_name": "Nail_And_Gear",
"n_vectors": 200,
"drawn_path_color": "#39FF14",
}
class NailAndGearZoomedInFourierSeriesExample(ZoomedInFourierSeriesExample):
CONFIG = {
"file_name": "Nail_And_Gear",
"n_vectors": 200,
"drawn_path_color": "#39FF14",
}
class SigmaFourierSeriesExampleWithRectForZoom(FourierSeriesExampleWithRectForZoom):
CONFIG = {
"n_vectors": 200,
"drawn_path_color": PINK,
"rect_stroke_width": 0,
}
def get_shape(self):
return TexMobject("\\Sigma")
class SigmaZoomedInFourierSeriesExample(SigmaFourierSeriesExampleWithRectForZoom, ZoomedInFourierSeriesExample):
pass
class FourierOfFourier(FourierSeriesExampleWithRectForZoom):
CONFIG = {
"file_name": "FourierOneLine",
"n_vectors": 300,
"rect_stroke_width": 1,
}
class FourierOfFourierZoomedIn(ZoomedInFourierSeriesExample):
CONFIG = {
"file_name": "FourierOneLine",
"max_circle_stroke_width": 0.3,
"n_vectors": 300,
}
class FourierOfFourier100xZoom(ZoomedInFourierSeriesExample100x):
CONFIG = {
"file_name": "FourierOneLine",
"max_circle_stroke_width": 0.3,
"n_vectors": 300,
"slow_factor": 0.001,
}
def run_one_cycle(self):
self.vector_clock.set_value(0.3)
self.wait(40)
class FourierOfHilbert(FourierSeriesExampleWithRectForZoom):
CONFIG = {
"n_vectors": 300,
"rect_stroke_width": 1,
"drawn_path_stroke_width": 4,
"drawn_path_color": BLUE,
}
def get_path(self):
path = HilbertCurve(order=5)
path.set_height(self.drawing_height)
path.to_edge(DOWN)
combined_path = VMobject()
for sm in path.family_members_with_points():
combined_path.append_vectorized_mobject(sm)
start = combined_path.get_start()
end = combined_path.get_end()
points = [
interpolate(end, start, alpha)
for alpha in np.linspace(0, 1, 10)
]
for point in points:
combined_path.add_line_to(point)
combined_path.set_stroke(width=0)
return combined_path
class FourierOfHilbertZoomedIn(FourierOfHilbert, ZoomedInFourierSeriesExample):
pass
class FourierOfBritain(FourierSeriesExampleWithRectForZoom):
CONFIG = {
"file_name": "Britain",
"n_vectors": 500,
"drawn_path_color": RED,
}
class FourierOfBritainZoomedIn(FourierOfBritain, ZoomedInFourierSeriesExample):
pass
class FourierOfSeattle(FourierSeriesExampleWithRectForZoom):
CONFIG = {
"file_name": "SeattleSkyline",
"drawing_height": 7,
"n_vectors": 400,
"drawn_path_color": TEAL,
"drawn_path_stroke_width": 5,
}
class FourierOfSeattleZoomedIn(ZoomedInFourierSeriesExample):
CONFIG = {
"file_name": "SeattleSkyline",
"drawing_height": 7,
"n_vectors": 400,
"drawn_path_color": TEAL,
"drawn_path_stroke_width": 5,
"max_circle_stroke_width": 0.3,
}
class VideoWrapper(Scene):
def construct(self):
fade_rect = FullScreenFadeRectangle()
fade_rect.set_fill(DARK_GREY, 1)
screen_rect = ScreenRectangle()
screen_rect.set_height(4)
screen_rect.set_fill(BLACK, 1)
screen_rect.set_stroke(width=0)
boundary = AnimatedBoundary(screen_rect)
title = TextMobject("Learn the math")
title.scale(1.5)
title.next_to(screen_rect, UP)
self.add(fade_rect)
self.add(screen_rect)
self.add(boundary)
self.play(FadeInFromDown(title))
self.wait(19)

View File

@@ -0,0 +1,235 @@
from manimlib.imports import *
class WhyWouldYouCare(TeacherStudentsScene):
def construct(self):
self.student_says(
"Who cares!",
target_mode="sassy",
student_index=2,
added_anims=[self.teacher.change, "guilty"],
)
self.wait()
self.play(
RemovePiCreatureBubble(self.students[2]),
self.teacher.change, "raise_right_hand",
self.get_student_changes(
"pondering", "erm", "thinking",
look_at_arg=self.screen,
)
)
self.look_at(self.screen)
self.wait(5)
class SolveForWavesNothingElse(TeacherStudentsScene):
def construct(self):
self.student_says(
"Sure, we can\\\\solve it for\\\\sums of waves...",
target_mode="sassy",
student_index=2,
added_anims=[self.teacher.change, "guilty"]
)
self.change_student_modes("pondering", "pondering", "sassy")
self.look_at(self.screen)
self.wait(4)
self.student_says(
"But nothing else!",
target_mode="angry",
)
self.change_student_modes(
"concerned_musician",
"concerned_musician",
"angry",
)
self.wait(5)
class HangOnThere(TeacherStudentsScene):
def construct(self):
student = self.students[2]
axes1 = Axes(
x_min=0,
x_max=1,
y_min=-1.5,
y_max=1.5,
x_axis_config={
"tick_frequency": 0.25,
"include_tip": False,
"unit_size": 3,
},
y_axis_config={
"tick_frequency": 0.5,
"include_tip": False,
},
)
axes1.set_stroke(width=2)
axes2 = axes1.deepcopy()
neq = TexMobject("\\neq")
neq.scale(2)
group = VGroup(axes1, neq, axes2)
group.arrange(RIGHT)
group.set_height(4)
group.next_to(
student.get_corner(UL), UP,
buff=LARGE_BUFF,
)
step_graph = axes1.get_graph(
lambda x: (1 if x < 0.5 else -1),
discontinuities=[0.5],
)
step_graph.set_color(YELLOW)
wave_graphs = VGroup(*[
axes2.get_graph(
lambda x: (4 / PI) * np.sum([
(u / n) * np.cos(n * PI * x)
for u, n in zip(
it.cycle([1, -1]),
range(1, max_n, 2),
)
]),
)
for max_n in range(3, 103, 2)
])
wave_graphs.set_stroke(width=3)
wave_graphs.set_color_by_gradient(WHITE, PINK)
last_wave_graph = wave_graphs[-1]
last_wave_graph.set_stroke(PINK, 2)
wave_graphs.remove(last_wave_graph)
# wave_graphs[-1].set_stroke(width=3)
# wave_graphs[-1].set_stroke(BLACK, 5, background=True)
group.add(step_graph)
self.student_says(
"Hang on\\\\hang on\\\\hang on...",
target_mode="surprised",
content_introduction_class=FadeIn,
student_index=2,
added_anims=[
self.teacher.change, "guilty"
],
run_time=1,
)
self.wait()
self.play(
RemovePiCreatureBubble(
student,
target_mode="raise_left_hand",
look_at_arg=group,
),
FadeInFromDown(group),
)
last_wg = VectorizedPoint()
n_first_fades = 4
for wg in wave_graphs[:n_first_fades]:
self.play(
last_wg.set_stroke, {"width": 0.1},
FadeIn(wg),
)
last_wg = wg
self.play(
LaggedStart(
*[
UpdateFromAlphaFunc(
wg,
lambda m, a: m.set_stroke(
width=(3 * there_and_back(a) + 0.1 * a)
),
)
for wg in wave_graphs[n_first_fades:]
],
run_time=5,
lag_ratio=0.2,
),
ApplyMethod(
last_wg.set_stroke, {"width": 0.1},
run_time=0.25,
),
FadeIn(
last_wave_graph,
rate_func=squish_rate_func(smooth, 0.9, 1),
run_time=5,
),
self.teacher.change, "thinking",
)
self.change_student_modes(
"confused", "confused", "angry"
)
self.wait(3)
class YouSaidThisWasEasier(TeacherStudentsScene):
def construct(self):
self.change_all_student_modes(
"confused", look_at_arg=self.screen,
)
self.student_says(
"I'm sorry, you said\\\\this was easier?",
target_mode="sassy"
)
self.play(self.teacher.change, "guilty")
self.wait(3)
self.teacher_says(
"Bear with\\\\me",
bubble_kwargs={"height": 3, "width": 3},
)
self.look_at(self.screen)
self.wait(3)
class LooseWithLanguage(TeacherStudentsScene):
def construct(self):
terms = VGroup(
TextMobject("``Complex number''"),
TextMobject("``Vector''"),
)
colors = [YELLOW, BLUE]
for term, color in zip(terms, colors):
term.set_color(color)
terms.scale(1.5)
terms.arrange(DOWN, buff=LARGE_BUFF)
terms.to_edge(UP)
terms.match_x(self.students)
self.teacher_says(
"Loose with\\\\language",
bubble_kwargs={"width": 3, "height": 3},
run_time=2,
)
self.play(
FadeInFrom(terms[1], DOWN),
self.get_student_changes(
"thinking", "pondering", "erm",
look_at_arg=terms,
)
)
self.play(FadeInFromDown(terms[0]))
self.wait()
self.play(Swap(*terms))
self.wait(3)
class FormulaOutOfContext(TeacherStudentsScene):
def construct(self):
formula = TexMobject(
"c_{n} = \\int_0^1 e^{-2\\pi i {n} {t}}f({t}){dt}",
tex_to_color_map={
"{n}": YELLOW,
"{t}": PINK,
}
)
formula.scale(1.5)
formula.next_to(self.students, UP, LARGE_BUFF)
self.add(formula)
self.change_all_student_modes(
"horrified",
look_at_arg=formula,
)
self.play(self.teacher.change, "tease")
self.wait(3)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,371 @@
from manimlib.imports import *
from active_projects.diffyq.part2.heat_equation import BringTwoRodsTogether
from active_projects.diffyq.part3.staging import FourierSeriesIllustraiton
class StepFunctionExample(BringTwoRodsTogether, FourierSeriesIllustraiton):
CONFIG = {
"axes_config": {
"y_min": -1.5,
"y_max": 1.5,
"y_axis_config": {
"unit_size": 2.5,
"tick_frequency": 0.5,
},
"x_min": 0,
"x_max": 1,
"x_axis_config": {
"unit_size": 8,
"tick_frequency": 0.1,
"include_tip": False,
},
},
"y_labels": [-1, 1],
"graph_x_min": 0,
"graph_x_max": 1,
"midpoint": 0.5,
"min_temp": -1,
"max_temp": 1,
"alpha": 0.25,
"step_size": 0.01,
"n_range": range(1, 41, 2),
}
def construct(self):
self.setup_axes()
self.setup_graph()
self.setup_clock()
self.bring_rods_together()
self.let_evolve_for_a_bit()
self.add_labels()
self.compare_to_sine_wave()
self.sum_of_sine_waves()
def bring_rods_together(self):
rods = VGroup(
self.get_rod(0, 0.5),
self.get_rod(0.5, 1),
)
rods.add_updater(self.update_rods)
arrows = VGroup(
Vector(RIGHT).next_to(rods[0], UP),
Vector(LEFT).next_to(rods[1], UP),
)
words = VGroup(
TextMobject("Hot").next_to(rods[0], DOWN),
TextMobject("Cold").next_to(rods[1], DOWN),
)
for pair in rods, words:
pair.save_state()
pair.space_out_submobjects(1.2)
black_rects = VGroup(*[
Square(
side_length=1,
fill_color=BLACK,
fill_opacity=1,
stroke_width=0,
).move_to(self.axes.c2p(0, u))
for u in [1, -1]
])
black_rects[0].add_updater(
lambda m: m.align_to(rods[0].get_right(), LEFT)
)
black_rects[1].add_updater(
lambda m: m.align_to(rods[1].get_left(), RIGHT)
)
self.add(
self.axes,
self.graph,
self.clock,
)
self.add(rods, words)
self.add(black_rects)
kw = {
"run_time": 2,
"rate_func": rush_into,
}
self.play(
Restore(rods, **kw),
Restore(words, **kw),
*map(ShowCreation, arrows)
)
self.remove(black_rects)
self.to_fade = VGroup(words, arrows)
self.rods = rods
def let_evolve_for_a_bit(self):
rods = self.rods
# axes = self.axes
time_label = self.time_label
graph = self.graph
graph.save_state()
graph.add_updater(self.update_graph)
time_label.next_to(self.clock, DOWN)
time_label.add_updater(
lambda d, dt: d.increment_value(dt)
)
rods.add_updater(self.update_rods)
self.add(time_label)
self.play(
FadeOut(self.to_fade),
self.get_clock_anim(1)
)
self.play(self.get_clock_anim(3))
time_label.clear_updaters()
graph.clear_updaters()
self.play(
self.get_clock_anim(
-4,
run_time=1,
rate_func=smooth,
),
graph.restore,
time_label.set_value, 0,
)
rods.clear_updaters()
self.wait()
def add_labels(self):
axes = self.axes
y_axis = axes.y_axis
x_axis = axes.x_axis
y_numbers = y_axis.get_number_mobjects(
*np.arange(-1, 1.5, 0.5),
number_config={
"unit": "^\\circ",
"num_decimal_places": 1,
}
)
x_numbers = x_axis.get_number_mobjects(
*np.arange(0.2, 1.2, 0.2),
number_config={
"num_decimal_places": 1,
},
)
self.play(FadeIn(y_numbers))
self.play(ShowCreationThenFadeAround(y_numbers[-1]))
self.play(ShowCreationThenFadeAround(y_numbers[0]))
self.play(
LaggedStartMap(
FadeInFrom, x_numbers,
lambda m: (m, UP)
),
self.rods.set_opacity, 0.8,
)
self.wait()
def compare_to_sine_wave(self):
phi_tracker = ValueTracker(0)
get_phi = phi_tracker.get_value
k_tracker = ValueTracker(TAU)
get_k = k_tracker.get_value
A_tracker = ValueTracker(1)
get_A = A_tracker.get_value
sine_wave = always_redraw(lambda: self.axes.get_graph(
lambda x: get_A() * np.sin(
get_k() * x - get_phi()
),
x_min=self.graph_x_min,
x_max=self.graph_x_max,
).color_using_background_image("VerticalTempGradient"))
self.play(ShowCreation(sine_wave, run_time=3))
self.wait()
self.play(A_tracker.set_value, 1.25)
self.play(A_tracker.set_value, 0.75)
self.play(phi_tracker.set_value, -PI / 2)
self.play(k_tracker.set_value, 3 * TAU)
self.play(k_tracker.set_value, 2 * TAU)
self.play(
k_tracker.set_value, PI,
A_tracker.set_value, 4 / PI,
run_time=3
)
self.wait()
self.sine_wave = sine_wave
def sum_of_sine_waves(self):
curr_sine_wave = self.sine_wave
axes = self.axes
sine_graphs = self.get_sine_graphs(axes)
partial_sums = self.get_partial_sums(axes, sine_graphs)
curr_partial_sum = partial_sums[0]
curr_partial_sum.set_color(WHITE)
self.play(
FadeOut(curr_sine_wave),
FadeIn(curr_partial_sum),
FadeOut(self.rods),
)
# Copy-pasting from superclass...in theory,
# this should be better abstracted, but eh.
pairs = list(zip(sine_graphs, partial_sums))[1:]
for sine_graph, partial_sum in pairs:
anims1 = [
ShowCreation(sine_graph)
]
partial_sum.set_stroke(BLACK, 4, background=True)
anims2 = [
curr_partial_sum.set_stroke,
{"width": 1, "opacity": 0.25},
curr_partial_sum.set_stroke,
{"width": 0, "background": True},
ReplacementTransform(
sine_graph, partial_sum,
remover=True
),
]
self.play(*anims1)
self.play(*anims2)
curr_partial_sum = partial_sum
#
def setup_axes(self):
super().setup_axes()
self.axes.shift(
self.axes.c2p(0, 0)[1] * DOWN
)
class BreakDownStepFunction(StepFunctionExample):
CONFIG = {
"axes_config": {
"x_axis_config": {
"stroke_width": 2,
},
"y_axis_config": {
"tick_frequency": 0.25,
"stroke_width": 2,
},
"y_min": -1.25,
"y_max": 1.25,
},
"alpha": 0.1,
"wait_time": 30,
}
def construct(self):
self.setup_axes()
self.setup_graph()
self.setup_clock()
self.add_rod()
self.wait()
self.init_updaters()
self.play(
self.get_clock_anim(self.wait_time)
)
def setup_axes(self):
super().setup_axes()
axes = self.axes
axes.to_edge(LEFT)
mini_axes = VGroup(*[
axes.deepcopy()
for x in range(4)
])
for n, ma in zip(it.count(1, 2), mini_axes):
if n == 1:
t1 = TexMobject("1")
t2 = TexMobject("-1")
else:
t1 = TexMobject("1 / " + str(n))
t2 = TexMobject("-1 / " + str(n))
VGroup(t1, t2).scale(1.5)
t1.next_to(ma.y_axis.n2p(1), LEFT, MED_SMALL_BUFF)
t2.next_to(ma.y_axis.n2p(-1), LEFT, MED_SMALL_BUFF)
ma.y_axis.numbers.set_opacity(0)
ma.y_axis.add(t1, t2)
for mob in mini_axes.get_family():
if isinstance(mob, Line):
mob.set_stroke(width=1, family=False)
mini_axes.arrange(DOWN, buff=2)
mini_axes.set_height(FRAME_HEIGHT - 1.5)
mini_axes.to_corner(UR)
self.scale_factor = fdiv(
mini_axes[0].get_width(),
axes.get_width(),
)
# mini_axes.arrange(RIGHT, buff=2)
# mini_axes.set_width(FRAME_WIDTH - 1.5)
# mini_axes.to_edge(LEFT)
dots = TexMobject("\\vdots")
dots.next_to(mini_axes, DOWN)
dots.shift_onto_screen()
self.add(axes)
self.add(mini_axes)
self.add(dots)
self.mini_axes = mini_axes
def setup_graph(self):
super().setup_graph()
graph = self.graph
self.add(graph)
mini_axes = self.mini_axes
mini_graphs = VGroup()
for axes, u, n in zip(mini_axes, it.cycle([1, -1]), it.count(1, 2)):
mini_graph = axes.get_graph(
lambda x: (4 / PI) * (u / 1) * np.cos(PI * n * x),
)
mini_graph.set_stroke(WHITE, width=2)
mini_graphs.add(mini_graph)
# mini_graphs.set_color_by_gradient(
# BLUE, GREEN, RED, YELLOW,
# )
self.mini_graphs = mini_graphs
self.add(mini_graphs)
def setup_clock(self):
super().setup_clock()
clock = self.clock
time_label = self.time_label
clock.move_to(3 * RIGHT)
clock.to_corner(UP)
time_label.next_to(clock, DOWN)
self.add(clock)
self.add(time_label)
def add_rod(self):
self.rod = self.get_rod(0, 1)
self.add(self.rod)
def init_updaters(self):
self.graph.add_updater(self.update_graph)
for mg in self.mini_graphs:
mg.add_updater(
lambda m, dt: self.update_graph(
m, dt,
alpha=self.scale_factor * self.alpha
)
)
self.time_label.add_updater(
lambda d, dt: d.increment_value(dt)
)
self.rod.add_updater(
lambda r: self.update_rods([r])
)

View File

@@ -0,0 +1,474 @@
from manimlib.imports import *
from active_projects.diffyq.part3.temperature_graphs import TemperatureGraphScene
from active_projects.diffyq.part2.wordy_scenes import WriteHeatEquationTemplate
class ShowLinearity(WriteHeatEquationTemplate, TemperatureGraphScene):
CONFIG = {
"temp_text": "Temp",
"alpha": 0.1,
"axes_config": {
"z_max": 2,
"z_min": -2,
"z_axis_config": {
"tick_frequency": 0.5,
"unit_size": 1.5,
},
},
"default_surface_config": {
"resolution": (16, 16)
# "resolution": (4, 4)
},
"freqs": [2, 5],
}
def setup(self):
TemperatureGraphScene.setup(self)
WriteHeatEquationTemplate.setup(self)
def construct(self):
self.init_camera()
self.add_three_graphs()
self.show_words()
self.add_function_labels()
self.change_scalars()
def init_camera(self):
self.camera.set_distance(1000)
def add_three_graphs(self):
axes_group = self.get_axes_group()
axes0, axes1, axes2 = axes_group
freqs = self.freqs
scalar_trackers = Group(
ValueTracker(1),
ValueTracker(1),
)
graphs = VGroup(
self.get_graph(axes0, [freqs[0]], [scalar_trackers[0]]),
self.get_graph(axes1, [freqs[1]], [scalar_trackers[1]]),
self.get_graph(axes2, freqs, scalar_trackers),
)
plus = TexMobject("+").scale(2)
equals = TexMobject("=").scale(2)
plus.move_to(midpoint(
axes0.get_right(),
axes1.get_left(),
))
equals.move_to(midpoint(
axes1.get_right(),
axes2.get_left(),
))
self.add(axes_group)
self.add(graphs)
self.add(plus)
self.add(equals)
self.axes_group = axes_group
self.graphs = graphs
self.scalar_trackers = scalar_trackers
self.plus = plus
self.equals = equals
def show_words(self):
equation = self.get_d1_equation()
name = TextMobject("Heat equation")
name.next_to(equation, DOWN)
name.set_color_by_gradient(RED, YELLOW)
group = VGroup(equation, name)
group.to_edge(UP)
shift_val = 0.5 * RIGHT
arrow = Vector(1.5 * RIGHT)
arrow.move_to(group)
arrow.shift(shift_val)
linear_word = TextMobject("``Linear''")
linear_word.scale(2)
linear_word.next_to(arrow, RIGHT)
self.add(group)
self.wait()
self.play(
ShowCreation(arrow),
group.next_to, arrow, LEFT
)
self.play(FadeInFrom(linear_word, LEFT))
self.wait()
def add_function_labels(self):
axes_group = self.axes_group
graphs = self.graphs
solution_labels = VGroup()
for axes in axes_group:
label = TextMobject("Solution", "$\\checkmark$")
label.set_color_by_tex("checkmark", GREEN)
label.next_to(axes, DOWN)
solution_labels.add(label)
kw = {
"tex_to_color_map": {
"T_1": BLUE,
"T_2": GREEN,
}
}
T1 = TexMobject("a", "T_1", **kw)
T2 = TexMobject("b", "T_2", **kw)
T_sum = TexMobject("T_1", "+", "T_2", **kw)
T_sum_with_scalars = TexMobject(
"a", "T_1", "+", "b", "T_2", **kw
)
T1.next_to(graphs[0], UP)
T2.next_to(graphs[1], UP)
T_sum.next_to(graphs[2], UP)
T_sum.shift(SMALL_BUFF * DOWN)
T_sum_with_scalars.move_to(T_sum)
a_brace = Brace(T1[0], UP, buff=SMALL_BUFF)
b_brace = Brace(T2[0], UP, buff=SMALL_BUFF)
s1_decimal = DecimalNumber()
s1_decimal.match_color(T1[1])
s1_decimal.next_to(a_brace, UP, SMALL_BUFF)
s1_decimal.add_updater(lambda m: m.set_value(
self.scalar_trackers[0].get_value()
))
s2_decimal = DecimalNumber()
s2_decimal.match_color(T2[1])
s2_decimal.next_to(b_brace, UP, SMALL_BUFF)
s2_decimal.add_updater(lambda m: m.set_value(
self.scalar_trackers[1].get_value()
))
self.play(
FadeInFrom(T1[1], DOWN),
FadeInFrom(solution_labels[0], UP),
)
self.play(
FadeInFrom(T2[1], DOWN),
FadeInFrom(solution_labels[1], UP),
)
self.wait()
self.play(
TransformFromCopy(T1[1], T_sum[0]),
TransformFromCopy(T2[1], T_sum[2]),
TransformFromCopy(self.plus, T_sum[1]),
*[
Transform(
graph.copy().set_fill(opacity=0),
graphs[2].copy().set_fill(opacity=0),
remover=True
)
for graph in graphs[:2]
]
)
self.wait()
self.play(FadeInFrom(solution_labels[2], UP))
self.wait()
# Show constants
self.play(
FadeIn(T1[0]),
FadeIn(T2[0]),
FadeIn(a_brace),
FadeIn(b_brace),
FadeIn(s1_decimal),
FadeIn(s2_decimal),
FadeOut(T_sum),
FadeIn(T_sum_with_scalars),
)
def change_scalars(self):
s1, s2 = self.scalar_trackers
kw = {
"run_time": 2,
}
for graph in self.graphs:
graph.resume_updating()
self.play(s2.set_value, -0.5, **kw)
self.play(s1.set_value, -0.2, **kw)
self.play(s2.set_value, 1.5, **kw)
self.play(s1.set_value, 1.2, **kw)
self.play(s2.set_value, 0.3, **kw)
self.wait()
#
def get_axes_group(self):
axes_group = VGroup(*[
self.get_axes()
for x in range(3)
])
axes_group.arrange(RIGHT, buff=2)
axes_group.set_width(FRAME_WIDTH - 1)
axes_group.to_edge(DOWN, buff=1)
return axes_group
def get_axes(self, **kwargs):
axes = self.get_three_d_axes(**kwargs)
# axes.input_plane.set_fill(opacity=0)
# axes.input_plane.set_stroke(width=0.5)
# axes.add(axes.input_plane)
self.orient_three_d_mobject(axes)
axes.rotate(-5 * DEGREES, UP)
axes.set_width(4)
axes.x_axis.label.next_to(
axes.x_axis.get_end(), DOWN,
buff=2 * SMALL_BUFF
)
return axes
def get_graph(self, axes, freqs, scalar_trackers):
L = axes.x_max
a = self.alpha
def func(x, t):
scalars = [st.get_value() for st in scalar_trackers]
return np.sum([
s * np.cos(k * x) * np.exp(-a * (k**2) * t)
for freq, s in zip(freqs, scalars)
for k in [freq * PI / L]
])
def get_surface_graph_group():
return VGroup(
self.get_surface(axes, func),
self.get_time_slice_graph(axes, func, t=0),
)
result = always_redraw(get_surface_graph_group)
result.func = func
result.suspend_updating()
return result
class CombineSeveralSolutions(ShowLinearity):
CONFIG = {
"default_surface_config": {
"resolution": (16, 16),
# "resolution": (4, 4),
},
"n_top_graphs": 5,
"axes_config": {
"y_max": 15,
},
"target_scalars": [
0.81, -0.53, 0.41, 0.62, -0.95
],
"final_run_time": 14,
}
def construct(self):
self.init_camera()
self.add_all_axes()
self.setup_all_graphs()
self.show_infinite_family()
self.show_sum()
self.show_time_passing()
def add_all_axes(self):
top_axes_group = VGroup(*[
self.get_axes(
z_min=-1.25,
z_max=1.25,
z_axis_config={
"unit_size": 2,
"tick_frequency": 0.5,
},
)
for x in range(self.n_top_graphs)
])
top_axes_group.arrange(RIGHT, buff=2)
top_axes_group.set_width(FRAME_WIDTH - 1.5)
top_axes_group.to_corner(UL)
dots = TexMobject("\\dots")
dots.next_to(top_axes_group, RIGHT)
low_axes = self.get_axes()
low_axes.center()
low_axes.scale(1.2)
low_axes.to_edge(DOWN, buff=SMALL_BUFF)
self.add(top_axes_group)
self.add(dots)
self.add(low_axes)
self.top_axes_group = top_axes_group
self.low_axes = low_axes
def setup_all_graphs(self):
scalar_trackers = Group(*[
ValueTracker(1)
for x in range(self.n_top_graphs)
])
freqs = np.arange(self.n_top_graphs)
freqs += 1
self.top_graphs = VGroup(*[
self.get_graph(axes, [n], [st])
for axes, n, st in zip(
self.top_axes_group,
freqs,
scalar_trackers,
)
])
self.low_graph = self.get_graph(
self.low_axes, freqs, scalar_trackers
)
self.scalar_trackers = scalar_trackers
def show_infinite_family(self):
top_axes_group = self.top_axes_group
top_graphs = self.top_graphs
scalar_trackers = self.scalar_trackers
decimals = self.get_decimals(
top_axes_group, scalar_trackers
)
self.play(LaggedStart(*[
AnimationGroup(
Write(graph[0]),
FadeIn(graph[1]),
)
for graph in top_graphs
]))
self.wait()
self.play(FadeIn(decimals))
for graph in top_graphs:
graph.resume_updating()
self.play(LaggedStart(*[
ApplyMethod(st.set_value, value)
for st, value in zip(
scalar_trackers,
self.target_scalars,
)
]), run_time=3)
self.wait()
def show_sum(self):
top_graphs = self.top_graphs
low_graph = self.low_graph
low_graph.resume_updating()
low_graph.update()
self.play(
LaggedStart(*[
Transform(
top_graph.copy().set_fill(opacity=0),
low_graph.copy().set_fill(opacity=0),
remover=True,
)
for top_graph in top_graphs
]),
FadeIn(
low_graph,
rate_func=squish_rate_func(smooth, 0.7, 1)
),
run_time=3,
)
self.wait()
def show_time_passing(self):
all_graphs = [*self.top_graphs, self.low_graph]
all_axes = [*self.top_axes_group, self.low_axes]
time_tracker = ValueTracker(0)
get_t = time_tracker.get_value
anims = [
ApplyMethod(
time_tracker.set_value, 1,
run_time=1,
rate_func=linear
)
]
for axes, graph_group in zip(all_axes, all_graphs):
graph_group.clear_updaters()
surface, gslice = graph_group
plane = self.get_const_time_plane(axes)
plane.t_tracker.add_updater(
lambda m: m.set_value(get_t())
)
gslice.axes = axes
gslice.func = graph_group.func
gslice.add_updater(lambda m: m.become(
self.get_time_slice_graph(
m.axes, m.func, t=get_t()
)
))
self.add(gslice)
self.add(plane.t_tracker)
anims.append(FadeIn(plane))
self.play(*anims)
run_time = self.final_run_time
self.play(
time_tracker.increment_value, run_time,
run_time=run_time,
rate_func=linear,
)
#
def get_decimals(self, axes_group, scalar_trackers):
result = VGroup()
for axes, st in zip(axes_group, scalar_trackers):
decimal = DecimalNumber()
decimal.move_to(axes.get_bottom(), UP)
decimal.shift(SMALL_BUFF * RIGHT)
decimal.set_color(YELLOW)
decimal.scalar_tracker = st
times = TexMobject("\\times")
times.next_to(decimal, LEFT, SMALL_BUFF)
decimal.add_updater(lambda d: d.set_value(
d.scalar_tracker.get_value()
))
group = VGroup(times, decimal)
group.scale(0.7)
result.add(group)
return result
class CycleThroughManyLinearCombinations(CombineSeveralSolutions):
CONFIG = {
"default_surface_config": {
"resolution": (16, 16),
# "resolution": (4, 4),
},
"n_cycles": 10,
}
def construct(self):
self.init_camera()
self.add_all_axes()
self.setup_all_graphs()
#
self.cycle_through_superpositions()
def cycle_through_superpositions(self):
top_graphs = self.top_graphs
low_graph = self.low_graph
scalar_trackers = self.scalar_trackers
self.add(self.get_decimals(
self.top_axes_group, scalar_trackers
))
for graph in [low_graph, *top_graphs]:
graph.resume_updating()
self.add(graph)
nst = len(scalar_trackers)
for x in range(self.n_cycles):
self.play(LaggedStart(*[
ApplyMethod(st.set_value, value)
for st, value in zip(
scalar_trackers,
3 * np.random.random(nst) - 1.5
)
]), run_time=3)
self.wait()

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
from manimlib.imports import *
from old_projects.crypto import sha256_tex_mob, bit_string_to_mobject, BitcoinLogo
from from_3b1b.old.crypto import sha256_tex_mob, bit_string_to_mobject, BitcoinLogo
def get_google_logo():
result = SVGMobject(

View File

@@ -2,8 +2,8 @@
from manimlib.imports import *
from old_projects.uncertainty import Flash
from old_projects.WindingNumber import *
from from_3b1b.old.uncertainty import Flash
from from_3b1b.old.WindingNumber import *
# Warning, this file uses ContinualChangingDecimal,

View File

@@ -746,7 +746,7 @@ class StartingCalc101(PiCreatureScene):
def get_aha_image(self):
creature = self.pi_creature.copy()
creature.change_mode("hooray")
from old_projects.eoc.chapter3 import NudgeSideLengthOfCube
from from_3b1b.old.eoc.chapter3 import NudgeSideLengthOfCube
scene = NudgeSideLengthOfCube(
end_at_animation_number=7,
skip_animations=True

View File

@@ -1,7 +1,7 @@
from manimlib.imports import *
from old_projects.lost_lecture import GeometryProofLand
from old_projects.quaternions import SpecialThreeDScene
from old_projects.uncertainty import Flash
from from_3b1b.old.lost_lecture import GeometryProofLand
from from_3b1b.old.quaternions import SpecialThreeDScene
from from_3b1b.old.uncertainty import Flash
class Introduction(TeacherStudentsScene):
@@ -807,7 +807,7 @@ class FunctionGOutputSpace(FunctionGInputSpace):
x_max=2.5,
y_min=-2.5,
y_max=2.5,
number_line_config={'unit_size': 1.5}
axis_config={'unit_size': 1.5}
)
for axis in axes:
numbers = list(range(-2, 3))

View File

@@ -1,5 +1,5 @@
from manimlib.imports import *
from old_projects.brachistochrone.curves import *
from from_3b1b.old.brachistochrone.curves import *
class RollAlongVector(Animation):
CONFIG = {

View File

@@ -3,7 +3,7 @@ import itertools as it
from manimlib.imports import *
from old_projects.brachistochrone.curves import Cycloid
from from_3b1b.old.brachistochrone.curves import Cycloid
class MultilayeredGlass(PhotonScene, ZoomedScene):
CONFIG = {

View File

@@ -3,7 +3,7 @@ import itertools as it
from manimlib.imports import *
from old_projects.brachistochrone.curves import \
from from_3b1b.old.brachistochrone.curves import \
Cycloid, PathSlidingScene, RANDY_SCALE_FACTOR, TryManyPaths

View File

@@ -2,7 +2,7 @@ import numpy as np
import itertools as it
from manimlib.imports import *
from old_projects.brachistochrone.curves import Cycloid
from from_3b1b.old.brachistochrone.curves import Cycloid
class PhysicalIntuition(Scene):
def construct(self):

View File

@@ -2,8 +2,8 @@ import numpy as np
import itertools as it
from manimlib.imports import *
from old_projects.brachistochrone.light import PhotonScene
from old_projects.brachistochrone.curves import *
from from_3b1b.old.brachistochrone.light import PhotonScene
from from_3b1b.old.brachistochrone.curves import *
class MultilayeredScene(Scene):

View File

@@ -3,7 +3,7 @@ import itertools as it
import os
from manimlib.imports import *
from old_projects.brachistochrone.drawing_images import sort_by_color
from from_3b1b.old.brachistochrone.drawing_images import sort_by_color
class Intro(Scene):
def construct(self):

View File

@@ -1,10 +1,10 @@
from old_projects.clacks import question
from old_projects.clacks.solution2 import block_collision_scenes
from old_projects.clacks.solution2 import mirror_scenes
from old_projects.clacks.solution2 import pi_creature_scenes
from old_projects.clacks.solution2 import position_phase_space
from old_projects.clacks.solution2 import simple_scenes
from old_projects.clacks.solution2 import wordy_scenes
from from_3b1b.old.clacks import question
from from_3b1b.old.clacks.solution2 import block_collision_scenes
from from_3b1b.old.clacks.solution2 import mirror_scenes
from from_3b1b.old.clacks.solution2 import pi_creature_scenes
from from_3b1b.old.clacks.solution2 import position_phase_space
from from_3b1b.old.clacks.solution2 import simple_scenes
from from_3b1b.old.clacks.solution2 import wordy_scenes
OUTPUT_DIRECTORY = "clacks/solution2"
SCENES_IN_ORDER = [

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env python
from manimlib.imports import *
from old_projects.clacks.question import BlocksAndWallExample
from from_3b1b.old.clacks.question import BlocksAndWallExample
class NameBump(BlocksAndWallExample):

View File

@@ -325,8 +325,8 @@ class BlocksAndWallScene(Scene):
counter_mob = Integer(self.n_clacks)
counter_mob.next_to(
counter_label[-1], RIGHT,
aligned_edge=DOWN,
)
counter_mob.align_to(counter_label[-1][-1], DOWN)
counter_group = VGroup(
counter_label,
counter_mob,
@@ -747,7 +747,7 @@ class BlocksAndWallExampleMass1e2(BlocksAndWallExample):
"velocity": -0.6,
}
},
"wait_time": 25,
"wait_time": 35,
}
@@ -888,7 +888,7 @@ class PiComputingAlgorithmsAxes(Scene):
y_min=0,
x_max=9,
y_max=5,
number_line_config={
axis_config={
"tick_frequency": 100,
"numbers_with_elongated_ticks": [],
}

View File

@@ -1,6 +1,6 @@
from manimlib.imports import *
from old_projects.clacks.question import *
from old_projects.div_curl import ShowTwoPopulations
from from_3b1b.old.clacks.question import *
from from_3b1b.old.div_curl import ShowTwoPopulations
OUTPUT_DIRECTORY = "clacks/solution1"
@@ -633,7 +633,7 @@ class IntroduceVelocityPhaseSpace(AskAboutFindingNewVelocities):
"x_min": -3.5,
"x_max": 4,
},
"number_line_config": {
"axis_config": {
"unit_size": 0.7,
},
},
@@ -1204,6 +1204,8 @@ class CircleDiagramFromSlidingBlocks(Scene):
"fill_color": GREEN,
"fill_opacity": 0.3,
},
"show_dot": True,
"show_vector": False,
}
def construct(self):
@@ -1211,6 +1213,9 @@ class CircleDiagramFromSlidingBlocks(Scene):
show_flash_animations=False,
write_to_movie=False,
wait_time=0,
file_writer_config={
"output_directory": ".",
}
)
blocks = sliding_blocks_scene.blocks
times = [pair[1] for pair in blocks.clack_data]
@@ -1229,7 +1234,17 @@ class CircleDiagramFromSlidingBlocks(Scene):
dot = Dot(color=RED, radius=0.06)
dot.move_to(lines[0].get_start())
self.add(end_zone, axes, circle, dot)
vector = Vector(lines[0].get_start())
vector.set_color(RED)
vector.add_updater(lambda v: v.put_start_and_end_on(
ORIGIN, dot.get_center()
))
vector.set_stroke(BLACK, 2, background=True)
dot.set_opacity(int(self.show_dot))
vector.set_opacity(int(self.show_vector))
self.add(end_zone, axes, circle, dot, vector)
last_time = 0
for time, line in zip(times, lines):
@@ -1238,7 +1253,7 @@ class CircleDiagramFromSlidingBlocks(Scene):
self.wait(time - last_time)
last_time = time
dot.move_to(line.get_end())
self.add(line, dot)
self.add(line, dot, vector)
self.wait()
def get_circle(self):
@@ -2597,7 +2612,7 @@ class UnitCircleIntuition(Scene):
def draw_unit_circle(self):
unit_size = 2.5
axes = Axes(
number_line_config={"unit_size": unit_size},
axis_config={"unit_size": unit_size},
x_min=-2.5, x_max=2.5,
y_min=-1.5, y_max=1.5,
)

View File

@@ -1,5 +1,5 @@
from manimlib.imports import *
from old_projects.clacks.question import BlocksAndWallExample
from from_3b1b.old.clacks.question import BlocksAndWallExample
class PreviousTwoVideos(BlocksAndWallExample):

View File

@@ -1,7 +1,7 @@
from manimlib.imports import *
from old_projects.clacks.question import Block
from old_projects.clacks.question import Wall
from old_projects.clacks.question import ClackFlashes
from from_3b1b.old.clacks.question import Block
from from_3b1b.old.clacks.question import Wall
from from_3b1b.old.clacks.question import ClackFlashes
class PositionPhaseSpaceScene(Scene):

Some files were not shown because too many files have changed in this diff Show More