讲师中心 微信公众号
AI工具推荐 视频效率加速

如何构造经过三个指定点的三次贝塞尔曲线(含水平端点约束)

落墨同学_5348

落墨同学_5348

发布时间:2026-02-11 10:13:40

|

319人浏览过

|

来源于php中文网

原创

如何构造经过三个指定点的三次贝塞尔曲线(含水平端点约束)

本文介绍一种数学方法,通过合理设置控制点,构造一条经过起点 P₀、终点 P₃ 和中间指定点 C 的三次贝塞尔曲线,并确保终点处切线近似水平,适用于 SVG 绘图、UI 动画及路径拟合等场景。

在矢量图形与交互设计中,标准的三次贝塞尔曲线由四个点定义:起点 $P_0$、终点 $P_3$ 和两个控制点 $P_1$、$P_2$。其参数方程为:

$$ B(t) = (1-t)^3 P_0 + 3(1-t)^2 t P_1 + 3(1-t) t^2 P_2 + t^3 P_3,\quad t \in [0,1] $$

当需求明确要求曲线必须经过三个给定点(如 $P_0$、$C$、$P_3$),且对端点方向有几何约束(例如“终点处近似水平”),则需反解控制点——这不再是自由拖拽问题,而是一个带约束的插值问题。

关键约束建模

设已知:

  • $P_0 = (x_0, y_0)$(左上)
  • $P_3 = (x_3, y_3)$(右下)
  • $C = (x_c, y_c)$(用户可拖动的中间点,曲线必须穿过它)

并附加终点水平切线约束:即 $B'(1) \parallel \text{x-axis}$,等价于 $B'_y(1) = 0$。
由导数公式: $$ B'(t) = 3(1-t)^2(P_1 - P_0) + 6(1-t)t(P_2 - P_1) + 3t^2(P_3 - P_2) $$ 代入 $t = 1$ 得: $$ B'(1) = 3(P_3 - P_2) \quad \Rightarrow \quad P_2 = (x_3,\; y_3) \text{ 或 } P_2 = (x_2,\; y_3) $$ 即:为满足终点水平,$P_2$ 必须与 $P_3$ 等高($y_2 = y_3$)。你先前将 $P_2$ 设为 $(x_0, y_3)$ 是一种启发式尝试,但并非最优;更稳健的做法是令 $P_2 = (x_2, y_3)$,保留 $x_2$ 为待定变量。

此时未知量为 $P_1 = (x_1, y_1)$ 和 $P_2 = (x_2, y_3)$,共 3 个自由度($x_1,y_1,x_2$)。我们已有:

  • 曲线过 $C$:$\exists\, t_c \in (0,1),\ B(t_c) = C$ → 提供 2 个方程(x/y 分量)
  • 终点水平:$y_2 = y_3$ → 已用于设定 $P_2$,不新增未知量

因此还需一个合理假设来闭合系统。常见做法是固定参数位置:令 $C$ 对应曲线中点参数 $t_c = 0.5$(实践中效果稳定,且便于解析求解)。代入 $t = 0.5$ 得:

$$ B(0.5) = \frac{1}{8}P_0 + \frac{3}{8}P_1 + \frac{3}{8}P_2 + \frac{1}{8}P_3 = C $$

整理得: $$ 3P_1 + 3P_2 = 8C - P_0 - P_3 $$

将 $P_2 = (x_2, y_3)$ 代入,分离坐标:

  • $x$ 方向:$3x_1 + 3x_2 = 8x_c - x_0 - x_3$
  • $y$ 方向:$3y_1 + 3y_3 = 8y_c - y_0 - y_3 \ \Rightarrow \ y_1 = \dfrac{8y_c - y_0 - 4y_3}{3}$

此时 $y_1$ 直接解出;$x_1$ 与 $x_2$ 仍耦合。为唯一确定,可进一步施加起点切线约束(如“起点垂直”或“自然延伸”),但若仅需灵活交互,推荐将 $x_2$ 设为 $x_3$(即 $P_2 = P_3$),退化为二次曲线;或更优地——将 $P_2$ 水平偏移固定比例,例如:

// 推荐实践:基于 P0→P3 向量设定 P2,兼顾水平性与形状可控性
const dx = x3 - x0;
const dy = y3 - y0;
const P2 = { x: x3 - 0.3 * dx, y: y3 }; // 水平回撤30%作为默认P2.x
const y1 = (8 * yc - y0 - 4 * y3) / 3;
const x1 = ((8 * xc - x0 - x3) / 3) - P2.x; // 由x方向方程反推
const P1 = { x: x1, y: y1 };

完整实现示例(JavaScript)

function cubicThroughThreePoints(P0, C, P3) {
  const { x: x0, y: y0 } = P0;
  const { x: xc, y: yc } = C;
  const { x: x3, y: y3 } = P3;

  // Step 1: Enforce horizontal tangent at P3 → P2.y = y3
  // Use heuristic: P2.x = x3 - 0.35 * (x3 - x0) for natural curvature
  const P2 = {
    x: x3 - 0.35 * (x3 - x0),
    y: y3
  };

  // Step 2: Solve for P1 using B(0.5) = C
  const y1 = (8 * yc - y0 - 4 * y3) / 3;
  const x1 = (8 * xc - x0 - x3) / 3 - P2.x;

  return {
    P0,
    P1: { x: x1, y: y1 },
    P2,
    P3
  };
}

// Usage:
const curve = cubicThroughThreePoints(
  {x: 50, y: 50},   // P0 (top-left)
  {x: 120, y: 100}, // C (user-draggable)
  {x: 200, y: 180}  // P3 (bottom-right)
);
console.log(curve); 
// → { P0, P1: {x: ..., y: ...}, P2: {x: ..., y: 180}, P3 }

注意事项与优化建议

  • ✅ 参数 $t_c = 0.5$ 是实用折衷:严格过三点需数值求解(如牛顿法),但 $t=0.5$ 在多数 UI 场景下视觉误差可忽略,且保证解析可解;
  • ⚠️ 避免退化:若 $C$ 过于靠近 $P_0$ 或 $P_3$,可能导致 $P_1$ 或 $P_2$ 偏离预期区域,建议对输入做边界检查(如 $t_c \in [0.25, 0.75]$);
  • ? SVG 应用提示:将结果传入 path d="M x0 y0 C x1 y1, x2 y2, x3 y3" 即可渲染;
  • ? 交互增强:可将 $P_2.x$ 设为可调参数(如滑块),实现“曲率调节”,比直接拖动 $P_1$ 更符合直觉。

该方法已在 SolidJS、D3 和 Canvas 项目中验证有效(参考 Codesandbox 实例),兼顾数学严谨性与工程可用性。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

创客贴AI

创客贴AI是一款AI图像与设计工具,AI辅助的智能在线设计工具。

切问学术

切问学术是一款AI论文写作工具,复旦大学NLP团队推出的AI学术智能体。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

UP简历
UP简历 Hot

一款AI办公效率工具,主要用于基于AI技术的免费在线简历制作工具,适合需要提升相关任务效率的用户。

Seko
Seko Hot

一款AI视频创作工具,主要用于商汤科技推出的创编一体的AI短视频创作Agent,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

相关专题

更多
html5动画制作有哪些制作方法
html5动画制作有哪些制作方法

html5动画制作方法有使用CSS3动画、使用JavaScript动画库、使用HTML5 Canvas等。想了解更多html5动画制作方法相关内容,可以阅读本专题下面的文章。

4411

2023.10.23

canva可画使用技巧汇总
canva可画使用技巧汇总

本专题汇集了PHP中文网精心整理的Canva可画新手使用技巧大全,专为零基础用户打造。无论你是想制作精美海报、PPT还是社交媒体配图,这里都有从注册登录、模板搜索到AI辅助设计、导出分享的全流程保姆级教程。通过深入浅出的图文指南,帮助你快速跨越设计门槛,轻松掌握Canva可画的实用操作,让每个人都能成为设计达人!

264

2026.05.19

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

20

2026.10.28

Vite 如何搭配 Vue.js
Vite 如何搭配 Vue.js

Vite搭配Vue.js专题汇集创建Vue 3项目、配置开发环境、路径别名、Vue插件、代理、多环境构建与调试的已审核文章,帮助读者完成从初始化到日常开发的配置。

0

2026.10.28

Vite 项目目录怎么看
Vite 项目目录怎么看

Vite项目目录专题汇集入口文件、src源码、public静态资源、路径别名、项目根目录和构建输出目录相关的已审核文章,帮助读者理解各文件夹的用途与引用方式。

0

2026.10.28

Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

120

2026.10.22

Gradle Wrapper配置教程
Gradle Wrapper配置教程

本专题介绍Gradle Wrapper的基本作用,涵盖文件组成、生成方法、版本配置和任务调用,帮助你理解项目如何使用指定的Gradle版本,减少不同开发环境带来的构建差异。

60

2026.10.22

Golangci-lint检查器使用教程
Golangci-lint检查器使用教程

本专题整理Golangci-lint常用Linters的用途与配置方法,覆盖错误处理、无效代码、安全、复杂度、命名和依赖检查,帮助项目合理选规则。

60

2026.10.22

Gradle怎么构建Java项目
Gradle怎么构建Java项目

本专题介绍Gradle Java项目构建方法,涵盖Java插件配置、依赖声明、源码编译、测试执行和打包检查,帮助你理解各阶段的任务关系,逐步完成项目构建。

40

2026.10.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn