ブレッドボードの絵を描くコマンドを作る(抵抗編)

bread3-titile
アニメ『ReLIFE』
会社でいろいろあって心も体も疲れきってしまった主人公は、高校生からやり直す研究の対象に選ばれます。研究所の薬を飲むと外見が若返るのですが、衰えた運動能力や今までの記憶は失いません。大人の週間が抜けずに学校にタバコとか持って行ってしまって指導を受けてしまうところが笑える。高校生やらやり直すわけですが、元々会社でのある出来事がなければ仕事はできる主人公で、周囲とのコミュニケーションは完璧、リーダーシップまで発揮します。若い男子女子に紛れて甘酸っぱい青春を再度経験。ああ青春っていいですね。

タイトル絵は、今回作成した抵抗を配置するコマンドで描きました。

では、ブレッドボードコマンドの続きを作って行きます。
抵抗のサブルーチン名はこのようにします。

put_resistor($x1,$x1,$x2,$y2,$ohm)

$x1 抵抗のワイヤーのX座標(穴座標)始点
$y1 抵抗のワイヤーのY座標(穴座標)始点
$x2 抵抗のワイヤーのX座標(穴座標)終点
$y2 抵抗のワイヤーのY座標(穴座標)終点
$ohmは抵抗値(1000を指定したら1kΩ)

穴座標x1,y1,x2,y2を、画像座標xx1,yy1,xx2,yy2に変換したら、ワイヤーの中間に抵抗を配置したいので、始点と終点の中間点を求めます。
bread3-001
中間点を求めるサブルーチンです。

sub get_center{
        my($xx1,$yy1,$xx2,$yy2) = @_;

        my $xxc = $xx1 + ($xx2 - $xx1)/2;
        my $yyc = $yy1 + ($yy2 - $yy1)/2;
        return ($xxc,$yyc);
}

角度はアークタンジェントで求めます。
bread3-002
atan2の戻り値はラジアンなので、度に変換します。rad2degを使うためMath::Trigをuseします。

use Math::Trig;
sub get_rr{
        my($xx1,$yy1,$xx2,$yy2) = @_;
        my($ww, $hh) = ($xx2-$xx1, $yy2-$yy1);
        my $rr = rad2deg atan2($ww,$hh);

        return 90 - $rr;
}

全体はこうなりました。もう長すぎです。

~$ cat -n bread.sh
     1	a=`perl -e '
     2	use Math::Trig;
     3	@colors=("black","brown","red","orange","yellow","green","blue","purple","gray","white");
     4	foreach(split / /, "0,60 62,125 197,125 324,60"){
     5		my($x,$w) = split /,/,$_;
     6		print qq#<rect x="$x" y="0" width="$w" height="650" stroke="black" fill="none"></rect>#;
     7	}
     8	foreach(split / /, "8:red 50:blue 334:red 376:blue"){
     9		my($x,$c) = split /:/,$_;
    10		print qq#<line x1="$x" y1="25" x2="$x" y2="620" stroke="$c" stroke-width="2"/>#;
    11	}
    12	
    13	$x=90;
    14	foreach $ch (split //,"abcdefghij"){
    15		print qq#<text x="$x" y="20" font-size="15" text-anchor="middle">$ch</text>#;
    16		print qq#<text x="$x" y="638" font-size="15" text-anchor="middle">$ch</text>#;
    17		$x += 20;
    18		$x += 25 if($ch eq "e");
    19	}
    20	
    21	for($x=1;$x<=14;$x++){
    22		for($y=1;$y<=30;$y++){
    23			my($xx,$yy) = get_board_xxyy($x,$y);
    24			print qq#<rect x="$xx" y="$yy" width="9" height="9" fill="black"></rect>#;
    25			if($x == 5 or $x == 14){
    26				$xx -=10 if($x == 5);
    27				$xx +=20 if($x == 14);;
    28				$yy +=10;
    29				print qq#<text x="$xx" y="$yy" font-size="13" text-anchor="middle">$y</text>#;
    30			}
    31		}
    32	}
    33	
    34	foreach (@ARGV){
    35		put_resistor(split /,/,$_) if(/R$/);
    36		put_wire(split /,/,$_) if(/W$/);
    37	}
    38	
    39	sub put_wire{
    40		my($color,$x1,$y1, $x2,$y2) = @_;
    41		my($xx1,$yy1) = get_xxyy($x1,$y1);
    42		my($xx2,$yy2) = get_xxyy($x2,$y2);
    43		print qq#<circle cx="$xx1" cy="$yy1" r="3" fill="white" />#;
    44		print qq#<circle cx="$xx2" cy="$yy2" r="3" fill="white" />#;
    45		print qq#<line x1="$xx1" y1="$yy1" x2="$xx2" y2="$yy2" stroke="$color" stroke-width="8"/>#;
    46	
    47	}
    48	
    49	sub put_stripedwire{
    50		my($x1,$y1, $x2,$y2) = @_;
    51		my($xx1,$yy1) = get_xxyy($x1,$y1);
    52		my($xx2,$yy2) = get_xxyy($x2,$y2);
    53		my($xxc,$yyc) = get_center($xx1,$yy1,$xx2,$yy2);
    54		my($rr) = get_rr($xx1,$yy1,$xx2,$yy2);
    55		print qq#<circle cx="$xx1" cy="$yy1" r="3" fill="white" />#;
    56		print qq#<circle cx="$xx2" cy="$yy2" r="3" fill="white" />#;
    57		print qq#<line x1="$xx1" y1="$yy1" x2="$xx2" y2="$yy2" stroke="black" stroke-width="5"/>#;
    58		print qq#<line x1="$xx1" y1="$yy1" x2="$xx2" y2="$yy2" stroke="silver" stroke-width="4"/>#;
    59		return ($xxc,$yyc,$rr);
    60	}
    61	
    62	sub put_resistor{
    63		my $ohm = @_[4];
    64		my($xxc,$yyc,$rr) = put_stripedwire(@_);
    65		@resi = split //,$ohm;
    66	
    67		my ($xx1,$yy1) = ($xxc-20,$yyc-5);
    68		my ($xxb1,$yyb1,$cb1) = ($xxc-15,$yyc-5,$colors[$resi[0]]);
    69		my ($xxb2,$yyb2,$cb2) = ($xxc-7,$yyc-5,$colors[$resi[1]]);
    70		my ($xxb3,$yyb3,$cb3) = ($xxc+1,$yyc-5,$colors[$#resi]);
    71		my ($xxb4,$yyb4,$cb4) = ($xxc+11,$yyc-5,"gold");
    72	
    73		print qq#<rect x="$xx1" y="$yy1" width="40" height="10" stroke="black" fill="white" transform="rotate($rr,$xxc,$yyc)"></rect>#;
    74		print qq#<rect x="$xxb1" y="$yyb1" width="4" height="10" fill="$cb1" transform="rotate($rr,$xxc,$yyc)"></rect>#;
    75		print qq#<rect x="$xxb2" y="$yyb2" width="4" height="10" fill="$cb2" transform="rotate($rr,$xxc,$yyc)"></rect>#;
    76		print qq#<rect x="$xxb3" y="$yyb3" width="4" height="10" fill="$cb3" transform="rotate($rr,$xxc,$yyc)"></rect>#;
    77		print qq#<rect x="$xxb4" y="$yyb4" width="4" height="10" fill="$cb4" transform="rotate($rr,$xxc,$yyc)"></rect>#;
    78	}
    79	
    80	sub get_center{
    81		my($xx1,$yy1,$xx2,$yy2) = @_;
    82	
    83		my $xxc = $xx1 + ($xx2 - $xx1)/2;
    84		my $yyc = $yy1 + ($yy2 - $yy1)/2;
    85		return ($xxc,$yyc);
    86	}
    87	
    88	sub get_rr{
    89		my($xx1,$yy1,$xx2,$yy2) = @_;
    90		my($ww, $hh) = ($xx2-$xx1, $yy2-$yy1);
    91		my $rr = rad2deg atan2($ww,$hh);
    92	
    93		return 90 - $rr;
    94	}
    95	
    96	sub get_xxyy{
    97		my($xx,$yy) = get_board_xxyy(@_);
    98		return ($xx+4,$yy+4);
    99	}
   100	
   101	sub get_board_xxyy{
   102		my($x,$y) = @_;
   103		$x-=1;
   104		$y-=1;
   105		if($x < 4){
   106			my $w = 20;
   107			$xx = $x * $w + 15 + ($x >= 2)*285;
   108			$y = 0 if($y >= 25);
   109			$yy = $y * 20 + 35 + int($y /5) * 20;
   110		}else{
   111			my $w = 19;
   112			$xx = $x * $w + 10 + ($x >= 9)*32;
   113			$yy = $y * 20 + 30;
   114		}
   115		return ($xx,$yy);
   116	}
   117	' $@`
   118	
   119	cat <<EOL > /tmp/tmp.svg
   120	<svg width="384" height="650">
   121	<rect x="0" y="0" width="384" height="650" fill="white"></rect>
   122	$a
   123	</svg>
   124	EOL
   125	inkscape -z -e out.png /tmp/tmp.svg -w 384 -h 600

使ってみます。例によってランダム実行。

~$ r(){
perl -e '
printf"%d,%d,%d,%d,%d,R",
1+int rand(4),
1+int rand(25),
4+int rand(10),
1+int rand(30),
1+int rand(100000);
'
}
~$ . bread.sh `r` `r` `r` `r` `r` `r` `r` `r` `r` `r` `r` `r` `r` 

bread3-003

One response to “ブレッドボードの絵を描くコマンドを作る(抵抗編)

  1. It’s woendrful to have you on our side, haha!

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA