边学边做Manim中的切线

Manim中,TangentLine 是一个用于在曲线上某点创建切线的工具,如果你希望绘制某个VMobject形体某一点处的切线,那么切线类TangentLine能够做到这一点。为了定位你所指定的切点的位置,你需要传入一个参数alpha,这个参数的取值范围为0到1,代表的意思为你选取的VMobject上的切点到绘制的起点的长度比上整个VMobject的轮廓线长度。以下是详细的使用方法和示例:

1.切线类TangentLine的属性:

属性 说明
vmob 需要绘制切线的VMobject形体对象
alpha 指定切点到起点的长度比上vmob整体的轮廓线长度
length 切线长度,默认为1
d_alpha 近似切线的割线的两个点分别到切点的距离,默认为1e-6,值越小,得到的切线越精准

2.简单的实例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from manim import *

class geometry(Scene):
def construct(self):
circle = Circle(
radius=3,
color=(BLUE),
fill_opacity=0.5
)
line = TangentLine(
vmob=circle,
alpha=0.5,
length=4
)
self.play(Write(circle))
self.play(Write(line))
self.wait()

实际效果如下

从上图中可以看到,圆是从(1,0)这个点开始逆时针绘制的,因此alpha=0.5代表了我们选取的切点在整个绘制的轮廓线的一半的地方,也就是(-1,0)的地方。如果我们选取alpha=0.25,那么切点就在(0,1)处。我们来把代码修改,进行测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from manim import *

class CircleTangentLineUp(Scene):
def construct(self):
circle = Circle(
radius=3,
color=(BLUE),
fill_opacity=0.5
)
line = TangentLine(
vmob=circle,
alpha=0.25,
length=4
)
self.play(Write(circle))
self.play(Write(line))
self.wait()

测试效果如下

如此一来,我们就可以通过修改参数alpha的值,来调整切线在圆的周围的位置。当然我们也可以通过一个角度值,来确定一个点

3..指定角度制的点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from manim import *

class CircleTangentLine(Scene):
def construct(self):
# 创建圆
circle = Circle(radius=2, color=BLUE)
# 指定圆上的点(使用角度)
angle = 45 * DEGREES # 45度处的点
point_on_circle = circle.point_at_angle(angle)
# 创建切线
tangent = TangentLine(circle, alpha=angle/(2*PI), length=3, color=RED)
# 标记点
dot = Dot(point_on_circle, color=YELLOW)
# 添加角度标签
angle_label = MathTex(r"\theta = 45^\circ", font_size=24)
angle_label.next_to(dot, UR, buff=0.1)
self.play(Create(circle), Create(tangent), Create(dot), Create(angle_label))
self.wait(2)

Manim参数化曲线系统中alpha是一个在 [0, 1] 范围内的参数,表示曲线上的相对位置,alpha = 0 表示曲线的起点,alpha = 1 表示曲线的终点,alpha = 0.5 表示曲线的中点,角度和 alpha 的对应关系,

1
2
3
4
5
6
角度 (弧度)  角度 (度数)  alpha
0 0° 0
π/2 90° 0.25
π 180° 0.5
3π/2 270° 0.75
2π 360° 1

显示代码如下

虽然离我们日常几何作图还有一段距离,但是毕竟向前迈进了一步,试着做出了圆的切线问题。然后看下面的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from manim import *
import numpy as np

class TangentToCircle(Scene):
def construct(self):
# 创建所有元素
circle = Circle(radius=5, color=BLUE)
angle = np.arctan2(4, 3)
tangent = TangentLine(circle, alpha=angle/(2*PI), length=10, color=RED)
point = Dot([3, 4, 0], color=GREEN)
label = MathTex("P(3,4)", color=GREEN).next_to(point, UP)

# 方法1:使用VGroup缩放所有元素
group = VGroup(circle, tangent, point, label)
group.scale(0.5) # 缩小为1/2

# 动画
self.play(Create(circle))
self.play(FadeIn(point), Write(label))
self.play(Create(tangent))
self.wait()

这段代码的要求是,画一个半径为5的圆,然后过圆上的P(4,3)的点做圆的切线,

1
angle = np.arctan2(4, 3)

利用反正切函数返回点P(4,3)点对应的角度值,然后通过

1
alpha=angle/(2*PI)

弧度制转换来得到alpha的参数,因为超出了屏幕,所以我们将画出的图形组合,然后缩小,来看演示的效果

距离我们的要求总算是更精进一步,思路就是利用反正切函数将点的坐标转换成角度,再转换成弧度,再转换成切线的参数值。