微元法可视化

微元法计算转动惯量

围绕微元法计算转动惯量,观察转动惯量、微元法、定积分之间的关系与推理路径。

打开原视频

diameter_moment_of_inertia.py
1from manim import *2import numpy as np3 4class PointMassInertiaScene(ThreeDScene):5    def construct(self):6        # 设置相机7        self.set_camera_orientation(phi=75 * DEGREES, theta=30 * DEGREES)8        self.camera.set_zoom(0.8)9        10        # 标题11        title = Text("质点的转动惯量", font_size=36)12        title.to_corner(UL)13        self.add_fixed_in_frame_mobjects(title)14        self.play(Write(title), run_time=1)15        16        # 创建坐标系17        axes = ThreeDAxes(18            x_range=[-3, 3, 1],19            y_range=[-3, 3, 1],20            z_range=[-1, 3, 1],21            x_length=6,22            y_length=6,23            z_length=424        )25        26        x_label = axes.get_x_axis_label("x")27        y_label = axes.get_y_axis_label("y")28        z_label = axes.get_z_axis_label("z")29        labels = VGroup(x_label, y_label, z_label)30        31        self.play(32            Create(axes),33            Create(labels),34            run_time=1.535        )36        37        # 创建旋转轴(x轴)38        rotation_axis = Line3D(39            start=np.array([-3, 0, 0]),40            end=np.array([3, 0, 0]),41            color=RED42        )43        axis_label = Text("旋转轴", font_size=24).set_color(RED)44        axis_label.next_to(rotation_axis.get_end(), RIGHT)45        self.add_fixed_in_frame_mobjects(axis_label)46        47        self.play(48            Create(rotation_axis),49            Write(axis_label),50            run_time=151        )52        self.wait(0.5)53        54        # 创建质点55        point_position = np.array([1, 2, 0]) # 修改z坐标为0,使点位于xoy平面56        point = Sphere(radius=0.15, color=BLUE).move_to(point_position)57        point_label = Text("质点m", font_size=24).set_color(BLUE)58        point_label.next_to(point, UP+RIGHT)59        self.add_fixed_in_frame_mobjects(point_label)60        61        self.play(62            Create(point),63            Write(point_label),64            run_time=165        )66        self.wait(0.5)67        68        # 显示质点到旋转轴的距离69        # 找到质点到x轴的最短距离点70        projection_point = np.array([point_position[0], 0, 0])71        72        # 创建从质点到投影点的线段(表示垂直距离)73        distance_line = Line3D(74            start=point_position,75            end=projection_point,76            color=GREEN77        )78        79        # 距离标签使用字母r80        distance_label = MathTex("r", font_size=30).set_color(GREEN)81        distance_label.move_to((point_position + projection_point) / 2 + np.array([0.3, 0.3, 0]))82        self.add_fixed_in_frame_mobjects(distance_label)83        84        self.play(85            Create(distance_line),86            Write(distance_label),87            run_time=1.588        )89        self.wait(1)90        91        # 展示转动惯量公式92        formula = MathTex(r"I = mr^2", font_size=36)93        formula.to_edge(RIGHT).shift(UP * 2)94        self.add_fixed_in_frame_mobjects(formula)95        self.play(Write(formula), run_time=1)96        self.wait(1)97        98        # 演示转动99        self.begin_ambient_camera_rotation(rate=0.2)100        101        self.play(102            Rotating(103                point,104                axis=RIGHT,105                about_point=ORIGIN,106                radians=2*PI,107                run_time=4,108                rate_func=linear109            )110        )111        112        # 显示多个质点的转动惯量113        self.stop_ambient_camera_rotation()114        115        # 淡出单个质点的内容116        self.play(117            FadeOut(point),118            FadeOut(point_label),119            FadeOut(distance_line),120            FadeOut(distance_label),121            run_time=1122        )123        124        # 创建多个质点125        points = []126        point_positions = [127            np.array([1, 2, 0]),   # 修改z坐标为0128            np.array([-1, 1, 0]),  # 修改z坐标为0129            np.array([0, -1.5, 0]), # 修改z坐标为0130            np.array([-2, -1, 0])   # 修改z坐标为0131        ]132        133        point_masses = [2, 1, 3, 2]  # 不同质点的质量,仅用于设置半径大小134        135        for i, pos in enumerate(point_positions):136            p = Sphere(radius=0.1 + 0.05 * point_masses[i], color=BLUE).move_to(pos)137            points.append(p)138        139        # 一次性创建所有质点140        self.play(141            *[Create(p) for p in points],142            run_time=1.5143        )144        145        # 为每个质点创建到旋转轴的距离线146        distance_lines = []147        distance_labels = []148        149        for i, pos in enumerate(point_positions):150            proj = np.array([pos[0], 0, 0])151            line = Line3D(start=pos, end=proj, color=GREEN)152            # 使用字母r_i表示距离153            label = MathTex(f"r_{i+1}", font_size=24).set_color(GREEN)154            label_pos = (pos + proj) / 2 + np.array([0.3, 0.3, 0])155            label.move_to(label_pos)156            157            distance_lines.append(line)158            distance_labels.append(label)159            self.add_fixed_in_frame_mobjects(label)160        161        self.play(162            *[Create(line) for line in distance_lines],163            *[Write(label) for label in distance_labels],164            run_time=2165        )166        167        # 计算每个质点的转动惯量贡献 - 使用字母168        inertia_contributions = []169        170        for i in range(4):171            contrib = MathTex(172                f"I_{i+1} = m_{i+1} r_{i+1}^2",173                font_size=24174            )175            inertia_contributions.append(contrib)176        177        # 垂直排列所有贡献178        contributions_group = VGroup(*inertia_contributions).arrange(DOWN, aligned_edge=LEFT)179        contributions_group.to_corner(DL).shift(UP * 2 + RIGHT)180        181        for contrib in inertia_contributions:182            self.add_fixed_in_frame_mobjects(contrib)183            self.play(Write(contrib), run_time=0.8)184        185        # 总和186        total_inertia = MathTex(187            r"I_{\text{total}} = \sum_i I_i = \sum_i m_i r_i^2",188            font_size=30189        )190        total_inertia.next_to(contributions_group, DOWN, aligned_edge=LEFT)191        self.add_fixed_in_frame_mobjects(total_inertia)192        193        self.play(Write(total_inertia), run_time=1.5)194        195        # 强调总和196        total_box = SurroundingRectangle(total_inertia, buff=0.2, color=YELLOW)197        self.add_fixed_in_frame_mobjects(total_box)198        self.play(Create(total_box), run_time=1)199        self.wait(1)200        201        # 展示所有质点同时转动202        self.begin_ambient_camera_rotation(rate=0.15)203        204        self.play(205            *[Rotating(206                p, 207                axis=RIGHT,208                about_point=ORIGIN, 209                radians=2*PI, 210                run_time=4,211                rate_func=linear212            ) for p in points],213            run_time=4214        )215        216        self.stop_ambient_camera_rotation()217        218        # 结论219        conclusion = Text("从离散质点到连续质量分布", font_size=32)220        conclusion.to_edge(DOWN)221        self.add_fixed_in_frame_mobjects(conclusion)222        223        self.play(224            FadeOut(contributions_group),225            FadeOut(total_inertia),226            FadeOut(total_box),227            Write(conclusion),228            run_time=1.5229        )230        231        self.wait(2)232        233        # 淡出所有元素,为下一个场景做准备234        self.play(235            *[FadeOut(mob) for mob in self.mobjects],236            run_time=1.5237        )238 239 240class DiameterMomentOfInertiaScene(ThreeDScene):241    def construct(self):242        # 设置相机243        self.set_camera_orientation(phi=70 * DEGREES, theta=30 * DEGREES)244        self.camera.set_zoom(0.8)245        246        # 标题 - 居中显示247        title = Text("圆盘对直径的转动惯量", font_size=36)248        title.to_edge(UP)  # 居中显示在顶部249        self.add_fixed_in_frame_mobjects(title)250        self.play(Write(title), run_time=1)251        252        # 先创建坐标系253        axes = ThreeDAxes(254            x_range=[-3, 3, 1],255            y_range=[-3, 3, 1],256            z_range=[-1, 3, 1],257            x_length=6,258            y_length=6,259            z_length=4260        )261        262        x_label = axes.get_x_axis_label("x")263        y_label = axes.get_y_axis_label("y")264        z_label = axes.get_z_axis_label("z")265        labels = VGroup(x_label, y_label, z_label)266        267        self.play(268            Create(axes),269            Create(labels),270            run_time=1.5271        )272        273        # 创建圆盘274        disk = Surface(275            lambda u, v: np.array([276                v * np.cos(u),277                v * np.sin(u),278                0279            ]),280            u_range=[0, 2*PI],281            v_range=[0, 2],282            resolution=(24, 10),283            fill_opacity=0.3,284            fill_color=BLUE,285            stroke_color=BLUE_E,286            stroke_width=1287        )288        289        # 创建直径旋转轴(x轴)290        diameter = Line3D(291            start=np.array([-2.5, 0, 0]),292            end=np.array([2.5, 0, 0]),293            color=RED294        )295        axis_label = Text("旋转轴(直径)", font_size=24).set_color(RED)296        axis_label.next_to(diameter.get_end(), RIGHT+UP)297        self.add_fixed_in_frame_mobjects(axis_label)298        299        # 显示圆盘和旋转轴300        self.play(301            Create(disk),302            Create(diameter),303            Write(axis_label),304            run_time=2305        )306        self.wait(1)307        308        # 展示圆盘微元(在圆盘平面内的水平矩形条带)309        strips = []310        strip_heights = []  # 每个条带的y坐标中心位置311        312        num_strips = 10313        strip_colors = [BLUE_B, BLUE_C, BLUE_D, BLUE_E] * 3314        radius = 2  # 圆盘半径315        316        strip_height = (2 * radius) / num_strips  # 每个矩形条带的高度317        318        for i in range(num_strips):319            # 计算条带中心的y坐标320            y_center = -radius + (i + 0.5) * strip_height321            strip_heights.append(y_center)322            323            # 根据圆的方程计算该y坐标处的宽度324            width = 2 * np.sqrt(radius**2 - y_center**2)325            326            # 创建矩形条带327            strip = Rectangle(328                width=width,329                height=strip_height,330                fill_opacity=0.4,331                fill_color=strip_colors[i % len(strip_colors)],332                stroke_color=WHITE,333                stroke_width=1334            )335            336            # 将矩形移动到对应位置337            strip.move_to(np.array([0, y_center, 0]))338            strips.append(strip)339        340        # 一次性绘制所有矩形条带341        self.play(342            *[Create(strip) for strip in strips],343            run_time=1.5344        )345        self.wait(1)346        347        # 高亮显示一个条带 - 保持黄色高亮348        highlight_index = 6349        strips[highlight_index].set_fill(YELLOW, opacity=0.7)350        351        # 标记这个条带的y坐标(到x轴的距离)352        y_center = strip_heights[highlight_index]353        354        # 创建标记线和标签 - 使用更明显的颜色355        distance_line = Line3D(356            start=np.array([0, y_center, 0]),357            end=np.array([0, 0, 0]),358            color=ORANGE359        )360        361        # 创建距离标签 - 使用更明显的颜色362        distance_label = MathTex("r", font_size=30).set_color(ORANGE)363        distance_label.move_to(np.array([0.3, y_center/2, 0.1]))364        self.add_fixed_in_frame_mobjects(distance_label)365        366        # 添加微元标签367        dm_label = MathTex("dm", font_size=26).set_color(YELLOW)368        dm_label.move_to(np.array([1, y_center, 0.1]))369        self.add_fixed_in_frame_mobjects(dm_label)370        371        # 显示标记372        self.play(373            Create(distance_line),374            Write(distance_label),375            Write(dm_label),376            run_time=1.5377        )378        self.wait(1)379        380        # 现在开始显示微元计算公式381        # 首先展示单个微元的转动惯量贡献 - 调整位置382        contribution = MathTex(r"dI = r^2 \cdot dm", font_size=28)383        contribution.next_to(title, DOWN, buff=0.5).align_to(title, LEFT).shift(LEFT * 4)  # 更靠左显示384        self.add_fixed_in_frame_mobjects(contribution)385        self.play(Write(contribution), run_time=1.5)386        387        # 解释微元的特点 - 右移388        explanation = Text("对于平行于y轴的条带微元,r=|y|是常量", font_size=20)389        explanation.next_to(contribution, RIGHT, buff=1.0)390        self.add_fixed_in_frame_mobjects(explanation)391        self.play(Write(explanation), run_time=1.5)392        393        # 添加I=积分dI的表达式394        integral_connection = MathTex(r"I = \iint_{D} dI", font_size=28)395        integral_connection.next_to(contribution, DOWN, buff=0.4).align_to(contribution, LEFT)396        self.add_fixed_in_frame_mobjects(integral_connection)397        self.play(Write(integral_connection), run_time=1.5)398        399        # 添加I=二重积分r^2dm的表示400        r_squared_dm = MathTex(r"I = \iint_{D} r^2 \, dm", font_size=28)401        r_squared_dm.next_to(integral_connection, DOWN, buff=0.4).align_to(integral_connection, LEFT)402        self.add_fixed_in_frame_mobjects(r_squared_dm)403        self.play(Write(r_squared_dm), run_time=1.5)404        self.wait(0.5)  # 减少等待时间405        406        # 展示二重积分形式 - 改用rho表示密度,dsigma表示面积微元407        double_integral = MathTex(r"I = \iint_D y^2 \, \rho \, d\sigma", font_size=24)408        double_integral.next_to(r_squared_dm, DOWN, buff=0.4).align_to(r_squared_dm, LEFT)409        self.add_fixed_in_frame_mobjects(double_integral)410        self.play(Write(double_integral), run_time=1.5)411        412        # 解释二重积分413        integral_explain = Text("D是圆盘区域,dσ是面积微元", font_size=16)414        integral_explain.next_to(double_integral, RIGHT, buff=0.5)415        self.add_fixed_in_frame_mobjects(integral_explain)416        self.play(Write(integral_explain), run_time=1.5)417        self.wait(0.5)  # 减少等待时间418        419        # 极坐标下的积分表达式 - 改用rho表示密度420        polar_integral = MathTex(r"I = \rho \int_{0}^{R} \int_{0}^{2\pi} r^2\sin^2\theta \cdot r \, d\theta \, dr", font_size=22)421        polar_integral.next_to(double_integral, DOWN, buff=0.4).align_to(double_integral, LEFT)422        self.add_fixed_in_frame_mobjects(polar_integral)423        self.play(Write(polar_integral), run_time=1.5)424        self.wait(0.5)  # 减少等待时间425        426        # 极坐标下的解释 - 修复错误427        explanation_1 = Text("ρ: 面密度", font_size=16)428        explanation_2 = Text("r sin θ: 到x轴的距离", font_size=16)429        polar_explanations = VGroup(explanation_1, explanation_2).arrange(DOWN, aligned_edge=LEFT, buff=0.1)430        polar_explanations.next_to(polar_integral, RIGHT, buff=0.5)431        self.add_fixed_in_frame_mobjects(polar_explanations)432        self.play(Write(polar_explanations), run_time=1.5)433        self.wait(0.5)  # 减少等待时间434        435        # 积分计算过程 - 使用rho替代sigma436        calc_1 = MathTex(r"I &= \rho \int_{0}^{R} r^3 \, dr \int_{0}^{2\pi} \sin^2 \theta \, d\theta \\", font_size=20)437        calc_2 = MathTex(r"&= \rho \int_{0}^{R} r^3 \, dr \cdot \pi \\", font_size=20)438        calc_3 = MathTex(r"&= \pi \rho \cdot \frac{R^4}{4} \\", font_size=20)439        calc_4 = MathTex(r"&= \frac{\pi R^2 \rho \cdot R^2}{4} \\", font_size=20)440        calc_5 = MathTex(r"&= \frac{1}{4} M R^2", font_size=20)441        442        calculations = VGroup(calc_1, calc_2, calc_3, calc_4, calc_5).arrange(DOWN, aligned_edge=LEFT, buff=0.15)443        calculations.next_to(polar_integral, DOWN, buff=0.4, aligned_edge=LEFT)444        445        for calc in calculations:446            self.add_fixed_in_frame_mobjects(calc)447            self.play(Write(calc), run_time=0.6)  # 减少每步计算的显示时间448            self.wait(0.1)  # 减少每步之间的等待时间449        450        # 最终结果451        final_box = SurroundingRectangle(calc_5, buff=0.2, color=YELLOW)452        self.add_fixed_in_frame_mobjects(final_box)453        self.play(Create(final_box), run_time=0.8)  # 减少框显示时间454        self.wait(0.2)  # 减少等待时间455        456        # 将最终结果显示在屏幕下方,不使用飞入动画457        final_result = MathTex(r"I = \frac{1}{4} M R^2", font_size=32, color=YELLOW)458        final_result.to_edge(DOWN).shift(UP * 0.5)459        self.add_fixed_in_frame_mobjects(final_result)460        self.play(Write(final_result), run_time=1.0)  # 缩短结果显示时间461        self.wait(0.5)  # 减少最终结果后的等待时间462        463        # 淡出微元划分,只保留整个圆盘464        self.play(465            *[FadeOut(strip) for strip in strips],466            FadeOut(distance_line),467            FadeOut(distance_label),468            FadeOut(dm_label),469            run_time=1.0470        )471        472        # 演示旋转 - 只旋转圆盘473        self.move_camera(phi=90 * DEGREES, theta=0)474        self.begin_ambient_camera_rotation(rate=0.15)475        476        # 只旋转圆盘477        self.play(478            Rotating(479                disk,480                axis=RIGHT,481                radians=2*PI,482                run_time=5,483                rate_func=linear484            ),485            run_time=5486        )487        488        self.stop_ambient_camera_rotation()489        self.wait(2)  # 添加一点等待时间后结束490 491 492class CombinedInertiaScene(ThreeDScene):493    def construct(self):494        # 设置相机495        self.set_camera_orientation(phi=75 * DEGREES, theta=30 * DEGREES)496        self.camera.set_zoom(0.8)497        498        # 标题499        title = Text("转动惯量计算演示", font_size=42)500        title.to_edge(UP)501        self.add_fixed_in_frame_mobjects(title)502        self.play(Write(title), run_time=1.5)503        504        # 介绍文本505        intro = Text("从质点到连续质量分布", font_size=36)506        intro.next_to(title, DOWN, buff=1)507        self.add_fixed_in_frame_mobjects(intro)508        509        self.play(Write(intro), run_time=1.5)510        self.wait(1)511        512        # 淡出介绍513        self.play(514            FadeOut(title),515            FadeOut(intro),516            run_time=1.5517        )518        519        #-------------------------------------------520        # 第一部分:质点的转动惯量521        #-------------------------------------------522        # 标题523        title = Text("质点的转动惯量", font_size=36)524        title.to_edge(UP)  # 改为居中显示525        self.add_fixed_in_frame_mobjects(title)526        self.play(Write(title), run_time=1)527        528        # 创建坐标系529        axes = ThreeDAxes(530            x_range=[-3, 3, 1],531            y_range=[-3, 3, 1],532            z_range=[-1, 3, 1],533            x_length=6,534            y_length=6,535            z_length=4536        )537        538        x_label = axes.get_x_axis_label("x")539        y_label = axes.get_y_axis_label("y")540        z_label = axes.get_z_axis_label("z")541        labels = VGroup(x_label, y_label, z_label)542        543        self.play(544            Create(axes),545            Create(labels),546            run_time=1.5547        )548        549        # 创建旋转轴(x轴)- 修改为x轴550        rotation_axis = Line3D(551            start=np.array([-3, 0, 0]),552            end=np.array([3, 0, 0]),553            color=RED554        )555        axis_label = Text("旋转轴", font_size=24).set_color(RED)556        axis_label.next_to(rotation_axis.get_end(), RIGHT)557        self.add_fixed_in_frame_mobjects(axis_label)558        559        self.play(560            Create(rotation_axis),561            Write(axis_label),562            run_time=1563        )564        self.wait(0.5)565        566        # 创建质点567        point_position = np.array([1, 2, 0]) # 修改z坐标为0,使点位于xoy平面568        point = Sphere(radius=0.15, color=BLUE).move_to(point_position)569        point_label = Text("质点m", font_size=24).set_color(BLUE)570        point_label.next_to(point, UP+RIGHT)571        self.add_fixed_in_frame_mobjects(point_label)572        573        self.play(574            Create(point),575            Write(point_label),576            run_time=1577        )578        self.wait(0.5)579        580        # 显示质点到旋转轴的距离581        # 找到质点到x轴的最短距离点582        projection_point = np.array([point_position[0], 0, 0])583        584        # 创建从质点到投影点的线段(表示垂直距离)585        distance_line = Line3D(586            start=point_position,587            end=projection_point,588            color=GREEN589        )590        591        # 距离标签使用字母r592        distance_label = MathTex("r", font_size=30).set_color(GREEN)593        # 调整标签位置594        distance_label.move_to((point_position + projection_point) / 2 + np.array([0.3, 0.3, 0]))595        self.add_fixed_in_frame_mobjects(distance_label)596        597        self.play(598            Create(distance_line),599            Write(distance_label),600            run_time=1.5601        )602        self.wait(1)603        604        # 展示转动惯量公式605        formula = MathTex(r"I = mr^2", font_size=36)606        formula.to_edge(RIGHT).shift(UP * 2)607        self.add_fixed_in_frame_mobjects(formula)608        self.play(Write(formula), run_time=1)609        self.wait(1)610        611        # 演示转动612        self.begin_ambient_camera_rotation(rate=0.2)613        614        self.play(615            Rotating(616                point,617                axis=RIGHT, # 修改为绕x轴旋转618                about_point=ORIGIN,619                radians=2*PI,620                run_time=4,621                rate_func=linear622            )623        )624        625        # 显示多个质点的转动惯量626        self.stop_ambient_camera_rotation()627        628        # 淡出单个质点的内容629        self.play(630            FadeOut(point),631            FadeOut(point_label),632            FadeOut(distance_line),633            FadeOut(distance_label),634            run_time=1635        )636        637        # 创建多个质点638        points = []639        point_positions = [640            np.array([1, 2, 0]),   # 修改z坐标为0641            np.array([-1, 1, 0]),  # 修改z坐标为0642            np.array([0, -1.5, 0]), # 修改z坐标为0643            np.array([-2, -1, 0])   # 修改z坐标为0644        ]645        646        point_masses = [2, 1, 3, 2]  # 不同质点的质量,仅用于设置半径大小647        648        for i, pos in enumerate(point_positions):649            p = Sphere(radius=0.1 + 0.05 * point_masses[i], color=BLUE).move_to(pos)650            points.append(p)651        652        # 一次性创建所有质点653        self.play(654            *[Create(p) for p in points],655            run_time=1.5656        )657        658        # 为每个质点创建到旋转轴的距离线659        distance_lines = []660        distance_labels = []661        662        for i, pos in enumerate(point_positions):663            proj = np.array([pos[0], 0, 0]) # 修改为到x轴的投影664            line = Line3D(start=pos, end=proj, color=GREEN)665            # 使用字母r_i表示距离666            label = MathTex(f"r_{i+1}", font_size=24).set_color(GREEN)667            label_pos = (pos + proj) / 2 + np.array([0.3, 0.3, 0])668            label.move_to(label_pos)669            670            distance_lines.append(line)671            distance_labels.append(label)672            self.add_fixed_in_frame_mobjects(label)673        674        self.play(675            *[Create(line) for line in distance_lines],676            *[Write(label) for label in distance_labels],677            run_time=2678        )679        680        # 计算每个质点的转动惯量贡献 - 使用字母681        inertia_contributions = []682        683        for i in range(4):684            contrib = MathTex(685                f"I_{i+1} = m_{i+1} r_{i+1}^2",686                font_size=24687            )688            inertia_contributions.append(contrib)689        690        # 垂直排列所有贡献691        contributions_group = VGroup(*inertia_contributions).arrange(DOWN, aligned_edge=LEFT)692        contributions_group.to_corner(DL).shift(UP * 2 + RIGHT)693        694        for contrib in inertia_contributions:695            self.add_fixed_in_frame_mobjects(contrib)696            self.play(Write(contrib), run_time=0.8)697        698        # 总和699        total_inertia = MathTex(700            r"I_{\text{total}} = \sum_i I_i = \sum_i m_i r_i^2",701            font_size=30702        )703        total_inertia.next_to(contributions_group, DOWN, aligned_edge=LEFT)704        self.add_fixed_in_frame_mobjects(total_inertia)705        706        self.play(Write(total_inertia), run_time=1.5)707        708        # 强调总和709        total_box = SurroundingRectangle(total_inertia, buff=0.2, color=YELLOW)710        self.add_fixed_in_frame_mobjects(total_box)711        self.play(Create(total_box), run_time=1)712        self.wait(1)713        714        # 展示所有质点同时转动715        self.begin_ambient_camera_rotation(rate=0.15)716        717        self.play(718            *[Rotating(719                p, 720                axis=RIGHT, # 修改为绕x轴旋转721                about_point=ORIGIN, 722                radians=2*PI, 723                run_time=4,724                rate_func=linear725            ) for p in points],726            run_time=4727        )728        729        self.stop_ambient_camera_rotation()730        731        # 结论和过渡到下一部分732        transition = Text("从离散质点到连续质量分布", font_size=32)733        transition.to_edge(DOWN)734        self.add_fixed_in_frame_mobjects(transition)735        736        self.play(737            FadeOut(contributions_group),738            FadeOut(total_inertia),739            FadeOut(total_box),740            Write(transition),741            run_time=1.5742        )743        744        self.wait(2)745        746        # 淡出所有元素,为下一个场景做准备747        self.play(748            *[FadeOut(mob) for mob in self.mobjects],749            run_time=1.5750        )751        752        #-------------------------------------------753        # 第二部分:圆盘对直径的转动惯量754        #-------------------------------------------755        756        # 重新设置相机757        self.set_camera_orientation(phi=70 * DEGREES, theta=30 * DEGREES)758        self.camera.set_zoom(0.8)759        760        # 标题 - 居中显示761        title = Text("圆盘对直径的转动惯量", font_size=36)762        title.to_edge(UP)  # 居中显示在顶部763        self.add_fixed_in_frame_mobjects(title)764        self.play(Write(title), run_time=1)765        766        # 先创建坐标系767        axes = ThreeDAxes(768            x_range=[-3, 3, 1],769            y_range=[-3, 3, 1],770            z_range=[-1, 3, 1],771            x_length=6,772            y_length=6,773            z_length=4774        )775        776        x_label = axes.get_x_axis_label("x")777        y_label = axes.get_y_axis_label("y")778        z_label = axes.get_z_axis_label("z")779        labels = VGroup(x_label, y_label, z_label)780        781        self.play(782            Create(axes),783            Create(labels),784            run_time=1.5785        )786        787        # 创建圆盘788        disk = Surface(789            lambda u, v: np.array([790                v * np.cos(u),791                v * np.sin(u),792                0793            ]),794            u_range=[0, 2*PI],795            v_range=[0, 2],796            resolution=(24, 10),797            fill_opacity=0.3,798            fill_color=BLUE,799            stroke_color=BLUE_E,800            stroke_width=1801        )802        803        # 创建直径旋转轴(x轴)804        diameter = Line3D(805            start=np.array([-2.5, 0, 0]),806            end=np.array([2.5, 0, 0]),807            color=RED808        )809        axis_label = Text("旋转轴(直径)", font_size=24).set_color(RED)810        axis_label.next_to(diameter.get_end(), RIGHT+UP)811        self.add_fixed_in_frame_mobjects(axis_label)812        813        # 显示圆盘和旋转轴814        self.play(815            Create(disk),816            Create(diameter),817            Write(axis_label),818            run_time=2819        )820        self.wait(1)821        822        # 展示圆盘微元(在圆盘平面内的水平矩形条带)823        strips = []824        strip_heights = []  # 每个条带的y坐标中心位置825        826        num_strips = 10827        strip_colors = [BLUE_B, BLUE_C, BLUE_D, BLUE_E] * 3828        radius = 2  # 圆盘半径829        830        strip_height = (2 * radius) / num_strips  # 每个矩形条带的高度831        832        for i in range(num_strips):833            # 计算条带中心的y坐标834            y_center = -radius + (i + 0.5) * strip_height835            strip_heights.append(y_center)836            837            # 根据圆的方程计算该y坐标处的宽度838            width = 2 * np.sqrt(radius**2 - y_center**2)839            840            # 创建矩形条带841            strip = Rectangle(842                width=width,843                height=strip_height,844                fill_opacity=0.4,845                fill_color=strip_colors[i % len(strip_colors)],846                stroke_color=WHITE,847                stroke_width=1848            )849            850            # 将矩形移动到对应位置851            strip.move_to(np.array([0, y_center, 0]))852            strips.append(strip)853        854        # 一次性绘制所有矩形条带855        self.play(856            *[Create(strip) for strip in strips],857            run_time=1.5858        )859        self.wait(1)860        861        # 高亮显示一个条带 - 保持黄色高亮862        highlight_index = 6863        strips[highlight_index].set_fill(YELLOW, opacity=0.7)864        865        # 标记这个条带的y坐标(到x轴的距离)866        y_center = strip_heights[highlight_index]867        868        # 创建标记线和标签 - 使用更明显的颜色869        distance_line = Line3D(870            start=np.array([0, y_center, 0]),871            end=np.array([0, 0, 0]),872            color=ORANGE873        )874        875        # 创建距离标签 - 使用更明显的颜色876        distance_label = MathTex("r", font_size=30).set_color(ORANGE)877        distance_label.move_to(np.array([0.3, y_center/2, 0.1]))878        self.add_fixed_in_frame_mobjects(distance_label)879        880        # 添加微元标签881        dm_label = MathTex("dm", font_size=26).set_color(YELLOW)882        dm_label.move_to(np.array([1, y_center, 0.1]))883        self.add_fixed_in_frame_mobjects(dm_label)884        885        # 显示标记886        self.play(887            Create(distance_line),888            Write(distance_label),889            Write(dm_label),890            run_time=1.5891        )892        self.wait(1)893        894        # 现在开始显示微元计算公式895        # 首先展示单个微元的转动惯量贡献 - 调整位置896        contribution = MathTex(r"dI = r^2 \cdot dm", font_size=28)897        contribution.next_to(title, DOWN, buff=0.5).align_to(title, LEFT).shift(LEFT * 4)  # 更靠左显示898        self.add_fixed_in_frame_mobjects(contribution)899        self.play(Write(contribution), run_time=1.5)900        901        # 解释微元的特点 - 右移902        explanation = Text("对于平行于y轴的条带微元,r=|y|是形同的", font_size=20)903        explanation.next_to(contribution, RIGHT, buff=1.0)904        self.add_fixed_in_frame_mobjects(explanation)905        self.play(Write(explanation), run_time=1.5)906        907        # 添加I=积分dI的表达式908        integral_connection = MathTex(r"I = \iint_{D} dI", font_size=28)909        integral_connection.next_to(contribution, DOWN, buff=0.4).align_to(contribution, LEFT)910        self.add_fixed_in_frame_mobjects(integral_connection)911        self.play(Write(integral_connection), run_time=1.5)912        913        # 添加I=二重积分r^2dm的表示914        r_squared_dm = MathTex(r"I = \iint_{D} r^2 \, dm", font_size=28)915        r_squared_dm.next_to(integral_connection, DOWN, buff=0.4).align_to(integral_connection, LEFT)916        self.add_fixed_in_frame_mobjects(r_squared_dm)917        self.play(Write(r_squared_dm), run_time=1.5)918        self.wait(0.5)  # 减少等待时间919        920        # 展示二重积分形式 - 改用rho表示密度,dsigma表示面积微元921        double_integral = MathTex(r"I = \iint_D y^2 \, \rho \, d\sigma", font_size=24)922        double_integral.next_to(r_squared_dm, DOWN, buff=0.4).align_to(r_squared_dm, LEFT)923        self.add_fixed_in_frame_mobjects(double_integral)924        self.play(Write(double_integral), run_time=1.5)925        926        # 解释二重积分927        integral_explain = Text("D是圆盘区域,dσ是面积微元", font_size=16)928        integral_explain.next_to(double_integral, RIGHT, buff=0.5)929        self.add_fixed_in_frame_mobjects(integral_explain)930        self.play(Write(integral_explain), run_time=1.5)931        self.wait(0.5)  # 减少等待时间932        933        # 极坐标下的积分表达式 - 改用rho表示密度934        polar_integral = MathTex(r"I = \rho \int_{0}^{R} \int_{0}^{2\pi} r^2\sin^2\theta \cdot r \, d\theta \, dr", font_size=22)935        polar_integral.next_to(double_integral, DOWN, buff=0.4).align_to(double_integral, LEFT)936        self.add_fixed_in_frame_mobjects(polar_integral)937        self.play(Write(polar_integral), run_time=1.5)938        self.wait(0.5)  # 减少等待时间939        940        # 极坐标下的解释 - 修复错误941        explanation_1 = Text("ρ: 面密度", font_size=16)942        explanation_2 = Text("r sin θ: 到x轴的距离", font_size=16)943        polar_explanations = VGroup(explanation_1, explanation_2).arrange(DOWN, aligned_edge=LEFT, buff=0.1)944        polar_explanations.next_to(polar_integral, RIGHT, buff=0.5)945        self.add_fixed_in_frame_mobjects(polar_explanations)946        self.play(Write(polar_explanations), run_time=1.5)947        self.wait(0.5)  # 减少等待时间948        949        # 积分计算过程 - 使用rho替代sigma950        calc_1 = MathTex(r"I &= \rho \int_{0}^{R} r^3 \, dr \int_{0}^{2\pi} \sin^2 \theta \, d\theta \\", font_size=20)951        calc_2 = MathTex(r"&= \rho \int_{0}^{R} r^3 \, dr \cdot \pi \\", font_size=20)952        calc_3 = MathTex(r"&= \pi \rho \cdot \frac{R^4}{4} \\", font_size=20)953        calc_4 = MathTex(r"&= \frac{\pi R^2 \rho \cdot R^2}{4} \\", font_size=20)954        calc_5 = MathTex(r"&= \frac{1}{4} M R^2", font_size=20)955        956        calculations = VGroup(calc_1, calc_2, calc_3, calc_4, calc_5).arrange(DOWN, aligned_edge=LEFT, buff=0.15)957        calculations.next_to(polar_integral, DOWN, buff=0.4, aligned_edge=LEFT)958        959        for calc in calculations:960            self.add_fixed_in_frame_mobjects(calc)961            self.play(Write(calc), run_time=0.6)  # 减少每步计算的显示时间962            self.wait(0.1)  # 减少每步之间的等待时间963        964        # 最终结果965        final_box = SurroundingRectangle(calc_5, buff=0.2, color=YELLOW)966        self.add_fixed_in_frame_mobjects(final_box)967        self.play(Create(final_box), run_time=0.8)  # 减少框显示时间968        self.wait(0.2)  # 减少等待时间969        970        # 将最终结果显示在屏幕下方,不使用飞入动画971        final_result = MathTex(r"I = \frac{1}{4} M R^2", font_size=32, color=YELLOW)972        final_result.to_edge(DOWN).shift(UP * 0.5)973        self.add_fixed_in_frame_mobjects(final_result)974        self.play(Write(final_result), run_time=1.0)  # 缩短结果显示时间975        self.wait(0.5)  # 减少最终结果后的等待时间976        977        # 淡出微元划分,只保留整个圆盘978        self.play(979            *[FadeOut(strip) for strip in strips],980            FadeOut(distance_line),981            FadeOut(distance_label),982            FadeOut(dm_label),983            run_time=1.0984        )985        986        # 演示旋转 - 只旋转圆盘987        self.move_camera(phi=90 * DEGREES, theta=0)988        self.begin_ambient_camera_rotation(rate=0.15)989        990        # 只旋转圆盘991        self.play(992            Rotating(993                disk,994                axis=RIGHT,995                radians=2*PI,996                run_time=5,997                rate_func=linear998            ),999            run_time=51000        )1001        1002        self.stop_ambient_camera_rotation()1003        self.wait(2)  # 添加一点等待时间后结束1004 1005        # 删除以下结束语部分1006        # self.move_camera(phi=70 * DEGREES, theta=30 * DEGREES)1007        # 1008        # end_title = Text("转动惯量计算演示完成", font_size=42)1009        # end_title.to_edge(UP)1010        # self.add_fixed_in_frame_mobjects(end_title)1011        # 1012        # conclusion = Text("从微元到积分的物理意义", font_size=36)1013        # conclusion.next_to(end_title, DOWN, buff=1)1014        # self.add_fixed_in_frame_mobjects(conclusion)1015        # 1016        # self.play(1017        #     FadeOut(title),1018        #     Write(end_title),1019        #     Write(conclusion),1020        #     run_time=21021        # )1022        # self.wait(2)1023        # 1024        # self.play(1025        #     FadeOut(end_title),1026        #     FadeOut(conclusion),1027        #     run_time=1.51028        # )

讲解

这个视频围绕「微元法计算转动惯量」展开。画面把问题、图像和公式放在同一条理解路径中,让抽象关系先被看见。

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

画面中出现的文字「质点的转动惯量」给出视觉入口。随后画面通过对象创建、移动、淡入淡出和高亮,把抽象命题拆成可以跟随的步骤。

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

核心公式可以写成:

I=mr2I = mr^2

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

观察路径

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

本页可以从转动惯量、微元法、定积分、物理量微元这些概念进入,继续沿相邻问题观察同一类数学结构。