python动画:manim中的目标位置移动,线条末端和两条线相切的位置处理

news2024/11/8 6:35:08

一,Manim中目标的位置移动

在 Manim 中,shift 函数用于在三维空间或二维平面上对对象进行平移。通过 shift 方法,用户可以快速移动场景中的物体,指定移动的方向和距离。方向通常由预定义的常量(如 UPDOWNLEFTRIGHTINOUT 等)来表示。这些常量代表了坐标系中的特定方向,例如,UP 表示在 Y 轴正方向上移动一个单位,而 RIGHT 则表示在 X 轴正方向上移动许多单位。

使用 shift 方法,可以将任何基于 Mobject 的对象(如图形、文本等)沿着指定的方向进行移动,这在动画制作中尤为重要。例如,可以通过 shift(UP) 将对象向上移动,从而在场景中创建生动的动画效果。结合其他动画方法,shift 可以有效地增强场景的表现力,使得图形的移动更加流畅和自然。这使得 Manim 成为制作数学视频和可视化工具的强大工具。

  1. ORIGIN(原点):表示三维坐标系统中的点 (0, 0, 0),是所有其他坐标的参考点。

  2. UP(向上):表示在正 Y 方向移动一个单位,通常对应于三维空间中的向上。

  3. DOWN(向下):表示在负 Y 方向移动一个单位,通常对应于三维空间中的向下。

  4. RIGHT(向右):表示在正 X 方向移动一个单位,通常对应于平面或立体空间中的向右。

  5. LEFT(向左):表示在负 X 方向移动一个单位,通常对应于向左的方向。

  6. IN(向内):表示在负 Z 方向移动一个单位,通常意味着朝屏幕内或者远离观察者的方向。

  7. OUT(向外):表示在正 Z 方向移动一个单位,通常意味着朝观察者或者屏幕外的方向。

  8. UL(左上):表示向上移动一个单位,然后向左移动一个单位。

  9. UR(右上):表示向上移动一个单位,然后向右移动一个单位。

  10. DL(左下):表示向下移动一个单位,然后向左移动一个单位。

  11. DR(右下):表示向下移动一个单位,然后向右移动一个单位。

  12. PI(圆周率):是圆的周长与直径的比值,约为3.14159。

  13. TAU(双圆周率):是圆的周长与半径的比值,等于2PI,约为6.28318。

  14. DEGREES(度数):表示弧度与角度之间的换算关系。通常用于在计算中进行角度转换。

 

from manim import *  

class CoordinateSystem(Scene):  
    def construct(self):  
        # 创建坐标系  
        axes = Axes(  
            x_range=(-5, 5, 1),  
            y_range=(-5, 5, 1),  
            axis_config={"color": BLUE},  
        )  

        # 显示坐标系  
        self.play(Create(axes))  

        # 创建一个点在原点  
        point = Dot(ORIGIN,radius=0.25, color=YELLOW)  
        self.play(FadeIn(point))  

        # 向上移动  
        self.play(point.animate.shift(UP))  
        self.wait(1)  

        # 向下移动  
        self.play(point.animate.shift(DOWN))  
        self.wait(1)  

        # 向右移动  
        self.play(point.animate.shift(RIGHT))  
        self.wait(1)  

        # 向左移动  
        self.play(point.animate.shift(LEFT))  
        self.wait(1)  

        # 向内移动  
        self.play(point.animate.shift(IN))  
        self.wait(1)  

        # 向外移动  
        self.play(point.animate.shift(OUT))  
        self.wait(1)  

        # 组合移动:左上  
        self.play(point.animate.shift(UL))  
        self.wait(1)  

        # 组合移动:右上  
        self.play(point.animate.shift(UR))  
        self.wait(1)  

        # 组合移动:左下  
        self.play(point.animate.shift(DL))  
        self.wait(1)  

        # 组合移动:右下  
        self.play(point.animate.shift(DR))  
        self.wait(1)  

        # 结束演示  
        self.play(FadeOut(point), FadeOut(axes))  

 二,设置线条的端点样式【CapStyleType】

在计算机图形学中,线条的端点样式(也称为线帽样式)对于实现图形的视觉效果至关重要。manim 库中的 CapStyleType 是一个用于设置线条端点样式的工具,提供了多种选项来定义线条的外观,从而加强视觉表现和美观程度。

常见的线条端点样式主要有三种:圆形(Round)、方形(Square)和平头(Butt)。圆形样式使得线条的两端呈现出光滑的半圆形效果,这种样式通常用于需要增加视觉柔和感的场景,例如演示动画中的渐变线条。方形样式的端点则是平坦的方形,这种效果给人一种坚固和明确的感觉,常用于技术化或现代风格的设计中。平头样式是直接剪裁在极限位置,没有任何延伸部分,因此在许多设计中应用广泛,例如用于描绘精确的几何形状时。

通过选择不同的 CapStyleType,用户可以在构建动画或插图时,根据特定情境强调或隐藏线条的特性。这种灵活性不仅增强了图形的可读性,还支持创作个性化的艺术风格,使得视觉表达更具吸引力和独特性。

构造函数

CapStyleType(value, names=None, *, module=None, qualname=None, type=None,
 start=1, boundary=None)

参数解释:

  1. value: 该样式的值,通常是一个整数,代表具体的线条样式。
  2. names: 可选的样式名称,可以是字符串或其他可迭代对象,描述该样式的名称。
  3. module: 指定定义此类型的模块。一般在使用 manim 时,这个参数会自动处理。
  4. qualname: 完全限定名称,可以是该类型的完整路径。
  5. type: 可选参数,指定对象的具体类型,这通常与渲染时的外观相关。
  6. start: 起始值,通常是索引的起始一点,序列的计数方式。
  7. boundary: 可选参数,表示该样式的边界条件。

示例代码1:

下面是一个 manim 使用 CapStyleType 的示例,展示如何创建一个带有不同端点样式的线段。

from manim import *  

class ExampleCapStyle(Scene):  
    def construct(self):  
        # 创建一个线段,使用已定义的 CapStyleType  
        line1 = Line(LEFT, RIGHT,color=RED,stroke_width=30, cap_style=CapStyleType.AUTO)  # 自动选择最合适的线条端点样式。 
        line2 = Line(LEFT * 2, RIGHT * 2,color=PURE_BLUE, stroke_width=30,
                     cap_style=CapStyleType.ROUND).shift(DOWN)  # 两端呈现出半圆形的边缘 
        line3 = Line(LEFT * 3, RIGHT * 3, color=PURE_GREEN,stroke_width=30, 
                     cap_style=CapStyleType.BUTT).shift(2*DOWN)# 结束部分是平坦的,没有任何突出部分
        line4 = Line(LEFT * 4, RIGHT * 4,color=PURPLE_A, stroke_width=30, 
                     cap_style=CapStyleType.SQUARE).shift(3*DOWN)  #线条端点呈现为正方形,线条在结束位置平直切割,形成方形的边缘

        # 将线段放置在场景中  
        self.add(line1)
        self.add(line2)
        self.add(line3)
        self.add(line4)

代码解释

  1. 导入所需的类:从 manim 库中导入*,这样就可以使用库中的所有基础对象和功能。
  2. 创建场景:定义一个场景类 ExampleCapStyle,并在其中的 construct 方法中创建线段。
  3. 使用预定义的 CapStyle:通过 CapStyle 类直接引用 ROUNDSQUARE 和 BUTT 属性,而不是尝试构造新实例。

在 manim 库中,AUTOROUNDBUTT 和 SQUARE 是定义线条端点样式(又称为线帽样式)的几种类型。这些样式决定了线条的两端如何呈现。下面是对每个样式的详细解释:

1. AUTO

  • 解释AUTO 样式允许 manim 根据上下文自动选择最合适的线条端点样式。这个选项通常用于希望简化设计而不需要明确指定具体样式的场景。当使用 AUTO 时,库将根据线条的宽度、背景及其他因素选择一个适当的端点样式。

2. ROUND

  • 解释ROUND 样式使得线条的两端呈现出半圆形的边缘。这样的样式通常用于需要视觉柔和感的场景。这类端点适合于动画、艺术效果或者任何需要使线条看起来更平滑的设计。它们通常给人一种更自然、更流动的感觉。

3. BUTT

  • 解释BUTT 样式表示线条的结束部分是平坦的,没有任何突出部分。这种样式在技术图纸或精确的几何形状中常常使用,因为它提供了一种清晰干净的效果。与圆形或方形样式相比,平头样式带来的视觉效果更加直接,适合用于强调线段的起止位置。

4. SQUARE

  • 解释SQUARE 样式的线条端点呈现为正方形,线条在结束位置平直切割,形成方形的边缘。这种风格在某些情况下提供了更为强烈和现代的视觉效果,适用于技术化、直线条的设计,常见于建筑或工程图纸中。方形样式给人一种坚固、明确的感觉。

总结

这四种样式为线条的视觉呈现提供了灵活性,设计师和动画制作者可以根据需要选择合适的样式来增强视觉效果或传达特定的信息。在不同的场景中,合适的端点样式能够显著提升设计的美观性和可读性。

 实例2:

from manim import *

class CapStyleVariants(Scene):
    def construct(self):
        arcs = VGroup(*[
            Arc(
                radius=1,
                start_angle=0,
                angle=TAU / 4,
                stroke_width=20,
                color=GREEN,
                cap_style=cap_style,
            )
            for cap_style in CapStyleType
        ])
        arcs.arrange(RIGHT, buff=1)
        self.add(arcs)
        for arc in arcs:
            label = Text(arc.cap_style.name, font_size=24).next_to(arc, DOWN)
            self.add(label)

三, 处理线段或连接的类型【LineJointType

LineJointType 是一个构造函数,通常用于定义线段或连接的类型,以便在图形或几何处理的上下文中使用。它的主要功能是创建一个表示特定连接方式的对象,该对象可以用于控制和描述线段之间的连接特性。

该构造函数有多个参数,包括 value,用于定义连接的基本特性,如“直线”或“曲线”。可选参数 names 可用于指明与该连接类型相关的名称,会在相关操作或处理流程中起到重要作用。module 和 qualname 则提供了命名空间的信息,有助于避免类型冲突并明确数据来源。

此外,type 参数可指定连接的具体类型,如“Bezier”曲线,而 start 提供了连接的起始点,通常默认设置为1。boundary 参数为连接的属性提供了附加约束条件。这使得 LineJointType 在构建复杂的几何图形或在动画生成等方面具有广泛的应用。通过这些参数,用户可以灵活控制线段的表现与交互特性。

LineJointType(value, names=None, *, module=None, qualname=None, type=None,
 start=1, boundary=None)

参数解释

  • value: 主参数,通常是描述连接类型的值,具体含义取决于上下文。
  • names: 可选参数,通常是一个字符串或字符串列表,用于定义与此连接类型相关联的名称。
  • module: 可选参数,指定模块的名称,可以用于关联或命名目的。
  • qualname: 可选参数,表示类型的限定名称(qualified name),在某些情况下它有助于维护类型的命名空间。
  • type: 可选参数,通常用于定义连接的特定类型,可能是某种自定义类型或标准类型。
  • start: 可选参数,默认值为1,通常表示连接的起始点。
  • boundary: 可选参数,可以代表连接的边界条件或约束。

示例代码

from manim import *  

class LineJointVariantsNoFOR(Scene):  
    def construct(self):  
        # 创建一个基本的线段作为模板  
        mob = VMobject(stroke_width=20, color=GREEN).set_points_as_corners([  
            np.array([-2, 0, 0]),  
            np.array([0, 0, 0]),  
            np.array([-1.5, 3, 0]),
        ])  

        # 所有连接类型的示例列表  
        joint_types = [  
            LineJointType.AUTO,   # 示例连接类型  
            LineJointType.ROUND,    # 示例连接类型  
            LineJointType.BEVEL,    # 示例连接类型  
            LineJointType.MITER,    # 示例连接类型  
        ]  

        # 为每种连接类型创建线段和标签  
        line1 = self.create_line_with_label(mob, joint_types[0], 0)  
        line2 = self.create_line_with_label(mob, joint_types[1], 1)  
        line3 = self.create_line_with_label(mob, joint_types[2], 2)
        line4 = self.create_line_with_label(mob, joint_types[3], 3)  

        # 将线段排列在一起  
        lines = VGroup(line1, line2, line3,line4)  
        lines.arrange(RIGHT, buff=1)  

        # 添加线段和标签到场景中  
        self.add(lines)  

    def create_line_with_label(self, mob, joint_type, index):  
        """创建带有标签的线段,避免代码重复。"""  
        line = mob.copy()  
        line.joint_type = joint_type  
        label = Text(line.joint_type.name).next_to(line, DOWN)  

        # 创建一个组,将线段和标签组合在一起  
        return VGroup(line, label).shift(RIGHT * index)  # 根据索引进行右移以排列线段

代码说明

  1. 创建新方法:添加了 create_line_with_label 方法以封装创建线段和标签的逻辑,从而减少代码重复。这个新方法接收一个 mob 对象、一个连接类型 joint_type,以及在水平排列中的索引 index

  2. 参数和返回值create_line_with_label 方法将创建传入连接类型的线段和标签,并返回组合在一起的 VGroup 对象。通过将每个线段和标签的组在 shift 方法中右移,这样就能控制它们的排列。

  3. 简化的 construct 方法:在 construct 方法中,调用 create_line_with_label 方法三次来创建每条线段和标签,使得代码结构更清晰,也更易于扩展。

功能与扩展性

使用这种方式,未来如果需要添加更多的连接类型,只需在 joint_types 列表中添加类型,并相应地调用 create_line_with_label 方法,而不需要重复代码的逻辑。这提高了代码的可读性和可维护性。

实例代码2:

from manim import *

class LineJointVariants(Scene):
    def construct(self):
        mob = VMobject(stroke_width=20, color=GREEN).set_points_as_corners([
            np.array([-2, 0, 0]),
            np.array([0, 0, 0]),
            np.array([-2, 1, 0]),
        ])
        lines = VGroup(*[mob.copy() for _ in range(len(LineJointType))])
        for line, joint_type in zip(lines, LineJointType):
            line.joint_type = joint_type

        lines.arrange(RIGHT, buff=1)
        self.add(lines)
        for line in lines:
            label = Text(line.joint_type.name).next_to(line, DOWN)
            self.add(label)

 四,渲染器【RendererType】

RendererType 并不是 Manim 的内置类或方法,因此可能是你遇到的特定上下文或自定义代码的一部分。不过,基于你提供的参数,我们可以猜测这个函数被用作某个 Renderer(渲染器)的类型定义。

RendererType(value, names=None, *, module=None, qualname=None, type=None,
 start=1, boundary=None)

在这种情况下,我会试着解释每个参数的意义:

参数解释

  1. value: 这个参数很可能代表渲染器的主体类型或名称,定义了要渲染的基本类型(例如,图形、文本等)。

  2. names: 这是一个可选参数,可以接受包含一组名称的列表,这些名称可能对应于渲染器的不同特性或处理方式。

  3. module: 这个参数可能是指包含该渲染器的 Python 模块的名称,以帮助识别和组织渲染器。

  4. qualname: 表示该对象的限定名称(qualified name),通常用于调试和错误追踪,显示从模块和类的上下文中引用的名称。

  5. type: 该参数可能用来指定渲染器的具体行为或类型。比如它可能代表某种算法或渲染方式,比如“Bezier”或“线性渲染”。

  6. start: 默认值为1,可能用于指示某种计数或索引的开始位置。

  7. boundary: 这个参数可能用于定义渲染的边界条件,通常以一个元组的形式传递,表示最小和最大边界值。

使用场景

在一个图形处理或渲染框架中,RendererType 可能用于定义图形或对象如何在不同条件下呈现或显示。通过传递不同的参数,用户可以灵活地构造多种渲染器类型,以适应不同的需求和场景。

Manim 示例代码

以下是一个简单的 Manim 代码示例,展示如何绘制一个简单的图形,并为其创建渲染标签。同时包含代码注释帮助理解。

from manim import *  

# 假设 RendererType 是一个可以用来为不同渲染类型构建类的函数  
class RendererType:  
    def __init__(self, value, names=None, module=None, qualname=None, type=None, start=1, boundary=None):  
        self.value = value  
        self.names = names or []  
        self.module = module  
        self.qualname = qualname  
        self.type = type  
        self.start = start  
        self.boundary = boundary  

    def __repr__(self):  
        return f"RendererType(value={self.value}, names={self.names})"  

class RendererDemo(Scene):  
    def construct(self):  
        # 使用 RendererType 创建不同的渲染器实例  
        rectangle_renderer = RendererType("RectangleRenderer", names=["rect1", "rect2"], type="Shape")  
        circle_renderer = RendererType("CircleRenderer", names=["circle1"], type="Shape")  

        # 创建矩形  
        rectangle = Rectangle(width=4, height=2, color=BLUE).set_fill(BLUE, opacity=0.5).shift(3*LEFT+2*UP)  
        label_rectangle = Text(rectangle_renderer.value).next_to(rectangle, DOWN)  

        # 创建圆形  
        circle = Circle(radius=1, color=GREEN).shift(RIGHT * 3+1*DOWN)  
        label_circle = Text(circle_renderer.value).next_to(circle, DOWN)  

        # 动画展示  
        self.play(Create(rectangle), Write(label_rectangle))  
        self.wait(1)  
        self.play(Create(circle), Write(label_circle))  
        self.wait(2)  

代码说明

  1. 假设的 RendererType 类:我们定义了 RendererType 类,这个类接受多个参数来标识不同的渲染器,并保存这些参数。

    • value: 渲染器的名称或类型。
    • names: 可选参数,表示与该渲染器相关的一组名称。
    • modulequalname: 与渲染器的模块和限定名称相关的参数。
    • type: 用于指定渲染器的具体类型(例如,“Shape”)。
    • startboundary: 较高级的配置参数可能用于特定需求。
  2. 创建 RendererDemo 场景:我们在场景中实例化 RendererType 对象。

    • 一个用于矩形的渲染器 (rectangle_renderer)。
    • 一个用于圆形的渲染器 (circle_renderer)。
  3. 绘制和动画:随后,按照之前的示例创建矩形和圆形,并为它们添加相应的标签,展示出来。

应用场景

尽管实际的 Manim 类库不包含 RendererType,这种构造展示了如何在代码中组织渲染相关的信息,并将其与场景中的视觉元素关联起来。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2072890.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

opencv-python图像增强十五:高级滤镜实现

文章目录 前言二、鲜食滤镜三、巧克力滤镜三,冷艳滤镜: 前言 在之前两个滤镜文章中介绍了六种简单的滤镜实现,它们大多都是由一个单独函数实现的接下来介绍五种结合了之前图像增强文章提的的算法的复合滤镜。本案例中的算法来自于文章一&…

【数学建模】TOPSIS法(优劣解距离法)

TOPSIS法(Technique for Order Preference by Similarity to Ideal Solution,优劣解距离法)是一种多准则决策分析方法,它基于这样一个概念:最理想的方案应该是距离理想解最近而距离负理想解最远的方案。以下是使用TOPS…

【React原理 - 任务调度和时间分片详解】

概述 在React15的时候,React使用的是从根节点往下递归的方式同步创建虚拟Dom,由于递归具有同步不可中断的特性,所以当执行长任务时(通常以60帧为标准,即16.6ms)就会长时间占用主线程长时间无响应,导致页面卡顿&#x…

如何使用Gitee管理自己的项目

如何使用Gitee管理自己的项目 前言 本地创建的工程项目不利于管理,电脑设备丢失损坏,代码就找不回来了。 并且多人同时使用一个项目工程也不方便。 国内的代码托管平台,Gitee为我实现了远程代码管理。 并且该平台可以设置为开源和私有两种…

公司邮箱如何建立

而建立一套完善的公司邮箱系统,则是实现这一目标的重要一环。本文将深入探讨公司邮箱的建立过程,以及其在业务中的重要性。 1. 确定邮箱域名 公司邮箱的建立首先要确定一个专属的邮箱域名。域名是公司在网络上的身份标识,例如,公…

程序猿成长之路之数据挖掘篇——Kmeans聚类算法

Kmeans 是一种可以将一个数据集按照距离(相似度)划分成不同类别的算法,它无需借助外部标记,因此也是一种无监督学习算法。 什么是聚类 用官方的话说聚类就是将物理或抽象对象的集合分成由类似的对象组成的多个类的过程。用自己的…

VSCode插件 live Server

普通打开 安装live Server 包含端口 说明内置了服务器

改造小蚁摄像头支持免费无限容量云储存(Samba挂载篇)

为什么要改造? 插卡摄像头最大的一个问题就是频繁的读写会导致内存卡寿命急速下降,哪怕是市面上支持NAS转存的摄像头也是先录制到SD卡里,然后把SD卡上的视频再转存到NAS。同样对内存卡和NAS硬盘寿命都是损耗巨大。而这类监控视频绝大多数情况…

重磅!小米将对外公开超 1000 万行的 Xiaomi Vela 开源代码

点击上方关注 “终端研发部” 设为“星标”,和你一起掌握更多数据库知识 如果说接下来的澎湃OS系统会带来很强的吸引力,那么第二个惊喜也是随之而来,那就是小米Vela开源大动作。 早在2017年起,小米就活跃于 NuttX 社区&#xff0c…

Reinforcement-Learning 2.State Value and Bellman Equation

目录 0.Outline 1.Motivating examples Motivating example 1: Why return is important? Motivating example 2: How to calculate return? 2.State value 3.Bellman equation: Derivation Deriving the Bellman equation An illustrative example Exercise 4.Be…

FreeSWITCH 1.10.10 简单图形化界面28 - 麒麟V10 SP3服务器系统X86和ARM版本安装FreeSWITCH

FreeSWITCH 1.10.10 简单图形化界面28 - 麒麟V10 SP3 服务器系统X86和ARM版本安装FreeSWITCH 界面预览00、先看使用手册01、 麒麟服务器v10 sp3 x86版本1、安装操作系统2、下载安装脚本3、安装 02、麒麟服务器v10 sp3 arm版本1、安装操作系统2、下载安装脚本3、安装 03、登录网…

搭建一个私有的知识库mm-wiki

文章目录 前言一、mm-wiki二、安装步骤下载安装 总结 前言 一般公司内部想要记录一些东西,都需要一个共享文档,当然可以选择类似比较简单易用的,有道云笔记,腾讯文档,语雀等,但是肯定有些公司是保密的,所以不希望这些数据被泄露,当然选择本地存储是最安全的~ 一、mm-wiki 对于…

vue3+vite配置环境变量实现开发、测试、生产的区分

文章目录 一、为什么需要区分 (dev)、测试 (test) 和生产 (prod) 环境二、vue3的项目如何通过配置方式区分不同的环境1、创建不同环境的.env文件2、在不同的.env文件中配置相应的环境变量1).env.develoment2).env.test3).env.production 3、在…

查找2

树表的查找 1)二叉排序树 I)二叉排序树的插入 II)二叉排序树的生成 III)二叉排序树的删除 2)平衡二叉树 I)平衡二叉树调整 、

MMOE+ESSM

MMOE 动机 多个任务之间的相关性并不是很强,这个时候如果再用过去那种共享底座embedding的结构,往往会导致『跷跷板』现象。 当前学术界已经有很多工作意识到1中描述的问题并且尝试去解决,但大多数工作的套路都是『大力出奇迹』的路子&…

zigbee笔记、十五、组播通信原理

一、zigbee四种通讯 1、单播(略) 2、广播(略) 3、组播:在zigbee网络中,模块可以用分组来标记,发送的模块如果发送的组号和网络里面标记接收模块的组号相对应,那么这些模块就可以拿到…

深度剖析渗透测试:流程、规范与实战全指南

一、引言 在当今数字化时代,网络安全问题日益凸显。渗透测试作为一种主动的安全评估方法,能够帮助企业和组织发现潜在的安全漏洞,提高系统的安全性。本文将详细介绍渗透测试的实施流程、规范、不同类型的测试方法以及相关的 checklist 和报告…

Matlab处理H5文件

1.读取h5文件 filenamexxx.h5; h5disp(filename) 2.h5文件保存为mat文件 读取 HDF5 文件中的数据 % 指定 HDF5 文件的路径 filename xxx.h5;% 读取 HDF5 文件中的各个数据集 A241_P h5read(filename, /A241_P); A241_W h5read(filename, /A241_W); A242_P h5read(filen…

ensp 中 wlan 的配置过程和示例

一、拓朴: 要求:vlan20 用于笔记本上网,使用Huawei信号,vlan30 用于手机上网,使用 Huawei-5G 信号 二、配置过程: 1、SW1 基本配置: 起 vlan batch 10 20 30,10 为管理 vlan&#…

Acrobat Pro DC 2024 for mac/Win:跨平台PDF编辑与管理的巅峰之作

Adobe Acrobat Pro DC 2024是一款专为Mac和Windows用户设计的全面PDF解决方案软件,它集成了创建、编辑、转换、共享和签署PDF文件的强大功能,为用户带来前所未有的高效与便捷体验。 强大的PDF编辑功能 Acrobat Pro DC 2024在PDF编辑方面表现出色。用户…