ベジェ曲線

Bézier Curve別名:ベジエ曲線、ベジェパス

概要

数個の制御点で形を決める、なめらかな曲線。曲線は両端の点(アンカー)を通り、あいだの点(ハンドル)は通らずに曲線を引き寄せる。ベクター画像、フォント、アニメーションの補間曲線に広く使われる。

デモ

デモを読み込んでいます
四角い点(アンカー)と丸い点(ハンドル)をドラッグして形を変えられます。緑と青の線は、曲線上の点を求める作図です。「ハンドルをそろえる」を切り替えると、2 本の曲線のつなぎ目がなめらかになるか、角ができるかを比べられます。

使われる場面

  • ベクターイラストとロゴ

    ペンツールで描く線や図形の輪郭は、ベジェ曲線をつないだパスでできている。拡大しても輪郭がなめらかなまま保たれる。

  • フォント

    文字の輪郭はベジェ曲線で記述されている。フォントの形式によって、2 次の曲線を使うものと 3 次の曲線を使うものがある。

  • アニメーションの補間

    キーフレームのあいだで値がどう変わるかを、ベジェ曲線のグラフで指定する。イージングの曲線もその一つである。

  • 3D の経路と形状

    カメラや物体が通る経路や、ケーブル、ホース、道路のような細長い形状の芯になる線を、ベジェ曲線で作る。

判断基準

こういうときこうする
なめらかな線や輪郭を、少ない点で描きたいベジェ曲線を使う。点が少ないほど曲線はなめらかになりやすく、あとからの修正も楽になる。
2 本の曲線を、角を作らずにつなぎたいつなぎ目の前後のハンドルを、アンカーをはさんで一直線にそろえる。長さまでそろえると、曲線に沿って物を動かしたときの速さもつなぎ目で変わらない。
つなぎ目にはっきりした角を立てたい前後のハンドルを別々の向きに置く。
円や楕円を描きたいベジェ曲線では円を正確には表せない。4 本の 3 次曲線で近似するのが一般的で、誤差は見て分からないほど小さい。
決まった点を必ず通る曲線を引きたい(計測した点をなめらかにつなぐなど)ハンドルを手で置くベジェ曲線より、与えた点を通るように作られたスプライン曲線(Catmull-Rom スプラインなど)が向いている。

こう見えたら

  • 曲線のつなぎ目が折れて、角ができている形と陰影
  • 線がなめらかでなく、細かく波打っている形と陰影
  • 曲線に沿った動きの速さにむらがある動き

指示の例

  • 曲線のつなぎ目に角ができている。つなぎ目の前後のハンドルを一直線にそろえて

  • 曲線に沿って動く物体が、区間によって速くなったり遅くなったりする。曲線の長さに応じて進む位置を割り当て直して、一定の速さで動かして

  • 線がなめらかでなく、細かく波打っている。アンカーの数を減らして、ハンドルで曲がり方を調整して

  • この点を必ず通る曲線にしたい。ベジェ曲線ではなく、点を通るスプライン曲線を使って

詳細

線形補間を重ねて作る

2 点 AA と BB を結ぶ線分上で、AA から割合 tt だけ進んだ点は (1−t)A+tB(1 - t)A + tB で表せる。ベジェ曲線は、この線形補間を何段も重ねて作る曲線である。4 つの制御点 P0,P1,P2,P3P_0, P_1, P_2, P_3 があるとき、隣り合う点どうしを tt で内分して 3 点を作り、その 3 点から同じように 2 点、最後に 1 点を作る。この 1 点が曲線上の位置 B(t)B(t) で、tt を 0 から 1 まで動かすと P0P_0 から P3P_3 まで曲線をたどる。この作図の手順をド・カステリョのアルゴリズムと呼び、デモの緑の線が 1 段目、青の線が 2 段目にあたる。2 段目の線分は、求めた点での曲線の接線にもなっている。

式

作図を展開すると、3 次ベジェ曲線は次の式になる。

B(t)=(1−t)3P0+3(1−t)2t P1+3(1−t)t2P2+t3P3(0≤t≤1)B(t) = (1-t)^3 P_0 + 3(1-t)^2 t\, P_1 + 3(1-t) t^2 P_2 + t^3 P_3 \qquad (0 \le t \le 1)

各制御点の係数は tt によって変わる重みで、合計は常に 1 になる。t=0t = 0 では P0P_0 の重みだけが 1 に、t=1t = 1 では P3P_3 の重みだけが 1 になるので、曲線は両端の点を通る。P1P_1 と P2P_2 の重みはどの tt でも 1 にならないため、曲線はこれらの点を通らず、引き寄せられるだけである。また、端での曲線の向きは P0→P1P_0 \to P_1 と P2→P3P_2 \to P_3 の向きに一致する。そのため、曲線が通る端の点をアンカー、端での向きを決める点をハンドルと呼ぶ。制御点が 3 つなら 2 次ベジェ曲線になる。

function bezier(p0, p1, p2, p3, t) {
  const u = 1 - t;
  const w = [u * u * u, 3 * u * u * t, 3 * u * t * t, t * t * t]; // 各制御点の重み
  return {
    x: w[0] * p0.x + w[1] * p1.x + w[2] * p2.x + w[3] * p3.x,
    y: w[0] * p0.y + w[1] * p1.y + w[2] * p2.y + w[3] * p3.y,
  };
}

つなぎ目と落とし穴

複雑な形は、1 本の曲線の次数を上げるのではなく、3 次の曲線を何本もつないで作る。つなぎ目がなめらかになるのは、つなぎ目の前後のハンドルがアンカーをはさんで一直線に並ぶときである。一直線でなければ、曲線の向きがつなぎ目で急に変わり、角ができる。

tt を等間隔に動かしても、曲線上の点は等間隔には進まない。制御点どうしが離れている区間では点が速く進み、詰まっている区間では遅く進む。曲線に沿って一定の速さで物を動かすには、曲線の長さを測り、長さに応じて tt を割り当て直す必要がある。

曲線全体は、制御点を囲む凸多角形の内側に必ず収まる。この性質(凸包性)を使うと、曲線そのものを計算しなくても、当たり判定や描画範囲をおおまかに見積もれる。

関連