如何求出二次贝塞尔曲线上面的各个点呢

如何求出二次贝塞尔曲线上面的各个点呢_第1张图片

1、需求:用 canvas 在上面的曲线上面加几个箭头,指明方向

2、问题:这个曲线我是第一次见,搞半天还发现不是圆的弧,是一种很奇怪的弧形,于是我就上网查 quadraticCurveTo 方法,才知道这个二次贝塞尔曲线的秘密

3、定义:它的形状由三个点决定:P0(起始点) , P1(控制点), P2 (终点),起始点和终点顾名思义,而控制点则控制了这个弧形的扭曲方向和扭曲程度,该曲线的发明是为了方便大家在电脑上画各种圆滑的弧线

公式:

令P0(x1,y1),P2(x2,y2), P1(cx,cy)

那么就是弧线上的点满足的方程就是

x = Math.pow(1-t, 2) * x1 + 2 * t * (1-t) * cx + Math.pow(t, 2) * x2

y = Math.pow(1-t, 2) * y1 + 2 * t * (1-t) * cy + Math.pow(t, 2) * y2

 

4、画弧线的主要代码:

ctx.moveTo(x1, y1); 
ctx.quadraticCurveTo(cx, cy, x2, y2);

5、加箭头:设我现在要加的箭头数量是 arrowNum,而且我要均匀地点缀到弧线上面去
 

    var arrowNum = arrowNum + 1;
    var share = 1 / arrowNum;
    for(var i = 1; i <= arrowNum; i++){
        t = i * share;
        x = Math.pow(1-t, 2) * x1 + 2 * t * (1-t) * cx + Math.pow(t, 2) * x2;
        y = Math.pow(1-t, 2) * y1 + 2 * t * (1-t) * cy + Math.pow(t, 2) * y2;
        // 加箭头方法就不详写了,主要讲的就是这个曲线上面取点的问题
        addArrow(x, y);
    }

 

6、补充箭头方向说明

一开始没考虑到这个问题,在曲线上面加箭头的时候,各个箭头的方向是随着曲线位置的变化而变化的,此处涉及到求取曲线上面的点的斜率的问题

已知曲线 P0(x1,y1),P2(x2,y2), P1(cx,cy)三个点位值,以及 x,y 关于 t 的函数方程,斜率这样求:

k= dy/dx = (dy/dt) / (dx/dt)  此处涉及求导,高数上面有介绍,我这里直接写结果了

k = ((-2) * (1 - t) * x1 + 2 * (1 - t) * cx - 2 * t * cx + 2 * t * x2 ) / ((-2) * (1 - t) * y1 + 2 * (1 - t) * cy - 2 * t * cy + 2 * t * y2)

k 就是箭头所在直线上的斜率,就相当于 tan(a),注意这里求导的角度只是直线的角度,至于箭头指向直线的那一头就要自己做判断了,这个a求出来也并不是度数,而时用 Math.PI 表示的角度,这里可能会涉及到转换,不要直接当成是度数来用

 

 

你可能感兴趣的:(前端)