VectorField

VectorField

class manimlib.mobject.vector_field.VectorField(func: Callable[[float, float], Sequence[float]], coordinate_system: CoordinateSystem, **kwargs)

向量场

传入的 func 自变量为 x 和 y,返回值为与 x 和 y 相关的二元组

向量将会被绘制在 coordinate_system

  • magnitude_range : 用于梯度颜色的范围

  • color_map : 颜色梯度范围,默认为 3b1b_colormap

  • length_func : 映射向量长度的函数,可改为 linear 表示原长

  • vector_config : 每个向量的属性设置

初始化之后为一系列向量

StreamLines

class manimlib.mobject.vector_field.StreamLines(func: Callable[[float, float], Sequence[float]], coordinate_system: CoordinateSystem, **kwargs)

流线

传入的 func 自变量为 x 和 y,返回值为与 x 和 y 相关的二元组

随机生成一系列起点,并且根据 func 流动形成图形,绘制在 coordinate_system

  • dt : 每次流动的时间(默认为 0.05)

  • arc_len : 弧线长度

  • max_time_steps : 最大流动步数

  • n_samples_per_line : 每条线的采样数

  • color_by_magnitude : 根据距离上色 - magnitude_range : 距离范围

  • color_map : 颜色梯度的范围,默认为 3b1b_colormap

  • cutoff_norm : 运行每条流线的最大长度

AnimatedStreamLines

class manimlib.mobject.vector_field.AnimatedStreamLines(stream_lines: manimlib.mobject.vector_field.StreamLines, **kwargs)

自动实现流动效果的物体(利用 StreamLines 和转化为 updater 的动画)

传入的 stream_lines 为一个 StreamLines 实例

  • lag_range : 延迟的范围

  • line_anim_class : 对每条线执行的动画,默认为 ShowPassingFlash

  • line_anim_config : 对每条线执行动画的属性设置

update(dt: float) → None

更新物件状态,为 动画 (Animation)更新 (updater) 调用

AnimatedStreamLinesExample
class AnimatedStreamLinesExample(Scene):
    def construct(self):
        coord = Axes(x_range=[-7, 7, 1], width=14,
                     y_range=[-4, 4, 1], height=8)
        s = StreamLines(
            lambda x, y: (x * 0.7 + y * 0.5, y * 0.7 - x * 0.5),
            coord,
            magnitude_range=(0.5, 5)
        )
        asl = AnimatedStreamLines(s)
        self.add(coord, asl)
        self.wait(5)

这里附上 GZTime 写的一个示例,读者可以自己尝试渲染一下

https://mkcdn.tonycrane.cc/manimgl_assets/mobject/vector_field/FuncFlow.jpg
AnimatedStreamLinesExample
from manimlib import *


def get_vector_field_and_stream_lines(func, coordinate_system,
                                      magnitude_range=(0.5, 4),
                                      vector_opacity=0.75,
                                      vector_thickness=0.03,
                                      color_by_magnitude=False,
                                      line_color=GREY_A,
                                      line_width=3,
                                      line_opacity=0.75,
                                      sample_freq=5,
                                      n_samples_per_line=10,
                                      arc_len=3,
                                      time_width=0.3,
                                      ):
    vector_field = VectorField(
        func, coordinate_system,
        magnitude_range=magnitude_range,
        vector_config={
            "fill_opacity": vector_opacity,
            "thickness": vector_thickness,
        }
    )

    stream_lines = StreamLines(
        func, coordinate_system,
        step_multiple=1.0 / sample_freq,
        n_samples_per_line=n_samples_per_line,
        arc_len=arc_len,
        magnitude_range=magnitude_range,
        color_by_magnitude=color_by_magnitude,
        stroke_color=line_color,
        stroke_width=line_width,
        stroke_opacity=line_opacity,
    )
    animated_lines = AnimatedStreamLines(
        stream_lines,
        line_anim_config={
            "time_width": time_width,
        },
    )

    return vector_field, animated_lines


class FuncFlow(Scene):
    CONFIG = {
        "field_config": {
            "color_by_magnitude": True,
            "magnitude_range": (0.5, 9),
            "arc_len": 3,
        },
        "plane_config": {
            "x_range": [-8, 8],
            "y_range": [-4, 4],
            "height": 8,
            "width": 16,
        },
        "label_height": 3,
        "run_time": 30,
        "slow_factor": 0.25,
    }

    def construct(self):
        mr = np.array(self.field_config["magnitude_range"])

        self.field_config["magnitude_range"] = self.slow_factor * mr

        plane = NumberPlane(**self.plane_config)
        plane.add_coordinate_labels()

        vector_field, animated_lines = get_vector_field_and_stream_lines(
            self.func, plane,
            **self.field_config,
        )

        func_label = Tex("\\begin{cases} \
            x = x + y \\\\ \
            y = x - y \
            \\end{cases}")
        func_label.to_corner(UR)
        func_label.set_stroke(BLACK, 5, background=True)

        self.add(plane)
        self.add(vector_field)
        self.add(animated_lines)
        self.add(func_label)
        self.wait(self.run_time)

    def func(self, x, y):
        return self.slow_factor * np.array([x + y, x - y])