1

我有一条由起点、终点和 2 个控制点定义的贝塞尔曲线(此参数:http ://www.w3schools.com/tags/canvas_beziercurveto.asp )。首先,我需要计算这条曲线的宽度和高度。如果我围绕曲线制作矩形,它的宽度和高度就是我需要的。然后我需要这个矩形的起点(左上角的x,y)。

我该如何计算呢?谢谢。

4

3 回答 3

1

对于真正的边界,您需要计算曲线分量函数的末端,然后将它们插入到每个末端的 (x,y) 坐标的贝塞尔函数中。我在http://pomax.github.io/bezierinfo/#extremities对此进行了介绍,它还解释了如何在通向四肢部分的文本中完成大部分所需的步骤。第 11 段和第 12/13 段然后涵盖边界框(分别是您可能感兴趣的普通框和紧密框)

于 2013-08-10T21:27:36.450 回答
1

我在其他一些主题中找到了近似解决方案(我不记得是哪一个),但这里有一个简单的 JS 函数来计算它:

function getCurveBoundary(ax, ay, bx, by, cx, cy, dx, dy) {
        var tobx = bx - ax;
        var toby = by - ay;
        var tocx = cx - bx;
        var tocy = cy - by;
        var todx = dx - cx;
        var tody = dy - cy;
        var step = 1 / 40;    // precission
        var d, px, py, qx, qy, rx, ry, tx, ty, sx, sy, x, y, i, minx, miny, maxx, maxy;
        function min(num1, num2) {
            if (num1 > num2)
                return num2;
            if (num1 < num2)
                return num1;
            return num1;
        }
        function max(num1, num2) {
            if (num1 > num2)
                return num1;
            if (num1 < num2)
                return num2;
            return num1;
        }
        for (var i = 0; i < 41; i++)
        {
            d = i * step;
            px = ax + d * tobx;
            py = ay + d * toby;
            qx = bx + d * tocx;
            qy = by + d * tocy;
            rx = cx + d * todx;
            ry = cy + d * tody;
            toqx = qx - px;
            toqy = qy - py;
            torx = rx - qx;
            tory = ry - qy;

            sx = px + d * toqx;
            sy = py + d * toqy;
            tx = qx + d * torx;
            ty = qy + d * tory;
            totx = tx - sx;
            toty = ty - sy;

            x = sx + d * totx;
            y = sy + d * toty;
            if (i == 0)
            {
                minx = x;
                miny = y;
                maxx = x;
                maxy = y;
            }
            else
            {
                minx = min(minx, x);
                miny = min(miny, y);
                maxx = max(maxx, x);
                maxy = max(maxy, y);
            }
        }
        return {x: Math.round(minx), y: Math.round(miny), width: Math.round(maxx - minx), height: Math.round(maxy - miny)};
    }
于 2014-01-05T18:31:43.993 回答
0

如果您正在寻找一个近似解,很容易计算一个总是足够大以覆盖曲线但可能太大的解。

贝塞尔曲线满足“凸壳属性”,这意味着您可以获取控制点的边界框,这将限制曲线本身。

如果您正在寻找更准确的东西,那么最简单的方法是评估曲线上的一堆不同点并获取曲线上这些点的边界框。您可以改变测试的点数,以改变质量/速度的权衡。

如果您正在寻找直接计算确切答案的东西,那么您需要一个根查找器来查找函数 x(t) 和 y(t) 的极值。

于 2013-08-09T11:27:32.493 回答