如何计算贝塞尔曲线上的控制点?

发布于 2024-09-28 02:37:25 字数 814 浏览 9 评论 0原文

我确实有一条贝塞尔曲线,在某个点上,我想要第二条贝塞尔曲线以平滑的方式“分支”第一条曲线。除了计算交点(贝塞尔曲线后面的百分比)之外,我还需要控制点(切线和权重)。 交点是使用以下 javascript 计算的:(

getBezier = function getBez(percent,p1,cp1,cp2,p2) {
    function b1(t) { return t*t*t }
    function b2(t) { return 3*t*t*(1-t) }
    function b3(t) { return 3*t*(1-t)*(1-t) }
    function b4(t) { return (1-t)*(1-t)*(1-t) }
    var pos = {x:0,y:0};
    pos.x = p1.x*b1(percent) + cp1.x*b2(percent) + cp2.x*b3(percent) + p2.x*b4(percent);
    pos.y = p1.y*b1(percent) + cp1.y*b2(percent) + cp2.y*b3(percent) + p2.y*b4(percent);
    return pos;
}

非 IE 浏览器可以在 http://www. iscriptdesign.com -> 教程 -> 组和路径)。 我现在需要的是分支点的控制点或(切线和权重)(我不知道从哪里开始,我希望有人可以指出一些代码或数学方程,如果可能的话作为来自相同参数的函数如上面的 getBezier 函数)。

I do have a bezier curve, and at a certain point, I want a second bezier curve "branching off" the first curve in a smooth manner. Together with calculating the intersection point (with a percentage following the Bezier curve), I need also the control point (the tangent and weight).
The intersection point is calculated with the following piece of javascript:

getBezier = function getBez(percent,p1,cp1,cp2,p2) {
    function b1(t) { return t*t*t }
    function b2(t) { return 3*t*t*(1-t) }
    function b3(t) { return 3*t*(1-t)*(1-t) }
    function b4(t) { return (1-t)*(1-t)*(1-t) }
    var pos = {x:0,y:0};
    pos.x = p1.x*b1(percent) + cp1.x*b2(percent) + cp2.x*b3(percent) + p2.x*b4(percent);
    pos.y = p1.y*b1(percent) + cp1.y*b2(percent) + cp2.y*b3(percent) + p2.y*b4(percent);
    return pos;
}

(Non IE browsers can see it in action at http://www.iscriptdesign.com -> Tutorial -> Groups & Paths).
All I need now is the controlpoint or (tangent and weight) for the branchpoint ( I don't have a clue where to start, and I hope somebody can point to some code, or mathematical equation, if possible as function from the same parameters as the getBezier function above).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

凉墨 2024-10-05 02:37:25

发现并实现它:de-Casteljau 算法被证明是最快的可实现解决方案。目前它位于:
iScriptDesign(教程 -> Spit Bezier)。

Found and implemented it: de-Casteljau algorithm turned out to be the fastest implementable solution. It is currently present under:
iScriptDesign (Tutorial ->Spit Bezier).

魂归处 2024-10-05 02:37:25

示例用法(我想,我需要@drjerry的帮助)

我有一个css3计时函数,这称为ease-in-out:cubic-bezier(.42,0,.58,1) 。从图形上看,这看起来像: http://cubic-bezier.com/#.42 ,0,.58,1

我想创建一个新的计时函数,它只是该图的下半部分,然后是上半部分。

所以下半部分是ease-incubic-bezier(.42,0,1,1)。以图形方式表示: http://cubic-bezier.com/#.42,0,1 ,1

上半部分是ease-outcubic-bezier(0,0,.58,1)。以图形方式表示: http://cubic-bezier.com/#0,0,.58 ,1

所以现在让我困惑的是,根据 iScriptDesign 的脚本,它告诉我它们是不同的。

iScriptDeisgn 表示 ease-in-out 的开始部分(即 ease-in)是:cubic-bezier(.21, 0, .355, .25)。以图形方式表示: http://cubic-bezier.com/#.21,0 ,.35,.25

iScriptDeisgn 表示 ease-in-out 的结尾部分(即 ease-out)是:cubic-贝塞尔曲线(.145,.25,.29,.5)。以图形方式表示: http://cubic-bezier.com/#.14, .25,.29,.5

为什么iScriptDesign split函数返回的ease-inease-out与真实的ease不同-in 和真正的ease-out?我不明白。

本示例的代码。

//////////////////START FROM ISCRIPTDESIGN
var splitBezier = function(array, perc) {
    array.unshift({x:0, y:0});
    var coll = [];
    while (array.length > 0) {
    for (var i = 0;i < array.length-1; i++) {
        coll.unshift(array[i]);
        array[i] = interpolate(array[i], array[i+1], perc);
    }
    coll.unshift(array.pop());
    }
    return {b1: [{x:coll[5].x, y:coll[5].y}, {x:coll[2].x, y:coll[2].y},{x:coll[0].x, y:coll[0].y}]
        , b2: [{x:coll[1].x - coll[0].x,y:coll[1].y-coll[0].y}, {x:coll[3].x - coll[0].x,y:coll[3].y-coll[0].y}, {x:coll[6].x - coll[0].x,y:coll[6].y-coll[0].y}]};
}

var interpolate = function (p0, p1, percent) {
    if (typeof percent === 'undefined') percent = 0.5;  
    return  {x: p0.x + (p1.x - p0.x) * percent
         , y: p0.y + (p1.y - p0.y) * percent};
}
//////////////////END FROM ISCRIPTDESIGN
var coord = function (x,y) {
  if(!x) var x=0;
  if(!y) var y=0;
  return {x: x, y: y};
}
var easeInOut = [new coord(.42,0), new coord(.58,1), new coord(1,1)];
var split50percent = splitBezier(easeInOut.slice(), .5);

因此 split50percent 设置为:

({
    b1: [{
        x: 0.21,
        y: 0
    }, {
        x: 0.355,
        y: 0.25
    }, {
        x: 0.5,
        y: 0.5
    }],
    b2: [{
        x: 0.14500000000000002,
        y: 0.25
    }, {
        x: 0.29000000000000004,
        y: 0.5
    }, {
        x: 0.5,
        y: 0.5
    }]
})

easeInOutSine 相同

  • easeInOutSine:.44,.05,.55,.95
  • REAL
    • easeInSine:0.47, 0, 0.745, 0.715
    • easeOutSine:0.39、0.575、0.565、1
  • iScriptDesign
    • easeInSine:.22,.03,.36,.26
    • easeOutSine:.14,.24,.28,.48

Example usage (I think, i need help from @drjerry)

I have a css3 timing function, this is called ease-in-out: cubic-bezier(.42,0,.58,1). Graphically this looks like: http://cubic-bezier.com/#.42,0,.58,1

I want to make a new timing function that is just the bottom half and then top half of this graph.

So the bottom half is ease-in: cubic-bezier(.42,0,1,1). Graphically: http://cubic-bezier.com/#.42,0,1,1

And the top half is ease-out: cubic-bezier(0,0,.58,1). Graphically: http://cubic-bezier.com/#0,0,.58,1

So now what confuses me is that according to the script at iScriptDesign it tells me they are different.

iScriptDeisgn says the starting half of ease-in-out is (which is ease-in) is: cubic-bezier(.21, 0, .355, .25). Graphically: http://cubic-bezier.com/#.21,0,.35,.25

iScriptDeisgn says the ending half of ease-in-out is (which is ease-out) is: cubic-bezier(.145, .25, .29, .5). Graphically: http://cubic-bezier.com/#.14,.25,.29,.5

Why is the ease-in and ease-out returned by the iScriptDesign split function different from the real ease-in and real ease-out? I don't get it.

Code for this example.

//////////////////START FROM ISCRIPTDESIGN
var splitBezier = function(array, perc) {
    array.unshift({x:0, y:0});
    var coll = [];
    while (array.length > 0) {
    for (var i = 0;i < array.length-1; i++) {
        coll.unshift(array[i]);
        array[i] = interpolate(array[i], array[i+1], perc);
    }
    coll.unshift(array.pop());
    }
    return {b1: [{x:coll[5].x, y:coll[5].y}, {x:coll[2].x, y:coll[2].y},{x:coll[0].x, y:coll[0].y}]
        , b2: [{x:coll[1].x - coll[0].x,y:coll[1].y-coll[0].y}, {x:coll[3].x - coll[0].x,y:coll[3].y-coll[0].y}, {x:coll[6].x - coll[0].x,y:coll[6].y-coll[0].y}]};
}

var interpolate = function (p0, p1, percent) {
    if (typeof percent === 'undefined') percent = 0.5;  
    return  {x: p0.x + (p1.x - p0.x) * percent
         , y: p0.y + (p1.y - p0.y) * percent};
}
//////////////////END FROM ISCRIPTDESIGN
var coord = function (x,y) {
  if(!x) var x=0;
  if(!y) var y=0;
  return {x: x, y: y};
}
var easeInOut = [new coord(.42,0), new coord(.58,1), new coord(1,1)];
var split50percent = splitBezier(easeInOut.slice(), .5);

So split50percent is set to:

({
    b1: [{
        x: 0.21,
        y: 0
    }, {
        x: 0.355,
        y: 0.25
    }, {
        x: 0.5,
        y: 0.5
    }],
    b2: [{
        x: 0.14500000000000002,
        y: 0.25
    }, {
        x: 0.29000000000000004,
        y: 0.5
    }, {
        x: 0.5,
        y: 0.5
    }]
})

Same thing with easeInOutSine

  • easeInOutSine:.44,.05,.55,.95
  • REAL
    • easeInSine:0.47, 0, 0.745, 0.715
    • easeOutSine:0.39, 0.575, 0.565, 1
  • iScriptDesign
    • easeInSine:.22,.03,.36,.26
    • easeOutSine:.14,.24,.28,.48
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文