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

在Manim中沿测量曲线移动Mobject的更优实现方案问询

问题描述

我想找一种更合理的方法,让Mobject沿由n维向量ts、xs、ys(可选zs)定义的路径移动。目前我用ParametricFunction加MoveAlongPath实现,还得定义速率函数来保证时序,但这个方法既繁琐又不够可靠。我觉得应该有内置函数,但一直没找到。

现有实现代码:

# This function takes a path defined by arrays and returns a function
# ts is assumed to be strictly increasing
def manim_curve(ts,xs,ys):
    ts,xs,ys = map(np.array,(ts,xs,ys))

    # Calculate the total distance traveled over the curve
    dist = np.cumsum(np.abs(np.diff(xs+1j*ys,prepend=0))) 

    # Normalize to a time range of [0,1]
    nts   = ts   / ts[-1]
    ndist = dist / dist[-1]

    # Create a function that can be passed `ParametricFunction`
    def f(t):
        n = np.abs(nts-t).argmin() # Find index from t
        return (xs[n],ys[n],0)
    
    # Create a rate function for `MoveAlongPath`
    def rate(t):
        n = np.abs(nts-t).argmin() # Find index from t
        return ndist[n]
    
    # Create manim curve
    curve = ParametricFunction(function=f)

    return curve,rate

# Animation class to move along a discretely defined path  
class MoveAlongMeasuredPath(MoveAlongPath):
    def __init__(self,object,ts,xs,ys,**kwargs):
        ts,xs,ys   = map(np.array,(ts,xs,ys))
        curve,rate = manim_curve(ts,xs,ys)
        super().__init__(object,curve,
                         run_time  = ts[-1],
                         rate_func = rate,
                         **kwargs)
解决方案

Manim目前没有直接支持这种带时序离散点路径的内置动画,但可以通过更简洁可靠的方式实现,核心是用插值替代原方法的索引查找,同时优化路径构建逻辑:

优化后的实现

import numpy as np
from scipy.interpolate import interp1d
from manim import *

class MoveAlongDiscretePath(MoveAlongPath):
    def __init__(self, mobject, ts, xs, ys, zs=None, **kwargs):
        ts, xs, ys = map(np.array, (ts, xs, ys))
        # 处理3D路径的zs参数,默认全0
        zs = np.zeros_like(xs) if zs is None else np.array(zs)
        
        # 用离散点构建Path对象,比ParametricFunction更高效
        path_points = np.column_stack((xs, ys, zs))
        path = Path()
        path.set_points_as_corners(path_points)
        
        # 计算路径各段距离及累积距离,用于时序映射
        segment_distances = np.linalg.norm(np.diff(path_points, axis=0), axis=1)
        cumulative_dist = np.cumsum(np.insert(segment_distances, 0, 0))
        total_dist = cumulative_dist[-1]
        
        # 构建时间到路径进度的线性插值函数,保证时序准确
        time_to_progress = interp1d(ts, cumulative_dist / total_dist, kind='linear')
        
        # 定义速率函数:将动画时间[0,1]映射为路径进度[0,1]
        def rate_func(t):
            actual_time = np.clip(t * ts[-1], ts[0], ts[-1])
            return time_to_progress(actual_time)
        
        super().__init__(
            mobject, path,
            run_time=ts[-1],
            rate_func=rate_func,
            **kwargs
        )

优化点说明

  • 平滑移动:用线性插值替代原方法的argmin索引查找,避免移动时的跳变,路径过渡更自然
  • 3D支持:新增可选zs参数,直接支持3D路径移动
  • 高效路径构建:用Path类直接通过离散点构建路径,比ParametricFunction更符合Manim的内部路径处理逻辑,性能更优
  • 边界处理:通过np.clip限制时间范围,避免越界问题

使用示例

class TestDiscretePathAnimation(Scene):
    def construct(self):
        dot = Dot(color=RED, radius=0.1)
        # 定义带时序的路径点
        ts = np.array([0, 1.5, 3, 4.5, 6])
        xs = np.array([0, 2, 0, -2, 0])
        ys = np.array([0, 0, 2, 0, -2])
        
        self.add(dot)
        # 播放路径动画
        self.play(MoveAlongDiscretePath(dot, ts, xs, ys))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 16:35:22