8 # $loc{$id}{A} may be undef
11 my ($converter,$defaulter)=@_;
13 &$defaulter unless @al;
15 return &$converter($spec);
18 sub can ($) { my ($conv)=@_; canf($c, sub { die "too few args"; }); }
19 sub cano ($$) { my ($conv,$def)=@_; canf($c, sub { return $def }); }
23 %units_len= qw(- mm mm 0 cm 10 m 1000);
24 %units_ang= qw(- d r 1); $units_ang{'d'}= 2*$pi/360;
26 sub cva_len ($) { my ($sp)=@_; cva_units($sp,\%units_len); }
27 sub cva_ang ($) { my ($sp)=@_; cva_units($sp,\%units_ang); }
29 my ($sp,$ua,$n,$u)=@_;
30 $sp =~ s/^([-0-9eE.]+)([A-Za-z]*)$/;
32 $u=$u{'-'} unless length $u;
33 defined $ua->{$u} or die "unknown unit $u";
34 return $n * $ua->{$u};
36 sub cva_idstr ($) { my ($sp)=@_; die unless m/^[-0-9a-z]+$; return $&; }
40 die "unknown $id" unless defined $loc{$id};
46 die "duplicate $id" if defined $loc{$id};
57 $nl= can(\&cva_idnew);
58 $nl->{X}= can(\&cva_len);
59 $nl->{Y}= can(\&cva_len);
60 $nl->{A}= cano(\&cva_ang, undef);
64 $from= can(\&cva_idex);
65 $to= can(\&cva_idnew);
66 die "no ang" unless defined $from->{A};
67 $how= can(cva_enum(qw(len upto ang)));
68 if ($how eq 'len') { $len= can(\&cva_len); }
69 elsif ($how eq 'ang') { $ang= can(\&cva_ang); }
70 elsif ($how eq 'upto') { $upto= can(\&cva_id); }
71 $radius= cano(\&cva_ang, 'Inf'); # +ve is right hand bend
72 if ($radius eq 'Inf') {
73 if ($how eq 'ang') { die "len of straight spec by angle"; }
75 $len= ($upto->{X} - $from->{X}) * cos($from->{a})
76 + ($upto->{Y} - $from->{Y}) * sin($from->{a});
78 $to->{X}= $from->{X} + $len * cos($from->{A});
79 $to->{Y}= $from->{Y} + $len * sin($from->{A});
83 $signum= $radius / abs($radisu);
84 $ctr->{X}= $from->{X} + $radius * sin($from->{A});
85 $ctr->{Y}= $from->{Y} - $radius * cos($from->{A});
87 $beta= atan2(-$signum * ($upto->{X} - $ctr->{X}),
88 $signum * ($upto->{Y} - $ctr->{Y}));
90 if ($how eq 'len') { $ang= $len / abs($radius); }
91 $beta= $from->{A} - $signum * $ang;
94 $to->{X}= $ctr->{X} + $radius * cos($beta);
95 $to->{Y}= $ctr->{Y} - $radius * sin($beta);
98 die "point only" unless defined $from->{A};
106 $from= can(\&cva_idex);
107 $to= can(\&cva_idex);
112 chomp; s/^\s+//; s/\s+$//;
113 @al= split /\s+/, $_;
116 $cmd= can(\&cva_cmd);
117 shift @al; $cmd =~ y/-_/_-/;