【问题标题】:Calculate the slope of a tangent of an arbitrary point on a quadratic curve in Javascript在Javascript中计算二次曲线上任意点的切线的斜率
【发布时间】:2017-08-25 22:32:22
【问题描述】:

我从来不是三角冠军,经过大约 4 个小时的搜索,我决定在这里问:

我使用 Javascript 在 HTML5 Canvas 上绘制二次曲线(不是三次贝塞尔曲线),如下所示:

this.shape.moveTo(50,80).curveTo(100,120,40,190);

其中moveTo指定第一个点的x和y,curveTo的前两个参数指定控制点的x和y,curveTo的第3个和第4个参数指定结束点的x和y。

我需要制作一个函数,让我获得该曲线上任意点 t 的斜率,例如:

function getTangentSlope(P0,P1,P2,t) {
   blah blah blah
   return slope;
}

到目前为止,我找到的唯一解决方案是具有两个控制点的三次曲线 (Find the tangent of a point on a cubic bezier curve (on an iPhone)),或者我不理解符号 (https://www.math.usm.edu/lee/mathphysarchive/?p=542),或者断开的链接意味着我无法查看整个解决方案 (Quadratic Bezier Curve: Calculate Tangent)。

如果以度为单位给出斜率,最好还是这样。

有兄弟能帮帮我吗?

【问题讨论】:

    标签: javascript html canvas trigonometry


    【解决方案1】:

    这将返回二阶和三阶曲线单位位置处的归一化切线。

    请参阅this answer,了解以下对象的更详细用法。

    const geom = (()=>{
    
        function Vec(x,y){ 
            this.x = x;
            this.y = y;
        };
        function Bezier(p1,p2,cp1,cp2){  
            this.p1 =  p1;
            this.p2 =  p2;
            this.cp1 = cp1;
            this.cp2 = cp2;
        }    
        Bezier.prototype = {
            //======================================================================================
            // single dimension polynomials for 2nd (a,b,c) and 3rd (a,b,c,d) order bezier 
            //======================================================================================
            // for quadratic   f(t) = a(1-t)^2+2b(1-t)t+ct^2 
            //                      = a+2(-a+b)t+(a-2b+c)t^2
            // The derivative f'(t) =  2(1-t)(b-a)+2(c-b)t
            //======================================================================================
            // for cubic           f(t) = a(1-t)^3 + 3bt(1-t)^2 + 3c(1-t)t^2 + dt^3 
            //                          = a+(-2a+3b)t+(2a-6b+3c)t^2+(-a+3b-3c+d)t^3
            // The derivative     f'(t) = -3a(1-t)^2+b(3(1-t)^2-6(1-t)t)+c(6(1-t)t-3t^2) +3dt^2
            // The 2nd derivative f"(t) = 6(1-t)(c-2b+a)+6t(d-2c+b)
            //======================================================================================        
            p1 : undefined,
            p2 : undefined,
            cp1 : undefined,
            cp2 : undefined,
            tangentAsVec (position, vec ) { 
                var a, b, c, u;
                if (vec === undefined) { vec = new Vec(); }
    
                if (this.cp2 === undefined) {
                    a = (1-position) * 2;
                    b = position * 2;
                    vec.x = a * (this.cp1.x - this.p1.x) + b * (this.p2.x - this.cp1.x);
                    vec.y = a * (this.cp1.y - this.p1.y) + b * (this.p2.y - this.cp1.y);
                }else{
                    a  = (1-position)
                    b  = 6 * a * position;        // (6*(1-t)*t)
                    a *= 3 * a;                   // 3 * ( 1 - t) ^ 2
                    c  = 3 * position * position; // 3 * t ^ 2
                    vec.x  = -this.p1.x * a + this.cp1.x * (a - b) + this.cp2.x * (b - c) + this.p2.x * c;
                    vec.y  = -this.p1.y * a + this.cp1.y * (a - b) + this.cp2.y * (b - c) + this.p2.y * c;
                }   
                u = Math.sqrt(vec.x * vec.x + vec.y * vec.y);
                vec.x /= u;
                vec.y /= u;
                return vec;                 
            },      
        }
        return { Vec, Bezier,}
    })()
    

    二阶贝塞尔曲线的用法

       // ? represents any value 
       var p1 = new geom.Vec(?,?);  // start point
       var p2 = new geom.Vec(?,?);  // end point
       var cp1 = new geom.Vec(?,?); //control point
    
       var bez2 = new geom.Bezier(p1,p2,cp1); // create 2nd order bezier
       var t = ?;
       var tangent = bez2.tangentAsVec(t);
    

    三阶贝塞尔曲线的用法

       // ? represents any value 
       var p1 = new geom.Vec(?,?);  // start point
       var p2 = new geom.Vec(?,?);  // end point
       var cp1 = new geom.Vec(?,?); // 1st control point
       var cp2 = new geom.Vec(?,?); // 2nd control point
    
       var bez3 = new geom.Bezier(p1,p2,cp1,cp2); // create 3rd order bezier
       var t = ?;
       var tangent = bez2.tangentAsVec(t);
    

    【讨论】:

      【解决方案2】:

      嗯,我不知道这个函数看起来如何,但我知道你可以在哪里找到有用的例子 :)

      前段时间我用一个库来绘制图表。在这个库中,我发现了许多在折线图中绘制线条的函数。库称为 D3。挖掘代码后发现了一个有趣的文件:

      https://github.com/d3/d3-shape/tree/master/src/curve
      

      在这里你可以看到你可以得到什么效果:

      https://github.com/d3/d3-shape#curves
      

      祝你好运:)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-08-03
        • 1970-01-01
        • 2016-11-27
        • 2012-02-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-04
        相关资源
        最近更新 更多