このサイトで使用している暗号式は、以下のCGIスクリプトで生成しました。
動作させるためには、以下のものが必要です。
・perl-5.6以上が実行できる環境
・GD.pm
・GD(画像生成用のライブラリ), libpngライブラリ
・暗号文字用の適当なフォント(2種類)
私自身はUNIX環境でしかこのスクリプトの動作を試していません。
WindowsでperlやGDをインストールする場合は、このあたりのサイトが参考になるかもしれません。
なお実際に使用するためには、スクリプト冒頭の二カ所でフォントファイルの設定、および使う文字の設定が必要です。
今後の課題:
・適当に作ったのでスクリプトが汚い…(っていうかコメントぐらい書けよ)。
・扇形衝突判定ルーチンが遅い。多分、無駄な処理を何重にもしている
・扇形衝突判定ルーチンや、いくつかあるオブジェクト描画ルーチンのパッケージ化
・オブジェクトを増やして、より豊富な暗号式を生成可能に
・せっかくwrapperをかましているので、そこで切り離してGD以外の描画エンジンにも対応する
果たして使いたいなんて奇特な人がいるのか知りませんが、一応ライセンスはGPL ver.2以降としておきます。
#!/usr/bin/perl
use CGI;
use GD;
use Encode qw(decode);
use strict;
my $q = new CGI;
#使う文字の設定
my @strset1 = split(//, "ԱԲԳԴԵԶԷԸԹԺԻԽԿՀՁՂՃՄՅՆՇՈՉՊՋՌՍՎՏՐՑՒՓՔՕՖաբգդեզէըթժլխծկհձղճմյնշոչպջռսվտրւփքօֆ0123456789");
my @strset2 = split(//, decode("utf8", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"));
my $font1 = "MshtakanRegular.ttf"; # 暗号文字に使用するフォント(アルメニア語)
my $font2 = "Thonburi.ttf"; # 英字フォント
my $range = ($q->param("range") || 2);;
my $width = ($q->param("width") || 800) * $range;
my $height = ($q->param("height") || 600) * $range;
my $zoom = ($q->param("zoom") || 3);
my $max_objs = 200;
my $nr_objs = 0;
my $seed = $q->param('seed') || int(rand(999999));
my $log = "seed: $seed\n";
my $npp = 5; # nr_retry per point
srand($seed);
my $x = $width/2;
my $y = $height/2;
my @pattern = (
{ weight => 1, draw => \&pat1_draw, objs => \&pat1_objs, cons => \&pat1_cons },
{ weight => 1, draw => \&pat2_draw, objs => \&pat2_objs, cons => \&pat2_cons },
{ weight => 1, draw => \&pat3_draw, objs => \&pat3_objs, cons => \&pat3_cons },
{ weight => 1, draw => \&pat4_draw, objs => \&pat4_objs, cons => \&pat4_cons },
{ weight => .8, draw => \&pat5_draw, objs => \&pat5_objs, cons => \&pat5_cons },
{ weight => 1, draw => \&genr_draw, objs => \&genr_objs, cons => \&genr_cons },
);
my $pwsum = 0;
$pwsum += $_->{weight} for @pattern;
if (!$q->param('g')) {
print "Content-type: text/html\n\n";
print '';
print "\n";
exit;
}
$zoom /= $range;
my $im = new GD::Image($width*$zoom,$height*$zoom);
#$im->interlaced(true);
my $white = $im->colorAllocate(255,255,255);
my $black = $im->colorAllocate(0,0,0);
my $red = $im->colorAllocate(255,0,0);
my $green = $im->colorAllocate(0,255,0);
my $color = $white;
$im->fill(1,1,$black);
$im->transparent($black);
my $a180 = 3.1415926535897932384626;
my $a360 = $a180 * 2;
my $a90 = $a180 / 2;
my $a60 = $a180 / 3;
my $a45 = $a180 / 4;
my $a30 = $a180 / 6;
my $deg = $a180/180;
if (0) {
$pattern[0]->{draw}($x+200, $y+200, 0, 0xffff);
$x -= 100; $y -= 100;
my ($pat, $flag) = (4,0);
my $dir = 180;
my $cons = $pattern[$pat]->{cons}($x, $y, $dir, $flag);
draw_triangle_mark($_->[0], $_->[1], 0, $_->[2]) foreach (@$cons);
$pattern[$pat]->{draw}($x, $y, $dir, $flag);
my $objs = $pattern[$pat]->{objs}($x, $y, $dir, $flag);
if (1) {
$color = $red;
foreach (@$objs) {
draw_circle(@$_);
draw_line_from_circle($_->[0], $_->[1], 0, 0, $_->[2], $_->[3]) if ($_->[3]);
draw_line_from_circle($_->[0], $_->[1], 0, 0, $_->[2], $_->[4]) if ($_->[4]);
}
$color=$white;
}
} else {
arrange_patterns($x, $y);
}
draw_str($im, 5, 10*$range, 0, $font2, 9*$range, $log, $white) if $q->param('log');
print "Content-type: image/png\n\n", $im->png;
exit;
##########################################################
# wrapper
sub draw_arc {
my ($im,$x,$y,$w,$h,$b,$e,$p,$c) = @_;
my $d = $p * $zoom / 2 - 1;
do {
$im->arc($x*$zoom,$y*$zoom,$w*$zoom-$d,$h*$zoom-$d,$b,$e,$c);
$im->arc($x*$zoom+1,$y*$zoom,$w*$zoom-$d,$h*$zoom-$d,$b,$e,$c);
$im->arc($x*$zoom-1,$y*$zoom,$w*$zoom-$d,$h*$zoom-$d,$b,$e,$c);
$im->arc($x*$zoom,$y*$zoom,$w*$zoom-$d+1,$h*$zoom-$d,$b,$e,$c);
$im->arc($x*$zoom,$y*$zoom,$w*$zoom-$d-1,$h*$zoom-$d,$b,$e,$c);
} while ($d-- > -$p*$zoom/2);
}
sub draw_line {
my ($im,$x,$y,$x2,$y2,$p,$s,$c) = @_;
map {$_ = int($_+0.5)} ($x, $y, $x2, $y2);
my $d = $p * $zoom / 2;
do {
my $ix = ($d/2) * ($y-$y2) / sqrt(($x2-$x)**2 + ($y2-$y)**2);
my $iy = ($d/2) * ($x2-$x) / sqrt(($x2-$x)**2 + ($y2-$y)**2);
$im->line($x*$zoom+$ix+$s*$iy,$y*$zoom+$iy-$s*$ix,
$x2*$zoom+$ix-$s*$iy,$y2*$zoom+$iy+$s*$ix,$c);
$im->line($x*$zoom+$ix+$s*$iy+1,$y*$zoom+$iy-$s*$ix,
$x2*$zoom+$ix-$s*$iy+1,$y2*$zoom+$iy+$s*$ix,$c);
} while(--$d >= -$p*$zoom/2)
}
sub draw_str {
my ($im,$x,$y,$dir,$font,$size,$str,$c) = @_;
return $im->stringFT($c,$font,$size*$zoom,$dir,$x*$zoom,$y*$zoom,$str);
}
sub draw_triangle {
my ($im,$x,$y,$dir,$size,$c) = @_;
my $dx1 = sin($dir+$a45) * $size * $zoom;
my $dy1 = cos($dir+$a45) * $size * $zoom;
my $dx2 = sin($dir-$a45) * $size * $zoom;
my $dy2 = cos($dir-$a45) * $size * $zoom;
$im->line($x*$zoom, $y*$zoom, $x*$zoom+$dx1, $y*$zoom+$dy1, $c);
$im->line($x*$zoom, $y*$zoom, $x*$zoom+$dx2, $y*$zoom+$dy2, $c);
$im->line($x*$zoom+$dx1, $y*$zoom+$dy1, $x*$zoom+$dx2, $y*$zoom+$dy2, $c);
$im->fill($x*$zoom+($dx1+$dx2)/3, $y*$zoom+($dy1+$dy2)/3, $c);
}
# command lv 1
sub draw_circle {
my ($x, $y, $r, $start, $end) = @_;
$start -= int($start/360 - ($start<0?1:0))*360;
$end -= int($end/360 - ($end<0?1:0))*360;
$end += 360 if ($start >= $end);
draw_arc($im, $x, $y, $r*2, $r*2, 360+450-$end, 360+450-$start, 4, $color);
}
sub draw_text_on_line {
my ($x, $y, $dir, $str, $font, $s) = @_;
my $size = $s || 5;
$dir -= 90;
$dir *= $deg;
$x += sin($dir) * 8 + cos($dir) * 8;
$y += cos($dir) * 8 - sin($dir) * 8;
my @bounds = draw_str($im,$x,$y,$dir,$font,$size,$str,$color);
}
sub draw_text_in_circle {
my ($x, $y, $r, $start, $end, $str, $font, $s) = @_;
my $len = length $str;
my $o = $r - 13;
my $size = $s || 10;
$start += 8;
$end += 5;
$start *= $deg;
$end *= $deg;
for(my $i = 0; $i<$len; $i++) {
my $t = $start + ($end-$start)/$len*$i;
my $s = sin($t);
my $c = cos($t);
my @bounds = draw_str($im,$x-$size*$c+$o*$s,$y+$size*$s+$o*$c,$t+$a180,$font,$size,substr($str,$i,1),$color);
}
}
sub random_str {
my $loop = $_[0];
$_ = "";
$_ .= ($loop > 3 && rand() < 0.1) ? " " : $strset1[int(rand($#strset1))] while ($loop-->=0);
$_;
}
sub random_str2 {
my $loop = $_[0];
$_ = "";
$_ .= ($loop > 3 && rand() < 0.2) ? " " : $strset2[int(rand($#strset2))] while ($loop-->=0);
$_;
}
sub draw_triangle_mark {
my ($x, $y, $r, $dir) = @_;
$dir *= $deg;
$x += sin($dir)*$r;
$y += cos($dir)*$r;
draw_triangle($im,$x,$y,$dir,8,$color);
}
sub draw_triangle_mark2 {
my ($x, $y, $r, $dir, $l, $s) = @_;
$dir *= $deg;
$x += sin($dir)*($r+$l);
$y += cos($dir)*($r+$l);
my $dx = -sin($s*$deg+$a45)*$l;
my $dy = -cos($s*$deg+$a45)*$l;
my $dx2 = -sin($s*$deg-$a45)*$l;
my $dy2 = -cos($s*$deg-$a45)*$l;
draw_line($im,$x,$y,$x+$dx,$y+$dy,4,1,$color);
draw_line($im,$x+$dx,$y+$dy,$x+$dx2,$y+$dy2,4,1,$color);
draw_line($im,$x+$dx2,$y+$dy2,$x,$y,4,1,$color);
}
sub draw_3c_mark {
my ($x, $y, $r, $dir, $a) = @_;
$a = $a || 0;
draw_circle($x+sin($dir*$deg)*$r-sin($dir*$deg+$a*$a180)*8,
$y+cos($dir*$deg)*$r-cos($dir*$deg+$a*$a180)*8, 3);
draw_circle($x+sin($dir*$deg)*$r-sin(($dir+120)*$deg+$a*$a180)*8,
$y+cos($dir*$deg)*$r-cos(($dir+120)*$deg+$a*$a180)*8, 3);
draw_circle($x+sin($dir*$deg)*$r-sin(($dir+240)*$deg+$a*$a180)*8,
$y+cos($dir*$deg)*$r-cos(($dir+240)*$deg+$a*$a180)*8, 3);
}
sub calc_line_from_circle {
my ($x, $y, $r, $start, $l, $dir) = @_;
my $x1 = $x + $r * sin($start*$a180/180);
my $y1 = $y + $r * cos($start*$a180/180);
my $x2 = $x1 + $l * sin($dir*$a180/180);
my $y2 = $y1 + $l * cos($dir*$a180/180);
return ($x1, $y1, $x2, $y2);
}
sub draw_line_from_circle {
my ($x, $y, $r, $start, $l, $dir, $text) = @_;
my ($x1, $y1, $x2, $y2) = calc_line_from_circle(@_);
draw_line($im, $x1,$y1,$x2,$y2,4,0,$color);
if ($text) {
my $str = "";
my $_text = $text;
$text = -$_text if ($_text < 0);
for (; $text > 0; $text -= 3) {
$str .= random_str2(int($l/15)*($text>3?3:$text)) . "\n";
}
draw_text_on_line($_text>0?$x2:$x1, $_text>0?$y2:$y1, $dir+($_text>0?180:0), $str, $font2);
}
return ($x1,$y1, $x2, $y2);
}
sub draw_triangle_in_circle {
my ($x, $y, $r, $start, $text) = @_;
draw_line_from_circle($x, $y, $r, $start, $r*1.732, $start+150, $text&1);
draw_line_from_circle($x, $y, $r, $start+120, $r*1.732, $start+270, $text&2/2);
draw_line_from_circle($x, $y, $r, $start+240, $r*1.732, $start+390, ($text&4)/4);
}
sub draw_triangle_in_circle2 {
my ($x, $y, $r, $start, $text) = @_;
my $d = 15;
my $s = 0.82;
draw_line_from_circle($x, $y, $r, $start+30, $r*1.732*$s, $start-120-$d, $text&1);
draw_line_from_circle($x, $y, $r, $start+150, $r*1.732*$s, $start-$d, $text&2);
draw_line_from_circle($x, $y, $r, $start-90, $r*1.732*$s, $start+120-$d, ($text&4)/2);
}
# collision checking
sub len2 {
return ($_[0] - $_[2])*($_[0] - $_[2]) + ($_[1] - $_[3])*($_[1] - $_[3]);
}
sub vpoint {
my ($l1, $x, $y) = @_;
my ($x1, $y1, $x2, $y2) = @$l1;
my $dx = $x2-$x1;
my $dy = $y2-$y1;
my $a = $dx*$dx + $dy*$dy;
return ($x1, $y1) if ($a == 0);
my $b = $dx*($x1-$x) + $dy*($y1-$y);
my $t = -($b/$a);
$t = 0 if $t < 0;
$t = 1 if $t > 1;
return ($t*$dx+$x1, $t*$dy+$y1);
}
sub inangle {
my ($u,$s,$t) = @_;
return -1 unless ($s || $t);
my $cola = 5;
$s -= int($s/360 - ($s<0?1:0))*360;
$t -= int($t/360 - ($t<0?1:0))*360;
$u -= int($t/360 - ($u<0?1:0))*360;
$t += 360 if ($s > $t);
return ($s+$cola < $u && $u < $t-$cola || $s+$cola < $u+360 && $u+360 < $t-$cola);
}
sub infan {
my ($x, $y, $f2) = @_;
my ($a, $b, $r, $s, $t) = @$f2;
my $dx = $x-$a;
my $dy = $y-$b;
$r -= 3;
return 0 if ($dx*$dx+$dy*$dy>$r*$r);
return 1 unless ($s && $t);
my $u = atan2($dx,$dy) / $deg;
return inangle($u,$s,$t);
}
sub llcol {
my ($l1,$l2) = @_;
my ($x1,$y1,$x2,$y2) = @$l1;
my ($x3,$y3,$x4,$y4) = @$l2;
(($x1-$x2)*($y3-$y1)+($y1-$y2)*($x1-$x3)) *
(($x1-$x2)*($y4-$y1)+($y1-$y2)*($x1-$x4)) < 0 and
(($x3-$x4)*($y1-$y3)+($y3-$y4)*($x3-$x1)) *
(($x3-$x4)*($y2-$y3)+($y3-$y4)*($x3-$x2)) < 0;
}
sub lfcol {
my ($l1,$f2) = @_;
my ($x1,$y1,$x2,$y2) = @$l1;
my ($a,$b,$r,$s,$t) = @$f2;
$r -= 2;
my $px1 = $a + sin($s*$deg)*$r;
my $py1 = $b + cos($s*$deg)*$r;
my $px2 = $a + sin($t*$deg)*$r;
my $py2 = $b + cos($t*$deg)*$r;
return 1 if &llcol($l1,[$a,$b,$px1,$py1]);
return 2 if &llcol($l1,[$a,$b,$px2,$py2]);
return 3 if &infan($x1,$y1,$f2);
return 4 if &infan($x2,$y2,$f2);
return 5 if &infan(&vpoint($l1,$a,$b),$f2);
return 0;
}
sub ffcol {
my ($f1,$f2) = @_;
my ($x1,$y1,$r1,$s1,$t1) = @$f1;
my ($x2,$y2,$r2,$s2,$t2) = @$f2;
my $dx = $x2-$x1;
my $dy = $y2-$y1;
$r1 -= 2;
$r2 -= 2;
return 0 if ($dx*$dx+$dy*$dy>($r1+$r2)*($r1+$r2));
my $u = atan2($dx,$dy) / $deg;
return 1 if (inangle($u, $s1, $t1) && inangle($u+180, $s2, $t2));
return 2 if &infan($x2,$y2,$f1);
if ($s1 || $t1) {
my $px1 = $x1 + sin($s1*$deg)*$r1;
my $py1 = $y1 + cos($s1*$deg)*$r1;
my $px2 = $x1 + sin($t1*$deg)*$r1;
my $py2 = $y1 + cos($t1*$deg)*$r1;
return 4 if &lfcol([$x1,$y1,$px1,$py1],$f2);
return 5 if &lfcol([$x1,$y1,$px2,$py2],$f2);
}
if ($s1 || $t1) {
my $px1 = $x1 + sin($s1*$deg)*$r1;
my $py1 = $y1 + cos($s1*$deg)*$r1;
my $px2 = $x1 + sin($t1*$deg)*$r1;
my $py2 = $y1 + cos($t1*$deg)*$r1;
return 4 if &lfcol([$x1,$y1,$px1,$py1],$f2);
return 5 if &lfcol([$x1,$y1,$px2,$py2],$f2);
}
if ($s2 || $t2) {
my $px1 = $x2 + sin($s2*$deg)*$r2;
my $py1 = $y2 + cos($s2*$deg)*$r2;
my $px2 = $x2 + sin($t2*$deg)*$r2;
my $py2 = $y2 + cos($t2*$deg)*$r2;
return 6 if &lfcol([$x2,$y2,$px1,$py1],$f1);
return 7 if &lfcol([$x2,$y2,$px2,$py2],$f1);
}
return 0;
}
sub collision_check {
my ($objs, $lines, $f, $line) = @_;
if ($line) {
foreach (@$objs) {
return -1 if (lfcol($line, $_)); # line-objs collision
}
}
foreach (@$lines) {
return 1 if (lfcol($_, $f)); # obj-lines collision
}
foreach (@$objs) {
return 2 if (ffcol($f, $_)); # obj-objs collision
}
return 0;
}
# arrange_patterns
sub arrange_patterns {
my @objs = ();
my @lines = ([0,0,$width,0], [$width,0,$width,$height], [$width,$height,0,$height], [0,$height,0,0]);
my @point = ([$npp, $x, $y, 90], [$npp, $x, $y, -90]);
my $max_retry = 5000;
my $abort = 0;
# timeout
$SIG{ALRM} = sub {$abort = 1; $log .= "timeout!!\n"; $SIG{ALRM} = "DEFAULT"; alarm(10);};
alarm(20);
while ($#point >= 0) {
my $index = int(rand($#point+1));
my $target = $point[$index]; # connector to the object
#$color = $green; draw_triangle_mark($target->[0],$target->[1],0,$target->[2]); $color = $white;
my $flag = int(rand(0x10000));
my $patk = rand($pwsum);
my $pati = -1;
for (my $c = 0; $c < $patk; $c += $pattern[$pati]{weight}) { $pati += 1 }
my $pat = $pattern[$pati];
my $cons = $pat->{cons}(0, 0, 0, $flag);
my $coni = int(rand($#{@$cons}+1));
my $cont = $cons->[$coni]; # connector used inside the object
splice(@$cons, $coni, 1);
foreach my $line (rand() < .4 ? (0, 25, 50, 100) : (80, 200)) {
my $dir = (180 + $target->[3] - $cont->[2]) % 360;
#print STDERR "[$#point] @$target line: $line\n";
my $x = $target->[1] - cos($dir*$deg) * $cont->[0] - sin($dir*$deg) * $cont->[1];
my $y = $target->[2] + sin($dir*$deg) * $cont->[0] - cos($dir*$deg) * $cont->[1];
#$color = $red; draw_triangle_mark($x, $y, 0, $dir); $color = $white;
# add line
my $x1 = $target->[1];
my $y1 = $target->[2];
my $x2 = $x1 + sin($target->[3]*$deg) * $line;
my $y2 = $y1 + cos($target->[3]*$deg) * $line;
$x += $x2-$x1;
$y += $y2-$y1;
# collision check
my $objs = $pat->{objs}($x, $y, $dir, $flag);
my $need_retry = !($x >= 0 && $x < $width && $y >= 0 && $y < $height);
if (!$need_retry) {
foreach (@$objs) {
$need_retry = collision_check(\@objs, \@lines, $_, $line ? [$x1, $y1, $x2, $y2] : undef);
last if ($need_retry);
}
}
if ($need_retry) {
if ($max_retry-- <= 0 || $abort) {
$log .= "too many retries!!\n" unless ($abort);
$log .= "objs : $nr_objs\n";
return;
}
if ($need_retry < 0 || $line == 100 || $line == 200) {
splice(@point, $index, 1) if (--$target->[0] <= 0)
}
last if ($need_retry < 0);
next;
}
# draw and add info
splice(@point, $index, 1);
$pat->{draw}($x, $y, $dir, $flag);
push(@objs, @$objs);
$cons = $pat->{cons}($x, $y, $dir, $flag);
splice(@$cons, $coni, 1);
push(@point, map {unshift(@$_, $npp); $_} # nr_retry per point
grep {$_->[0] >= 0 && $_->[0] < $width &&
$_->[1] >= 0 && $_->[1] < $height} @$cons);
if ($line) {
draw_line($im, $x1, $y1, $x2, $y2, 4, 0, $color);
draw_text_on_line($x1, $y1, atan2($x2-$x1, $y2-$y1)/$deg, random_str2($line/8), $font2) if (rand()<.4);
push(@lines, [$x1, $y1, $x2, $y2]);
}
if (++$nr_objs >= $max_objs || $abort) {
#$log .= "retry-remain: $max_retry\n";
$log .= "objs : $nr_objs\n";
return;
}
last;
}
}
#$log .= "retry-remain: $max_retry\n";
$log .= "objs : $nr_objs\n";
}
sub add_con {
my ($ret, $x, $y, $r, $d) = @_;
my ($x1, $y1) = (calc_line_from_circle($x, $y, $r, $d))[2,3];
push(@$ret, [$x1, $y1, $d]);
}
# patterns
sub pat1_draw {
my ($x, $y, $dir, $flag) = @_;
draw_circle($x, $y, 100);
draw_text_in_circle($x, $y, 100, 0, 360, random_str(80), $font1);
draw_triangle_in_circle2($x, $y, 100, 45+$dir, 7);
if ($flag & 0x800) {
draw_circle($x, $y, 5);
draw_line_from_circle($x, $y, 0, 0, 10, $dir+90);
draw_line_from_circle($x, $y, 0, 0, 10, $dir-90);
draw_line_from_circle($x, $y, 5, $dir, 30, $dir);
}
draw_triangle_mark($x, $y, 12, $dir+180) if ($flag & 0x100);
draw_circle($x, $y, 26, $dir+120, $dir+240) if ($flag & 0x200);
draw_3c_mark($x, $y, 50, $dir) if ($flag & 0x400);
draw_line_from_circle($x, $y, 100, $dir+180, 50, $dir+180);
draw_line_from_circle($x, $y, 150, $dir+180, 50, $dir+180, 11);
draw_circle($x, $y, 200, $dir+180, $dir+195);
draw_text_in_circle($x, $y, 200+16, $dir+180, $dir+195, random_str(8), $font1);
draw_3c_mark($x, $y, 112, $dir+15, 1) if ($flag & 0x1000);
if ($flag & 0x1) {
my ($dx, $dy, $x2, $y2) = draw_line_from_circle($x, $y, 100, $dir+195, 15, $dir+210);
draw_circle($x2, $y2, 15);
draw_line_from_circle($x2, $y2, 0, 0, 15, $dir+120);
draw_line_from_circle($x2, $y2, 0, 0, 15, $dir+300);
draw_circle($x2, $y2, 30, $dir+150, $dir+322);
draw_line_from_circle($x2, $y2, 15, $dir+150, 25, $dir+150);
draw_circle($x2, $y2, 40, $dir+125, $dir+(($flag & 0x2)?160:210));
draw_circle($x2, $y2, 40, $dir+240, $dir+320);
}
return unless ($flag & 0x2);
draw_line_from_circle($x, $y, 100, $dir+225, 75, $dir+225);
draw_circle($x, $y, 130, $dir+180, $dir+225);
draw_circle($x, $y, 150, $dir+135+(($flag & 0x4)?10:0), $dir+405);
draw_line_from_circle($x, $y, 100, $dir+45, 75, $dir+45);
my ($dx, $dy, $x2, $y2) = draw_line_from_circle($x, $y, 100, $dir+135, 75, $dir+135);
if ($flag & 0x4) {
draw_circle($x2, $y2, 25);
draw_circle($x2, $y2, 50, $dir, $dir+270-7);
draw_circle($x2, $y2, 70, $dir+90, $dir+180);
draw_text_in_circle($x2, $y2, 70, $dir+45, $dir+225, random_str(30), $font1);
}
draw_line_from_circle($x, $y, 100, $dir+270, 30, $dir+270);
draw_circle($x, $y, 130, $dir+240, $dir+270);
draw_text_in_circle($x, $y, 150, $dir+240, $dir+305, random_str(25), $font1);
($dx, $dy, $x2, $y2) = draw_line_from_circle($x, $y, 100, $dir+315, 40, $dir+315);
draw_line_from_circle($x, $y, 140, $dir+315, 20, $dir+315);
if ($flag & 0x4000) {
draw_circle($x2, $y2, 20);
draw_circle($x2, $y2, 7, $dir+135, $dir+315);
draw_line_from_circle($x2, $y2, 0, 0, 20, $dir+45);
}
}
sub pat1_objs {
my ($x, $y, $dir, $flag) = @_;
my @ret = ([$x, $y, 100], [$x, $y, 200+16, $dir+180, $dir+195]);
if ($flag & 0x1) {
my ($x1, $y1, $x2, $y2) = calc_line_from_circle($x, $y, 100, $dir+195, 15, $dir+210);
push(@ret, [$x2, $y2, 40]);
}
if ($flag & 0x2) {
push (@ret, [$x, $y, 150, $dir+135, $dir+405]);
if ($flag & 0x4) {
my ($x1, $y1, $x2, $y2) = calc_line_from_circle($x, $y, 100, $dir+135, 75, $dir+135);
push (@ret, [$x2, $y2, 70]);
}
}
return \@ret;
}
sub pat1_cons {
my ($x, $y, $dir, $flag) = @_;
my @ret = ();
add_con(\@ret, $x, $y, 200+16, $dir+180);
if ($flag & 2) {
add_con(\@ret, $x, $y, 175, $dir+45);
add_con(\@ret, $x, $y, 175, $dir+135) unless ($flag & 4);
add_con(\@ret, $x, $y, 175, $dir+225);
add_con(\@ret, $x, $y, 160, $dir+315);
}
return \@ret;
}
#=======
sub pat2_draw {
my ($x, $y, $dir, $flag) = @_;
draw_circle($x, $y, 50);
draw_circle($x, $y, 100);
draw_text_in_circle($x, $y, 100, $dir+120, $dir+175, random_str(15), $font1);
draw_line_from_circle($x, $y, 0, 0, 50, $dir+45);
draw_line_from_circle($x, $y, 50, $dir+45, 50, $dir+45, -11);
draw_line_from_circle($x, $y, 100, $dir+45, 100, $dir+45);
draw_line_from_circle($x, $y, 0, 0, 200, $dir-135, 1);
draw_line_from_circle($x, $y, 0, 0, 200, $dir+90);
draw_circle($x, $y, 200, $dir+90, $dir+120);
draw_text_in_circle($x, $y, 200, $dir+90, $dir+120, random_str(14), $font1);
draw_circle($x+sin(($dir+105)*$deg)*100, $y+cos(($dir+105)*$deg)*100, 15) if ($flag & 0x100);
draw_circle($x+sin(($dir+202)*$deg)*100, $y+cos(($dir+202)*$deg)*100, 15) if ($flag & 0x200);
draw_circle($x, $y, 15) if ($flag & 0x400);
#
if ($flag & 0x1) {
draw_line_from_circle($x, $y, 50, $dir-45, 50, $dir-45);
draw_text_in_circle($x, $y, 96, $dir-58, $dir-45, random_str2(5), $font2, 5);
draw_text_in_circle($x, $y, 90, $dir-56, $dir-45, random_str2(4), $font2, 5);
draw_text_in_circle($x, $y, 84, $dir-54, $dir-45, random_str2(3), $font2, 5);
draw_line_from_circle($x, $y, 100, $dir-45, 100, $dir-45);
draw_circle($x, $y, 140, $dir-45, $dir-22.5);
draw_circle($x, $y, 150, $dir-45, $dir-30);
draw_circle($x, $y, 200, $dir-45, $dir-15);
draw_text_in_circle($x, $y, 200, $dir-45, $dir-15, random_str(15), $font1);
}
if ($flag & 0x2) {
draw_line_from_circle($x, $y, 100, $dir+135, 50, $dir+135);
draw_text_in_circle($x, $y, 165, $dir+95, $dir+150, random_str(30), $font1, 7);
draw_text_in_circle($x, $y, 142, $dir+115, $dir+130, random_str2(8), $font2, 5);
draw_text_in_circle($x, $y, 135, $dir+115, $dir+130, random_str2(8), $font2, 5);
draw_text_in_circle($x, $y, 128, $dir+115, $dir+130, random_str2(8), $font2, 5);
draw_text_in_circle($x, $y, 142, $dir+140, $dir+155, random_str2(8), $font2, 5);
draw_text_in_circle($x, $y, 135, $dir+140, $dir+170, random_str2(15), $font2, 5);
draw_text_in_circle($x, $y, 128, $dir+140, $dir+155, random_str2(8), $font2, 5);
}
if ($flag & 0x4) {
draw_line_from_circle($x, $y, 100, $dir+180, 50, $dir+180, -2);
}
if ($flag & 0x8) {
my ($dx1, $dy1, $x1, $y1) = draw_line_from_circle($x, $y, 50, $dir-45, 140, $dir-90, -1);
my ($dx1, $dy1, $x2, $y2) = draw_line_from_circle($x, $y, 50, $dir-135, 140, $dir-90, -1);
draw_line_from_circle($x, $y, 50, $dir-135, 145, $dir-62);
$x1 = ($x1+$x2)/2;
$y1 = ($y1+$y2)/2;
draw_circle($x1, $y1, 35.4);
if ($flag & 0x10) {
draw_text_in_circle($x1, $y1, 75, $dir-150, $dir-45, random_str(25), $font1, 7);
draw_text_on_line($x1+sin(($dir-90)*$deg)*40+cos(($dir-90)*$deg)*40, $y1+cos(($dir-90)*$deg)*40-sin(($dir-90)*$deg)*40, $dir+90, random_str2(9)."\n".random_str2(9)."\n".random_str2(9), $font2);
draw_text_on_line($x1+sin(($dir-90)*$deg)*60+cos(($dir-90)*$deg)*15, $y1+cos(($dir-90)*$deg)*60-sin(($dir-90)*$deg)*15, $dir+180, " ".random_str2(2)."\n ".random_str2(4)."\n".random_str2(6), $font2, 3);
}
}
if (($flag & 0x22) == 0x22) {
draw_circle($x, $y, 150);
}
if ($flag & 0x40) {
draw_line_from_circle($x, $y, 200, $dir+90, 50, $dir+90);
draw_circle($x, $y, 250, $dir+75, $dir+90);
draw_text_in_circle($x, $y, 254, $dir+75, $dir+86, random_str2(12), $font2, 5);
draw_text_in_circle($x, $y, 248, $dir+75, $dir+86, random_str2(11), $font2, 5);
draw_text_in_circle($x, $y, 242, $dir+75, $dir+86, random_str2(11), $font2, 5);
}
}
sub pat2_objs {
my ($x, $y, $dir, $flag) = @_;
my @ret = ([$x, $y, (($flag&0x22)==0x22)?150:100], [$x, $y, 200, $dir+90, $dir+120],
[$x, $y, 200, $dir+35, $dir+55], [$x, $y, 200, $dir+215, $dir+235]);
push (@ret, [$x, $y, 200, $dir-45, $dir-15]) if ($flag & 0x1);
push (@ret, [$x, $y, 165, $dir+90, $dir+150]) if ($flag & 0x2);
if ($flag & 0x8) {
my ($dx1, $dy1, $x1, $y1) = calc_line_from_circle($x, $y, 50, $dir-45, 140, $dir-90);
my ($dx2, $dy2, $x2, $y2) = calc_line_from_circle($x, $y, 50, $dir-135, 140, $dir-90);
push(@ret, [$x1, $y1, 100, $dir+90, $dir+120]);
push(@ret, [$x2, $y2, 100, $dir+60, $dir+90]);
$x1 = ($x1+$x2)/2;
$y1 = ($y1+$y2)/2;
push(@ret, [$x1, $y1, 35.4]);
push(@ret, [$x1, $y1, 75, $dir-150, $dir-45]) if ($flag & 0x10);
}
push(@ret, [$x, $y, 250, $dir+75, $dir+90]) if ($flag & 0x40);
return \@ret;
}
sub pat2_cons {
my ($x, $y, $dir, $flag) = @_;
my @ret = ();
add_con(\@ret, $x, $y, 200, $dir+45);
add_con(\@ret, $x, $y, 200, $dir-135);
add_con(\@ret, $x, $y, $flag&0x40?250:200, $dir+90);
add_con(\@ret, $x, $y, 200, $dir-45) if ($flag & 0x1);
add_con(\@ret, $x, $y, 150, $dir+180) if ($flag & 0x4);
return \@ret;
}
#=======
sub pat3_draw {
my ($x, $y, $dir, $flag) = @_;
draw_circle($x, $y, 50);
draw_text_in_circle($x, $y, 50, $dir+15, $dir+150, random_str(10), $font1);
draw_circle($x, $y, 100);
draw_triangle_in_circle($x, $y, 100, $dir, ($flag>>9)&7);
draw_line_from_circle($x, $y, 0, 0, 100, $dir) if ($flag & 0x100);;
draw_circle($x, $y, 75, $dir+228, $dir+348) if ($flag & 0x1000);
if ($flag & 0x07) {
draw_circle($x, $y, 140, $dir+90, $dir+225);
draw_circle($x, $y, 150, $dir+45, $dir+108);
draw_line_from_circle($x, $y, 100, $dir+45, 50, $dir+45);
draw_line_from_circle($x, $y, 100, $dir+225, 75, $dir+225);
draw_text_in_circle($x, $y, 140, $dir+90, $dir+135, random_str(10), $font1);
draw_text_in_circle($x, $y, 140, $dir+150, $dir+210, random_str(20), $font1);
draw_line_from_circle($x, $y, 100, $dir+135, 150, $dir+135);
if ($flag & 0x02) {
draw_circle($x, $y, 175, $dir+225, $dir+315);
draw_text_in_circle($x, $y, 175, $dir+225, $dir+315, random_str(30), $font1);
}
if ($flag & 0x04) {
my ($x1, $y1, $x2, $y2) = calc_line_from_circle($x, $y, 0, 0, 160, $dir+135);
draw_circle($x2, $y2, 75, $dir+15, $dir+255);
draw_circle($x, $y, 190, $dir+45, $dir+150);
draw_line_from_circle($x, $y, 140, $dir+150, 50, $dir+150);
draw_text_in_circle($x, $y, 190, $dir+60, $dir+107, random_str(20), $font1);
draw_text_in_circle($x, $y, 208, $dir+45, $dir+90, random_str(20), $font1);
}
}
}
sub pat3_objs {
my ($x, $y, $dir, $flag) = @_;
my @ret = ([$x, $y, 100]);
if ($flag & 0x07) {
push(@ret, [$x, $y, 150, $dir+45, $dir+45225]);
if ($flag & 0x02) {
push(@ret, [$x, $y, 175, $dir+225, $dir+315]);
}
if ($flag & 0x04) {
my ($x1, $y1, $x2, $y2) = calc_line_from_circle($x, $y, 0, 0, 160, $dir+135);
push(@ret, [$x2, $y2, 75]);
push(@ret, [$x, $y, 190, $dir+45, $dir+150]);
}
}
return \@ret;
}
sub pat3_cons {
my ($x, $y, $dir, $flag) = @_;
my @ret = ();
add_con(\@ret, $x, $y, 100, $dir);
if ($flag & 0x07) {
add_con(\@ret, $x, $y, 250, $dir+135);
add_con(\@ret, $x, $y, 175, $dir+225);
}
return \@ret;
}
#=======
sub pat4_draw {
my ($x, $y, $dir, $flag) = @_;
draw_circle($x, $y, 2);
draw_circle($x, $y, 25);
draw_circle($x, $y, 50);
draw_line_from_circle($x, $y, 0, 0, 50, $dir+270);
draw_line_from_circle($x, $y, 25, $dir+225, 25, $dir+225);
draw_text_in_circle($x, $y, 40, $dir+285, $dir+330, random_str2(6), $font2, 5);
draw_triangle_mark($x, $y, 35, $dir+90) if ($flag & 0x100);
if ($flag & 0x3f) {
draw_circle($x, $y, 100, $dir+100, $dir+180);
draw_line_from_circle($x, $y, 50, $dir+180, 70, $dir+180);
draw_circle($x, $y, 100, $dir-80, $dir+80);
draw_circle($x, $y, 120, $dir+100, $dir+255);
draw_text_in_circle($x, $y, 100, $dir+100, $dir+120, random_str(5), $font1) if ($flag & 0x200);
draw_text_in_circle($x, $y, 120, $dir+120, $dir+180, random_str(20), $font1);
}
if ($flag & 0x2) {
draw_line_from_circle($x, $y, 120, $dir+225, 55, $dir+225);
draw_circle($x, $y, 175, $dir+220, $dir+230);
}
if ($flag & 0x4) {
draw_line_from_circle($x, $y, 75, $dir, 50, $dir);
my ($dx, $dy, $x1, $y1) = calc_line_from_circle($x, $y, 65, $dir, 30, $dir-90);
draw_text_on_line($x1, $y1, $dir+90, random_str2(10), $font2);
}
if ($flag & 0x8) {
draw_line_from_circle($x, $y, 100, $dir+45, 20, $dir+45);
draw_circle($x, $y, 120, $dir+30, $dir+60);
}
if ($flag & 0x10) {
draw_line_from_circle($x, $y, 75, $dir+270, 75, $dir+270);
my ($dx, $dy, $x1, $y1) = calc_line_from_circle($x, $y, 65, $dir+270, 55, $dir+270);
draw_circle($x1, $y1, 45, $dir+80, $dir+100);
draw_circle($x1, $y1, 20, $dir+90, $dir+270);
draw_circle($x1, $y1, 2);
draw_circle($x1, $y1, 30, $dir+90, $dir+252);
draw_text_in_circle($x1, $y1, 25, $dir+120, $dir+180, random_str2(4), $font2, 5);
($dx, $dy, $x1, $y1) = calc_line_from_circle($x, $y, 0, 0, 150, $dir+270);
draw_circle($x1, $y1, 10);
draw_circle($x1, $y1, 2);
}
if ($flag & 0x20) {
draw_triangle_mark2($x, $y, 125, $dir+180, 20, $dir+180);
draw_triangle_mark2($x, $y, 120, $dir+170, 20, $dir);
draw_triangle_mark2($x, $y, 120, $dir+190, 20, $dir);
}
}
sub pat4_objs {
my ($x, $y, $dir, $flag) = @_;
my @ret = ([$x, $y, ($flag&0x3f)?100:50]);
if ($flag&0x3f) {
push(@ret, [$x, $y, 120, $dir+90, $dir+270]);
push(@ret, [$x, $y, 175, $dir+220, $dir+230]) if ($flag&0x02);
push(@ret, [$x, $y, 120, $dir+30, $dir+60]) if ($flag&0x08);
push(@ret, [$x, $y, 160, $dir+255, $dir+275]) if ($flag&0x10);
push(@ret, [$x, $y, 160, $dir+160, $dir+200]) if ($flag&0x20);
}
return \@ret;
}
sub pat4_cons {
my ($x, $y, $dir, $flag) = @_;
my @ret = ();
if ($flag & 0x3f) {
add_con(\@ret, $x, $y, ($flag&0x04)?125:100, $dir);
add_con(\@ret, $x, $y, 175, $dir+225) if ($flag & 0x02);
add_con(\@ret, $x, $y, 120, $dir+45) if ($flag & 0x08);
add_con(\@ret, $x, $y, 160, $dir+270) if ($flag & 0x10);
add_con(\@ret, $x, $y, 120, $dir+180) unless ($flag & 0x20);
} else {
add_con(\@ret, $x, $y, 50, $dir+225);
add_con(\@ret, $x, $y, 50, $dir+270);
}
return \@ret;
}
#=======
sub pat5_draw {
my ($x, $y, $dir, $flag) = @_;
if ($flag & 0x200) {
draw_circle($x, $y, 100, $dir, $dir+188);
draw_circle($x, $y, 100, $dir+202, $dir+360);
} else {
draw_circle($x, $y, 100);
}
draw_text_in_circle($x, $y, 100, $dir+245, $dir+290, random_str(10), $font1);
draw_line_from_circle($x, $y, 0, 0, 100, $dir);
draw_line_from_circle($x, $y, 0, 0, 100, $dir+15);
draw_line_from_circle($x, $y, 0, 0, 100, $dir+90);
draw_line_from_circle($x, $y, 0, 0, 70, $dir+180);
draw_line_from_circle($x, $y, 70, $dir+180, 20, $dir+90);
draw_line_from_circle($x, $y, 70, $dir+180, 20, $dir+270);
draw_line_from_circle($x, $y, 78, $dir+180, 20, $dir+90);
draw_line_from_circle($x, $y, 78, $dir+180, 20, $dir+270);
draw_line_from_circle($x, $y, 78, $dir+180, 22, $dir+180);
draw_line_from_circle($x, $y, 0, 0, 100, $dir+240);
draw_circle($x, $y, 25, $dir, $dir+15);
draw_circle($x, $y, 33, $dir, $dir+15);
draw_circle($x, $y, 70, $dir+15, $dir+90);
draw_circle($x, $y, 25, $dir+90, $dir+240);
draw_circle($x, $y, 50, $dir+240, $dir+375);
draw_text_in_circle($x, $y, 62, $dir+270, $dir+300, random_str(3), $font1);
if ($flag & 0x100) {
my ($dx1, $dy1, $x1, $y1) = calc_line_from_circle($x, $y, 0, 0, 100, $dir+90);
draw_circle($x1, $y1, 30);
}
if ($flag & 0x200) {
my ($dx1, $dy1, $x1, $y1) = calc_line_from_circle($x, $y, 0, 0, 100, $dir+195);
draw_circle($x1, $y1, 12);
draw_line_from_circle($x1, $y1, 0, 0, 12, $dir+195);
draw_line_from_circle($x1, $y1, 0, 0, 12, $dir+15);
}
if ($flag & 0x400) {
draw_circle($x, $y, 110, $dir+230, $dir+250);
}
if ($flag & 0x01) {
draw_line_from_circle($x, $y, 100, $dir+180, 20, $dir+180);
draw_circle($x, $y, 120, $dir+150, $dir+210);
draw_text_in_circle($x, $y, 135, $dir+150, $dir+210, random_str(15), $font1);
}
}
sub pat5_objs {
my ($x, $y, $dir, $flag) = @_;
my @ret = ([$x, $y, 100]);
if ($flag&0x200) {
push(@ret, [$x, $y, 135, $dir+150, $dir+210]);
}
return \@ret;
}
sub pat5_cons {
my ($x, $y, $dir, $flag) = @_;
my @ret = ();
add_con(\@ret, $x, $y, 100, $dir);
add_con(\@ret, $x, $y, 100, $dir+90);
unless ($flag&0x400) {
add_con(\@ret, $x, $y, 100, $dir+240);
}
unless ($flag&0x1) {
add_con(\@ret, $x, $y, 100, $dir+180);
}
return \@ret;
}
#=======
sub genr_draw {
my ($x, $y, $dir, $flag) = @_;
my (@r, @s, @t, @lf, $i);
$r[0] = $flag&0x01?100:75;
$s[0] = int(rand(8))*45;
$t[0] = $s[0] + int(rand(5))*90;
draw_circle($x, $y, $r[0]);
draw_text_in_circle($x, $y, $r[0], $s[0], $t[0], random_str($r[0]/1.5*($t[0]-$s[0])/360), $font1);
$r[1] = ($flag&0x01 && rand()<0.5) ? 75 : 50;
$r[2] = 25;
for (1..2) {
$s[$_] = int(rand(8))*45;
$t[$_] = $s[$_] + int(rand(5))*90;
$t[$_] = $s[$_]+45 if ($s[$_] == $t[$_]);
draw_circle($x, $y, $r[$_], $s[$_], $t[$_]);
}
for (1..2) {
$lf[$_] = [];
for ($i = 0; $i < 4; $i++) {
my $k = ($s[$_]/45 + int(rand(($t[$_]-$s[$_])/45+1))) % 8;
$lf[$_][$k] = 1;
for (my $j = $_-1; $j >= 1; $j--) {
unless ( $s[$j] < $k*45 && $k*45 < $t[$j] ||
$t[$j] > 360 && $k*45 < $t[$j]-360 ) {
$lf[$j][$k] = 1;
}
}
}
}
for my $k (1..2) {
for ($i = 0; $i < 8; $i++) {
draw_line_from_circle($x, $y, $r[$k], $i*45, $r[$k-1]-$r[$k], $i*45, 3*(rand()<0.3)) if ($lf[$k][$i]);
}
}
if ($t[2]-$s[2] <= 90 || $t[2]-$s[2] == 180 && rand() < 0.5 ) {
draw_line_from_circle($x, $y, 0, 0, $r[2], $s[2]);
draw_line_from_circle($x, $y, 0, 0, $r[2], $t[2]);
}
}
sub genr_objs {
my ($x, $y, $dir, $flag) = @_;
my @ret = ([$x, $y, $flag&0x01?100:75]);
return \@ret;
}
sub genr_cons {
my ($x, $y, $dir, $flag) = @_;
my @ret = ();
my $r = $flag&0x01?100:75;
for (my $d = 0; $d < 360; $d+=45) {
add_con(\@ret, $x, $y, $r, $dir+$d);
}
return \@ret;
}