向量分析可视化

高斯公式与散度

围绕高斯公式与散度,观察高斯公式、散度、通量之间的关系与推理路径。

打开原视频

gauss_theorem.py
1from manim import *2import numpy as np3 4config.tex_template = TexTemplateLibrary.ctex5config.tex_template.add_to_preamble(r"\setCJKmainfont{STSong}")6 7class GaussTheorem(ThreeDScene):8    def construct(self):9        # 创建标题10        title = Text("高斯公式与散度", font="STSong", font_size=48)11        self.add_fixed_in_frame_mobjects(title)12        self.play(Write(title))13        self.wait(1)14        self.play(FadeOut(title))15 16        # 创建3D坐标系17        axes = ThreeDAxes(18            x_range=[-2, 2, 1],19            y_range=[-2, 2, 1],20            z_range=[-2, 2, 1],21            x_length=6,22            y_length=6,23            z_length=624        )25 26        # 设置相机视角27        self.set_camera_orientation(28            phi=70*DEGREES,29            theta=-45*DEGREES30        )31 32        self.play(Create(axes))33        self.wait(1)34 35        # 创建一个球体(作为闭合曲面)36        sphere = Surface(37            lambda u, v: np.array([38                np.cos(u) * np.cos(v),39                np.cos(u) * np.sin(v),40                np.sin(u)41            ]),42            u_range=[-PI/2, PI/2],43            v_range=[0, 2*PI],44            resolution=(20, 40),45            checkerboard_colors=[BLUE_D, BLUE_E],46            fill_opacity=0.347        )48        49        self.play(Create(sphere))50        self.wait(1)51 52        # 创建向外的法向量场53        normal_vectors = VGroup()54        points = [55            (0, 0, 1),    # 顶部56            (0, 0, -1),   # 底部57            (1, 0, 0),    # 右58            (-1, 0, 0),   # 左59            (0, 1, 0),    # 前60            (0, -1, 0),   # 后61        ]62        63        for point in points:64            normal = np.array(point)  # 球面上的点就是其法向量方向65            vector = Arrow3D(66                start=normal,67                end=normal * 1.5,  # 延长法向量68                color=YELLOW,69                thickness=0.0370            )71            normal_vectors.add(vector)72 73        # 修改向量场为从一个偏移点发出74        source_point = np.array([0.3, 0.3, 0.3])  # 源点位置75        field_vectors = VGroup()76        for point in points:77            start = np.array(point) * 0.378            # 计算从源点到表面点的方向79            direction = np.array(point) - source_point80            # 归一化并设置长度81            direction = direction / np.linalg.norm(direction) * 1.582            end = start + direction83            84            vector = Arrow3D(85                start=start,86                end=end,87                color=RED,88                thickness=0.0389            )90            field_vectors.add(vector)91 92        93        # 创建点M处的向量场箭头(将在收缩后显示)94        point_vectors = VGroup()95        for direction in [(1, 0, 0), (-1, 0, 0), (0, 1, 0), 96                         (0, -1, 0), (0, 0, 1), (0, 0, -1)]:97            direction = np.array(direction)98            vector = Arrow3D(99                start=source_point,100                end=source_point + direction * 0.5,  # 较短的箭头101                color=RED,102                thickness=0.02103            )104            point_vectors.add(vector)105 106        # 修改等待时间107        self.play(Create(normal_vectors))108        self.wait(1.5)  # 增加等待时间109        self.play(Create(field_vectors))110        self.wait(2)    # 增加等待时间111 112        # 添加说明文字(右移1.5个单位)113        field_desc = MathTex(114            "\\text{向量场}\\,\\vec{F}",115            color=RED116        ).scale(0.7).to_corner(UL).shift(RIGHT*1.8)117        normal_desc = MathTex(118            "\\text{法向量}\\,\\vec{n}",119            color=YELLOW120        ).scale(0.7).next_to(field_desc, DOWN, buff=0.3)121 122        # 高斯公式123        gauss_formula = MathTex(124            "\\oiint_S \\vec{F} \\cdot \\vec{n} \\, dS = \\iiint_V (\\frac{\\partial F_x}{\\partial x} + \\frac{\\partial F_y}{\\partial y} + \\frac{\\partial F_z}{\\partial z}) \\, dV"125        ).scale(0.6).next_to(normal_desc, DOWN, buff=0.5)126 127        # 单位体积通量128        avg_div_formula = MathTex(129            "\\frac{1}{V} \\oiint_S \\vec{F} \\cdot \\vec{n} \\, dS = \\text{单位体积发出的通量}"130        ).scale(0.6).next_to(gauss_formula, DOWN, buff=0.3)131 132        # 极限公式(先不创建,等到需要时再创建)133 134        # 散度定义135        div_definition = MathTex(136            "\\text{div}\\,\\vec{F}(M) = \\lim_{V \\to 0} \\frac{1}{V} \\oiint_S \\vec{F} \\cdot \\vec{n} \\, dS"137        ).scale(0.6)  # 位置稍后设置138 139        # 物理解释140        explanation = Text(141            "散度表示向量场在点M处的发散强度",142            font="STSong",143            font_size=24144        )  # 位置稍后设置145 146        # 分别显示左边的文字说明147        self.add_fixed_in_frame_mobjects(field_desc)148        self.play(Write(field_desc))149        self.wait(1)    # 增加等待时间150        151        self.add_fixed_in_frame_mobjects(normal_desc)152        self.play(Write(normal_desc))153        self.wait(1)    # 增加等待时间154 155        # 显示高斯公式156        self.add_fixed_in_frame_mobjects(gauss_formula)157        self.play(Write(gauss_formula))158        self.wait(2)    # 增加等待时间159 160        # 显示单位体积通量161        self.add_fixed_in_frame_mobjects(avg_div_formula)162        self.play(Write(avg_div_formula))163        self.wait(2)    # 增加等待时间164 165        # 创建点M(最终收缩的目标点)166        point_M = Dot3D(source_point, color=YELLOW)167        point_M_label = MathTex("M").next_to(point_M, UP+RIGHT, buff=0.1)168        self.add_fixed_in_frame_mobjects(point_M_label)169 170        # 修改收缩动画,从源点位置开始收缩171        shrink_sphere = sphere.copy()172        shrink_vectors = field_vectors.copy()173        shrink_normals = normal_vectors.copy()174        175        # 直接淡出原始对象并显示新对象176        self.play(177            ReplacementTransform(sphere, shrink_sphere),178            ReplacementTransform(field_vectors, shrink_vectors),179            ReplacementTransform(normal_vectors, shrink_normals)180        )181        self.wait(1)    # 增加等待时间182 183        # 添加收缩更新函数184        def shrink_updater(mob, alpha):185            scale = 1 - alpha186            if scale > 0:187                if mob == shrink_sphere:188                    shrink_sphere.scale(scale, about_point=source_point)189                elif mob == shrink_vectors:190                    shrink_vectors.scale(scale, about_point=source_point)191                elif mob == shrink_normals:192                    shrink_normals.scale(scale, about_point=source_point)193 194        # 在收缩动画之前创建极限公式195        limit_formula = MathTex(196            "\\lim_{V \\to 0} \\frac{1}{V} \\oiint_S \\vec{F} \\cdot \\vec{n} \\, dS = \\text{div}\\,\\vec{F}(M)"197        ).scale(0.6).next_to(avg_div_formula, DOWN, buff=0.3)198        self.add_fixed_in_frame_mobjects(limit_formula)199 200        # 执行收缩动画201        self.play(202            UpdateFromAlphaFunc(shrink_sphere, shrink_updater),203            UpdateFromAlphaFunc(shrink_vectors, shrink_updater),204            UpdateFromAlphaFunc(shrink_normals, shrink_updater),205            Write(limit_formula),206            FadeIn(point_M),207            Write(point_M_label),208            run_time=3   # 增加收缩动画时间209        )210        self.wait(1)211 212        # 显示点M处的向量场213        self.play(Create(point_vectors))214        self.wait(1.5)215 216        # 显示散度定义217        div_definition.next_to(limit_formula, DOWN, buff=0.3)218        self.add_fixed_in_frame_mobjects(div_definition)219        self.play(Write(div_definition))220        self.wait(2)    # 增加等待时间221 222        # 显示物理解释223        explanation.next_to(div_definition, DOWN, buff=0.3)224        self.add_fixed_in_frame_mobjects(explanation)225        self.play(Write(explanation))226        self.wait(2)    # 增加等待时间227 228        # 最后的等待时间229        self.wait(4)    # 增加最后的等待时间230 231def main():232    import os233    os.system("manim -pqh gauss_theorem.py GaussTheorem")234 235if __name__ == "__main__":236    main()

讲解

这个视频围绕「高斯公式与散度」展开。画面把问题、图像和公式放在同一条理解路径中,让抽象关系先被看见。

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

画面中出现的文字「高斯公式与散度」给出视觉入口。随后画面通过对象创建、移动、淡入淡出和高亮,把抽象命题拆成可以跟随的步骤。

观察路径

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

本页可以从高斯公式、散度、通量、曲面积分、向量场这些概念进入,继续沿相邻问题观察同一类数学结构。