2017-03-03 78 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)