PHPでベジエ曲線を描く

(1/1)
ベジエ曲線(Bézier Curve)は、コンピュータ・グラフィックで滑らかな曲線を描く時に使われるもので、HTML の SVG や canvas で使えるほか、PHP でもメソッド ImagickDraw::bezier を使って描くことができる。
今回は、これらの機能を使わず、PHP で数式をプログラミングし、任意次元のベジエ曲線を描くプログラムを作る。

サンプル・プログラム:実行例

PHPでベジエ曲線を描く

サンプル・プログラム

ベジエ曲線の軌跡は、バーンスタイン基底関数によって次のように表現できる。
 mimetex 
2点間を結ぶ直線
まず、2 点 P0, P1 を結ぶ直線を考える。
2次ベジエ曲線
3 点 P0, P1, P2 を通るベジエ曲線が左図である。個の 3 点を制御点と呼び、始点と終点を含み、軌跡は途中の点に引っ張られるが、通過はしない。
制御点が 3 つあるものを 2 次ベジエ曲線と呼ぶ。
3次ベジエ曲線
制御点が 4 つになったものが、左図の 3 次ベジエ曲線となる。
SVG や canvas、Adobe Flash Player 11.0 以降では 3 次ベジエ曲線まで描くことができる。

準備:制御点

0035: //制御点
0036: $p = array(
0037: array( 30,  30),        //制御点(0) 始点
0038: array( 30, 270),        //制御点(1)
0039: array(570,  30),        //制御点(2)
0040: array(570, 270),        //制御点(3) 終点
0041: );

配列変数 $p に制御点の座標(X, Y)を用意する。
ここでは、制御点が 4 つある 3 次ベジエ曲線を描くが、制御点の座標及び数(次数)は任意に設定可能である。

解説:ベジエ曲線の座標計算

0177: /**
0178:  * ベジエ曲線の座標計算
0179:  * @param array  $p[$n][0] 制御点のX座標
0180:  *                       [1] 制御点のY座標
0181:  *                   $n = 0 は始点
0182:  * @param float  $t 0.0≦$t≦1.0
0183:  * @return array(X, Y)
0184: */
0185: function BezierCurve($p$t) {
0186:     $len = count($p);
0187:     if ($len == 1)  return $p[0];
0188: 
0189:     $left  = BezierCurve(array_slice($p, 0, $len - 1), $t);
0190:     $right = BezierCurve(array_slice($p, 1, $len), $t);
0191: 
0192:     return array((1 - $t) * $left[0] + $t * $right[0], (1 - $t) * $left[1] + $t * $right[1]);
0193: }

これを再帰手続きで実装したのが、ユーザー関数 BezierCurve である。
呼び出す側で、引数 $t を 0.0 から 1.0 の間で変化させることで、対応する座標(X, Y)を配列として戻す。

解説:ベジエ曲線を描く

0195: /**
0196:  * ベジエ曲線を描く
0197:  * @param array  $p[$n][0] 制御点のX座標
0198:  *                       [1] 制御点のY座標
0199:  *                   $n = 0 は始点
0200:  * @param obj   $image イメージストリーム
0201:  * @param int   $color 色ID(描画色)
0202:  * @param int   $thick 太さ(省略時=1)
0203:  * @return array(X, Y)
0204: */
0205: function drawBezierCurve($p$image$color$thick=1) {
0206:     $n = count($p) - 1;
0207: 
0208:     //始点
0209:     list($x1$y1) = array($p[0][0]$p[0][1]);
0210: 
0211:     //ベジエ曲線
0212:     for ($t = 0; $t <= 1; $t += 0.01) {
0213:         list($x2$y2) = BezierCurve($p$t);
0214:         imagesetthickness($image$thick);
0215:         $res = imageline($image$x1$y1$x2$y2$color);
0216:         if ($res == FALSE)  return FALSE;
0217:         list($x1$y1) = array($x2$y2);
0218:     }
0219: 
0220:     //終点
0221:     list($x2$y2) = array($p[$n][0]$p[$n][1]);
0222:     imagesetthickness($image$thick);
0223:     $res = imageline($image$x1$y1$x2$y2$color);
0224: 
0225:     return $res;
0226: }

ユーザー関数 drawBezierCurve は、前述の BezierCurve を呼び出し、ベジエ曲線を描く。

参考サイト

(この項おわり)
header