跳转至

点云

影片代码
import manimgx as m
import numpy as np


class PointCloudsHero(m.Scene):
    def construct(self) -> None:
        rng = np.random.default_rng(3)
        angles = rng.uniform(0, 2 * np.pi, 2000)
        radii = 3 * np.sqrt(rng.uniform(0, 1, 2000))
        points = np.stack(
            [radii * np.cos(angles), radii * np.sin(angles), np.zeros(2000)], axis=1
        )
        rgbas = np.array(
            [m.interpolate_color(m.BLUE, m.YELLOW, r / 3).to_rgba() for r in radii]
        )
        cloud = m.PMobject(stroke_width=6).add_points(points, rgbas)
        self.play(m.FadeIn(cloud))
        self.play(m.Rotate(cloud, m.PI / 2), run_time=2)
        self.wait()

点云是以点绘制的 mobject:每个点都是一个具有自身颜色的圆点,宽度等于点云的 描边宽度。点云适合表示数量多且体积小的事物:尘埃、星辰、样本。

PMobject

PMobjectExample
代码
import numpy as np

import manimgx as m


class PMobjectExample(m.Scene):
    def construct(self) -> None:
        t = np.linspace(0, 1, 300)
        spiral = np.column_stack(
            [3.5 * t * np.cos(20 * t), 3.5 * t * np.sin(20 * t), 0 * t]
        )
        colors = m.color_gradient([m.BLUE, m.GREEN, m.YELLOW], len(t))
        rgbas = np.array([color.to_rgba() for color in colors])
        cloud = m.PMobject(stroke_width=15).add_points(spiral, rgbas=rgbas)
        self.add(cloud)

点云:以点形式绘制的 mobject,每个点为自身颜色的圆点。

点通过 add_points 添加,每个带颜色; 样式方法为所有点着色。每个点是宽度为其 stroke_width 描边宽度的圆盘, 每单位宽度为百分之一场景单位:在默认 宽度 4 下,约 720p 帧的 4 像素。

m.PMobject(**kwargs)
color

填充与描边共用的颜色(默认白色);None 表示该类的默认值。

fill_color

填充的颜色;未给出时为 color。多个颜色沿 sheen_direction 构成渐变。

fill_opacity

填充的不透明度,取值从 0 到 1(默认 0:无填充)。

stroke_color

描边的颜色;未给出时为 color。多个颜色构成渐变。

stroke_opacity

描边的不透明度,取值从 0 到 1(默认 1)。

stroke_width

描边的宽度,以场景单位的百分之一计(默认 4;0:无描边)。

background_stroke_color

绘制于填充之后的轮廓颜色(默认黑色)。

background_stroke_opacity

轮廓的不透明度,取值从 0 到 1(默认 1)。

background_stroke_width

轮廓的宽度,以场景单位的百分之一计(默认 0:无)。

sheen_factor

颜色朝 sheen_direction 变亮的程度,取值从 -1 到 1(默认 0); 负值变暗。

sheen_direction

颜色变亮的方向(默认 UL)。

joint_type

描边在路径转折处的连接方式:圆角、斜切或斜接,按二维场景的绘制方式 (参见 LineJointType;默认 AUTO:斜接)。

cap_style

描边在其显示的每一端的端点样式(开放路径的端点、虚线的端点):圆头、平头 或方头,按二维场景的绘制方式(参见 CapStyleType;默认 AUTO:平头)。

shade_in_3d

三维场景的光是否对该 mobject 着色。

material

其表面在三维场景中如何反射场景的光(参见 Material);None:Manim 的着色(默认)。

name

mobject 的名称;未给出时为其类名。

z_index

其在绘制顺序中的位置:索引较高者绘制于较低者之上 (默认 0)。

target

MoveToTarget 将 mobject 移动至的状态。

还接受 样式关键字。

源码

manimgx\mobject.py

def __init__(self, **kwargs: Unpack[Style]) -> None:
    if (
        "color" in kwargs and kwargs["color"] is None
    ):  # not given: the class's default
        del kwargs["color"]
    self.style = style_defaults(type(self)) | kwargs
    """待定的构造器样式,包括类的默认值。基础颜色初始化会消耗此实例条目;
    当前外观保存在 [paint][manimgx.Mobject.paint] 中。点云保留其默认值供后续点使用。"""
    name = self.style.get("name")
    self.name = type(self).__name__ if name is None else name
    """mobject 的名称:其类的名称,除非创建时指定了名称。"""
    self.dim = 3
    """其每个点拥有的坐标数:3。"""
    self.target: Mobject | None = self.style.get("target")
    """[MoveToTarget][manimgx.MoveToTarget] 将 mobject 移动到的状态:由
    [generate_target][manimgx.Mobject.generate_target] 创建,或在创建 mobject 时给定;
    若两者皆无则为 None。"""
    self.z_index = self.style.get("z_index", 0.0)
    """mobject 在绘制顺序中的位置:索引值较高的绘制在索引值较低的之上
    (默认 0);参见 [set_z_index][manimgx.Mobject.set_z_index]。"""
    self.submobjects: list[Mobject] = []
    """mobject 的子对象,按绘制顺序排列:在相同 z 索引下,每个绘制在之前的之上。"""
    self.updaters: list[Updater[Self]] = []
    """mobject 自身的更新器,按运行顺序排列;参见
    [add_updater][manimgx.Mobject.add_updater]。"""
    self.updating_suspended = False
    """mobject 的更新器是否被暂停;参见
    [suspend_updating][manimgx.Mobject.suspend_updating]。"""
    self.paint = _UNPAINTED
    """mobject 自身当前的样式,作为一个值:其颜色、不透明度、
    描边宽度和光泽。样式方法会替换它;它永远不会被就地修改。"""
    self.reset_points()
    self.generate_points()
    self.init_colors()

add_points

在点云自身的点之后添加点,附带其颜色。

pmobject.add_points(points, rgbas=None, color=None, alpha=1.0)
points

点,场景坐标:(n, 3) 数组。

rgbas

颜色,每个点一行红、绿、蓝和不透明度(从 0 到 1); None 则全部使用 color。

color

当 rgbas 为 None 时的颜色;None 为点云的颜色(其 color 样式关键字,默认白色)。

alpha

当 rgbas 为 None 时的不透明度,从 0 到 1。

源码

manimgx\mobject.py

def add_points(
    self,
    points: Point3DLike_Array,
    rgbas: np.ndarray | None = None,
    color: ParsableManimColor | None = None,
    alpha: float = 1.0,
) -> Self:
    """在点云自身的点之后添加点,附带其颜色。

    Args:
        points: 点,场景坐标:(n, 3) 数组。
        rgbas: 颜色,每个点一行红、绿、蓝和不透明度(从 0 到 1);
            None 则全部使用 `color`。
        color: 当 `rgbas` 为 None 时的颜色;None 为点云的颜色(其 `color`
            样式关键字,默认白色)。
        alpha: 当 `rgbas` 为 None 时的不透明度,从 0 到 1。
    """
    points = np.asarray(points, dtype=float).reshape(-1, 3)
    if rgbas is None:
        c = ManimColor(color) if color else self._color()
        rgbas = np.repeat([c.to_rgba_with_alpha(alpha)], len(points), axis=0)
    elif len(rgbas) != len(points):
        raise ValueError("points and rgbas must have same length")
    self.points = np.append(self.points, points, axis=0)
    self.paint = self.paint.but(fill=np.append(self.paint.fill, rgbas, axis=0))
    return self

thin_out

保留家族中每个点云每 factor 个点中的一个,从第一个开始。

pmobject.thin_out(factor=5)
factor

每这么多个点保留一个;必须为正。

源码

manimgx\mobject.py

def thin_out(self, factor: int = 5) -> Self:
    """保留家族中每个点云每 `factor` 个点中的一个,从第一个开始。

    Args:
        factor: 每这么多个点保留一个;必须为正。
    """
    if factor < 1:
        raise ValueError("factor must be positive")
    for mob in self.family_members_with_points():
        mob.points, mob.paint = (
            mob.points[::factor],
            mob.paint.but(fill=mob.paint.fill[::factor].copy()),
        )
    return self

PointCloudDot

PointCloudDotExample
代码
import manimgx as m


class PointCloudDotExample(m.Scene):
    def construct(self) -> None:
        clouds = m.Group(
            m.PointCloudDot(),
            m.PointCloudDot(density=5, stroke_width=8, color=m.BLUE),
            m.PointCloudDot(density=15, stroke_width=4, color=m.RED),
        ).arrange(buff=0.6)
        self.add(clouds)

点圆盘:围绕圆心的点环,未加样式时为纯黄色。

各环相距 1/density 场景单位,从距圆心那么远到刚好在 radius 内,每环上的点 间距约相等。其点很小:stroke_width 为 2。

m.PointCloudDot(center=ORIGIN, radius=2.0, *, density=DEFAULT_POINT_DENSITY_1D, **kwargs)
center

其圆心位置,以场景坐标表示。

radius

其点达到多远,以场景单位计。

density

每场景单位多少环及每环多少点。

color

填充与描边共用的颜色(默认白色);None 表示该类的默认值。

fill_color

填充的颜色;未给出时为 color。多个颜色沿 sheen_direction 构成渐变。

fill_opacity

填充的不透明度,取值从 0 到 1(默认 0:无填充)。

stroke_color

描边的颜色;未给出时为 color。多个颜色构成渐变。

stroke_opacity

描边的不透明度,取值从 0 到 1(默认 1)。

stroke_width

描边的宽度,以场景单位的百分之一计(默认 4;0:无描边)。

background_stroke_color

绘制于填充之后的轮廓颜色(默认黑色)。

background_stroke_opacity

轮廓的不透明度,取值从 0 到 1(默认 1)。

background_stroke_width

轮廓的宽度,以场景单位的百分之一计(默认 0:无)。

sheen_factor

颜色朝 sheen_direction 变亮的程度,取值从 -1 到 1(默认 0); 负值变暗。

sheen_direction

颜色变亮的方向(默认 UL)。

joint_type

描边在路径转折处的连接方式:圆角、斜切或斜接,按二维场景的绘制方式 (参见 LineJointType;默认 AUTO:斜接)。

cap_style

描边在其显示的每一端的端点样式(开放路径的端点、虚线的端点):圆头、平头 或方头,按二维场景的绘制方式(参见 CapStyleType;默认 AUTO:平头)。

shade_in_3d

三维场景的光是否对该 mobject 着色。

material

其表面在三维场景中如何反射场景的光(参见 Material);None:Manim 的着色(默认)。

name

mobject 的名称;未给出时为其类名。

z_index

其在绘制顺序中的位置:索引较高者绘制于较低者之上 (默认 0)。

target

MoveToTarget 将 mobject 移动至的状态。

还接受 样式关键字。

源码

manimgx\mobjects\shapes.py

def __init__(
    self,
    center: Point3DLike = ORIGIN,
    radius: float = 2.0,
    *,
    density: int = DEFAULT_POINT_DENSITY_1D,
    **kwargs: Unpack[Style],
) -> None:
    self.radius = radius
    self.epsilon = 1.0 / density
    super().__init__(density=density, **kwargs)
    self.shift(center)