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

如何将单条三次贝塞尔曲线分割为两条视觉一致的连接曲线?

解决三次贝塞尔曲线分割问题:生成视觉完全一致的两条曲线

要精确分割三次贝塞尔曲线并保证拼接后和原曲线视觉完全一致,**德卡斯特里奥算法(De Casteljau's Algorithm)**是标准解决方案,能从数学上保证无误差,直接计算出分割后两条曲线的所有控制点,包括你需要的分割点的头部/尾部方向对应的全局位置。

分割计算步骤

针对原曲线的四个控制点(锚点P0、头部控制点P1、尾部控制点P2、锚点P3),在参数t(0<t<1)处分割:

  1. 先通过线性插值计算中间过渡点:
    • B0 = (1-t)*P0 + t*P1
    • B1 = (1-t)*P1 + t*P2
    • B2 = (1-t)*P2 + t*P3
    • C0 = (1-t)*B0 + t*B1
    • C1 = (1-t)*B1 + t*B2
    • D0 = (1-t)*C0 + t*C1 // 这就是你提到的分割红点,同时是第一条曲线的终点、第二条曲线的起点
  2. 分割后两条曲线的参数:
    • 第一条曲线(从P0到D0):
      锚点P0 → 头部控制点B0 → 尾部控制点C0 → 锚点D0
      其中C0就是分割点D0作为这条曲线终点的尾部全局控制点
    • 第二条曲线(从D0到P3):
      锚点D0 → 头部控制点C1 → 尾部控制点B2 → 锚点P3
      其中C1就是分割点D0作为这条曲线起点的头部全局控制点

方向向量计算

根据你定义的方向规则:

  • 分割点D0作为第二条曲线起点的头部方向:C1 - D0(从D0指向头部控制点C1的向量)
  • 分割点D0作为第一条曲线终点的尾部方向:D0 - C0(从尾部控制点C0指向D0的向量)

C# 代码实现

// 完整分割函数:返回两条曲线的所有控制点和分割点
public (
    (Vector3 P0, Vector3 P1, Vector3 P2, Vector3 P3) FirstCurve,
    (Vector3 P0, Vector3 P1, Vector3 P2, Vector3 P3) SecondCurve,
    Vector3 SplitPoint
) SplitCubicBezier(float t, Vector3 P0, Vector3 P1, Vector3 P2, Vector3 P3)
{
    // 用Vector3.Lerp简化线性插值计算,比手动计算更高效
    Vector3 B0 = Vector3.Lerp(P0, P1, t);
    Vector3 B1 = Vector3.Lerp(P1, P2, t);
    Vector3 B2 = Vector3.Lerp(P2, P3, t);
    
    Vector3 C0 = Vector3.Lerp(B0, B1, t);
    Vector3 C1 = Vector3.Lerp(B1, B2, t);
    
    Vector3 D0 = Vector3.Lerp(C0, C1, t);
    
    // 组装两条曲线的控制点组
    var firstCurve = (P0, B0, C0, D0);
    var secondCurve = (D0, C1, B2, P3);
    
    return (firstCurve, secondCurve, D0);
}

// 仅获取分割点及对应方向向量的函数
public (Vector3 SplitPoint, Vector3 HeadDirection, Vector3 TailDirection) GetSplitPointDirections(float t, Vector3 P0, Vector3 P1, Vector3 P2, Vector3 P3)
{
    Vector3 B0 = Vector3.Lerp(P0, P1, t);
    Vector3 B1 = Vector3.Lerp(P1, P2, t);
    Vector3 B2 = Vector3.Lerp(P2, P3, t);
    
    Vector3 C0 = Vector3.Lerp(B0, B1, t);
    Vector3 C1 = Vector3.Lerp(B1, B2, t);
    
    Vector3 D0 = Vector3.Lerp(C0, C1, t);
    
    // 头部方向:分割点作为新起点的指向向量
    Vector3 headDir = C1 - D0;
    // 尾部方向:分割点作为第一条曲线终点的指向向量
    Vector3 tailDir = D0 - C0;
    
    return (D0, headDir, tailDir);
}

为什么这个方法有效

德卡斯特里奥算法是贝塞尔曲线的原生构造逻辑,分割后的两条曲线在拼接处不仅位置连续,切线方向和曲率也完全一致,视觉上和原曲线完全重合,不存在近似误差。你之前尝试的线段法属于近似估算,自然达不到精确匹配的效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 02:20:30