mirror of
git://projects.qi-hardware.com/eda-tools.git
synced 2024-08-25 17:45:50 +03:00
223 lines
4.0 KiB
Perl
Executable File
223 lines
4.0 KiB
Perl
Executable File
#!/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";
|
|
}
|