我这个程序的最终目标是用弹簧模拟受约束的陀螺,但这是以后的目标,目前我一直在努力了解对象创建、定位和交互如何工作,并最终建立起来.

目前,我一直在try 让我的代码并排产生N个独立的课程,但它们都在同一位置产生.

我try 过很多事情,从try 定义一次创建多个课程的方法,到当前的迭代,我try 使用for循环来创建和移动钟摆的位置,但没有效果.

import numpy as np
import manim as mn

class Pendulum:
    def __init__(self, mass, length, theta):
        self.mass = mass
        self.length = length
        self.g = -9.81
        self.angle = theta
        self.angular_vel = 0

    def step(self, dt):
        # Defining RK4
        def runge_kutta_4(f, t, y0, h=None):
            if h is None:
                h = t[1] - t[0]
            n = len(t)
            y = np.zeros((n, len(y0)))
            y[0] = y0
            for i in range(n - 1):
                k1 = h * f(t[i], y[i])
                k2 = h * f(t[i] + h/2, y[i] + k1/2)
                k3 = h * f(t[i] + h/2, y[i] + k2/2)
                k4 = h * f(t[i] + h, y[i] + k3)
                y[i+1] = y[i] + (k1 + 2*k2 + 2*k3 + k4) / 6
            return y

        def pendulum_equations(t, state):
            theta, omega = state
            force = self.mass * self.g * np.sin(theta)
            torque = force * self.length
            MoI = 1/3 * self.mass * self.length**2
            alpha = torque / MoI
            return np.array([omega, alpha])

        state = np.array([self.angle, self.angular_vel])
        t = np.array([0, dt])
        sol = runge_kutta_4(pendulum_equations, t, state)
        self.angle = sol[-1, 0]
        self.angular_vel = sol[-1, 1]

class PhysicalPendulum(mn.Scene):
    def construct(self):
        p = Pendulum(2, 10, np.pi/2)
        N = 3 # change number of pendulums here
        pendulums = []
        scale = 0.5
        spacing = 3 # Adjust the spacing between pendulums as needed

        def get_pendulum(i, rod_width=0.2, rod_height=1):
            rod = mn.Rectangle(width=rod_width, height=scale * p.length, color=mn.BLUE)
            rod.shift(mn.DOWN * scale * p.length / 2)
            rod.rotate(p.angle, about_point=rod.get_top())
            pendulum = mn.VGroup(rod)
            pendulum.shift(mn.UP * 3) # Adjust the vertical shift as needed
            if i % 2 == 0:
                pendulum.shift(mn.RIGHT * spacing * i)
            else:
                pendulum.shift(mn.LEFT * spacing * i)
            return pendulum

        def step(pendulum, dt, i):
            p.step(dt)
            pendulum.become(get_pendulum(i))

        for i in range(N):
            pendulum = get_pendulum(i)
            pendulum.add_updater(lambda mob, dt: step(mob, dt, i))
            pendulums.append(pendulum)

        self.add(*pendulums)
        self.wait(20)

        for pendulum in pendulums:
            pendulum.remove_updater(step)

这也是我第一次try 面向对象编程,所以我很感激有关如何改进编码风格的任何提示以及对我做错的事情的任何 comments .

推荐答案

这是一个好问题的classic 例子.您的代码几乎完成了.我对此做了一些更改,当我在google.colab中这样做时,您可能需要添加一些内容,

import numpy as np
import manim as mn

class Pendulum:
    g = -9.81  

    def __init__(self, mass, length, theta):
        self.mass = mass
        self.length = length
        self.angle = theta
        self.angular_vel = 0

    def step(self, dt):
        def runge_kutta_4(f, t, y0, h=None):
            if h is None:
                h = t[1] - t[0]
            n = len(t)
            y = np.zeros((n, len(y0)))
            y[0] = y0
            for i in range(n - 1):
                k1 = h * f(t[i], y[i])
                k2 = h * f(t[i] + h/2, y[i] + k1/2)
                k3 = h * f(t[i] + h/2, y[i] + k2/2)
                k4 = h * f(t[i] + h, y[i] + k3)
                y[i+1] = y[i] + (k1 + 2*k2 + 2*k3 + k4) / 6
            return y

        def pendulum_equations(t, state):
            theta, omega = state
            force = self.mass * self.g * np.sin(theta)
            torque = force * self.length
            moment_of_inertia = 1/3 * self.mass * self.length**2
            alpha = torque / moment_of_inertia
            return np.array([omega, alpha])

        state = np.array([self.angle, self.angular_vel])
        t = np.array([0, dt])
        sol = runge_kutta_4(pendulum_equations, t, state)
        self.angle = sol[-1, 0]
        self.angular_vel = sol[-1, 1]

class PhysicalPendulum(mn.Scene):
    def construct(self):
        N = 3  
        pendulums = [Pendulum(2, 10, np.pi/2) for _ in range(N)]
        scale = 0.5
        spacing = 3  
        def get_pendulum(pendulum, i, rod_width=0.2, rod_height=1):
            rod = mn.Rectangle(width=rod_width, height=scale * pendulum.length, color=mn.BLUE)
            rod.shift(mn.DOWN * scale * pendulum.length / 2)
            rod.rotate(pendulum.angle, about_point=rod.get_top())
            pendulum_group = mn.VGroup(rod)
            pendulum_group.shift(mn.UP * 3)  
            pendulum_group.shift(mn.RIGHT * spacing * i) 
            return pendulum_group

        def step(pendulum, dt, i):
            pendulums[i].step(dt)
            pendulum.become(get_pendulum(pendulums[i], i))

        pendulum_groups = []
        for i in range(N):
            pendulum_group = get_pendulum(pendulums[i], i)
            pendulum_group.add_updater(lambda mob, dt, i=i: step(mob, dt, i))  
            pendulum_groups.append(pendulum_group)

        self.add(*pendulum_groups)
        self.wait(20)

        for pendulum_group in pendulum_groups:
            pendulum_group.remove_updater(step)

要在colab中运行它,如果您这样做,您必须做一些事情.在那里安装manin个相当棘手.您需要这样做:

!pip install manim
!apt-get install texlive texlive-latex-extra texlive-fonts-extra texlive-latex-recommended texlive-science dvipng
!apt-get install ffmpeg
!apt-get install sox
!apt-get install libcairo2-dev libjpeg-dev libgif-dev

!pip install manim


要运行代码:

%load_ext manim

%%manim -ql -v WARNING PhysicalPendulum

这是快照:

enter image description here

Python相关问答推荐

在上下文管理器中更改异常类型

通过仅导入pandas来在for循环中进行多情节

Pystata:从Python并行运行stata实例

Python上的Instagram API:缺少client_id参数"

处理带有间隙(空)的duckDB上的重复副本并有效填充它们

图像 pyramid .难以创建所需的合成图像

Python库:可选地支持numpy类型,而不依赖于numpy

如何从在虚拟Python环境中运行的脚本中运行需要宿主Python环境的Shell脚本?

将JSON对象转换为Dataframe

Python Tkinter为特定样式调整所有ttkbootstrap或ttk Button填充的大小,适用于所有主题

matplotlib图中的复杂箭头形状

从列表中获取n个元素,其中list [i][0]== value''

用SymPy在Python中求解指数函数

在用于Python的Bokeh包中设置按钮的样式

如何根据rame中的列值分别分组值

如何将泛型类类型与函数返回类型结合使用?

Pandas:计数器的滚动和,复位

有了Gekko,可以创建子模型或将模型合并在一起吗?

将数字数组添加到Pandas DataFrame的单元格依赖于初始化

无法在盐流道中获得柱子