利用manim实现如斯美丽的图象。并动画它,是一个让人很愉快的事情。
这三幅图像巧妙地结合了数学与物理的概念,展现了它们之间的深刻联系。
第一幅图像通过一条蓝色的曲线和两条黄色的切线,直观地展示了切线的概念。这种视觉效果不仅强调了曲线的变化,还引导观众思考切线与曲线之间的关系,体现了微积分中的导数概念。
第二幅图像则通过几何图形的组合,展示了角度和弧度的关系。椭圆和三角形的结合使得图形更加生动,强调了几何与代数之间的联系,尤其是在三角函数的应用中。
第三幅图像则进一步深化了这一主题,通过引入向量和三角函数的分解,展示了如何将一个向量分解为其在 x 轴和 y 轴上的分量。这种分解不仅在物理学中有广泛应用,也在数学中帮助理解三角函数的性质。
整体而言,这些图像通过生动的视觉表现和清晰的布局,成功地将数学与物理的概念结合在一起,激发了观众对这两个领域的兴趣和理解。
from manim import *
class TangentLine010(Scene):
def construct(self):
# 设置背景颜色
self.camera.background_color = "#003311"
# 创建表示 π 的文本符号
pi_symbol = Text("π", font_size=150, color=BLUE, font="MS PGothic")
pi_symbol.move_to(ORIGIN) # 将 π 符号移动到原点
# 创建两个点,用于绘制线段
dot = Dot(ORIGIN + 0.05 * LEFT)
dot2 = Dot(ORIGIN + 0.09 * RIGHT)
# 创建一条线段,稍微向上移动并旋转
line = Line(dot.get_center(), dot2.get_center(), stroke_width=6).set_color(BLACK).shift(0.49 * UP + 0.1 * RIGHT).rotate(-PI / 19)
# 创建眼睛的椭圆形状
left_eye = Ellipse(width=0.4, height=0.25, color=WHITE, fill_opacity=1).shift(LEFT * 0.15 + UP * 0.625).rotate(PI / 13)
right_eye = Ellipse(width=0.4, height=0.25, color=WHITE, fill_opacity=1).shift(RIGHT * 0.35 + UP * 0.625).rotate(-PI / 13)
# 创建眼珠
left_pupil = Dot(color=BLACK).shift(LEFT * 0.15 + UP * 0.625)
right_pupil = Dot(color=BLACK).shift(RIGHT * 0.35 + UP * UP * 0.625)
# 将眼睛和眼珠合并为一个组
eyes = VGroup(left_eye, right_eye, left_pupil, right_pupil)
que = Text("???", font_size=52, color=WHITE, font="Fantasy").next_to(pi_symbol, UP)
# 创建包含 π 符号、眼睛和其他元素的组合
pieye = VGroup(pi_symbol, eyes, que, line).shift(2 * DL + LEFT).scale(1.5).shift(2 * LEFT)
self.add(pieye) # 将组合添加到场景中
# 创建坐标轴
axes = Axes().add_coordinates()
# 定义函数
def func(x):
return -0.20 * x**2 + 3 # 二次函数的公式
# 绘制函数图像
graph = axes.plot(func, color=PURPLE_E, x_range=[-5, 5])
self.play(Create(graph), run_time=2) # 动画显示图像
# 设置切线的切点
tangent_point_x = 2
d01 = Dot(axes.c2p(tangent_point_x, func(tangent_point_x)), radius=0.1, color=RED) # 切线点
# 计算切线的 y 坐标和斜率
tangent_point_y = func(tangent_point_x)
tangent_slope = -0.40 * tangent_point_x
y_intercept = tangent_point_y - tangent_slope * tangent_point_x
# 创建切线函数
def ffff(x):
return tangent_slope * x + y_intercept
# 创建切线的起点和终点
arrow_start = Dot(axes.c2p(tangent_point_x, func(tangent_point_x))) # 切线起点
x1 = 5 # 切线终点的 x 值
y1 = ffff(x1) # 根据切线函数计算终点的 y 值
arrow_end = Dot(axes.c2p(x1, y1)) # 切线终点
# 创建切线的箭头
arrow = Arrow(start=arrow_start, end=arrow_end, buff=0, color=RED)
txt_aa = MathTex(r"u", color=YELLOW_B).next_to(arrow, LEFT).shift(RIGHT) # 标签
# 绘制切线
tangent_line = axes.plot(ffff, color=YELLOW, stroke_width=0.5)
# 在曲线的末端画个点
# 在曲线的末端画个点
end_p = 5 # 设置终点的 x 值
p_end = Dot(axes.c2p(end_p, func(end_p)), radius=0.12, color=WHITE) # 创建终点的点
# 添加切点标记
self.add(d01, p_end) # 将切点和末端点添加到场景中
# 创建 cos 向量
arrow_start_C = Dot(axes.c2p(tangent_point_x, func(tangent_point_x))) # cos 向量的起点
arrow_end_C = Dot(axes.c2p(x1, func(tangent_point_x))) # cos 向量的终点
# 创建向量
arrow_C = Arrow(start=arrow_start_C, end=arrow_end_C, buff=0, color=PURPLE) # 创建箭头
txt_c = MathTex(r"\parallel \overrightarrow{u} \parallel \cos(\theta)", color=PURPLE).next_to(arrow_C, UP) # cos 向量标签
# 创建 sin 向量
arrow_start_S = Dot(axes.c2p(x1, func(tangent_point_x))) # sin 向量的起点
arrow_end_S = Dot(axes.c2p(x1, y1)) # sin 向量的终点
# 创建向量
arrow_S = Arrow(start=arrow_start_S, end=arrow_end_S, buff=0, color=ORANGE) # 创建箭头
txt_S = MathTex(r"\parallel \overrightarrow{u} \parallel \sin(\theta)", color=ORANGE).next_to(arrow_C, RIGHT).shift(0.5 * DOWN).scale(0.7) # sin 向量标签
# 播放动画展示切线和箭头
self.play(Create(tangent_line), Create(arrow), Create(txt_aa)) # 显示切线和箭头的动画
self.wait(1) # 暂停一秒
self.play(Create(arrow_C), Create(arrow_end_C)) # 显示 cos 向量的动画
self.play(Create(txt_c)) # 显示 cos 向量的标签
self.play(Create(arrow_S), Create(arrow_end_S)) # 显示 sin 向量的动画
self.play(Create(txt_S)) # 显示 sin 向量的标签
# 画表示
# 手动定义三角形的顶点
y1 = Polygon(
[0, 1.5, 0], # 顶点 A
[0.5, 1, 0], # 顶点 B
[-2.5, -1, 0], # 顶点 C
color=WHITE, fill_opacity=0
).next_to(pi_symbol, UP).shift(2 * DOWN + 2 * LEFT) # 将三角形向下和左移动
y0 = Ellipse(width=4, height=2, color=WHITE, fill_opacity=1, stroke_width=1).next_to(pi_symbol, UP).shift(1.65 * LEFT + DOWN * 1.35) # 创建一个椭圆
# 合并
u = Union(y0, y1, fill_opacity=1, stroke_width=2, stroke_color=WHITE).shift(3 * UP + 3.5 * RIGHT) # 将椭圆和多边形合并
# 获取并集的中心
c_t = u.get_center() # 获取合并后的形状的中心
print(c_t) # 打印中心坐标
p0 = Dot().next_to(pi_symbol, UP) # 创建一个点在 π 符号上方
y2 = Ellipse(width=4, height=2, color=WHITE, fill_opacity=1, stroke_width=1).next_to(pi_symbol, UP).shift(1.65 * LEFT + DOWN * 1.35).shift(3 * UP + 3.5 * RIGHT) # 创建一个新的椭圆,并向右上方移动
self.play(Transform(p0, u)) # 将 p0 变换成形状 u
self.add(u) # 将合并后的形状 u 添加到场景中
self.add(y2) # 将新的椭圆 y2 添加到场景中
# 角度文本
tex_theta = MathTex(r"\theta = \frac{\arcsin}{\arccos} ", color=BLUE_D).next_to(y2).shift(-3 * RIGHT) # 创建表示角度的文本
self.play(Transform(p0, tex_theta)) # 将 p0 变换为角度文本
self.add(tex_theta) # 将角度文本添加到场景中
# 在运动后确保 tex_theta 在最上层
# self.bring_to_front(tex_theta) # 这行代码可以用来确保 tex_theta 在其他对象的上面
# 加视觉效果
self.wait() # 等待结束
代码解释
-
创建点和向量:
- 代码中创建了多个点,分别表示切线、cos 向量和 sin 向量的起始和终止位置,并用箭头表示这些向量。
- 还添加了对应的标签,例如
$ \parallel \overrightarrow{u} \parallel \cos(\theta)$
和$ \parallel \overrightarrow{u} \parallel \sin(\theta)$
。
-
动画播放:
- 通过
self.play()
方法来播放生成的图形和动画,确保逐步展示场景中添加的元素。 - 每个部分被创建时都有等候时间,以便观众可以清晰地看到每个元素的构建过程。
- 通过
-
合并图形:
- 代码通过
Polygon
和Ellipse
创建了多边形和椭圆,随后用Union
方法将这些图形合并,以创建新的形状。 - 中心位置可以通过
.get_center()
方法获得,用于后续的定位和转换。
- 代码通过
-
文本和公式:
- 通过
MathTex
创建了数学公式以表示角度关系,并将其添加到场景中。 - 可能的视觉效果通过等待和变换结合起来以增强观众体验。
- 通过
这一段代码整体上是为了更好地展示数学中的切线、三角函数(sin 和 cos),以及它们的几何表示,并通过动画增强理解。
运行结果我没有放出来。如果想看的画评论区留言。我会上传出来的