1

我正在尝试在画布浏览器上绘制隐士曲线。Hermite 曲线由 2 个点和 2 个导数定义。

Point1X = 71
Point1Y = 165
Deriv1X = -12
Deriv1Y = 2
Point2X = 210
Point2Y = 153
Deriv2X = 108
Deriv2Y = 0

我可以在画布上绘制贝塞尔曲线。有什么方法可以将 Hermite 曲线的点和推导转换为贝塞尔曲线,以便我可以在画布上绘制它?

还有其他选项可以在浏览器上绘制 Hermite 曲线吗?

感谢帮助。

4

2 回答 2

0

Canvas2d 不支持任意 Hermite 样条,但它支持三次 Bezier 曲线,并且由于三次 Bezier 是二阶 Hermite 曲线,我们可以在您的数据和 Bezier 曲线之间自由转换。

可以在此Primer on Bezier 曲线上找到执行此操作的数学,特别是对于这个问题,我们可以将 Hermite 点按 [p1, d1, p2, d2] 排序为:

Hermite points [p1,d1,p2,d2] = Bezier [p1, (p1 + d1/(2*t)), (p2 - d2/(2*t)), p2]

请注意,该t值是曲线张力并控制每个点的曲率顺序(张力越高,沿曲线上点附近的曲率变化率越高),在本例中为1

(没有张力值,您的四个坐标实际上定义了平面上的沙漏六边形区域,而不是单个曲线,因为方向向量不能保证是真正的切线;仅表示行进方向的向量。这些值定义的区域以一侧的线 {start, end} 为界,在起点和终点沿行进方向无限延伸)。

因此,您可以在画布上使用 Canvas2d API 绘制三次贝塞尔曲线的任何 Hermite 曲线:

// Hermite data
var p1 = ..., d1 = ..., p2 = ..., d2 = ...;
var cmpoints = [p1.x, p1.y, d1.x, d1.y, p2.x, p2.y, d2.x, d2.y];

// Bezier data
var tension = 1;
var tensionFactor = 2 * tension;
var bpoints = [
  p1.x,
  p1.y,
  p1.x + d1.x/tensionFactor,
  p1.y + d1.y/tensionFactor,
  p2.x - d2.x/tensionFactor,
  p2.y - d2.y/tensionFactor,
  p2.x,
  p2.y
]

// Draw code (where we assume you already
// have your canvas context as "ctx")
ctx.beginPath();
ctx.moveTo.apply(bpoints.slice(0,2));
ctx.bezierCurveTo.apply(bpoints.slice(2);
ctx.stroke();
于 2017-03-03T19:47:46.050 回答
-1

三次 Hermite 曲线(由 C(0)、C'(0)、C(1) 和 C'(1) 定义)和三次 Bezier 曲线(由 P0、P1、P2 和 P3 定义)可以相互关联经过

C(0) = P0,
C(1) = P3,
C'(0) = 3(P1-P0),
C'(1) = 3(P3-P2)

因此,您可以找到控制点为

P0=C(0),
P1=(1/3)*C'(0)+P0,
P2=P3-(1/3)*C'(1),
P3=C(1)

于 2017-03-04T00:09:22.670 回答