使用CoreGraphics查找二次贝塞尔曲线的最小/最大值

7

我正在使用CoreGraphics绘制二次贝塞尔曲线,但想要计算出曲线的最小/最大值。由于我不是数学背景,所以这变得有些麻烦。请问是否有任何关于如何解决这个问题的文章或想法?

3个回答

5

对于一个二次贝塞尔曲线,这其实很简单。

将三个控制点定义为P0 = (x0,y0)P1 = (x1,y1)P2 = (x2,y2)。要找到在x轴上的极值,请解决以下方程:

t = (x0 - x1) / (x0 - 2*x1 + x2)

如果 0 <= t <= 1,那么在t处计算你的曲线,并将该位置存储为Px。对于y,也进行相同的操作。
t = (y0 - y1) / (y0 - 2*y1 + y2)

如果0 <= t <= 1,则在t处计算曲线并将位置存储为Py。最后,找到包含 P0P2Px(如果存在)和Py(如果存在)的轴对齐边界框。此边界框也将紧密地限定您的二维二次贝塞尔曲线。


感谢kangax。修正了拼写错误。 - Naaff

2

微积分为查找连续可微曲线的最小值/最大值提供了标准技巧。

这里有一个示例讨论


1
我已经用Javascript制作了一个这样的表现:

Jsfiddle链接

function P(x,y){this.x = x;this.y = y; }
function pointOnCurve(P1,P2,P3,t){
    if(t<=0 || 1<=t || isNaN(t))return false;
    var c1 =  new P(P1.x+(P2.x-P1.x)*t,P1.y+(P2.y-P1.y)*t);
    var c2 =  new P(P2.x+(P3.x-P2.x)*t,P2.y+(P3.y-P2.y)*t);
    return new P(c1.x+(c2.x-c1.x)*t,c1.y+(c2.y-c1.y)*t);  
}
function getQCurveBounds(ax, ay, bx, by, cx, cy){
    var  P1 = new P(ax,ay);
    var  P2 = new P(bx,by);
    var  P3 = new P(cx,cy);
    var tx =  (P1.x - P2.x) / (P1.x - 2*P2.x + P3.x);
    var ty =  (P1.y - P2.y) / (P1.y - 2*P2.y + P3.y);
    var Ex = pointOnCurve(P1,P2,P3,tx);
    var xMin = Ex?Math.min(P1.x,P3.x,Ex.x):Math.min(P1.x,P3.x);
    var xMax = Ex?Math.max(P1.x,P3.x,Ex.x):Math.max(P1.x,P3.x);
    var Ey = pointOnCurve(P1,P2,P3,ty);
    var yMin = Ey?Math.min(P1.y,P3.y,Ey.y):Math.min(P1.y,P3.y);
    var yMax = Ey?Math.max(P1.y,P3.y,Ey.y):Math.max(P1.y,P3.y);
    return {x:xMin, y:yMin, width:xMax-xMin, height:yMax-yMin};
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接