You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Manim动画中如何在线段中点绘制等长标记(Tick)?

问题

我希望用标记(Tick)标注两条线段等长,如同几何中的常见做法(线段上的短竖线标记)。尽管我已尝试搜索,但未找到简单的内置解决方案。

我的繁琐实现方案

当然,给定线段后可以直接绘制标记。例如,我的实现如下:

from manim import *

class Test(Scene):
    def construct(self):
        line = Line()
        line.shift(3 * RIGHT + UP).rotate(35 * DEGREES)
        
        # 在线段中心添加标记作为子对象
        size = 0.1
        tick = Line(size * DOWN, size * UP)
        tick.rotate(line.get_angle())
        tick.move_to(line.get_center())
        line.add(tick)
        
        self.add(line)

疑问

为Line对象添加标记的最佳实践是什么?


推荐实现方案

针对这个需求,最佳实践是封装可复用的工具函数或自定义线段类,避免重复编写冗余代码,同时保证标记与原线段的联动性:

方案1:封装工具函数

from manim import *

def add_length_tick(line, tick_size=0.1, position=0.5, num_ticks=1):
    """
    给线段添加等长标记
    参数:
        line: 目标Line对象
        tick_size: 标记的长度
        position: 标记在线段上的位置,0为起点、1为终点,默认居中
        num_ticks: 标记数量,用于区分多组不同的等长线段
    """
    line_angle = line.get_angle()
    tick_spacing = 0.15  # 多标记之间的横向间距
    
    for i in range(num_ticks):
        # 计算标记的偏移位置,适配多标记场景
        offset = (i - (num_ticks - 1)/2) * tick_spacing
        tick_center = line.point_from_proportion(position) + offset * line.copy().rotate(90*DEGREES).get_unit_vector()
        
        tick = Line(tick_size * DOWN, tick_size * UP)
        tick.rotate(line_angle)
        tick.move_to(tick_center)
        line.add(tick)
    return line

class TestEqualLengths(Scene):
    def construct(self):
        # 第一组等长线段,用单标记标注
        line1 = Line(LEFT, RIGHT).shift(UP)
        line2 = Line(LEFT, RIGHT).shift(DOWN).rotate(30*DEGREES)
        add_length_tick(line1)
        add_length_tick(line2)
        
        # 第二组等长线段,用双标记区分
        line3 = Line(2*LEFT, 2*RIGHT).shift(2*UP)
        line4 = Line(2*LEFT, 2*RIGHT).shift(2*DOWN).rotate(-45*DEGREES)
        add_length_tick(line3, num_ticks=2)
        add_length_tick(line4, num_ticks=2)
        
        self.add(line1, line2, line3, line4)

方案2:自定义带标记的线段类

如果需要频繁使用带标记的线段,更推荐继承Line类实现自定义组件:

from manim import *

class LineWithTick(Line):
    def __init__(self, *args, tick_size=0.1, num_ticks=1, tick_position=0.5, **kwargs):
        super().__init__(*args, **kwargs)
        self._add_length_tick(tick_size, tick_position, num_ticks)
    
    def _add_length_tick(self, tick_size=0.1, position=0.5, num_ticks=1):
        line_angle = self.get_angle()
        tick_spacing = 0.15
        
        for i in range(num_ticks):
            offset = (i - (num_ticks - 1)/2) * tick_spacing
            tick_center = self.point_from_proportion(position) + offset * self.copy().rotate(90*DEGREES).get_unit_vector()
            
            tick = Line(tick_size * DOWN, tick_size * UP)
            tick.rotate(line_angle)
            tick.move_to(tick_center)
            self.add(tick)

class TestCustomLine(Scene):
    def construct(self):
        line1 = LineWithTick(LEFT, RIGHT, num_ticks=1).shift(UP)
        line2 = LineWithTick(LEFT, RIGHT, num_ticks=1).shift(DOWN).rotate(30*DEGREES)
        line3 = LineWithTick(2*LEFT, 2*RIGHT, num_ticks=2).shift(2*UP)
        
        self.add(line1, line2, line3)

方案优势

  • 复用性强:一次封装后可重复调用,避免重复编写相同逻辑
  • 灵活性高:支持调整标记的大小、位置、数量,适配不同几何绘图场景
  • 联动性好:标记作为线段的子对象,线段移动、旋转时标记会同步变化,无需单独处理

内容的提问来源于stack exchange,提问作者pch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 17:56:27