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
相关产品推荐
相关产品推荐

