Manim--旋转联动动画

1. 概要

最近用Manim制作一个数学动画时,用到了一些旋转的动画。

使用Manim来实现单个物体的旋转,或者绕着固定物体旋转都很简单,

但是实现多个物体之间旋转的联动则稍微麻烦一些,

这里借用太阳,地球,月亮的自转公转来介绍下多个物体旋转联动的实现思路,以供参考。

2. 地球自转

地球每天自己旋转一天就是自转

Manim中,自转就是绕着自己的中心点旋转。

python 复制代码
from manim import *

class RevolutionRotation(Scene):
    def construct(self):
        self.rotation()
        self.wait()

    # 自转
    def rotation(self):
        # 这是一个表示地球的图片
        earth = ImageMobject("assets\\earth")
        self.add(earth)

        self.play(
            Rotate(
                earth,
                about_point=ORIGIN,
                angle=2 * PI,
                axis=IN,
                run_time=2,
                rate_func=linear,
            ),
        )

3. 地球绕太阳公转

地球绕着太阳转就是公转

和自转的实现类似,公转就是围绕指定的中心点旋转。

python 复制代码
from manim import *

class RevolutionRotation(Scene):
    def construct(self):
        self.revolution()
        self.wait()

    # 公转
    def revolution(self):
        earth = ImageMobject("assets\\earth")
        sun = ImageMobject("assets\\sun")

        earth.scale(0.3).shift(UP * 2)
        self.add(earth, sun)

        self.play(
            Rotate(
                earth,
                about_point=ORIGIN,
                angle=2 * PI,
                axis=IN,
                run_time=2,
                rate_func=linear,
            ),
        )

4. 太阳,地球和月亮联动

地球绕着太阳转,月亮绕着地球转。

地球绕着太阳旋转和上一步一样,重点在于如何控制月亮的旋转。

我实现的思路是:

  1. 计算地球相对于太阳旋转的角度 <math xmlns="http://www.w3.org/1998/Math/MathML"> α \alpha </math>α
  2. 设置此时月亮相对于地球旋转的角度 <math xmlns="http://www.w3.org/1998/Math/MathML"> β \beta </math>β
  3. 通过Manimupdate机制,当地球旋转 <math xmlns="http://www.w3.org/1998/Math/MathML"> α \alpha </math>α角度之后
  4. 更新月亮相对于地球旋转的角度 <math xmlns="http://www.w3.org/1998/Math/MathML"> β \beta </math>β
  5. 下面的示例中,设置了 <math xmlns="http://www.w3.org/1998/Math/MathML"> β = 5 α \beta = 5\alpha </math>β=5α(设置太大,月亮会旋转太快看不清)
  6. 所以地球绕太阳1圈 时,月亮绕了地球5圈
python 复制代码
from manim import *
import numpy as np

# 求两个向量的夹角
def arccos_angle(a, b):
    cos_angle = np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
    angle = np.arccos(cos_angle)
    return angle

class RevolutionRotation(Scene):
    def construct(self):
        self.rr()
        self.wait()
        
	def rr(self):
        earth = ImageMobject("assets\\earth")
        sun = ImageMobject("assets\\sun")
        moon = ImageMobject("assets\\moon")

        earth.scale(0.4).shift(UP * 2)
        moon.scale(0.2).shift(UP * 2.8)
        self.add(earth, sun, moon)

        # 月亮的旋转角度
        def moon_updater(z):
            # a 是地球初始位置
            a = UP * 2
            # b 是地球当前的位置
            b = earth.get_center()

            # ang是地球相对于太阳旋转的角度
            ang = arccos_angle(a, b)

            # axis控制月亮左旋还是右旋
            axis = IN
            if b[0] < a[0]:
                axis = OUT

            # 不断更新月亮的位置
            return z.become(
                ImageMobject("assets\\moon")
                .move_to(b + np.array([0, 0.8, 0]))
                .scale(0.2)
                .rotate(
                    angle=ang * 5, # 月亮更新的角度是地球旋转的5倍
                    about_point=b,
                    axis=axis,
                )
            )

        moon.add_updater(moon_updater)

        # 地球旋转了1/4暂停一下,为了看效果
        # 此时月亮旋转了1+1/4圈。
        self.play(
            Rotate(
                earth,
                about_point=ORIGIN,
                angle=PI / 2,
                axis=IN,
                run_time=2,
                rate_func=linear,
            ),
        )
        self.wait()

        # 地球旋转剩下来的3/4圈
        self.play(
            Rotate(
                earth,
                about_point=ORIGIN,
                angle=3 * PI / 2,
                axis=IN,
                run_time=4,
                rate_func=linear,
            ),
        )

5. 总结

Manim本身提供的Rotate接口可以实现大部分常见的旋转操作,

本篇主要介绍的是多个物体联动的实现思路。

核心就是每个旋转的物体只要关心它所围绕的物体的位置,根据它所围绕物体的位置来更新自己的位置。

比如,上面的示例中,地球的旋转只要关注太阳的位置,月亮的旋转只要关注地球的位置。

如果有更多的物体联动旋转,也是一样的思路。

相关推荐
柳杉11 小时前
从动漫水面到赛博飞船:这位开发者的Three.js作品太惊艳了
前端·javascript·数据可视化
Triv202518 小时前
太阳能船远程信息处理:CAN数据记录 + Grafana仪表板实战案例
grafana·数据可视化·influxdb·嵌入式系统·can总线·数据采集与监控·智能船舶
lzq6031 天前
如何利用AI生成可视化图表(统计图、流程图、思维导图……)免代码一键绘制图表
人工智能·aigc·数据可视化
柳杉2 天前
两款惊艳的 WebGL 开源项目推荐
前端·javascript·数据可视化
weixin_505154463 天前
博维数孪创新引领,3D作业指导助力制造业升级
大数据·人工智能·3d·数字孪生·数据可视化·产品交互展示
dd_669963 天前
游戏上市公司合同系统实施案例(三):从需求分层到全生命周期管理
游戏·信息可视化·数据可视化
数据小玩子3 天前
精准归因:如何量化分析光伏电站的每一分发电损失?
大数据·人工智能·数据可视化·助睿数智·光伏电站运营
Highcharts.js4 天前
数据可视化不仅属于金融、互联网|农业数据可视化设计:Farmable与Highcharts的前端设计
前端·信息可视化·数据可视化·highcharts·农业可视化
山海鲸实战案例分享5 天前
【数字孪生实战案例】如何通过自定义区域颜色,让地图组件中的特定区域突出显示?~山海鲸可视化
数字孪生·数据可视化·零代码·中国地图·实战案例·山海鲸可视化·自定义区域颜色
FIT2CLOUD飞致云6 天前
安全漏洞修复,图表功能增强,DataEase开源BI工具v2.10.20 LTS版本发布
开源·数据可视化·dataease·bi·数据大屏