Epicycloid¶
In geometry, an epicycloid is a plane curve generated by tracing the path of a point on the circumference of a circle that rolls without slipping around a fixed circle.
Setup¶
Create a new Colab notebook at colab.new and run the cells below.
The session will restart to apply changes.
%pip install mscene
import mscene
%mscene -l manim plugins
from mscene.manim import *
from mscene.plugins import *
Actions¶
The epitrochoid_scene
function animates epicycloid or epitrochoid scenes. An epicycloid is a special case of epitrochoid where the tracing point is on the circumference of the rolling circle.
def epitrochoid_scene(
scene,
k,
angle=-TAU,
run_time=4,
markers=[(1, PI / 2, ManimColor("#6019E3"))],
scale=1,
title=None,
):
"""Animates epicycloid or epitrochoid scenes. An epicycloid is a special case of epitrochoid where the tracing point is on the circumference of the rolling circle.
Args:
scene (Scene): An instance of Manim Scene for animation.
k (float): The ratio R/r, where R is the radius of the fixed circle and r is the radius of the rolling circle. This affects the shape of the curve.
angle (float): The angle of rotation around the fixed circle. Defaults to -TAU.
run_time (float): The duration of rolling animation. Defaults to 4.
markers (list[tuple[float, float, ManimColor]]): A list of markers for tracing the path, where each marker is a tuple of distance, angle and color. Defaults to [(1, PI / 2, ManimColor("#6019E3"))].
scale (float): The scale factor to fit the scene within the frame. Defaults to 1.
title (str | None, optional): The title of the scene. If not provided (None), no title will be shown. Defaults to None.
Returns:
None
"""
h = config.frame_height * scale * 3 / 8
r = h / (2 + k)
wheel = Wheel(radius=r, color=ManimColor("#04D9FF"), markers=markers)
circle = Circle(radius=k * r, color=ManimColor("#6F828A"))
txt = f"k = {k}" if title is None else f"{title}\nk = {k}"
text = Text(txt).to_corner(UL, buff=2 / 3)
wheel.move(circle.get_top(), UP)
scene.play(FadeIn(text, circle, wheel))
scene.wait(0.5)
path = wheel.trace_paths()
scene.add(path)
scene.play(wheel.roll(angle, about=circle, run_time=run_time))
path.clear_updaters()
scene.wait(2)
scene.play(FadeOut(path))
scene.wait()
scene.play(FadeOut(text, circle, wheel))
scene.wait(0.5)
Scenes¶
Epicycloids¶
Scene One¶
%%manim -qm EpicycloidOne
class EpicycloidOne(Scene):
def construct(self):
epitrochoid_scene(self, k=3, angle=-TAU, title="Epicycloid")
Scene Two¶
%%manim -qm EpicycloidTwo
class EpicycloidTwo(Scene):
def construct(self):
k, angle, run_time = (1.5, -TAU * 2, 8)
# roll again with these values
# k, angle, run_time = (2, -TAU, 4)
# k, angle, run_time = (1, -TAU, 4)
# k, angle, run_time = (.5, -TAU*2, 8)
epitrochoid_scene(self, k, angle, run_time, title="Epicycloid")
Epitrochoids¶
%%manim -qm Epitrochoids
class Epitrochoids(Scene):
def construct(self):
k, angle, run_time = (3, -TAU, 5)
markers = [
(2, PI / 2, ManimColor("#6019E3")),
(0.5, -PI / 2, ManimColor("#E31937")),
]
epitrochoid_scene(
self, k, angle, run_time, markers, scale=0.875, title="Epitrochoids"
)
Two Rolling Circles¶
%%manim -qm TwoRollingCircles
class TwoRollingCircles(Scene):
def construct(self):
k, angle, run_time = (2.25, -4 * TAU, 16)
# try these values
# k, angle, run_time = (2.8, -5*TAU, 18)
h = config.frame_height * 3 / 8
r = h / (2 + k)
color_one = ManimColor("#6019E3")
color_two = ManimColor("#E31937")
wheel_one_markers = [(1, PI / 2, color_one)]
wheel_two_markers = [(1, -PI / 2, color_two)]
wheel_one = Wheel(
radius=r, color=ManimColor("#04D9FF"), markers=wheel_one_markers
)
wheel_two = Wheel(
radius=r, color=ManimColor("#04D9FF"), markers=wheel_two_markers
)
circle = Circle(radius=k * r, color=ManimColor("#6F828A"))
wheel_one.move(circle.get_top(), UP)
wheel_two.move(circle.get_top(), DOWN)
self.play(FadeIn(circle, wheel_one, wheel_two))
self.wait(0.5)
wheel_one_path = wheel_one.trace_paths()
wheel_two_path = wheel_two.trace_paths()
self.add(wheel_one_path, wheel_two_path)
self.play(
wheel_one.roll(angle, about=circle, run_time=run_time),
wheel_two.roll(angle, about=circle, run_time=run_time),
)
wheel_one_path.clear_updaters()
wheel_two_path.clear_updaters()
self.wait(2)
self.play(FadeOut(wheel_one_path, wheel_two_path))
self.wait()
self.play(FadeOut(circle, wheel_one, wheel_two))
self.wait(0.5)