多元微积分可视化

曲顶柱体的体积计算

围绕曲顶柱体的体积计算,观察二重积分、曲顶柱体体积、曲顶柱体之间的关系与推理路径。

打开原视频

double_integral_concept.py
1from manim import *2 3class DoubleIntegralConcept(ThreeDScene):4    def construct(self):5        # 先显示标题6        title = Text("曲顶柱体的体积计算", font="SimSun").scale(0.8)7        title.to_corner(UR, buff=0.5)8        self.add_fixed_in_frame_mobjects(title)9        self.play(Write(title))10 11        self.wait(1)  # 给观众时间阅读标题12 13        # 创建3D坐标系14        axes = ThreeDAxes(15            x_range=[0, 2, 0.5],16            y_range=[0, 2, 0.5],17            z_range=[0, 4, 1],18            x_length=6,19            y_length=6,20            z_length=421        ).shift(RIGHT* 4)  # 将坐标系向下平移2个单位22 23        # 定义函数 z = f(x, y) = x^2 + y^224        def func(x, y):25            return x**2 + y**226 27        # 创建曲面28        surface = Surface(29            lambda u, v: axes.c2p(u, v, func(u, v)),30            u_range=[0, 2],31            v_range=[0, 2],32            resolution=(20, 20),33            fill_color=BLUE,34            fill_opacity=0.6,35            should_make_jagged=True36        )37 38        # 创建底部投影区域39        projection = Surface(40            lambda u, v: axes.c2p(u, v, 0),41            u_range=[0, 2],42            v_range=[0, 2],43            fill_color=GREEN,44            fill_opacity=0.3,45            should_make_jagged=True46        )47 48        # 设置网格参数49        dx = dy = 0.2  # 网格大小改为0.250        nx = ny = int(2 / dx)  # 计算网格数量51        52        # 创建网格线53        grid_lines = VGroup()54        55        # x方向的网格线56        for i in range(nx + 1):57            x = i * dx58            line = Line(59                start=axes.c2p(x, 0, 0),60                end=axes.c2p(x, 2, 0),61                color=WHITE,62                stroke_width=263            )64            grid_lines.add(line)65            66        # y方向的网格线67        for j in range(ny + 1):68            y = j * dy69            line = Line(70                start=axes.c2p(0, y, 0),71                end=axes.c2p(2, y, 0),72                color=WHITE,73                stroke_width=274            )75            grid_lines.add(line)76 77        # 创建坐标轴标签78        x_label = axes.get_x_axis_label("x")79        y_label = axes.get_y_axis_label("y")80        z_label = axes.get_z_axis_label("z")81        labels = VGroup(x_label, y_label, z_label)82 83        # 设置相机角度84        self.set_camera_orientation(phi=60 * DEGREES, theta=45 * DEGREES)85        86        # 显示坐标系和标签87        self.play(88            Create(axes),89            Create(labels),90            run_time=191        )92 93        # 显示曲面和投影94        self.play(95            Create(surface),96            Create(projection),97            Create(grid_lines),98            run_time=299        )100        self.wait(1)101 102        # 创建完整的曲顶柱体103        full_prism = VGroup()104        105        # 创建四个竖直面106        vertices = [107            [0, 0, 0],108            [2, 0, 0],109            [2, 2, 0],110            [0, 2, 0]111        ]112        for i in range(4):113            start = vertices[i]114            end = vertices[(i+1)%4]115            points = []116            # 底边两点117            points.append(axes.c2p(*start))118            points.append(axes.c2p(*end))119            # 上边两点(对应曲面上的点)120            points.append(axes.c2p(end[0], end[1], func(end[0], end[1])))121            points.append(axes.c2p(start[0], start[1], func(start[0], start[1])))122            123            side = Polygon(124                *[np.array(p) for p in points],125                fill_color=YELLOW,126                fill_opacity=0.3,127                stroke_width=1,128                stroke_color=WHITE129            )130            full_prism.add(side)131 132        # 显示完整曲顶柱体133        self.play(134            Create(full_prism),135            run_time=1136        )137        self.wait(1)138 139        # 淡出完整曲顶柱体,准备显示分割的小柱体140        self.play(141            FadeOut(full_prism),142            run_time=1143        )144 145        # 创建并显示小柱体146        columns = VGroup()147        148        for i in range(nx):149            for j in range(ny):150                x = i * dx151                y = j * dy152                153                # 计算底面中心点的高度154                center_x = x + dx/2155                center_y = y + dy/2156                height = func(center_x, center_y)  # 使用中心点的函数值157                158                # 创建柱体159                column = Prism(160                    dimensions=[0.6, 0.6, height],161                    fill_color=YELLOW,162                    fill_opacity=0.1,163                    stroke_width=1,164                    stroke_color=WHITE165                )166                167                # 调整柱体位置168                column.move_to(169                    axes.c2p(x + dx/2, y + dy/2, height/2),170                    aligned_edge=ORIGIN171                )172                columns.add(column)173 174                # 添加顶面 - 使用中心点高度175                top_vertices = [176                    axes.c2p(x, y, height),177                    axes.c2p(x + dx, y, height),178                    axes.c2p(x + dx, y + dy, height),179                    axes.c2p(x, y + dy, height)180                ]181                top_face = Polygon(182                    *[np.array(v) for v in top_vertices],183                    fill_color=BLUE,184                    fill_opacity=0.4,185                    stroke_width=1186                )187                columns.add(top_face)188 189        # 分批显示小柱体 - 减少批次以使显示更连续190        n_batches = 3  # 减少批次数量191        columns_list = [columns[i::n_batches] for i in range(n_batches)]192        for batch in columns_list:193            self.play(194                Create(batch),195                run_time=0.8  # 增加运行时间使动画更流畅196            )197 198        # 在右侧创建一个单独的示例柱体199        # 选择一个合适的位置(比如x=1, y=1附近的柱体)200        sample_x = dx * 5201        sample_y = dy * 5202        sample_center_x = sample_x + dx/2203        sample_center_y = sample_y + dy/2204        sample_height = func(sample_center_x, sample_center_y)205 206        # 创建一个新的坐标系用于示例 - 位置调整到y轴延长线上207        sample_axes = ThreeDAxes(208            x_range=[-0.5, 1.5, 0.5],209            y_range=[-0.5, 1.5, 0.5],210            z_range=[0, 4, 1],211            x_length=3,212            y_length=3,213            z_length=4214        ).shift(LEFT * 1 + UP * 4)  # 调整位置到y轴延长线上215 216        # 创建示例柱体217        sample_column = Prism(218            dimensions=[0.6, 0.6, sample_height],219            fill_color=YELLOW,220            fill_opacity=0.3,221            stroke_width=2,  # 示例柱体的边界线可以稍粗一些222            stroke_color=WHITE223        ).move_to(sample_axes.c2p(0.5, 0.5, sample_height/2))224 225        # 创建穿过柱体的曲面部分226        sample_surface = Surface(227            lambda u, v: sample_axes.c2p(228                u, v, 229                func(sample_x + u*dx, sample_y + v*dy)230            ),231            u_range=[0.3, 0.7],232            v_range=[0.3, 0.7],233            resolution=(20, 20),234            fill_color=BLUE,235            fill_opacity=0.8236        )237 238        # 添加连接线,表示这是放大的部分239        start_point = axes.c2p(sample_x, sample_y, func(sample_x, sample_y))240        end_point = sample_axes.c2p(0.6, 0.6, 0)241        connection_line = DashedLine(242            start_point,243            end_point,244            dash_length=0.1,245            color=RED  # 改为红色246        )247        self.play(Create(connection_line))248 249        # 添加示例图形250        self.play(251            Create(sample_axes),252            run_time=1253        )254        self.play(255            Create(sample_column),256            Create(sample_surface),257            run_time=1258        )259 260        # 添加说明标签261        sample_label = Text("局部放大", font="SimSun").scale(0.6)262        sample_label.next_to(sample_axes, UP, buff=0.2)263        self.add_fixed_in_frame_mobjects(sample_label)264        self.play(Write(sample_label))265 266        # 在示例坐标系底面添加dσ符号267        d_sigma = MathTex(r"d\sigma_i").scale(0.6)268        d_sigma.move_to(269            sample_axes.c2p(0.5, 0.5, 0)  # 放在xy平面上270        )271        272        # 添加小柱体体积计算公式 - 放在xoy平面上273        volume_formula = MathTex(274            r"dV = f(\xi_i, \zeta_i)d\sigma"275        ).scale(0.9)276        277        # 将公式放在xoy平面上,不再旋转278        volume_formula.move_to(279            sample_axes.c2p(0.8, 0.3, 0)  # 放在xoy平面上,调整位置避免重叠280        )281 282        # 显示公式283        self.play(284            Write(d_sigma),285            Write(volume_formula),286            run_time=1287        )288 289        self.wait(1)  # 给观众一些时间阅读公式290 291        # 开始相机旋转292        self.begin_ambient_camera_rotation(rate=0.2)293        self.wait(8)294        self.stop_ambient_camera_rotation()295 296        self.wait(2) 297 298        # 移除之前的fixed_in_frame设置299        # self.add_fixed_in_frame_mobjects(d_sigma, volume_formula) 300 301        # 停止相机旋转后,显示二重积分定义式302        integral_formula = MathTex(303            r"V = \iint_D f(x,y)\,d\sigma = \lim_{||T||\to 0} \sum_{i=1}^n f(\xi_i, \zeta_i)\Delta \sigma_i",304        ).scale(0.7)305        306        # 将公式放在屏幕底部并向右平移307        integral_formula.to_edge(DOWN, buff=0.5).shift(RIGHT * 3)308        309        # 添加为固定在屏幕上的元素310        self.add_fixed_in_frame_mobjects(integral_formula)311        312        # 渐变显示公式313        self.play(314            FadeIn(integral_formula),315            run_time=2316        )317 318        self.wait(2)

讲解

这个视频围绕「曲顶柱体的体积计算」展开。画面把问题、图像和公式放在同一条理解路径中,让抽象关系先被看见。

开头先建立问题背景和主要对象,让观察从标题、坐标或第一组关系进入。

画面中出现的文字「曲顶柱体的体积计算」给出视觉入口。随后画面通过对象创建、移动、淡入淡出和高亮,把抽象命题拆成可以跟随的步骤。

随后出现更具体的图像或公式提示,动画会把局部对象和整体结论联系起来。这里可以重点观察变量、曲线、区域或向量如何随镜头推进而变化。

核心公式可以写成:

dσid\sigma_i

这类公式可以和画面中的符号一一对应。

观察路径

观察路径可以分三步:先锁定「曲顶柱体的体积计算」中的核心对象,尤其留意二重积分、曲顶柱体体积、曲顶柱体之间的联系;再跟随画面中变量、图像或向量的变化;最后回到公式或结论,判断局部变化如何支撑整体关系。

本页可以从二重积分、曲顶柱体体积、曲顶柱体、黎曼和极限这些概念进入,继续沿相邻问题观察同一类数学结构。