PHPで雪の結晶を描く

(1/1)
PHPで雪の結晶を描く
PHPで樹木曲線を描く」の応用で、雪の結晶(のようなもの)を描いてみることにする。

樹木曲線の枝を3本に増やし、中心から角度を変えて複数生やしてやることで、雪の結晶のような図形ができあがる。

(2022年4月17日)PHP8対応,リファラ・チェック改良。

目次

サンプル・プログラム

圧縮ファイルの内容
CrystalSnow.phpサンプル・プログラム本体

解説:再帰図形

0176: /**
0177:  * 雪の結晶を描く
0178:  * @param   int   $corner 結晶の角の数
0179:  * @param   int   $recur  再帰回数
0180:  * @param   float $fac    枝の発生位置
0181:  * @return  -
0182: */
0183: function CrystalSnow($corner$recur$fac) {
0184:     $angle = deg2rad(360 / $corner);     //回転角(度)
0185: 
0186:     $this->setPenThick($recur);
0187:     $this->movePen(4, 2, FALSE);
0188:     for ($i = 0; $i < $corner$i++) {
0189:         $this->tree3($recur, 1, $fac$angle * $i);
0190:     }
0191: }

主要処理はクラス pahooCrystalSnow として定義している。

再帰図形の描き方は、「PHPで樹木曲線を描く」とほぼ同じである。

ユーザー関数 CrystalSnow では、中心から結晶の角の数(デフォルトでは正六角形)だけ回転させ、tree3 を呼び出す。

tree3 は再帰呼び出しによる樹木曲線で、枝を2本から3本に増やしている。

解説:太さのある直線

0076: /**
0077:  * 太さのある直線を描画する
0078:  * @param   obj  $imageイメージストリーム
0079:  * @param   float ($x1, $y1) - ($x1, $y2)  線分の座標
0080:  * @param   int  $colorペンの色
0081:  * @param   foat $thickペンの太さ(省略時=1)
0082:  * @return  bool TRUE:成功/FALSE:失敗
0083: */
0084: function imagelinethick($image$x1$y1$x2$y2$color$thick = 1) {
0085:     //太さ = 1
0086:     if ($thick == 1) {
0087:         return imageline($image$x1$y1$x2$y2$color);
0088:     }
0089:     //太さ > 1
0090:     $t = $thick / 2 - 0.5;
0091:     if ($x1 == $x2 || $y1 == $y2) {
0092:         return imagefilledrectangle($imageround(min($x1$x2) - $t), round(min($y1$y2) - $t), round(max($x1$x2) + $t), round(max($y1$y2) + $t), $color);
0093:     }
0094:     $k = ($y2 - $y1) / ($x2 - $x1); //y = kx + q
0095:     $a = $t / sqrt(1 + pow($k, 2));
0096:     $points = array(
0097:         round($x1 - (1 + $k) * $a), round($y1 + (1 - $k) * $a),
0098:         round($x1 - (1 - $k) * $a), round($y1 - (1 + $k) * $a),
0099:         round($x2 + (1 + $k) * $a), round($y2 - (1 - $k) * $a),
0100:         round($x2 + (1 - $k) * $a), round($y2 + (1 + $k) * $a),
0101:     );
0102:     imagefilledpolygon($image$points, 4, $this->PenColor);
0103: 
0104:     return imagepolygon($image$points, 4, $this->PenColor);
0105: }

結晶の中心に行くほど太さがある直線になるよう、ユーザー関数 imagelinethick を用意した。

解説:各種パラメータ

0323: /**
0324:  * $_GETまたは $_POSTから正規化した数値を取り出す
0325:  * @param   string $type int:整数float:浮動小数
0326:  * @param   string $keyキー
0327:  * @param   mixed $min, $max最小値、最大値
0328:  * @param   string $errmsgエラーメッセージを格納する
0329:  * @return  mixed取得値/NULL:エラー
0330: */
0331: function getParameters(&$items) {
0332:     static $tbl_val = array(
0333:         //描画領域(正方形)の1辺の長さ(ピクセル)
0334:         'width'=>array('type'=>'float', 'min'=>100, 'max' => 1000, 'def'=>500),
0335:         //再帰回数
0336:         'recur'=>array('type'=>'int', 'min'=>1, 'max'=>8, 'def'=>6),
0337:         //結晶の角の数(何角形か)
0338:         'corner'=>array('type'=>'int', 'min'=>3, 'max'=>12, 'def'=>6),
0339:         //枝の発生位置(比率)
0340:         'fac'=>array('type'=>'float', 'min'=>0.2, 'max'=>0.8, 'def'=>0.55)
0341:     );
0342:     static $tbl_str = array(
0343:         //背景色
0344:         'bgcolor'=>array('pat'=>'/^([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/i', 'def'=>'000000'),
0345:         //描画色
0346:         'color'=>array('pat'=>'/^([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/i', 'def'=>'CCCCFF')
0347:     );
0348:     foreach ($tbl_val as $key=>$arr) {
0349:         $items[$key] = getValidNumber($key$arr['type'], $arr['min'], $arr['max'], $arr['def']);
0350:     }
0351:     foreach ($tbl_str as $key=>$arr) {
0352:         $items[$key] = '#' . getValidString($key$arr['pat'], $arr['def']);
0353:     }
0354: }

コメントに記したように、描画領域の大きさ、再帰回数、結晶の角の数など、パラメータとして指定できるようにしてある。

参考サイト

(この項おわり)
header