2017-03-03 79 views
1

我想在画布浏览器上绘制隐士曲线。埃尔米特曲线是根据2点和2阶导数定义的。在浏览器画布上绘制埃米特曲线(javascript)

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

我可以在画布上绘制贝塞尔曲线。有没有什么办法可以将曲线的点和派生曲线转换为贝塞尔曲线,这样我就可以在画布上绘制它了?

是否有另一种选择,我可以在浏览器上绘制hermite曲线?

感谢您的帮助。

+1

请提供一个[最小,完整,可验证](http://stackoverflow.com/help/mcve)尝试,所以我们可以尝试解决你的问题,并解释为什么你自己的尝试失败 - 这样你可以学习一些对你未来发展有用的东西,并且得到这个单一问题的答案。 –

+0

这[小提琴](http://jsfiddle.net/jmchen/m9k8qn0v/1/)可能会有所提示。 –

+0

[这里](http://stackoverflow.com/a/15528789/1693593)是一个Catmull-Rom实现与张力(又名基数样条)。 – K3N

回答

0

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

做到这一点的数学可以在这个Primer on Bezier curves找到了,并专门针对这个问题,我们可以转换埃尔米特点有序[P1,D1,P2,D2]为:

​​

注意,值是曲线张力并控制每个点处的曲率顺序(张力越高,曲线上点附近的曲率变化率越高),在这种情况下仅为1

(没有张力值,您的四个坐标实际上在平面上定义了一个沙漏六角形区域,而不是单个曲线,因为方向矢量不能保证是真正的切线;只是表示行进方向的矢量。这些值定义的区域由一边的{start,end}行界定,在开始和结束时沿着行进方向具有无限延伸的边界)。

所以与,可以绘制在画布上的画布上的任何埃尔米特曲线,使用用于三次贝塞尔曲线Canvas2d API:

// 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(); 
0

三次Hermite曲线(由C(O),C”定义(0),C(1)和C'(1))和三次Bezier曲线(由P0,P1,P2和P3所定义)可以通过

C(0)=彼此相关(0)= 3(P1-P0),
C'(1)= 3(P3-P2)

因此,可以发现控制点作为

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