PHPで雪の結晶を描く

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

樹木曲線の枝を3本に増やし、中心から角度を変えて複数生やしてやることで、雪の結晶のような図形ができあがる。
(2026年2月21日)PHP8.5対応:imagedestroyを使わない. imagepolygon, imagefilledpolygonの第3引数除去, pahooInputData.phph導入

目次

サンプル・プログラム

圧縮ファイルの内容
CrystalSnow.phpサンプル・プログラム本体
pahooInputData.phpデータ入力に関わる関数群。
使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。
complementaryColor.php 更新履歴
バージョン 更新日 内容
1.3.0 2026/02/21 PHP8.5対応:imagedestroyを使わない
1.2.0 2024/12/21 主な変換式をクラス pahooColor に分離
1.1 2022/04/09 PHP8対応,リファラ・チェック改良
1.0 2017/02/24 初版
pahooInputData.php 更新履歴
バージョン 更新日 内容
2.0.1 2025/08/11 getParam() bug-fix
2.0.0 2025/08/11 pahooLoadEnv() 追加
1.9.0 2025/07/26 getParam() 引数に$trim追加
1.8.1 2025/03/15 validRegexPattern() debug
1.8.0 2024/11/12 validRegexPattern() 追加

準備:pahooInputData 関数群

PHPのバージョンや入力データのバリデーションなど、汎用的に使う関数群を収めたファイル "pahooInputData.php" が同梱されているが、include_path が通ったディレクトリに配置してほしい。他のプログラムでも "pahooInputData.php" を利用するが、常に最新のファイルを1つ配置すればよい。

また、各種クラウドサービスに登録したときに取得するアカウント情報、アプリケーションパスワードなどを登録した .pahooEnv ファイルから読み込む関数 pahooLoadEnv を備えている。こちらについては、「各種クラウド連携サービス(WebAPI)の登録方法」をご覧いただきたい。

解説:再帰図形

CrystalSnow.php

 192: /**
 193:  * 雪の結晶を描く
 194:  * @param   int   $corner 結晶の角の数
 195:  * @param   int   $recur  再帰回数
 196:  * @param   float $fac    枝の発生位置
 197:  * @return  -
 198: */
 199: function CrystalSnow($corner, $recur, $fac) {
 200:     $angle = deg2rad(360 / $corner);        // 回転角(度)
 201: 
 202:     $this->setPenThick($recur);
 203:     $this->movePen(4, 2, FALSE);
 204:     for ($i = 0$i < $corner$i++) {
 205:         $this->tree3($recur, 1, $fac, $angle * $i);
 206:     }
 207: }

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

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

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

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

解説:太さのある直線

CrystalSnow.php

  92: /**
  93:  * 太さのある直線を描画する
  94:  * @param   obj  $image イメージストリーム
  95:  * @param   float ($x1, $y1) - ($x1, $y2)  線分の座標
  96:  * @param   int  $color ペンの色
  97:  * @param   foat $thick ペンの太さ(省略時=1)
  98:  * @return  bool TRUE:成功/FALSE:失敗
  99: */
 100: function imagelinethick($image, $x1, $y1, $x2, $y2, $color, $thick = 1) {
 101:     // 太さ = 1
 102:     if ($thick == 1) {
 103:         return imageline($image, $x1, $y1, $x2, $y2, $color);
 104:     }
 105:     // 太さ > 1
 106:     $t = $thick / 2 - 0.5;
 107:     if ($x1 == $x2 || $y1 == $y2) {
 108:         return imagefilledrectangle($image, round(min($x1, $x2- $t), round(min($y1, $y2- $t), round(max($x1, $x2+ $t), round(max($y1, $y2+ $t), $color);
 109:     }
 110:     $k = ($y2 - $y1) / ($x2 - $x1); // y = kx + q
 111:     $a = $t / sqrt(1 + pow($k, 2));
 112:     $points = array(
 113:         round($x1 - (1 + $k* $a), round($y1 + (1 - $k* $a),
 114:         round($x1 - (1 - $k* $a), round($y1 - (1 + $k* $a),
 115:         round($x2 + (1 + $k* $a), round($y2 - (1 - $k* $a),
 116:         round($x2 + (1 - $k* $a), round($y2 + (1 + $k* $a),
 117:     );
 118:     imagefilledpolygon($image, $points, $this->PenColor);
 119: 
 120:     return imagepolygon($image, $points, $this->PenColor);
 121: }

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

解説:各種パラメータ

CrystalSnow.php

 254: /**
 255:  * $_GET または $_POST から正規化した数値を取り出す
 256:  * @param   array $items 取り出した数値を格納する配列
 257:  * @return  なし
 258: */
 259: function getParameters(&$items) {
 260:     static $tbl_val = array(
 261:         // 描画領域(正方形)の1辺の長さ(ピクセル)
 262:         'width'=>array('type'=>FALSE, 'min'=>100, 'max' => 1000, 'def'=>500),
 263:         // 再帰回数
 264:         'recur'=>array('type'=>FALSE, 'min'=>1, 'max'=>8, 'def'=>6),
 265:         // 結晶の角の数(何角形か)
 266:         'corner'=>array('type'=>TRUE, 'min'=>3, 'max'=>12, 'def'=>6),
 267:         // 枝の発生位置(比率)
 268:         'fac'=>array('type'=>FALSE, 'min'=>0.2, 'max'=>0.8, 'def'=>0.55)
 269:     );
 270:     static $tbl_str = array(
 271:         // 背景色
 272:         'bgcolor'=>array('pat'=>'/^([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/i', 'def'=>'000000'),
 273:         // 描画色
 274:         'color'=>array('pat'=>'/^([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/i', 'def'=>'CCCCFF')
 275:     );
 276:     $errmsg = '';
 277: 
 278:     foreach ($tbl_val as $key=>$arr) {
 279:         $items[$key] = getValidNumber($key, $errmsg, $arr['def'], $arr['type'], $arr['min'], $arr['max']);
 280:     }
 281:     foreach ($tbl_str as $key=>$arr) {
 282:         $items[$key] = '#' . getValidString($key, $errmsg, $arr['def'], 6, 6, TRUE, [$arr['pat']]);
 283:     }
 284: }

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

参考サイト

(この項おわり)
header