#!/usr/bin/perl require "parser.pl"; require "misc.pl"; $H = 50; # character height $W = $H*0.9; # character width $L = $H+20; # line skip sub normalize { my @t = @_; # convert from (x0, y0, w, h) to (x0, y0, x1, y1) $t[2] += $t[0]; $t[3] = $t[1]-$t[3]; return ($t[0], $t[3], $t[2], $t[1]); } # # 2x2 matrix inversion # http://en.wikipedia.org/wiki/Invertible_matrix#Inversion_of_2.C3.972_matrices # sub invert { my @m = @_; my $f = 1/($m[0]*$m[3]-$m[1]*$m[2]); return ($f*$m[3], -$f*$m[1], -$f*$m[2], $f*$m[0]); } sub block { my @t = &normalize(@_); push(@block, [ @t ]); $wnl .= "Wire Notes Line\n\t$t[0] $t[1] $t[2] $t[3]\n"; } sub pass { my @t = &normalize(@_); for (@block) { my @b = @{ $_ }; next if $t[0] > $b[2]; next if $t[2] < $b[0]; next if $t[1] > $b[3]; next if $t[3] < $b[1]; return 0; } return 1; } sub put { local ($x0, $y0, $ref, @s) = @_; my $h = @s*$L; my $w = 0; for (@s) { my $t = $W*length $_; $w = $t if $t > $w; } my $a = 270; my $r = 100; my $x, $y; my $ym = $y0-$h+$H/2; for ($i = 0; $i != 128; $i++) { $x = int($x0+$r*cos($a/180*3.14159)); $y = int($ym+$r*sin($a/180*3.14159)); last if &pass($x, $y, $w, $h); $a += 22.5; $r += $L/8; } warn "no place found for \"$s[0]\"" if $i == 128; my @m = &invert( @{ $m{$ref} }); &block($x, $y+$H/2, $w, $h); my $n = 10; for my $s (reverse @s) { my $dx = $x-$x0; my $dy = $y-$y0; my $sx = $x0+$dx*$m[0]+$dy*$m[1]; my $sy = $y0+$dx*$m[2]+$dy*$m[3]; ($hv, $hj, $vj) = ("H", "L", "C") if $m[0] == 1; ($hv, $hj, $vj) = ("H", "R", "C") if $m[0] == -1; ($hv, $hj, $vj) = ("V", "C", "B") if $m[1] == 1; ($hv, $hj, $vj) = ("V", "C", "T") if $m[1] == -1; $s =~ s/~/-/g; print "F $n \"$s\" $hv $sx $sy $H 0000 $hj ${vj}NN\n"; $y -= $L; $n++; } } sub dsc_parts { local ($ref) = @_; my @p = @{ $parts{$ref} }; my @f = (); while (@p) { my @id = splice(@p, 0, 2); my $id = "$id[0] $id[1]"; my $dsc = &dsc_find($id); push(@f, &dsc) if defined $dsc; } return @f; } sub dsc_order { local ($ref) = @_; my @f = (); for my $id (keys %order) { my @p = @{ $order{$id} }; for (splice(@p, 3)) { push(@f, &dsc_find($id)) if $_ eq $ref; } } return @f; } sub usage { print STDERR "usage: $0 [-s/from/to/ ...] ...\n"; exit(1); } while ($ARGV[0] =~ /^-s/) { &usage unless &dsc_xlat_arg($'); shift @ARGV; } &usage if $ARGV[0] =~ /^-./; &parse; # # pass 1: find the orientation of all parts # for (@eeschema) { $ref = $1 if /^L \S+ (\S+)/; undef $ref if /^\$EndComp/; next unless /^\s+(-?[01])\s+(-?[01])\s+(-?[01])\s+(-?[01])\s*$/; my @m = split(/\s+/); shift @m; $m{$ref} = [ @m ]; } # # pass 2: block the spaces occupied by fields # for (@eeschema) { $ref = $1 if /^L \S+ (\S+)/; if (/^P (\d+) (\d+)/) { $x0 = $1; $y0 = $2; } next unless /^F /; die "$_" unless /^F \d+ "([^"]*)" ([HV]) (\d+) (\d+) (\d+) +(\d+) ([LC]) (C)/; ($s, $hv, $x, $y, $size, $flag, $hj, $vj) = ($1, $2, $3, $4, $5, $6, $7, $8); $dx = $x-$x0; $dy = $y-$y0; $x = $x0+$dx*$m{$ref}[0]+$dy*$m{$ref}[1]; $y = $y0+$dx*$m{$ref}[2]+$dy*$m{$ref}[3]; next if $flag != 0; $w = $size*0.8*length $s; # we don't need to consider H/V &block($hj eq "L" ? $x : $x-$w/2, $y+$size/2, $w, $size); } # # pass 3: # for (@eeschema) { undef @f if /^\$Comp/; if (/^L \S+ (\S+)/) { $ref = $1; push(@f, &dsc_order($ref)) if %order; push(@f, &dsc_parts($ref)) if %parts; } if (/^P (\d+) (\d+)/) { $x = $1; $y = $2; } if (/^\s+/) { my %seen; my @u = (); for (@f) { next if $seen{$_}; push(@u, $_); $seen{$_} = 1; } undef @f; # $m{$ref}[0] == 1 OK # $m{$ref}[0] == -1 OK # $m{$ref}[1] == 1 OK # $m{$ref}[1] == -1 OK (small deviations found) &put($x, $y, $ref, @u) if 1 || $m{$ref}[1] == -1; } if (/\$EndSCHEMATC/) { # uncomment for debugging # print $wnl; } print "$_\n"; }