一元微积分可视化

微元法求曲边梯形面积

用矩形微元、黎曼和与极限过程解释曲边梯形面积为什么可以写成定积分。

打开原视频

curved_trapezoid_area.py
1from manim import *2import numpy as np3 4class CurvedTrapezoidAreaScene(Scene):5    def construct(self):6        # 标题7        title = Text("微元法求曲边梯形面积", font_size=42)8        title.to_edge(UP)9        self.play(Write(title), run_time=1.5)10        11        # 介绍文本12        intro = Text("将曲边梯形划分为无数个矩形微元,通过积分求总面积", font_size=28)13        intro.next_to(title, DOWN, buff=0.8)14        self.play(Write(intro), run_time=1.5)15        self.wait(1)16        17        # 淡出介绍18        self.play(FadeOut(intro), run_time=1)19        20        # 创建坐标系21        axes = Axes(22            x_range=[0, 4, 1],23            y_range=[0, 4, 1],24            x_length=8,25            y_length=6,26            axis_config={"color": BLUE}27        )28        29        # 添加坐标轴标签30        x_label = axes.get_x_axis_label("x")31        y_label = axes.get_y_axis_label("y")32        33        # 显示坐标系34        self.play(35            Create(axes),36            Write(x_label),37            Write(y_label),38            run_time=1.539        )40        41        # 定义函数 f(x) = x^2 + 142        def func(x):43            return x*x*0.3 + 144        45        # 创建函数曲线46        curve = axes.plot(func, x_range=[0.5, 3.5], color=RED)47        curve_label = MathTex("y = f(x)", font_size=32, color=RED)48        curve_label.next_to(curve.get_end(), UP)49        50        self.play(51            Create(curve),52            Write(curve_label),53            run_time=254        )55        self.wait(1)56        57        # 定义积分区间58        a, b = 1, 359        60        # 创建曲边梯形区域61        area = axes.get_area(curve, x_range=[a, b], color=BLUE, opacity=0.3)62        63        # 标记积分区间64        a_line = axes.get_vertical_line(axes.c2p(a, 0), color=GREEN)65        b_line = axes.get_vertical_line(axes.c2p(b, 0), color=GREEN)66        67        a_label = MathTex("a", font_size=28, color=GREEN)68        a_label.next_to(axes.c2p(a, 0), DOWN)69        70        b_label = MathTex("b", font_size=28, color=GREEN)71        b_label.next_to(axes.c2p(b, 0), DOWN)72        73        self.play(74            Create(area),75            Create(a_line),76            Create(b_line),77            Write(a_label),78            Write(b_label),79            run_time=280        )81        self.wait(1)82        83        # 显示面积标记84        area_label = Text("曲边梯形面积", font_size=24, color=BLUE)85        area_label.move_to(axes.c2p(2, 1.5))86        self.play(Write(area_label), run_time=1)87        self.wait(1)88        89        # 开始微元分割90        self.play(FadeOut(area_label), run_time=0.5)91        92        # 创建矩形微元93        n = 8  # 矩形数量94        rectangles = []95        dx = (b - a) / n96        97        for i in range(n):98            x_left = a + i * dx99            x_right = a + (i + 1) * dx100            height = func(x_left)  # 使用左端点的函数值101            102            # 创建矩形103            rect = Rectangle(104                width=axes.x_axis.unit_size * dx,105                height=axes.y_axis.unit_size * height,106                fill_opacity=0.4,107                fill_color=YELLOW,108                stroke_color=WHITE,109                stroke_width=2110            )111            112            # 定位矩形113            rect.align_to(axes.c2p(x_left, 0), DOWN + LEFT)114            rectangles.append(rect)115        116        # 逐个绘制矩形117        self.play(118            FadeOut(area),119            *[Create(rect) for rect in rectangles],120            run_time=2121        )122        self.wait(1)123        124        # 高亮显示一个矩形微元125        highlight_index = 3126        rectangles[highlight_index].set_fill(RED, opacity=0.7)127        128        # 标记微元129        x_i = a + highlight_index * dx130        131        # 创建标记线和标签132        dx_line = Line(133            axes.c2p(x_i, 0),134            axes.c2p(x_i + dx, 0),135            color=ORANGE,136            stroke_width=4137        )138        139        height_line = Line(140            axes.c2p(x_i, 0),141            axes.c2p(x_i, func(x_i)),142            color=PURPLE,143            stroke_width=4144        )145        146        # 标签147        dx_label = MathTex("dx", font_size=28, color=ORANGE)148        dx_label.next_to(dx_line, DOWN)149        150        height_label = MathTex("f(x)", font_size=28, color=PURPLE)151        height_label.next_to(height_line, LEFT)152        153        area_element_label = MathTex("dA", font_size=28, color=RED)154        area_element_label.move_to(rectangles[highlight_index].get_center())155        156        self.play(157            Create(dx_line),158            Create(height_line),159            Write(dx_label),160            Write(height_label),161            Write(area_element_label),162            run_time=2163        )164        self.wait(1)165        166        # 显示微元面积公式167        formula_group = VGroup()168        169        # 微元面积公式170        element_formula = MathTex(r"dA = f(x) \cdot dx", font_size=28)171        element_formula.to_corner(UR).shift(LEFT * 2 + DOWN * 0.5)172        formula_group.add(element_formula)173        174        # 积分公式175        integral_formula = MathTex(r"A = \int_a^b f(x) \, dx", font_size=28)176        integral_formula.next_to(element_formula, DOWN, aligned_edge=LEFT, buff=0.3)177        formula_group.add(integral_formula)178        179        # 说明文字180        explanation = Text("总面积 = 所有微元面积之和", font_size=20)181        explanation.next_to(integral_formula, DOWN, aligned_edge=LEFT, buff=0.3)182        formula_group.add(explanation)183        184        self.play(Write(formula_group), run_time=2)185        self.wait(2)186        187        # 演示增加矩形数量的效果188        self.play(189            FadeOut(dx_line),190            FadeOut(height_line),191            FadeOut(dx_label),192            FadeOut(height_label),193            FadeOut(area_element_label),194            run_time=1195        )196        197        # 更多的矩形198        for num_rects in [16, 32]:199            new_rectangles = []200            new_dx = (b - a) / num_rects201            202            for i in range(num_rects):203                x_left = a + i * new_dx204                height = func(x_left)205                206                rect = Rectangle(207                    width=axes.x_axis.unit_size * new_dx,208                    height=axes.y_axis.unit_size * height,209                    fill_opacity=0.4,210                    fill_color=YELLOW,211                    stroke_color=WHITE,212                    stroke_width=1 if num_rects > 16 else 2213                )214                215                rect.align_to(axes.c2p(x_left, 0), DOWN + LEFT)216                new_rectangles.append(rect)217            218            # 淡出旧矩形,淡入新矩形219            self.play(220                *[FadeOut(rect) for rect in rectangles],221                run_time=1222            )223            224            self.play(225                *[FadeIn(rect) for rect in new_rectangles],226                run_time=1.5227            )228            229            # 更新矩形列表230            rectangles = new_rectangles231            self.wait(1)232        233        # 显示极限过程234        limit_text = Text("当 n → ∞ 时,矩形面积和趋向于曲边梯形的精确面积", font_size=24)235        limit_text.to_edge(DOWN)236        self.play(Write(limit_text), run_time=2)237        self.wait(1)238        239        # 最终显示精确的曲边梯形面积240        exact_area = axes.get_area(curve, x_range=[a, b], color=BLUE, opacity=0.6)241        242        self.play(243            *[FadeOut(rect) for rect in rectangles],244            FadeIn(exact_area),245            run_time=2246        )247        248        # 最终结果249        final_formula = MathTex(r"A = \int_a^b f(x) \, dx", font_size=36, color=YELLOW)250        final_box = SurroundingRectangle(final_formula, buff=0.3, color=YELLOW)251        final_group = VGroup(final_formula, final_box)252        final_group.move_to(axes.c2p(2, 3))253        254        self.play(255            FadeOut(formula_group),256            FadeOut(limit_text),257            Write(final_group),258            run_time=2259        )260        261        self.wait(2)262        263        # 结论264        conclusion = Text("微元法的核心:积分是无限细分后的求和过程", font_size=28)265        conclusion.to_edge(DOWN)266        self.play(Write(conclusion), run_time=2)267        268        self.wait(3)269        270        # 淡出所有元素271        self.play(*[FadeOut(mob) for mob in self.mobjects], run_time=1.5)272 273 274if __name__ == "__main__":275    # 直接渲染场景276    scene = CurvedTrapezoidAreaScene()277    scene.render()

讲解

这个视频从曲边梯形面积入手,把“面积”拆成一连串足够窄的矩形微元。设曲线为 y=f(x)y=f(x),积分区间为 [a,b][a,b],曲线下方的面积可以看成许多小矩形面积的极限。

开场画面先建立坐标系和函数图像,让观众看到曲线 y=f(x)y=f(x) 所在的位置。区域标注部分给出区间端点 a,ba,b,并填充曲线、直线 x=ax=ax=bx=bxx 轴围成的曲边梯形区域。

微元面积

分割步骤把区间 [a,b][a,b] 划分成 nn 个小区间,每个小区间宽度为

Δx=ban.\Delta x=\frac{b-a}{n}.

构造记录使用左端点 xix_i 的函数值作为矩形高度,于是第 ii 个小矩形的面积近似为

ΔAif(xi)Δx.\Delta A_i \approx f(x_i)\Delta x.

微元标注画面高亮其中一个矩形,并用 dxdxf(x)f(x)dAdA 标出微元的宽、高和面积。这里的 dAdA 不是一个孤立公式,而是把局部小矩形和整体面积联系起来的桥。

从求和到积分

面积微元关系写成:

dA=f(x)dx,dA=f(x)\,dx,

因此总面积来自所有微元面积之和:

A=abf(x)dx.A=\int_a^b f(x)\,dx.

更完整地说,先得到有限个矩形的面积和

i=1nf(xi)Δx,\sum_{i=1}^{n} f(x_i)\Delta x,

再让分割无限变细:

A=limni=1nf(xi)Δx=abf(x)dx.A=\lim_{n\to\infty}\sum_{i=1}^{n} f(x_i)\Delta x =\int_a^b f(x)\,dx.

极限画面

极限演示把矩形数量从 88 增加到 16163232。矩形越来越窄,锯齿状近似越来越贴近曲线。最终面积提示强调:当 nn\to\infty 时,矩形面积和趋向曲边梯形的精确面积。

结尾总结微元法的核心:积分不是凭空出现的符号,而是“无限细分后的求和过程”。