位置
影片代码 import manimgx as m
class PositionsHero ( m . Scene ):
def construct ( self ) -> None :
plane = m . NumberPlane (
background_line_style = { "stroke_color" : m . GREY_D , "stroke_width" : 1 },
axis_config = { "stroke_color" : m . GREY_B , "stroke_width" : 2 },
)
self . add ( plane )
names = [ "ORIGIN" , "UP" , "DOWN" , "LEFT" , "RIGHT" , "UL" , "UR" , "DL" , "DR" ]
points = [ m . ORIGIN , m . UP , m . DOWN , m . LEFT , m . RIGHT , m . UL , m . UR , m . DL , m . DR ]
dots = m . VGroup ()
labels = m . VGroup ()
for name , point in zip ( names , points , strict = True ):
dot = m . Dot ( 2.5 * point , radius = 0.12 , color = m . YELLOW )
label = m . Text ( name , font = "monospace" , font_size = 30 )
label . next_to ( dot , m . DOWN , buff = 0.2 )
label . add_background_rectangle ( opacity = 1 , buff = 0.05 )
dots . add ( dot )
labels . add ( label )
self . play (
m . LaggedStart ( * [ m . GrowFromCenter ( dot ) for dot in dots ], lag_ratio = 0.1 )
)
self . play ( m . FadeIn ( labels ))
self . wait ()
每个 mobject 在画面中都有一个位置。位置是一个点,即三个数字 [x, y, z],以画面中心为
原点按单位度量。x 向右增长,y 向上增长,z 向屏幕外、朝向观察者增长。画面的短边为 8 个
单位:宽屏视频的 y 范围为 −4 到 4,x 范围约为 −7.1 到 7.1。
mobject 的位置是其包围盒:沿坐标轴方向围绕其绘制内容的最小盒子。其中心、边缘和角都是
该盒子的点。以下方法读取这些点,并移动 mobject 使其中某个点到达你指定的位置。每个方法
都会连同移动 mobject 的组成部分,并返回该 mobject,因此调用可以链式进行:
m.Text("Title").scale(1.5).to_edge(m.UP)。
方向
轴向是单位向量;对角线方向是它们的和。将方向乘以一个数,或将多个方向相加,可以构造其他
点:3 * m.RIGHT + 2 * m.UP 即为 [3, 2, 0]。
m.IN
向屏幕内一个单位,远离观察者:(0, 0, −1)。
m.OUT
向屏幕外一个单位,朝向观察者:(0, 0, 1)。
mobject 的位置
以下每个方法读取 mobject 包围盒的一个点,或其某个坐标。
get_center
mobject 边界框的中心。
返回
该点,以场景坐标表示。
源码
manimgx\mobject.py
def get_center ( self ) -> Point3D :
"""mobject 边界框的中心。
Returns:
该点,以场景坐标表示。
"""
return self . get_critical_point ( np . zeros ( self . dim ))
get_top
mobject 边界框顶边的中点。
返回
该点,以场景坐标表示。
源码
manimgx\mobject.py
def get_top ( self ) -> Point3D :
"""mobject 边界框顶边的中点。
Returns:
该点,以场景坐标表示。
"""
return self . get_critical_point ( UP )
get_bottom
mobject 边界框底边的中点。
返回
该点,以场景坐标表示。
源码
manimgx\mobject.py
def get_bottom ( self ) -> Point3D :
"""mobject 边界框底边的中点。
Returns:
该点,以场景坐标表示。
"""
return self . get_critical_point ( DOWN )
get_left
mobject 边界框左边的中点。
返回
该点,以场景坐标表示。
源码
manimgx\mobject.py
def get_left ( self ) -> Point3D :
"""mobject 边界框左边的中点。
Returns:
该点,以场景坐标表示。
"""
return self . get_critical_point ( LEFT )
get_right
mobject 边界框右边的中点。
返回
该点,以场景坐标表示。
源码
manimgx\mobject.py
def get_right ( self ) -> Point3D :
"""mobject 边界框右边的中点。
Returns:
该点,以场景坐标表示。
"""
return self . get_critical_point ( RIGHT )
get_critical_point
mobject 边界框上的一个点,以方向命名:其中心、
一条边的中点或一个角点。
每个坐标在方向分量为负时取边界框的最低值,为正时取
最高值,为 0 时取中值:UR 命名右上角,UP 命名顶边中点,
ORIGIN 命名中心。该边界框为
boundary_box ,围绕 mobject 绘制的内容:
路径的曲线本身,而非其控制点。
mobject . get_critical_point ( direction )
direction
方向,如 UP、UR 或 ORIGIN。
返回
该点,以场景坐标表示;若 mobject 无点则为原点。
源码
manimgx\mobject.py
def get_critical_point ( self , direction : Vector3DLike ) -> Point3D :
"""mobject 边界框上的一个点,以方向命名:其中心、
一条边的中点或一个角点。
每个坐标在方向分量为负时取边界框的最低值,为正时取
最高值,为 0 时取中值:UR 命名右上角,UP 命名顶边中点,
ORIGIN 命名中心。该边界框为
[boundary_box][manimgx.Mobject.boundary_box],围绕 mobject 绘制的内容:
路径的曲线本身,而非其控制点。
Args:
direction: 方向,如 UP、UR 或 ORIGIN。
Returns:
该点,以场景坐标表示;若 mobject 无点则为原点。
"""
box = self . boundary_box ()
if box is None :
return np . zeros ( self . dim )
lo , hi = box . tolist ()
return np . array (
[
lo [ k ] if d < 0 else hi [ k ] if d > 0 else ( lo [ k ] + hi [ k ]) / 2
for k , d in enumerate ( np . asarray ( direction ) . tolist ()[: self . dim ])
]
)
get_boundary_point
mobject 在某方向上最远的点:在其绘制经过的点中,
沿 direction 方向最远的那个。
与 get_critical_point 不同,它是
这些点之一(对于路径,为其某条曲线的端点),而非 mobject
边界框上的点。
mobject . get_boundary_point ( direction )
返回
该点,以场景坐标表示。
源码
manimgx\mobject.py
def get_boundary_point ( self , direction : Vector3DLike ) -> Point3D :
"""mobject 在某方向上最远的点:在其绘制经过的点中,
沿 `direction` 方向最远的那个。
与 [get_critical_point][manimgx.Mobject.get_critical_point] 不同,它是
这些点之一(对于路径,为其某条曲线的端点),而非 mobject
边界框上的点。
Returns:
该点,以场景坐标表示。
"""
points = self . get_points_defining_boundary ()
return points [ np . argmax ( points @ np . asarray ( direction ))]
get_x
mobject 中心的 x 坐标,或其边界框某边的 x 坐标。
mobject . get_x ( direction = ORIGIN )
direction
LEFT 表示其左边,RIGHT 表示其右边;ORIGIN
(默认)表示其中心。
源码
manimgx\mobject.py
def get_x ( self , direction : Vector3DLike = ORIGIN ) -> float :
"""mobject 中心的 x 坐标,或其边界框某边的 x 坐标。
Args:
direction: LEFT 表示其左边,RIGHT 表示其右边;ORIGIN
(默认)表示其中心。
"""
return self . get_coord ( 0 , direction )
get_y
mobject 中心的 y 坐标,或其边界框某边的 y 坐标。
mobject . get_y ( direction = ORIGIN )
direction
DOWN 表示其底边,UP 表示其顶边;ORIGIN(默认)
表示其中心。
源码
manimgx\mobject.py
def get_y ( self , direction : Vector3DLike = ORIGIN ) -> float :
"""mobject 中心的 y 坐标,或其边界框某边的 y 坐标。
Args:
direction: DOWN 表示其底边,UP 表示其顶边;ORIGIN(默认)
表示其中心。
"""
return self . get_coord ( 1 , direction )
get_z
mobject 中心的 z 坐标,或其边界框某面的 z 坐标。
mobject . get_z ( direction = ORIGIN )
direction
IN 表示其最低 z,OUT 表示其最高 z;ORIGIN(默认)表示
其中心。
源码
manimgx\mobject.py
def get_z ( self , direction : Vector3DLike = ORIGIN ) -> float :
"""mobject 中心的 z 坐标,或其边界框某面的 z 坐标。
Args:
direction: IN 表示其最低 z,OUT 表示其最高 z;ORIGIN(默认)表示
其中心。
"""
return self . get_coord ( 2 , direction )
boundary_box
mobject 的边界框:围绕其家族绘制内容的最小、与坐标轴对齐的框。
路径由其曲线本身测量,而非其控制点(曲线在转折处超出其锚点,
其控制柄超出曲线);其他类型由其点测量。描边宽度不计入。它是
所有度量所读取的唯一边界框:width 和
height ,角点、边和中心
(get_critical_point ),get_x 和 get_y,
对齐和布局,以及颜色渐变的范围。它合并家族各成员的边界框,
因此一个成员在任何持有它的组中跨度相同。
返回
一个 2 × 3 数组,最低 (x, y, z) 然后最高;若家族无点则为
None。
源码
manimgx\mobject.py
def boundary_box ( self ) -> np . ndarray | None :
"""mobject 的边界框:围绕其家族绘制内容的最小、与坐标轴对齐的框。
路径由其曲线本身测量,而非其控制点(曲线在转折处超出其锚点,
其控制柄超出曲线);其他类型由其点测量。描边宽度不计入。它是
所有度量所读取的唯一边界框:[width][manimgx.Mobject.width] 和
[height][manimgx.Mobject.height],角点、边和中心
([get_critical_point][manimgx.Mobject.get_critical_point]),`get_x` 和 `get_y`,
对齐和布局,以及颜色渐变的范围。它合并家族各成员的边界框,
因此一个成员在任何持有它的组中跨度相同。
Returns:
一个 2 × 3 数组,最低 (x, y, z) 然后最高;若家族无点则为
None。
"""
return _family_box ( self . get_family ())
移动 mobject
move_to
代码 import manimgx as m
class MobjectMoveToExample ( m . Scene ):
def construct ( self ) -> None :
dot = m . Dot ([ 3 , 1.5 , 0 ], radius = 0.15 , color = m . YELLOW )
origin = m . Dot ( radius = 0.15 , color = m . RED )
square = m . Square ( color = m . BLUE , fill_opacity = 0.5 ) . shift ( 4 * m . LEFT )
self . add ( dot , origin , square )
self . play ( square . animate . move_to ( dot ))
self . play ( square . animate . move_to ( m . ORIGIN , aligned_edge = m . DL ))
将 mobject 移动到一个点,或到另一个 mobject 上:其中心,或
其边界框上 aligned_edge 所命名的点,到达该处。
mobject . move_to ( point_or_mobject , aligned_edge = ORIGIN , coor_mask = ( 1 , 1 , 1 ))
point_or_mobject
一个点,以场景坐标表示,或一个 mobject:此时为
其边界框上 aligned_edge 所命名的点(默认为其中心)。
aligned_edge
到达该处的 mobject 上的点,以
方向命名:ORIGIN(默认)表示其中心,DL 表示其左下
角。
coor_mask
哪些坐标改变:mobject 沿其移动的每个轴为 1,
保持不变的轴为 0((1, 0, 0) 仅水平移动)。
源码
manimgx\mobject.py
def move_to (
self ,
point_or_mobject : "Point3DLike | Mobject" ,
aligned_edge : Vector3DLike = ORIGIN ,
coor_mask : Vector3DLike = ( 1 , 1 , 1 ),
) -> Self :
"""将 mobject 移动到一个点,或到另一个 mobject 上:其中心,或
其边界框上 `aligned_edge` 所命名的点,到达该处。
Args:
point_or_mobject: 一个点,以场景坐标表示,或一个 mobject:此时为
其边界框上 `aligned_edge` 所命名的点(默认为其中心)。
aligned_edge: 到达该处的 mobject 上的点,以
方向命名:ORIGIN(默认)表示其中心,DL 表示其左下
角。
coor_mask: 哪些坐标改变:mobject 沿其移动的每个轴为 1,
保持不变的轴为 0(`(1, 0, 0)` 仅水平移动)。
Examples:
```python
import manimgx as m
class MobjectMoveToExample(m.Scene):
def construct(self) -> None:
dot = m.Dot([3, 1.5, 0], radius=0.15, color=m.YELLOW)
origin = m.Dot(radius=0.15, color=m.RED)
square = m.Square(color=m.BLUE, fill_opacity=0.5).shift(4 * m.LEFT)
self.add(dot, origin, square)
self.play(square.animate.move_to(dot))
self.play(square.animate.move_to(m.ORIGIN, aligned_edge=m.DL))
```
"""
if isinstance ( point_or_mobject , Mobject ):
target = point_or_mobject . get_critical_point ( aligned_edge )
else :
target = np . asarray ( point_or_mobject , dtype = float )
return self . shift (
( target - self . get_critical_point ( aligned_edge )) * np . asarray ( coor_mask )
)
shift
代码 import manimgx as m
class MobjectShiftExample ( m . Scene ):
def construct ( self ) -> None :
square = m . Square ( color = m . BLUE , fill_opacity = 0.5 )
self . add ( square )
self . play ( square . animate . shift ( 4 * m . LEFT ))
self . play ( square . animate . shift ( 2 * m . UP , 8 * m . RIGHT ))
将 mobject 及其整个家族按一个向量移动。
*vectors
向量,以场景单位表示(2 * RIGHT 将其向右移动两个单位);
多个向量会相加为一个。
源码
manimgx\mobject.py
def shift ( self , * vectors : Vector3DLike ) -> Self :
"""将 mobject 及其整个家族按一个向量移动。
Args:
*vectors: 向量,以场景单位表示(`2 * RIGHT` 将其向右移动两个单位);
多个向量会相加为一个。
Examples:
```python
import manimgx as m
class MobjectShiftExample(m.Scene):
def construct(self) -> None:
square = m.Square(color=m.BLUE, fill_opacity=0.5)
self.add(square)
self.play(square.animate.shift(4 * m.LEFT))
self.play(square.animate.shift(2 * m.UP, 8 * m.RIGHT))
```
"""
# one vector (a (1, 3) array too, as CE takes it)
vector = vectors [ 0 ] if len ( vectors ) == 1 else reduce ( np . add , vectors )
total = np . asarray ( vector , dtype = float ) . reshape ( - 1 )
for mob in self . family_members_with_points ():
mob . _geometry = mob . _geometry . translated ( total )
return self
center
移动 mobject 使其边界框的中心位于原点。
源码
manimgx\mobject.py
def center ( self ) -> Self :
"""移动 mobject 使其边界框的中心位于原点。"""
return self . shift ( - self . get_center ())
set_x
左右移动 mobject 使其中心或边界框的某边
位于 x。
mobject . set_x ( x , direction = ORIGIN )
x
x 坐标,以场景单位表示。
direction
LEFT 放置其左边,RIGHT 放置其右边;ORIGIN
(默认)放置其中心。
源码
manimgx\mobject.py
def set_x ( self , x : float , direction : Vector3DLike = ORIGIN ) -> Self :
"""左右移动 mobject 使其中心或边界框的某边
位于 `x`。
Args:
x: x 坐标,以场景单位表示。
direction: LEFT 放置其左边,RIGHT 放置其右边;ORIGIN
(默认)放置其中心。
"""
return self . set_coord ( x , 0 , direction )
set_y
上下移动 mobject 使其中心或边界框的某边位于
y。
mobject . set_y ( y , direction = ORIGIN )
y
y 坐标,以场景单位表示。
direction
DOWN 放置其底边,UP 放置其顶边;ORIGIN(默认)
放置其中心。
源码
manimgx\mobject.py
def set_y ( self , y : float , direction : Vector3DLike = ORIGIN ) -> Self :
"""上下移动 mobject 使其中心或边界框的某边位于
`y`。
Args:
y: y 坐标,以场景单位表示。
direction: DOWN 放置其底边,UP 放置其顶边;ORIGIN(默认)
放置其中心。
"""
return self . set_coord ( y , 1 , direction )
set_z
内外移动 mobject 使其中心或边界框的某面位于
z。
mobject . set_z ( z , direction = ORIGIN )
z
z 坐标,以场景单位表示。
direction
IN 放置其最低 z,OUT 放置其最高 z;ORIGIN(默认)放置其
中心。
源码
manimgx\mobject.py
def set_z ( self , z : float , direction : Vector3DLike = ORIGIN ) -> Self :
"""内外移动 mobject 使其中心或边界框的某面位于
`z`。
Args:
z: z 坐标,以场景单位表示。
direction: IN 放置其最低 z,OUT 放置其最高 z;ORIGIN(默认)放置其
中心。
"""
return self . set_coord ( z , 2 , direction )
依据另一个 mobject 放置
两个 mobject 之间的间距称为 buff。以下是其常用尺寸。
m.MED_SMALL_BUFF
中偏小间距,以场景单位表示:0.25,是相邻排列的 mobject 之间的默认间距。
m.MED_LARGE_BUFF
中偏大间距,以场景单位表示:0.5,是 mobject 与画面边缘之间的默认间距。
m.DEFAULT_MOBJECT_TO_MOBJECT_BUFFER
相邻排列的 mobject 之间的默认间距,以场景单位表示:0.25
(next_to、arrange)。
m.DEFAULT_MOBJECT_TO_EDGE_BUFFER
mobject 默认与画面边缘保持的间距,以场景单位表示:0.5
(to_edge、to_corner)。
next_to
代码 import manimgx as m
class MobjectNextToExample ( m . Scene ):
def construct ( self ) -> None :
square = m . Square ( side_length = 3 , color = m . BLUE , fill_opacity = 0.5 )
right = m . Text ( "RIGHT" ) . next_to ( square , m . RIGHT )
up = m . Text ( "UP, aligned LEFT" ) . next_to (
square , m . UP , aligned_edge = m . LEFT
)
down = m . Text ( "DOWN, buff=1" ) . next_to ( square , m . DOWN , buff = 1 )
dot = m . Dot ( radius = 0.2 , color = m . YELLOW )
dot . next_to ( square , m . UL , buff = 0 )
self . add ( square , right , up , down , dot )
将 mobject 放在另一个旁边,或一个点旁边,沿某方向
间隔 buff。
mobject 沿 direction 反方向面向的边到达另一个沿该方向面向的边,
再远 buff:使用 RIGHT 时,其左边中点到达另一个右边中点
右侧 buff 处。对角方向(UR)使角对角。
mobject_or_point
要放在其旁边的 mobject(其边界框)或点。
direction
方向:RIGHT(默认)、UP、DL、…
buff
沿 direction 的间距,以场景单位表示(默认 0.25)。
aligned_edge
两个对象在它们相遇侧旁对齐所沿的边,
以方向命名:当方向为 RIGHT 和 UP 时,
它们的顶部对齐(默认 ORIGIN:居中)。
submobject_to_align
要放在另一对象旁边的 mobject 的一部分,代替
其位置;其余部分随其移动。
index_of_submobject_to_align
每个 mobject 中要对齐部分的索引:
此对象的部分放在另一对象的部分旁边。
coor_mask
哪些坐标改变:mobject 沿其移动的每个轴为 1,
保持不变的轴为 0。
源码
manimgx\mobject.py
def next_to (
self ,
mobject_or_point : "Mobject | Point3DLike" ,
direction : Vector3DLike = RIGHT ,
buff : float = DEFAULT_MOBJECT_TO_MOBJECT_BUFFER ,
aligned_edge : Vector3DLike = ORIGIN ,
submobject_to_align : "Mobject | None" = None ,
index_of_submobject_to_align : int | None = None ,
coor_mask : Vector3DLike = ( 1 , 1 , 1 ),
) -> Self :
"""将 mobject 放在另一个旁边,或一个点旁边,沿某方向
间隔 `buff`。
mobject 沿 `direction` 反方向面向的边到达另一个沿该方向面向的边,
再远 `buff`:使用 RIGHT 时,其左边中点到达另一个右边中点
右侧 `buff` 处。对角方向(UR)使角对角。
Args:
mobject_or_point: 要放在其旁边的 mobject(其边界框)或点。
direction: 方向:RIGHT(默认)、UP、DL、…
buff: 沿 `direction` 的间距,以场景单位表示(默认 0.25)。
aligned_edge: 两个对象在它们相遇侧旁对齐所沿的边,
以方向命名:当方向为 RIGHT 和 UP 时,
它们的顶部对齐(默认 ORIGIN:居中)。
submobject_to_align: 要放在另一对象旁边的 mobject 的一部分,代替
其位置;其余部分随其移动。
index_of_submobject_to_align: 每个 mobject 中要对齐部分的索引:
此对象的部分放在另一对象的部分旁边。
coor_mask: 哪些坐标改变:mobject 沿其移动的每个轴为 1,
保持不变的轴为 0。
Examples:
```python
import manimgx as m
class MobjectNextToExample(m.Scene):
def construct(self) -> None:
square = m.Square(side_length=3, color=m.BLUE, fill_opacity=0.5)
right = m.Text("RIGHT").next_to(square, m.RIGHT)
up = m.Text("UP, aligned LEFT").next_to(
square, m.UP, aligned_edge=m.LEFT
)
down = m.Text("DOWN, buff=1").next_to(square, m.DOWN, buff=1)
dot = m.Dot(radius=0.2, color=m.YELLOW)
dot.next_to(square, m.UL, buff=0)
self.add(square, right, up, down, dot)
```
"""
d , edge = (
np . asarray ( direction , dtype = float ),
np . asarray ( aligned_edge , dtype = float ),
)
if isinstance ( mobject_or_point , Mobject ):
target_aligner = (
mobject_or_point
if index_of_submobject_to_align is None
else mobject_or_point [ index_of_submobject_to_align ]
)
target = target_aligner . get_critical_point ( edge + d )
else :
target = np . asarray ( mobject_or_point , dtype = float )
if submobject_to_align is not None :
aligner : Mobject = submobject_to_align
elif index_of_submobject_to_align is not None :
aligner = self [ index_of_submobject_to_align ]
else :
aligner = self
point_to_align = aligner . get_critical_point ( edge - d )
return self . shift (( target - point_to_align + buff * d ) * np . asarray ( coor_mask ))
align_to
代码 import manimgx as m
class MobjectAlignToExample ( m . Scene ):
def construct ( self ) -> None :
floor = m . Line ( 6 * m . LEFT , 6 * m . RIGHT ) . shift ( 3 * m . DOWN )
shapes = m . VGroup (
m . Circle ( color = m . BLUE ),
m . Square ( side_length = 3 , color = m . GREEN ),
m . Triangle ( color = m . YELLOW ),
m . Star ( color = m . RED ),
) . arrange ( buff = 1 )
self . add ( floor , shapes )
self . play ( * ( s . animate . align_to ( floor , m . DOWN ) for s in shapes ))
移动 mobject 使其某侧与另一个对齐:在 direction 不为 0 的每个轴上,
其边界框在该方向上的侧到达另一个对应侧的位置。
align_to(other, UP) 将其顶部放到另一个顶部的高度,仅上下移动;
align_to(other, UL) 同时对齐顶部和左侧。
使用默认 ORIGIN 时,什么也不移动。
mobject . align_to ( mobject_or_point , direction = ORIGIN )
mobject_or_point
要与之对齐的 mobject(其边界框上 direction
命名的侧),或一个点。
direction
侧,以方向命名:UP、DL、…
源码
manimgx\mobject.py
def align_to (
self ,
mobject_or_point : "Mobject | Point3DLike" ,
direction : Vector3DLike = ORIGIN ,
) -> Self :
"""移动 mobject 使其某侧与另一个对齐:在 `direction` 不为 0 的每个轴上,
其边界框在该方向上的侧到达另一个对应侧的位置。
`align_to(other, UP)` 将其顶部放到另一个顶部的高度,仅上下移动;
`align_to(other, UL)` 同时对齐顶部和左侧。
使用默认 ORIGIN 时,什么也不移动。
Args:
mobject_or_point: 要与之对齐的 mobject(其边界框上 `direction`
命名的侧),或一个点。
direction: 侧,以方向命名:UP、DL、…
Examples:
```python
import manimgx as m
class MobjectAlignToExample(m.Scene):
def construct(self) -> None:
floor = m.Line(6 * m.LEFT, 6 * m.RIGHT).shift(3 * m.DOWN)
shapes = m.VGroup(
m.Circle(color=m.BLUE),
m.Square(side_length=3, color=m.GREEN),
m.Triangle(color=m.YELLOW),
m.Star(color=m.RED),
).arrange(buff=1)
self.add(floor, shapes)
self.play(*(s.animate.align_to(floor, m.DOWN) for s in shapes))
```
"""
point = (
mobject_or_point . get_critical_point ( direction )
if isinstance ( mobject_or_point , Mobject )
else np . asarray ( mobject_or_point )
)
for dim in range ( self . dim ):
if direction [ dim ] != 0 :
self . set_coord ( point [ dim ], dim , direction )
return self
match_x
左右移动 mobject 至另一个的 x:中心,或左右
边对齐。
mobject . match_x ( mobject , direction = ORIGIN )
mobject
要匹配的 mobject。
direction
LEFT 对齐左边,RIGHT 对齐右边;ORIGIN
(默认)对齐中心。
源码
manimgx\mobject.py
def match_x ( self , mobject : "Mobject" , direction : Vector3DLike = ORIGIN ) -> Self :
"""左右移动 mobject 至另一个的 x:中心,或左右
边对齐。
Args:
mobject: 要匹配的 mobject。
direction: LEFT 对齐左边,RIGHT 对齐右边;ORIGIN
(默认)对齐中心。
"""
return self . match_coord ( mobject , 0 , direction )
match_y
上下移动 mobject 至另一个的 y:中心,或顶边或底边
对齐。
mobject . match_y ( mobject , direction = ORIGIN )
mobject
要匹配的 mobject。
direction
DOWN 对齐底边,UP 对齐顶边;ORIGIN
(默认)对齐中心。
源码
manimgx\mobject.py
def match_y ( self , mobject : "Mobject" , direction : Vector3DLike = ORIGIN ) -> Self :
"""上下移动 mobject 至另一个的 y:中心,或顶边或底边
对齐。
Args:
mobject: 要匹配的 mobject。
direction: DOWN 对齐底边,UP 对齐顶边;ORIGIN
(默认)对齐中心。
"""
return self . match_coord ( mobject , 1 , direction )
match_z
内外移动 mobject 至另一个的 z:中心,或面对齐。
mobject . match_z ( mobject , direction = ORIGIN )
mobject
要匹配的 mobject。
direction
IN 对齐最低 z,OUT 对齐最高 z;ORIGIN(默认)对齐
中心。
源码
manimgx\mobject.py
def match_z ( self , mobject : "Mobject" , direction : Vector3DLike = ORIGIN ) -> Self :
"""内外移动 mobject 至另一个的 z:中心,或面对齐。
Args:
mobject: 要匹配的 mobject。
direction: IN 对齐最低 z,OUT 对齐最高 z;ORIGIN(默认)对齐
中心。
"""
return self . match_coord ( mobject , 2 , direction )
在画面中放置 mobject
to_edge
代码 import manimgx as m
class MobjectToEdgeExample ( m . Scene ):
def construct ( self ) -> None :
top = m . Text ( "to_edge(UP)" ) . to_edge ( m . UP )
left = m . Text ( "to_edge(LEFT)" ) . to_edge ( m . LEFT )
circle = m . Circle ( color = m . BLUE ) . shift ( 2 * m . DOWN )
circle . to_edge ( m . RIGHT , buff = 0 )
self . add ( top , left , circle )
将 mobject 移到画框的某边,距其 buff 向内;沿该边方向
保持原位。
画框为已配置的画框,以原点为中心,无论相机看向何处。
edge
边:UP、DOWN、LEFT(默认)或 RIGHT。
buff
mobject 与边之间的边距,以场景单位表示(默认
0.5)。
源码
manimgx\mobject.py
def to_edge (
self , edge : Vector3DLike = LEFT , buff : float = DEFAULT_MOBJECT_TO_EDGE_BUFFER
) -> Self :
"""将 mobject 移到画框的某边,距其 `buff` 向内;沿该边方向
保持原位。
画框为已配置的画框,以原点为中心,无论相机看向何处。
Args:
edge: 边:UP、DOWN、LEFT(默认)或 RIGHT。
buff: mobject 与边之间的边距,以场景单位表示(默认
0.5)。
Examples:
```python
import manimgx as m
class MobjectToEdgeExample(m.Scene):
def construct(self) -> None:
top = m.Text("to_edge(UP)").to_edge(m.UP)
left = m.Text("to_edge(LEFT)").to_edge(m.LEFT)
circle = m.Circle(color=m.BLUE).shift(2 * m.DOWN)
circle.to_edge(m.RIGHT, buff=0)
self.add(top, left, circle)
```
"""
return self . align_on_border ( edge , buff )
to_corner
代码 import manimgx as m
class MobjectToCornerExample ( m . Scene ):
def construct ( self ) -> None :
self . add ( m . Text ( "UL" ) . to_corner ( m . UL ))
self . add ( m . Text ( "UR, buff=0" ) . to_corner ( m . UR , buff = 0 ))
self . add ( m . Circle ( color = m . BLUE ) . to_corner ( m . DL ))
self . add ( m . Square ( color = m . YELLOW ) . to_corner ( m . DR , buff = 1 ))
将 mobject 移入画框的某角,距两条边各 buff 向内。
画框为已配置的画框,以原点为中心,无论相机看向何处。
corner
角:UL、UR、DL(默认)或 DR。
buff
mobject 与画框每条边之间的边距,以场景
单位表示(默认 0.5)。
源码
manimgx\mobject.py
def to_corner (
self , corner : Vector3DLike = DL , buff : float = DEFAULT_MOBJECT_TO_EDGE_BUFFER
) -> Self :
"""将 mobject 移入画框的某角,距两条边各 `buff` 向内。
画框为已配置的画框,以原点为中心,无论相机看向何处。
Args:
corner: 角:UL、UR、DL(默认)或 DR。
buff: mobject 与画框每条边之间的边距,以场景
单位表示(默认 0.5)。
Examples:
```python
import manimgx as m
class MobjectToCornerExample(m.Scene):
def construct(self) -> None:
self.add(m.Text("UL").to_corner(m.UL))
self.add(m.Text("UR, buff=0").to_corner(m.UR, buff=0))
self.add(m.Circle(color=m.BLUE).to_corner(m.DL))
self.add(m.Square(color=m.YELLOW).to_corner(m.DR, buff=1))
```
"""
return self . align_on_border ( corner , buff )
shift_onto_screen
将 mobject 移回画框内,当它越过某边或距某边
不足 buff 时:移到该边,向内 buff(参见
to_edge )。
buff
与画框边保持的边距,以场景单位表示(默认
0.5)。
源码
manimgx\mobject.py
def shift_onto_screen ( self , buff : float = DEFAULT_MOBJECT_TO_EDGE_BUFFER ) -> Self :
"""将 mobject 移回画框内,当它越过某边或距某边
不足 `buff` 时:移到该边,向内 `buff`(参见
[to_edge][manimgx.Mobject.to_edge])。
Args:
buff: 与画框边保持的边距,以场景单位表示(默认
0.5)。
"""
radii = ( config . frame_x_radius , config . frame_y_radius )
for vect in ( UP , DOWN , LEFT , RIGHT ):
dim = int ( np . argmax ( np . abs ( vect )))
if np . dot ( self . get_critical_point ( vect ), vect ) > radii [ dim ] - buff :
self . to_edge ( vect , buff = buff )
return self
is_off_screen
mobject 是否完全在画框之外:已配置的画框,以原点为中心。
返回
若其边界框完全越过画框某边则为 True。
源码
manimgx\mobject.py
def is_off_screen ( self ) -> bool :
"""mobject 是否完全在画框之外:已配置的画框,以原点为中心。
Returns:
若其边界框完全越过画框某边则为 True。
"""
x , y = config . frame_x_radius , config . frame_y_radius
return bool (
self . get_left ()[ 0 ] > x
or self . get_right ()[ 0 ] < - x
or self . get_bottom ()[ 1 ] > y
or self . get_top ()[ 1 ] < - y
)
计算点
点是 NumPy 数组,因此可使用 NumPy 进行计算。以下函数完成场景中常见的操作。
interpolate
从一个值到另一个值之间某分数位置上的值:(1 − alpha)·start + alpha·end。
m . interpolate ( start , end , alpha )
start
0 处的值:一个数或一个数组。
end
1 处的值,类型相同。
alpha
从 start 到 end 的距离:0 给出 start,1 给出 end,超出
此范围则沿直线继续延伸;数组则每个元素给一个值。
返回
两者之间的值。
源码
manimgx\drawing\geometry.py
def interpolate [ T ]( start : T , end : T , alpha : float | np . ndarray ) -> T :
"""从一个值到另一个值之间某分数位置上的值:(1 − alpha)·start + alpha·end。
Args:
start: 0 处的值:一个数或一个数组。
end: 1 处的值,类型相同。
alpha: 从 `start` 到 `end` 的距离:0 给出 `start`,1 给出 `end`,超出
此范围则沿直线继续延伸;数组则每个元素给一个值。
Returns:
两者之间的值。
"""
return ( 1 - alpha ) * start + alpha * end # pyright: ignore[reportOperatorIssue] # ty: ignore[unsupported-operator] # T: numbers, arrays
midpoint
两点之间的中点。
p1
一个点。
p2
另一个点。
返回
两点之间的点。
源码
manimgx\drawing\geometry.py
def midpoint ( p1 : Point3D , p2 : Point3D ) -> Point3D :
"""两点之间的中点。
Args:
p1: 一个点。
p2: 另一个点。
Returns:
两点之间的点。
"""
return ( np . asarray ( p1 ) + np . asarray ( p2 )) / 2
normalize
向量方向上的单位向量。
vect
该向量。
返回
该向量除以其长度;零向量保持为零。
源码
manimgx\drawing\geometry.py
def normalize ( vect : Vector3DLike ) -> Vector3D :
"""向量方向上的单位向量。
Args:
vect: 该向量。
Returns:
该向量除以其长度;零向量保持为零。
"""
v = np . asarray ( vect , dtype = float )
norm = np . linalg . norm ( v )
return v / norm if norm > 0 else np . zeros ( len ( v ))
rotate_vector
绕一条过原点的轴旋转后的向量。
m . rotate_vector ( vector , angle , axis = _OUT )
vector
该向量;二维向量的 z 取为 0。
angle
角度,以弧度为单位,从 axis 顶端看去为逆时针方向。
axis
该轴的方向。
返回
旋转后的向量。
源码
manimgx\drawing\geometry.py
def rotate_vector (
vector : Vector3DLike , angle : float , axis : Vector3DLike = _OUT
) -> Vector3D :
"""绕一条过原点的轴旋转后的向量。
Args:
vector: 该向量;二维向量的 z 取为 0。
angle: 角度,以弧度为单位,从 `axis` 顶端看去为逆时针方向。
axis: 该轴的方向。
Returns:
旋转后的向量。
"""
v = np . asarray ( vector , dtype = float )
if len ( v ) == 2 :
v = np . append ( v , 0 )
return rotation_matrix ( angle , axis ) @ v
angle_of_vector
向量在 xy 平面中相对于 x 轴逆时针方向的角度(其 z 被忽略)。
m . angle_of_vector ( vector )
返回
角度,以弧度为单位,从 −π 到 π。
源码
manimgx\drawing\geometry.py
def angle_of_vector ( vector : Vector3DLike ) -> float :
"""向量在 xy 平面中相对于 x 轴逆时针方向的角度(其 z 被忽略)。
Returns:
角度,以弧度为单位,从 −π 到 π。
"""
v = np . asarray ( vector )
return float ( np . angle ( complex ( v [ 0 ], v [ 1 ])))
angle_between_vectors
两个向量之间的夹角。
m . angle_between_vectors ( v1 , v2 )
v1
一个向量。
v2
另一个向量。
返回
角度,以弧度为单位,从 0 到 π。
源码
manimgx\drawing\geometry.py
def angle_between_vectors ( v1 : Vector3DLike , v2 : Vector3DLike ) -> float :
"""两个向量之间的夹角。
Args:
v1: 一个向量。
v2: 另一个向量。
Returns:
角度,以弧度为单位,从 0 到 π。
"""
a , b = normalize ( v1 ), normalize ( v2 )
return float ( 2 * np . arctan2 ( np . linalg . norm ( a - b ), np . linalg . norm ( a + b )))
line_intersection
xy 平面内两条直线的交点,每条直线由两个点确定(其 z 被忽略)。
若两直线平行则引发异常。
m . line_intersection ( line1 , line2 )
line1
第一条直线上的两个点。
line2
第二条直线上的两个点。
返回
交点,其 z 为 0。
源码
manimgx\drawing\geometry.py
def line_intersection ( line1 : Point3DLike_Array , line2 : Point3DLike_Array ) -> Point3D :
"""xy 平面内两条直线的交点,每条直线由两个点确定(其 z 被忽略)。
若两直线平行则引发异常。
Args:
line1: 第一条直线上的两个点。
line2: 第二条直线上的两个点。
Returns:
交点,其 z 为 0。
"""
padded = [
np . pad ( np . array ( line )[:, : 2 ], (( 0 , 0 ), ( 0 , 1 )), constant_values = 1 )
for line in ( line1 , line2 )
]
l1 , l2 = ( np . cross ( * p ) for p in padded )
x , y , z = np . cross ( l1 , l2 )
if z == 0 :
raise ValueError (
"The lines are parallel, there is no unique intersection point."
)
return np . array ([ x / z , y / z , 0 ])
perpendicular_bisector
线段垂直平分线上的两个点,位于垂直于某向量的平面内。
m . perpendicular_bisector ( line , norm_vector = _OUT )
line
线段的两个端点。
norm_vector
平分线所在平面的法向量。
返回
线段中点加上和减去其方向与 norm_vector 的叉积;对于单位法向量,
每个点距中点一个线段长度。
源码
manimgx\drawing\geometry.py
def perpendicular_bisector (
line : Point3DLike_Array , norm_vector : Vector3DLike = _OUT
) -> Point3D_Array :
"""线段垂直平分线上的两个点,位于垂直于某向量的平面内。
Args:
line: 线段的两个端点。
norm_vector: 平分线所在平面的法向量。
Returns:
线段中点加上和减去其方向与 `norm_vector` 的叉积;对于单位法向量,
每个点距中点一个线段长度。
"""
p1 , p2 = np . asarray ( line [ 0 ]), np . asarray ( line [ 1 ])
direction = np . cross ( p1 - p2 , np . asarray ( norm_vector ))
m = midpoint ( p1 , p2 )
return np . array ([ m + direction , m - direction ])
polylabel
多边形的不可及极点:多边形内部离其边最远的点,即标签最佳放置之处。
m . polylabel ( rings , precision = 0.01 )
rings
多边形的各环,每个闭合(首顶点在末尾重复):先是外轮廓,然后是
任意孔洞。其 x 和 y 计数。
precision
所找到的点在距边的距离上至多离最优点多远,以场景单位表示。
返回
所找到的单元,其 c 为该点(x 和 y),d 为其到最近边的距离。
源码
manimgx\drawing\geometry.py
def polylabel ( rings : Sequence [ Point3DLike_Array ], precision : float = 0.01 ) -> Cell :
"""多边形的不可及极点:多边形内部离其边最远的点,即标签最佳放置之处。
Args:
rings: 多边形的各环,每个闭合(首顶点在末尾重复):先是外轮廓,然后是
任意孔洞。其 x 和 y 计数。
precision: 所找到的点在距边的距离上至多离最优点多远,以场景单位表示。
Returns:
所找到的单元,其 `c` 为该点(x 和 y),`d` 为其到最近边的距离。
"""
np_rings : list [ Point2D_Array ] = [ np . asarray ( ring )[:, : 2 ] for ring in rings ]
polygon = Polygon ( np_rings )
mins = np . min ( polygon . array , axis = 0 )
maxs = np . max ( polygon . array , axis = 0 )
dims = maxs - mins
s = np . min ( dims )
h = s / 2.0
queue : list [ Cell ] = []
xv , yv = np . meshgrid ( np . arange ( mins [ 0 ], maxs [ 0 ], s ), np . arange ( mins [ 1 ], maxs [ 1 ], s ))
for corner in np . vstack ([ xv . ravel (), yv . ravel ()]) . T :
heapq . heappush ( queue , Cell ( corner + h , h , polygon ))
best = Cell ( polygon . centroid , 0 , polygon )
bbox = Cell ( mins + dims / 2 , 0 , polygon )
if bbox . d > best . d :
best = bbox
# No inscribed circle is wider than the bounding box.
if best . d >= h :
return best
directions = np . array ([[ - 1 , - 1 ], [ 1 , - 1 ], [ - 1 , 1 ], [ 1 , 1 ]])
while queue :
cell = heapq . heappop ( queue )
if cell . d > best . d :
best = cell
if cell . p - best . d > precision :
h = cell . h / 2.0
offsets = cell . c + directions * h
for offset in offsets :
heapq . heappush ( queue , Cell ( offset , h , polygon ))
return best
inverse_interpolate
某值从一个值到另一个值之间的距离:
interpolate 的逆。
m . inverse_interpolate ( start , end , value )
start
0 处的值。
end
1 处的值。
返回
分数,(value − start) / (end − start)。
源码
manimgx\drawing\geometry.py
def inverse_interpolate ( start : float , end : float , value : float ) -> float :
"""某值从一个值到另一个值之间的距离:
[interpolate][manimgx.interpolate] 的逆。
Args:
start: 0 处的值。
end: 1 处的值。
Returns:
分数,(value − start) / (end − start)。
"""
return float ( np . true_divide ( value - start , end - start ))