跳转至

组合形状

影片代码
import manimgx as m


class CombiningShapes(m.Scene):
    def construct(self) -> None:
        def pair() -> m.VGroup:
            return m.VGroup(
                m.Circle(radius=0.9).shift(0.45 * m.LEFT),
                m.Square(side_length=1.6).shift(0.45 * m.RIGHT),
            )

        made = m.VGroup()
        names = ["Union", "Intersection", "Difference", "Exclusion"]
        for kind, name in zip(
            [m.Union, m.Intersection, m.Difference, m.Exclusion], names, strict=True
        ):
            a, b = pair()
            shape = kind(a, b, color=m.BLUE, fill_opacity=0.7)
            outline = m.VGroup(a, b).set_stroke(m.GREY_B, width=2)
            label = m.Text(name, font="monospace", font_size=26).next_to(
                outline, m.DOWN, buff=0.4
            )
            made.add(m.VGroup(outline, shape, label))
        made.arrange(buff=0.6)
        self.play(m.LaggedStart(*[m.Create(cell[0]) for cell in made], lag_ratio=0.15))
        self.play(m.LaggedStart(*[m.FadeIn(cell[1:]) for cell in made], lag_ratio=0.15))
        self.wait()

两个形状重叠时形成三个区域:仅第一个形状所在的区域、仅第二个形状所在的区域,以及两者共同所在的区域。这些类中的每一个都从其中某些区域创建一条新路径,并按你指定的方式设置样式:原始形状保持不变。cutout(挖切)在形状中挖出孔洞,而 convex hull(凸包)如同一条带子般将点包裹起来。

Union

UnionExample
代码
import manimgx as m


class UnionExample(m.Scene):
    def construct(self) -> None:
        square = m.Square(3, color=m.RED, fill_opacity=0.5).shift(4.5 * m.LEFT)
        circle = m.Circle(1.5, color=m.BLUE, fill_opacity=0.5)
        circle.shift(3 * m.LEFT + m.UP)
        union = m.Union(square, circle, color=m.GREEN, fill_opacity=0.8)
        self.add(square, circle, union.shift(7 * m.RIGHT))

形状的并集:任一形状所覆盖的区域,作为新路径;未加样式时为白色。

由各形状自身路径(而非其子对象的)求得,每个为其填充所覆盖的区域,在屏幕平面内: 其 z 坐标被丢弃。形状保持原样。

m.Union(*vmobjects, **kwargs)
*vmobjects

形状:至少两个。

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, *vmobjects: VMobject, **kwargs: Unpack[Style]) -> None:
    if len(vmobjects) < 2:
        raise ValueError("At least 2 mobjects needed for Union.")
    super().__init__(**kwargs)
    outpen = _pathops().Path()
    _pathops().union(
        [
            _to_path(vmobject.points, vmobject.tolerance_for_point_equality)
            for vmobject in vmobjects
        ],
        outpen.getPen(),
    )
    _append_path(self, outpen)

Intersection

IntersectionExample
代码
import manimgx as m


class IntersectionExample(m.Scene):
    def construct(self) -> None:
        square = m.Square(3, color=m.RED, fill_opacity=0.5).shift(4.5 * m.LEFT)
        circle = m.Circle(1.5, color=m.BLUE, fill_opacity=0.5)
        circle.shift(3 * m.LEFT + m.UP)
        common = m.Intersection(square, circle, color=m.GREEN, fill_opacity=0.8)
        self.add(square, circle, common.shift(7 * m.RIGHT))

形状的交集:所有形状共同覆盖的区域,作为新路径;未加样式时为白色。

由各形状自身路径(而非其子对象的)求得,每个为其填充所覆盖的区域,在屏幕平面内: 其 z 坐标被丢弃。形状保持原样。

m.Intersection(*vmobjects, **kwargs)
*vmobjects

形状:至少两个。

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, *vmobjects: VMobject, **kwargs: Unpack[Style]) -> None:
    if len(vmobjects) < 2:
        raise ValueError("At least 2 mobjects needed for Intersection.")
    super().__init__(**kwargs)
    _append_path(self, _combine(_pathops().PathOp.INTERSECTION, *vmobjects))

Difference

DifferenceExample
代码
import manimgx as m


class DifferenceExample(m.Scene):
    def construct(self) -> None:
        square = m.Square(3, color=m.RED, fill_opacity=0.5).shift(4.5 * m.LEFT)
        circle = m.Circle(1.5, color=m.BLUE, fill_opacity=0.5)
        circle.shift(3 * m.LEFT + m.UP)
        cut = m.Difference(square, circle, color=m.GREEN, fill_opacity=0.8)
        self.add(square, circle, cut.shift(7 * m.RIGHT))

两形状的差:第一个覆盖而第二个不覆盖的区域,作为新路径;未加样式时为白色。

由各形状自身路径(而非其子对象的)求得,每个为其填充所覆盖的区域,在屏幕平面内: 其 z 坐标被丢弃。形状保持原样。

m.Difference(subject, clip, **kwargs)
subject

要取其一部分的形状。

clip

其区域被排除的形状。

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, subject: VMobject, clip: VMobject, **kwargs: Unpack[Style]
) -> None:
    super().__init__(**kwargs)
    _append_path(self, _combine(_pathops().PathOp.DIFFERENCE, subject, clip))

Exclusion

ExclusionExample
代码
import manimgx as m


class ExclusionExample(m.Scene):
    def construct(self) -> None:
        square = m.Square(3, color=m.RED, fill_opacity=0.5).shift(4.5 * m.LEFT)
        circle = m.Circle(1.5, color=m.BLUE, fill_opacity=0.5)
        circle.shift(3 * m.LEFT + m.UP)
        either = m.Exclusion(square, circle, color=m.GREEN, fill_opacity=0.8)
        self.add(square, circle, either.shift(7 * m.RIGHT))

两形状的异或:恰一者覆盖而非两者都覆盖的区域,作为新路径;未加样式时为白色。

由各形状自身路径(而非其子对象的)求得,每个为其填充所覆盖的区域,在屏幕平面内: 其 z 坐标被丢弃。形状保持原样。

m.Exclusion(subject, clip, **kwargs)
subject

第一个形状。

clip

第二个形状。

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, subject: VMobject, clip: VMobject, **kwargs: Unpack[Style]
) -> None:
    super().__init__(**kwargs)
    _append_path(self, _combine(_pathops().PathOp.XOR, subject, clip))

Cutout

CutoutExample
代码
import manimgx as m


class CutoutExample(m.Scene):
    def construct(self) -> None:
        holes = [
            m.Circle(0.7).shift(1.3 * m.UL),
            m.Square(1.4).shift(1.3 * m.UR),
            m.Triangle(radius=0.8).shift(1.3 * m.DL),
            m.Star(outer_radius=0.8).shift(1.3 * m.DR),
        ]
        card = m.Cutout(m.Square(5), *holes, color=m.BLUE, fill_opacity=1)
        behind = m.Circle(radius=2.2, color=m.YELLOW, fill_opacity=1)
        self.add(behind, card)

带洞的形状:主形状的轮廓,以其他形状的轮廓为洞;未加样式时为白色。

每个洞的路径与主形状反向运行,因此填充将其排除:作为洞给出的形状被原地翻转 为反向运行。仅使用形状自身的路径,而非其子对象的,且切出形状有自己的样式。

m.Cutout(main_shape, *mobjects, **kwargs)
main_shape

要从中切出洞的形状。

*mobjects

洞的形状,位于其中。

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, main_shape: VMobject, *mobjects: VMobject, **kwargs: Unpack[Style]
) -> None:
    super().__init__(**kwargs)
    self.append_points(main_shape.points)
    sub_direction: Literal["CCW", "CW"] = (
        "CCW" if main_shape.get_direction() == "CW" else "CW"
    )
    for mobject in mobjects:
        self.append_points(mobject.force_direction(sub_direction).points)

ConvexHull

ConvexHullExample
代码
import numpy as np

import manimgx as m


class ConvexHullExample(m.Scene):
    def construct(self) -> None:
        points = np.random.default_rng(7).uniform(-3, 3, (20, 3)) * [1.5, 1, 0]
        hull = m.ConvexHull(*points, color=m.YELLOW, fill_opacity=0.3)
        self.add(hull, *(m.Dot(point, radius=0.1) for point in points))

点的凸包:包围所有点的最小凸多边形,其顶点取自其中;未加样式时为蓝色。

在屏幕平面内求解:点的 z 坐标被忽略。

m.ConvexHull(*points, tolerance=1e-05, **kwargs)
*points

点:至少三个,不全部共线。

tolerance

点在包外多远仍可不成为其顶点,以场景单位计。

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, *points: Point3DLike, tolerance: float = 1e-05, **kwargs: Unpack[Style]
) -> None:
    array = np.array(points)[:, :2]
    hull = QuickHull(tolerance)
    hull.build(array)
    facets = set(hull.facets) - hull.removed
    facet = facets.pop()
    subfacets = list(facet.subfacets)
    while len(subfacets) <= len(facets):
        sf = subfacets[-1]
        (facet,) = hull.neighbors[sf] - {facet}
        (sf,) = facet.subfacets - {sf}
        subfacets.append(sf)
    coordinates = np.vstack([sf.coordinates for sf in subfacets])
    vertices = np.hstack((coordinates, np.zeros((len(coordinates), 1))))
    super().__init__(vertices, **kwargs)