Chr*_*gel 54 math curve point quadratic
我想计算二次曲线上的一个点.将它与HTML5的canvas元素一起使用.
当我quadraticCurveTo()
在JavaScript中使用该函数时,我有一个源点,一个目标点和一个控制点.
我怎么能计算出创建的二次曲线上的一个点,让我们说t=0.5
"只"知道这三点?
xan*_*xan 114
使用二次Bézier公式,例如,在BézierCurves的维基百科页面上找到:
在伪代码中,就是这样
t = 0.5; // given example value
x = (1 - t) * (1 - t) * p[0].x + 2 * (1 - t) * t * p[1].x + t * t * p[2].x;
y = (1 - t) * (1 - t) * p[0].y + 2 * (1 - t) * t * p[1].y + t * t * p[2].y;
Run Code Online (Sandbox Code Playgroud)
p[0]
是起点,p[1]
是控制点,p[2]
是终点.t
是参数,从0到1.
Tat*_*ize 32
如果有人需要立方体形式:
//B(t) = (1-t)**3 p0 + 3(1 - t)**2 t P1 + 3(1-t)t**2 P2 + t**3 P3
x = (1-t)*(1-t)*(1-t)*p0x + 3*(1-t)*(1-t)*t*p1x + 3*(1-t)*t*t*p2x + t*t*t*p3x;
y = (1-t)*(1-t)*(1-t)*p0y + 3*(1-t)*(1-t)*t*p1y + 3*(1-t)*t*t*p2y + t*t*t*p3y;
Run Code Online (Sandbox Code Playgroud)
如果有人需要第n种形式,这是算法.你喂N点,它将返回一个__CODE__
点数组,这解决了__CODE__
.最后一点是给定T值的曲线上的位置.
//B(t) = (1-t)**3 p0 + 3(1 - t)**2 t P1 + 3(1-t)t**2 P2 + t**3 P3
x = (1-t)*(1-t)*(1-t)*p0x + 3*(1-t)*(1-t)*t*p1x + 3*(1-t)*t*t*p2x + t*t*t*p3x;
y = (1-t)*(1-t)*(1-t)*p0y + 3*(1-t)*(1-t)*t*p1y + 3*(1-t)*t*t*p2y + t*t*t*p3y;
Run Code Online (Sandbox Code Playgroud)
您将算法0 1 2 3作为控制点,这些位置将是阵列的其余部分.最后一点(9)是您想要的值.
这也是你细分bezier曲线的方法,你给它__CODE__
你想要的值,然后你将细分曲线声明为金字塔的边.然后,您可以索引金字塔侧面的各个点以及从基座构建的金字塔的另一侧.所以例如在五联中:
//B(t) = (1-t)**3 p0 + 3(1 - t)**2 t P1 + 3(1-t)t**2 P2 + t**3 P3
x = (1-t)*(1-t)*(1-t)*p0x + 3*(1-t)*(1-t)*t*p1x + 3*(1-t)*t*t*p2x + t*t*t*p3x;
y = (1-t)*(1-t)*(1-t)*p0y + 3*(1-t)*(1-t)*t*p1y + 3*(1-t)*t*t*p2y + t*t*t*p3y;
Run Code Online (Sandbox Code Playgroud)
(原谅十六进制,我希望它很漂亮)
您可以将两条完美细分的曲线编入索引,分别为0,5,9,C,E和E,D,B,8,4.需要特别注意的是,第一条曲线以控制点(0)开始,以点结束在曲线(E)上,第二条曲线从曲线(E)开始,到控制点(4)结束.鉴于此,您可以完美地细分贝塞尔曲线,这是您所期望的.连接两条曲线的新控制点位于曲线上.
//B(t) = (1-t)**3 p0 + 3(1 - t)**2 t P1 + 3(1-t)t**2 P2 + t**3 P3
x = (1-t)*(1-t)*(1-t)*p0x + 3*(1-t)*(1-t)*t*p1x + 3*(1-t)*t*t*p2x + t*t*t*p3x;
y = (1-t)*(1-t)*(1-t)*p0y + 3*(1-t)*(1-t)*t*p1y + 3*(1-t)*t*t*p2y + t*t*t*p3y;
Run Code Online (Sandbox Code Playgroud)
你会发现它只是通过每组点数量的公式.对于N个解,你得到(N-1)个中值为(t),然后你得到那些中点,得到(N-2)个点,然后是(N-3)个等,直到你只有一个点.这一点在曲线上.因此,对于t,在0到1之间的值解决问题,将为您提供整个曲线.知道了这一点,我的实现只是在一个数组中向前传播值,节省了不止一次重新计算的内容.我已经将它用于100分,并且它仍然闪电般快速.
(如果你想知道,不是没有它真的值得.SVG是正确的停止立方体).
我创建了这个演示:
// x = a * (1-t)³ + b * 3 * (1-t)²t + c * 3 * (1-t)t² + d * t³
//------------------------------------------------------------
// x = a - 3at + 3at² - at³
// + 3bt - 6bt² + 3bt³
// + 3ct² - 3ct³
// + dt³
//--------------------------------
// x = - at³ + 3bt³ - 3ct³ + dt³
// + 3at² - 6bt² + 3ct²
// - 3at + 3bt
// + a
//--------------------------------
// 0 = t³ (-a+3b-3c+d) + => A
// t² (3a-6b+3c) + => B
// t (-3a+3b) + => c
// a - x => D
//--------------------------------
var A = d - 3*c + 3*b - a,
B = 3*c - 6*b + 3*a,
C = 3*b - 3*a,
D = a-x;
// So we need to solve At³ + Bt² + Ct + D = 0
Run Code Online (Sandbox Code Playgroud)
可以帮助别人.