[!]arcsline prefer [not] line between two arcs of min radius
if this doesn't resolve, will pick the shortest.
- defobj O
+ defobj|defpart O
[commands]
enddef
- Defines the object O. Inside the definition, the commands do not
- draw when the object is being defined. The object has its own
- coordinate space and its own location namespace.
+ Defines the object or part O. Inside the definition, the commands
+ do not draw when the object is being defined. The object has its
+ own coordinate space and its own location namespace. `defpart'
+ defines a `part', which is like an object except that:
+ * showlibrary lists only parts, not objects
+ * the -e and -E command line options distinguish parts and objects
+ part N [-]O [F A] [FR AR ...]
obj[flip] O A F [P]
- Places an instance of object O. The loc defined inside O as F
- (`formal parameter', F must be just <identifier>) is placed at
- existing loc A (`actual parameter'). If prefix P (syntax is that of
- an identifier) is specified, each other loc L inside O is exported
- into the global namespace as a new loc PL. P may be `=' to indicate
- an empty prefix (default is not to export locs). If `flip' is used
- then the object is placed with object-space y coordinates negated
- (ie, it is mirrored so that the object's North exchanges with
- South).
+ Places an instance of object or part O. The loc defined inside O as
+ F (`formal parameter', F must be just <identifier>) is placed at
+ existing loc A (`actual parameter').
+
+ Both objects (defined with defobj) and parts (defined with defpart)
+ may be placed with either command ! Whether it's a part or an obj
+ depends on the definition, not on the use - the use is just
+ different syntaxes for the same kind of operation, and where the
+ features offered by both `part' and `obj[flip]' overlap the
+ behaviour is identical.
+
+ If `part N -O' or `objflip' is used, rather than `part N O' or
+ `obj', then the object is placed with object-space y coordinates
+ negated (ie, it is mirrored so that the object's North exchanges
+ with South).
+
+ For `part', each FR (`formal result') and AR (`actual result')
+ specifies that the loc FR inside O is exported into the global
+ namespace as a new loc AR. Either FR or AR may start with `-'.
+ Also, each loc L inside O is exported into the global namespace as a
+ new loc N_L (unless N_L already exists).
+
+ For `obj[flip]' if prefix P (syntax is that of an identifier) is
+ specified, each other loc L inside O is exported into the global
+ namespace as a new loc PL (unless PL already exists). P may be `='
+ to indicate an empty prefix (default is not to export locs).
Command-line options
M mark locs with a bar
N mark locs with a bar in objs
O mark locs with a bar in parts
+
+ -q quiet: do not print info to stderr
+ (default: prints bounding box, at the moment)
+
+ Default is -d0, -EaRscLMNo, not quiet.
+
+Special comments in PostScript:
+
+ %L cmd S C [A...]
+ a command C with args A is read for execution in scope S
+ %L point SL X Y A
+ point L in scope S has coords X Y and angle A
+ %L bbox width W (L..R)
+ %L bbox height H (B..T)
+ bounding box, giving width W, height H, left L, right R,
+ bottom B and top T. Includes full swept area of track,
+ but only at locs (so curves which bend outside bounding
+ box don't get counted)
+ %L bbox no locs, no bbox
+ there were no locs, so there is no bounding box
+ usu because input file was just obj defns and showlibrary
+
+ Scope S is
+ O! when defining object or part O
+ N:T scope T but inside part (introduced with `part') N
+ O::T scope T but inside obj (introduced with `obj[flip]') O
$ctx->{Draw}= '';
}
-sub cmd_enddefobj {
+sub cmd_enddef {
my ($bit,$id);
$id= $ctx->{InDefObj};
- die "unmatched enddefobj" unless defined $id;
+ die "unmatched enddef" unless defined $id;
foreach $bit (qw(CmdLog Loc)) {
$objs{$id}{$bit}= $ctx->{$bit};
}
dv("cmd__runobj $obj_id ",'$ctx',$ctx);
foreach $c (@{ $objs{$obj_id}{CmdLog} }) {
@al= @$c;
- next if $al[0] eq 'enddefobj';
+ next if $al[0] eq 'enddef';
cmd__one();
}
}
+sub cmd_part { cmd__obj(Part); }
sub cmd_obj { cmd__obj(1); }
sub cmd_objflip { cmd__obj(-1); }
+
sub cmd__obj ($) {
- my ($flipsignum)=@_;
+ my ($how)=@_;
my ($obj_id, $ctx_save, $pfx, $actual, $formal_id, $formal, $formcv);
- my ($ctx_inobj, $obj, $id, $newid, $newpt);
+ my ($part_name, $ctx_inobj, $obj, $id, $newid, $newpt);
+ if ($how eq Part) {
+ $part_name= can(\&cva_idstr);
+ $how= (@al && $al[0] =~ s/^\-//) ? -1 : +1;
+ }
$obj_id= can(\&cva_idstr);
- $actual= can(\&cva_idex);
- $formal_id= can(\&cva_idstr);
+ if (defined $part_name) {
+ $formal_id= can(\&cva_idstr);
+ $actual= can(\&cva_idex);
+ } else {
+ $actual= can(\&cva_idex);
+ $formal_id= can(\&cva_idstr);
+ }
$obj= $objs{$obj_id};
dv("cmd__obj ",'$obj',$obj);
die "unknown obj $obj_id" unless $obj;
die "unknown formal $formal_id" unless $formal;
$ctx_save= $ctx;
newctx();
- $ctx->{Trans}{R}= $flipsignum;
- $ctx->{Trans}{A}= $actual->{A} - $formal->{A}/$flipsignum;
+ $ctx->{Trans}{R}= $how;
+ $ctx->{Trans}{A}= $actual->{A} - $formal->{A}/$how;
$formcv= ev_compose({}, $ctx->{Trans},$formal);
$ctx->{Trans}{X}= $actual->{X} - $formcv->{X};
$ctx->{Trans}{Y}= $actual->{Y} - $formcv->{Y};
- $ctx->{InRunObj}= $ctx_save->{InRunObj}."${obj_id}::";
+ if (defined $part_name) {
+ $ctx->{InRunObj}= $ctx_save->{InRunObj}."${part_name}:";
+ } else {
+ $ctx->{InRunObj}= $ctx_save->{InRunObj}."${obj_id}::";
+ }
$ctx->{Draw}= $ctx_save->{Draw};
if ($obj->{Part}) {
$ctx->{Draw} =~ s/[LMN]//g;
$ctx->{Draw} =~ s/N/MN/;
}
cmd__runobj($obj_id);
- if (@al && $al[0] eq '=') {
- $pfx= ''; shift @al;
+ if (defined $part_name) {
+ $pfx= $part_name.'_';
} else {
- $pfx= cano(\&cva_idstr,undef);
+ if (@al && $al[0] eq '=') {
+ $pfx= ''; shift @al;
+ } else {
+ $pfx= cano(\&cva_idstr,undef);
+ }
}
$ctx_inobj= $ctx;
$ctx= $ctx_save;
%$newpt= %{ $ctx_inobj->{Loc}{$id} };
}
}
+ if (defined $part_name) {
+ my ($formalr_id, $actualr_id, $formalr, $actualr);
+ while (@al) {
+ die "part results come in pairs\n" unless @al>=2;
+ ($formalr_id, $actualr_id, @al) = @al;
+ if ($actualr_id =~ s/^\-//) {
+ $formalr_id= "-$formalr_id";
+ $formalr_id =~ s/^\-\-//;
+ }
+ $formalr= cva_idex($formalr_id);
+ {
+ local ($ctx) = $ctx_save;
+ $actualr= cva_idnew($actualr_id);
+ };
+ %$actualr= %$formalr;
+ }
+ }
}
sub cmd__do {
}
next unless $got;
$obj= $objs{$obj_id};
+ next unless $obj->{Part};
($min_x, $max_x, $min_y, $max_y) = bbox($obj->{Loc});
newctx();
O MNO
m mnol);
-$ctx->{Draw}= uc $drawers;
+$ctx->{Draw}= 'RLMN';
-our $bbox=0;
+our $quiet=0;
while (@ARGV && $ARGV[0] =~ m/^\-/) {
last if $ARGV[0] eq '-';
while (length) {
if (s/^D(\d+)//) { $debug= $1; }
elsif (s/^D//) { $debug++; }
- elsif (s/^b//) { $bbox=1; }
+ elsif (s/^q//) { $quiet=1; }
elsif (s/^([Ee])([a-zA-Z]+)//) {
my ($ee,$c);
$ee= $1;
oflushpage();
-if ($bbox) {
+{
my ($min_x, $max_x, $min_y, $max_y) = bbox($ctx->{Loc});
+ my ($bboxstr);
if (defined $min_x) {
- printf(STDERR
- "width %.2d (%.2d..%2.d)\n".
- "height %.2d (%.2d..%2.d)\n",
- $max_x - $min_x, $min_x, $max_x,
- $max_y - $min_y, $min_y, $max_y);
+ $bboxstr= sprintf("width %.2d (%.2d..%2.d)\n".
+ "height %.2d (%.2d..%2.d)\n",
+ $max_x - $min_x, $min_x, $max_x,
+ $max_y - $min_y, $min_y, $max_y);
} else {
- print STDERR "no points, bbox\n";
+ $bboxstr= "no locs, no bbox\n";
}
+ if (!$quiet) { print STDERR $bboxstr; }
+ $bboxstr =~ s/^/\%L bbox /mg;
+ print $bboxstr or die $!;
}