贝塞尔曲线在计算机图形学中用于绘制形状、用于 CSS 动画和许多其他地方。它们是一件非常简单的事情,值得学习一次,然后在矢量图形和高级动画的世界中感到舒适。
一.控制点
贝塞尔曲线由控制点可能有 2、3、4 或更多。
例如,二次贝塞尔曲线:
三次贝塞尔曲线:
四次贝塞尔曲线:
如果你仔细观察这些曲线,你会立即注意到:
-
点并不总是在曲线上。这是完全正常的,稍后我们将看到曲线是如何构建的。
-
曲线顺序等于点数减去 1。 对于两点,我们有一条线性曲线(一条直线),对于三点 – 二次曲线(抛物线),对于四点 – 三次曲线。
-
曲线始终位于控制点的凸包内:
-
由于最后一个属性,在计算机图形学中,可以优化交叉点测试。如果凸包不相交,则曲线也不相交。因此,首先检查凸包相交可以给出非常快速的“无相交”结果。检查凸壳的交点要容易得多,因为它们是矩形、三角形等(见上图),比曲线简单得多。
贝塞尔曲线用于绘图的主要价值 – 通过移动点,曲线以直观、明显的方式发生变化。
二.数学表达式
贝塞尔曲线可以用数学公式来描述。正如我们所看到的——实际上没有必要知道它,大多数人只是通过用鼠标移动点来绘制曲线。但如果你喜欢数学——就在这里。
给定控制点的坐标:第一个控制点有坐标,第二个控制点有坐标:,依此类推,曲线坐标由依赖于线段参数的方程来描述。
-
2 点曲线的公式:
-
对于 3 个控制点:
-
对于 4 个控制点:
这些是向量方程。换句话说,我们可以把 and 而不是来获取相应的坐标。x,y,P
例如,3 点曲线由计算如下的点组成:(x,y)
相反,我们应该放置 3 个控制点的坐标,然后随着从 移动到 ,我们将拥有曲线的每个值。x1, y1, x2, y2, x3, y3,
t
0
1t(x,y)
例如,如果控制点为 , 和 ,则方程变为:(0,0)(0.5, 1)(1, 0)
现在,当从 到 运行时,每个值的集合构成了此类控制点的曲线。t
0
1(x,y)t
三,manim实现:应用函数
1.CubicBezier 曲线
在 Manim 中,CubicBezier 曲线需要指定起点、终点和两个控制点。CubicBezier 的构造函数的参数通常是 start, end, start_control, 和 end_control。
正确的使用方法 为了创建一条立方贝塞尔曲线,您需要提供开始和结束点,以及它们各自的控制点。下面是一个示例代码片段:
from manim import *
class BezierExample(Scene):
def construct(self):
# 定义起点、结束点和控制点
start_point = LEFT
end_point = RIGHT
start_control = UP
end_control = DOWN
# 创建三次贝塞尔曲线
bezier_curve = CubicBezier(start_point, start_control, end_control, end_point) # 绘制曲线 self.play(Create(bezier_curve)) self.wait(2)
解释
start_point: 曲线的起始坐标(左边的点)。
end_point: 曲线的结束坐标(右边的点)。
start_control: 控制曲线形状的第一个控制点。
end_control: 控制曲线形状的第二个控制点。
总结 :
确保在实例化 CubicBezier 时提供了所有必需的参数:起点、终点、起始控制点和结束控制点。这样可以避免 TypeError 并正确创建贝塞尔曲线。
2.常见的贝塞尔相关类和函数
在 Manim 中,除了 CubicBezier 函数外,还有其他几种函数和方法用于绘制不同类型的贝塞尔曲线。以下是一些常见的贝塞尔相关类和函数:
Bezier Bezier(points): 这个类可以用来表示任意阶的贝塞尔曲线。它的构造函数接受一个点的列表,这些点可以是任意数量的控制点。适用于线性、二次、三次乃至更高阶的贝塞尔曲线。
from manim import *
class BezierExample(Scene):
def construct(self):
points = [LEFT, UP, RIGHT] # 三个控制点
bezier_curve = Bezier(points) # 创建贝塞尔曲线
self.play(Create(bezier_curve))
self.wait(2)
QuadraticBezier QuadraticBezier(start, control, end): 创建一条二次贝塞尔曲线。需要提供起点、控制点和终点。
from manim import *
class QuadraticBezierExample(Scene):
def construct(self):
# 定义点
start = LEFT
control = UP
end = RIGHT
# 创建二次贝塞尔曲线
bezier_curve = QuadraticBezier(start, control, end) self.play(Create(bezier_curve))
self.wait(2)
CubicBezier CubicBezier(start, start_control, end_control, end): 创建一条三次贝塞尔曲线,使用起点、两个控制点和终点。 其他贝塞尔相关函数 在 Manim 中,除了以上类,您还可能遇到一些其他有用的函数和方法,如在动画中与路径相关的操作、插值和运动等。
使用示例 要使用这些不同类型的贝塞尔函数,您只需确保根据所需曲线类型提供适当数量和位置的点。
总结 在 Manim 中使用贝塞尔曲线时,您可以选择不同的类来创建线性、二次或三次贝塞尔曲线,具体取决于您所需的复杂性和形状。
四,实现贝塞尔曲线
from manim import *
class Bezier2305(Scene):
def construct(self):
# 定义控制点
P1 = np.array([-4, -2, 0])
P2 = np.array([0, 3, 0])
P3 = np.array([0, -1, 0]) # 二次贝塞尔曲线的控制点
P4 = np.array([2, 3, 0]) # 三次贝塞尔曲线的控制点
P5=np.array([5, 2, 0])
# 根据控制点计算各种贝塞尔曲线
bezier_2_points = [self.bezier_2_points(P1, P2, t) for t in np.linspace(0, 1, 100)]
bezier_3_points = [self.bezier_3_points(P1, P2, P3, t) for t in np.linspace(0, 1, 50)]
bezier_4_points = [self.bezier_4_points(P1, P2, P3, P4, t) for t in np.linspace(0, 1, 100)]
bezier_5_points = [self.bezier_5_points(P1, P2, P3, P4,P5, t) for t in np.linspace(0, 1, 100)]
# 创建 Mobject
curve_2 = self.create_curve(bezier_2_points)
curve_3 = self.create_curve(bezier_3_points)
curve_4 = self.create_curve(bezier_4_points)
curve_5 = self.create_curve(bezier_5_points)
# 动画展示
#二次
#点
d1 = Dot(P1,radius=0.2,color=GREEN,stroke_width=10, fill_opacity=0)
self.add(d1)
d2 = Dot(P2,radius=0.2,color=GREEN,stroke_width=10, fill_opacity=0)
self.add(d2)
#线
L1=Line(start=d1,end=d2,color=GREEN)
self.play(Create(curve_2))
self.play(Create(L1))
a=Text("二次贝塞尔曲线",color=PINK).shift(2*DOWN)
self.add(a)
self.wait(1)
self.play(FadeOut(curve_2,L1,d1,d2,a))
#三次
d1 = Dot(P1,radius=0.2,color=GREEN,stroke_width=10, fill_opacity=0)
#self.add(d1)
d2 = Dot(P2,radius=0.2,color=RED,stroke_width=10, fill_opacity=0)
#self.add(d2)
d3 = Dot(P3,radius=0.2,color=GREEN,stroke_width=10, fill_opacity=0)
#self.add(d3)
L1=Line(start=d1,end=d2,color=GREEN)
L2=Line(start=d2,end=d3,color=YELLOW)
#self.play(Create(L1))
b=Text("三次贝塞尔曲线",color=PINK).shift(2*DOWN)
self.add(b)
self.play(Create(curve_3))
self.play(Create(L1))
self.wait(1)
self.play(FadeOut(curve_3,d1,L1,d2,L2,d3,b))
self.wait(1.5)
#四次
d1 = Dot(P1,radius=0.2,color=GREEN,stroke_width=10, fill_opacity=0)
d2 = Dot(P2,radius=0.2,color=RED,stroke_width=10, fill_opacity=0)
d3 = Dot(P3,radius=0.2,color=GREEN,stroke_width=10, fill_opacity=0)
d4 = Dot(P4,radius=0.2,color=RED,stroke_width=10, fill_opacity=0)
#line
L1=Line(start=d1,end=d2,color=GREEN)
L2=Line(start=d2,end=d3,color=YELLOW)
L3=Line(start=d3,end=d4,color=YELLOW)
#曲线
self.play(Create(curve_4))
c=Text("四次贝塞尔曲线",color=PINK).shift(2*DOWN)
self.add(c)
self.wait(1)
self.play(Create(d1),Create(L1),Create(d2),Create(L2),Create(d3),Create(L3),Create(d4))
self.wait(1)
self.play(FadeOut(curve_4,d1,L1,d2,L2,d3,L3,d4,c))
#五次
d1 = Dot(P1,radius=0.2,color=GREEN,stroke_width=10, fill_opacity=0)
d2 = Dot(P2,radius=0.2,color=RED,stroke_width=10, fill_opacity=0)
d3 = Dot(P3,radius=0.2,color=GREEN,stroke_width=10, fill_opacity=0)
d4 = Dot(P4,radius=0.2,color=RED,stroke_width=10, fill_opacity=0)
d5=Dot(P5,radius=0.2,color=YELLOW,stroke_width=10, fill_opacity=0)
#line
L1=Line(start=d1,end=d2,color=GREEN)
L2=Line(start=d2,end=d3,color=YELLOW)
L3=Line(start=d3,end=d4,color=YELLOW)
L4=Line(start=d4,end=d5,color=RED)
#曲线
self.play(Create(curve_5))
d=Text("五次贝塞尔曲线",color=PINK).shift(2*DOWN)
self.add(d)
self.wait(1)
self.play(Create(d1),Create(L1),Create(d2),Create(L2),Create(d3),
Create(L3),Create(d4),Create(L4),Create(d5))
self.wait(1)
self.play(FadeOut(curve_5,d1,L1,d2,L2,d3,L3,d4,L4,d5,d))
self.wait(2)
def bezier_2_points(self, P1, P2, t):
"""计算2点贝塞尔曲线上的点"""
return (1 - t) * P1 + t * P2
def bezier_3_points(self, P1, P2, P3, t):
"""计算3点贝塞尔曲线上的点"""
return (1 - t)**2 * P1 + 2 * (1 - t) * t * P2 + t**2 * P3
def bezier_4_points(self, P1, P2, P3, P4, t):
"""计算4点贝塞尔曲线上的点"""
return (1 - t)**3 * P1 + 3 * (1 - t)**2 * t * P2 + 3 * (1 - t) * t**2 * P3 + t**3 * P4
def bezier_5_points(self, P1, P2, P3, P4,P5, t):
"""计算4点贝塞尔曲线上的点"""
return (1 - t)**4 * P1 + 4 * (1 - t)**3 * t * P2 + 4 * (1 - t) * t**3 * P3+ 4 * (1 - t) * t**3 * P4 + t**4 * P5
def create_curve(self, points):
"""创建通过给定点的曲线"""
return VMobject().set_points_smoothly(points)
%manim -qm -v WARNING Bezier2305
运行片段:
![]() | ![]() |
![]() | ![]() |