【manim】之圆规动画

1. 概要

Manim 是一个基于Python的动画库,主要用于创建数学和科学中难以用普通视频制作工具制作的图形和动画。

它提供了各种基础的动画对象,比如,点,线,面,三角形,矩形,立方体等等,

基于它们,可以组合定制出自己需要表达的动画效果。

本篇介绍如何基于Manim封装一个圆规动画。

2. 动画原理

对于单个的元素,manim本身就提供了非常多的动画函数。

比如:创建/消除的动画,移动元素的动画,旋转元素的动画等等,具体可以参考: Animations

但是,对于多个元素联动的动画,则需要编写各个元素之间的联动规则,来封装符合要求的动画。

圆规动画就是多个元素联动的动画,下面演示其如何封装。

圆规动画目的是画一个 圆弧 ,只是在绘制的圆弧的过程中还需要展示了圆弧的起点,终点,

以及绘制过程中动态更新起点终点之间的线。

首先,定义绘制函数:

python 复制代码
def ruler(sc: Scene, p1, p2, color=GREEN, angle=PI, axis=OUT):
    """
    圆规动画


    Parameters
    ---------
    sc
        绘制动画的场景
    p1
        代表圆规的针,绘制时不动的点
    p2
        代表圆规的笔芯,绘制圆弧的点
    color
        圆弧的颜色,默认绿色
    angle
        绘制圆弧的角度,默认PI,相当于绘制半个圆
    axis
        只有2个值 IN/OUT,分别表示顺时针还是逆时针作弧
    """
    # 省略。。。
    return arc

各个参数的含义参见注释。

实现动画的思路如下:

  1. 构建3个元素,即:
    1. d1(根据参数中p1坐标绘制的点)
    2. d2(根据参数中p2坐标绘制的点)
    3. dl(连接p1和p2的虚线)
  2. 设置dl的动画,随着 d1和d2变化不断重新绘制(这里 d1其实是不会变的)
  3. 再设置圆弧的动画,随着 d2的变动,不断绘制新的圆弧(圆弧就是起点到d2的弧)
  4. 通过 manim自带的动画函数让 d2先动,其他动画随之运动
  5. 最后删除不必要的元素,只保留圆弧在 场景(sc)中
python 复制代码
def ruler(sc: Scene, p1, p2, color=GREEN, angle=PI, axis=OUT):
    d1 = Dot(point=p1, color=RED)
    d2 = Dot(point=p2, color=color)
    dl = DashedLine(d1.get_center(), d2.get_center())

    r = np.linalg.norm(p2 - p1)
    arc = ArcBetweenPoints(p2, p2, stroke_width=2)

    dl.add_updater(lambda z: z.become(DashedLine(d1.get_center(), d2.get_center())))
    if np.array_equal(axis, OUT):
        arc.add_updater(
            lambda z: z.become(
                ArcBetweenPoints(
                    p2, d2.get_center(), radius=r, stroke_color=color, stroke_width=2
                )
            )
        )
    if np.array_equal(axis, IN):
        arc.add_updater(
            lambda z: z.become(
                ArcBetweenPoints(
                    d2.get_center(), p2, radius=r, stroke_color=color, stroke_width=2
                )
            )
        )

    sc.add(d1, d2, dl, arc)
    sc.play(
        Rotate(
            d2,
            about_point=d1.get_center(),
            axis=axis,
            angle=angle,
            rate_func=linear,
        )
    )

    arc.clear_updaters()
    dl.clear_updaters()
    sc.remove(d1, d2, dl)
    return arc

3. 动画效果

封装之后,看看使用的效果。

首先,试试按照逆时针(默认是逆时针)和顺时针方式绘制半圆。

python 复制代码
# -*- coding: utf-8 -*-
from manim import *
import numpy as np


class Sample(Scene):
    def construct(self):
        ruler(self, np.array([-1, 0, 0]), np.array([-1, 1, 0]))
        ruler(self, np.array([1, 0, 0]), np.array([1, 1, 0]), axis=IN)
        self.wait()

然后,试试绘制2个圆弧的交叉点。

python 复制代码
class Sample(Scene):
    def construct(self):
        ruler(self, np.array([-1, -1, 0]), np.array([1.1, -0.2222, 0]), angle=PI / 3)
        ruler(
            self,
            np.array([1, -1, 0]),
            np.array([-1.1, -0.2222, 0]),
            axis=IN,
            angle=PI / 3,
        )
        self.wait()

4. 总结

联动动画的实现其实也不难,关键在于先确认起始的动画是哪个元素开始的,

比如,上文中起始动画是由d2发起的。

确定了起始动画,其他元素的联动都要基于起始动画的元素,

比如,上文中的dl和arc元素。

这样,联动的效果就形成了。

我在视频号中基于此做了一个 高斯正17边形的尺规作图动画(weixin.qq.com/sph/AkfwsX)...%25E3%2580%2582 "https://weixin.qq.com/sph/AkfwsX)%E3%80%82")

注: 此链接是视频号中视频的链接,只能在微信中打开。

相关推荐
数安旭说5 小时前
企业终端资产与运行状态自动化审计方案,实现全网终端可视化管控
数据安全·it运维·数据可视化·资产管理·终端安全·终端资产·迪康大成
杨超越luckly1 天前
国庆V型、春节迁徙、五一升温:节假日数据里的中国旅游
agent·旅游·数据可视化·节假日·cpi·国定假日
龙亘川1 天前
健康服务规范化背后,数字化如何 “辅助赋能“
大数据·前端·人工智能·智慧城市·数据可视化
SL_staff2 天前
为什么业务总在等IT跑数?从组织断层看数据可用性落地实践
数据分析·数据可视化·全栈
SL_staff3 天前
为什么业务总在等BI报表?JVS-BI的可视化ELT实践解析
spring·数据分析·数据可视化
龙亘川3 天前
系统监控业务建模:从运行状态监测到异常处置恢复闭环
大数据·人工智能·智慧城市·开源软件·数据可视化
龙亘川3 天前
数字化支撑社保合规治理:亘川智城智慧人社模块实践路径
大数据·人工智能·智慧城市·开源软件·数据可视化
Flynt3 天前
开源"间谍卫星"说数据全是真的,我把它的免key数据源挨个试了一遍
前端·开源·数据可视化
柳杉4 天前
借助 Codex 和可视化工作流,从调研到完整实现,3D 大屏竟然可以这么简单
前端·ai编程·数据可视化
纸片人4 天前
甲方只给了一张卫星截图,我用 Three.js + Blender 建了一座 3D 能源站
three.js·数据可视化