ベジエ曲線のバウンディングボックス

Bézier curve - Wikipedia, the free encyclopedia

B(t) = (1-t)^3 * P0 + 3 * (1-t)^2 * t * P1 + 3 * (1-t) * t^2 * P2 + t^3 * P3
なので
B'(t) = -3 * P0 * (1 - t)^2 + 3 * P1 * (1 - t)^2 - 6 * P1 * (1 - t) * t + 6 * P2 * (1 - t) * t - 3 * P2 * t^2 + 3 * P3 * t^2
の解t = *1(-3 P0+9 P1-9 P2+3 P3!=0)のうち0~1に収まるtの時のB(t)の値を計算して、B(0) = P0、B(1) = P3とあわせて最小値と最大値を求めればいいな。たぶん。後で実装しよう。




あってそう。

(ここにあったコードは全然あっていなかったので削除しました)




こんどこそあってそう。




うひひ。

5次元の空間上に分布しているので切断面を変えると色々変わる。



しばらく動かしてみて特に目立った問題が見つからないので公開。MIT Licenseで、とか書いておくと使いやすいのかな??

    def calc_box(start, curves):
        P0 = start
        bounds = [[P0[0]], [P0[1]]]

        for c in curves:
            P1, P2, P3 = (
                (c[0], c[1]), 
                (c[2], c[3]), 
                (c[4], c[5]))

            bounds[0].append(P3[0])
            bounds[1].append(P3[1])

            for i in [0, 1]:
                f = lambda t: (
                    (1-t)**3 * P0[i] 
                    + 3 * (1-t)**2 * t * P1[i] 
                    + 3 * (1-t) * t**2 * P2[i]
                    + t**3 * P3[i])

                b = float(6 * P0[i] - 12 * P1[i] + 6 * P2[i])
                a = float(-3 * P0[i] + 9 * P1[i] - 9 * P2[i] + 3 * P3[i])
                c = float(3 * P1[i] - 3 * P0[i])

                if a == 0:
                    if b == 0:
                        continue
                    t = -c / b
                    if 0 < t < 1: 
                        bounds[i].append(f(t))
                    continue

                b2ac = b ** 2 - 4 * c * a
                if b2ac < 0: 
                    continue
                t1 = (-b + sqrt(b2ac))/(2 * a)
                if 0 < t1 < 1: bounds[i].append(f(t1))
                t2 = (-b - sqrt(b2ac))/(2 * a)
                if 0 < t2 < 1: bounds[i].append(f(t2))

            P0 = P3

        x = min(bounds[0])
        w = max(bounds[0]) - x
        y = min(bounds[1])
        h = max(bounds[1]) - y
        return (x, y, w, h)

*1:-6 P0+12 P1-6 P2)+-sqrt((6 P0-12 P1+6 P2)^2-4 (3 P1-3 P0) (-3 P0+9 P1-9 P2+3 P3)))/(2 (-3 P0+9 P1-9 P2+3 P3


アルファで混ざるだけで、加算合成にならないから、すごくアルファの低い状態にしておいて加算されてるっぽくするしかないのかなぁ。


しばらく離れてからもう一度見ると…やっぱりこれを光だというのには無理があるよねぇ。質感が。黒い紙に牛乳とかこぼしたとか、水を落としたら色が抜けた、とかみたいな。