From 5ee9ef45486b3e80704dd6e2ad9984495915f10c Mon Sep 17 00:00:00 2001 From: ian Date: Thu, 21 Oct 2004 20:54:03 +0000 Subject: [PATCH] layout/Makefile and .cvsignore tidied up after move; segment encoding and assignment - wip --- .cvsignore | 2 - layout/.cvsignore | 5 ++ layout/Makefile | 68 +++++++++++++++++++++++ layout/informat.txt | 105 +++++++++++++++++++++++++++++++---- layout/layout | 129 +++++++++++++++++++++++++++++++++---------- layout/segcmapassign | 26 +++++++++ 6 files changed, 293 insertions(+), 42 deletions(-) create mode 100644 layout/.cvsignore create mode 100644 layout/Makefile create mode 100755 layout/segcmapassign diff --git a/.cvsignore b/.cvsignore index d134ecb..f01613b 100644 --- a/.cvsignore +++ b/.cvsignore @@ -3,7 +3,6 @@ qs t u testjoin -*.d4 *.new *,*.gnuplot-data *,*.gnuplot-cmd @@ -21,6 +20,5 @@ divider-table.txt *.oprints-l-tmp *.tmp *.oprint-*.ps -ours-*.ps parts.ps *.zip.d diff --git a/layout/.cvsignore b/layout/.cvsignore new file mode 100644 index 0000000..6995301 --- /dev/null +++ b/layout/.cvsignore @@ -0,0 +1,5 @@ +*.d4 +ours-*.ps +*.new +*.segcmapreq +*.segcmap diff --git a/layout/Makefile b/layout/Makefile new file mode 100644 index 0000000..a31aea4 --- /dev/null +++ b/layout/Makefile @@ -0,0 +1,68 @@ + +M4INCS= parts.i4 + +E_TRACK= ArsCLMNo +LAYOUTOPTS_ALL= -ep=*Cm +LAYOUTOPTS= -E=*$(E_TRACK) $(LAYOUTOPTS_ALL) +LAYOUTOPTS_PHYS= -S1.0 $(LAYOUTOPTS) '-e*A' +XLAYOUTOPTS_LAYER= -e'=5AN' -E'*~=5rsm' -e'p~=5r' -e'*~=9C' -e'*=*l' + +LAYOUTOPTS_SEGS= '-e*=*r' '-e=5G' + +LAYERS_LS= 0 10 20 +LAYERS_PS= $(addsuffix .ps, $(LAYERS_LS)) +LAYERS_L= $(addprefix ours-l, $(LAYERS_PS)) +LAYERS_E= $(addprefix ours-e, $(LAYERS_PS)) +LAYERS= $(LAYERS_L) $(LAYERS_E) + +LPAGES= $(foreach x, 0 1 2 3 4 5 6, $(foreach y, 1 2 3 4 5, ours-p0-$xx$y.ps)) + +default: layers +all: default lpages + +layers: $(LAYERS) +lpages: $(LPAGES) + +o=>$@.new && mv -f $@.new $@ + +%.d4: %.m4 $(M4INCS) Makefile + m4 -s <$< $o + +%-a.ps: %.d4 layout + ./layout <$< $(LAYOUTOPTS) '-E*l' $o + +%-al.ps: %.d4 layout + ./layout <$< $(LAYOUTOPTS) '-e*C' '-ep=rm' $o + +%-ap.ps: %.d4 layout + ./layout -S1.0 <$< $(LAYOUTOPTS) '-e*A' '-ep=rm' $o + +ours-g%.ps: ours.d4 ours-g%.segcmap layout + ./layout <$< -l$* $(LAYOUTOPTS_SEGS) -GRours-g$*.segcmap $o + +ours-g%.segcmap: ours-g%.segcmapreq segcmapassign + ./segcmapassign <$< $o + +ours-g%.segcmapreq: ours.d4 layout + ./layout <$< -l$* $(LAYOUTOPTS_SEGS) -GL $o + +ours-l%.ps: ours.d4 layout + ./layout <$< -l$* $(LAYOUTOPTS) $(XLAYOUTOPTS_LAYER) $o + +ours-e%.ps: ours.d4 layout + ./layout <$< -l$* -E'=*aRsclMno' \ + -e'p=*rm' -e'=5RN' -E'*~=5rsm' -e'p~=5r' -e'*=*l' $o + +ours-p%.ps: ours.d4 layout + ./layout <$< -l$$(printf %s "$*" | sed -e 's/-/ -P/') \ + $(LAYOUTOPTS_PHYS) $(XLAYOUTOPTS_LAYER) $o + +parts.ps: showlib.d4 layout + ./layout <$< $(LAYOUTOPTS_ALL) $o + +clean: + -rm -f -- *.d4 *~ *.new + -rm -f ours-*.ps parts.ps + -rm -f *.oprint-*.ps + +.PRECIOUS: $(OPRINTS) diff --git a/layout/informat.txt b/layout/informat.txt index ea1cf8b..f03004b 100644 --- a/layout/informat.txt +++ b/layout/informat.txt @@ -33,6 +33,83 @@ Commands Defines loc T: start at loc F, go forward L, translate right R, turn left A (defaults are all 0). + segment [K*] [S0 D0 ...] Sn + Specifies that arcs and lines in layer kind K are part of subsegment + Sn. + + If additional Di and Si are provided then each Si apart from the + last is followed by a distance Di saying how much track it applies + to; the first D0 of track is part of subsegment S0, the next D1 of + track is part of the next subsegment S1, and so on, with the last + subsegment Sn (without a distance restriction) being used for track + beyond that. Each segment command resets the distance counter, and + it is not an error for there to be unused subsegment specs in a + segment command. For these distances, only track whose subsegment + encoding is actually drawn counts. + + If a part or object is used, then the arcs and lines inside it are + processed for subsegments as if they appeared directly. + + A subsegment is a specification of: + * The named electrically separate track segment of which + this track forms part. + * If this track is part of one possible configuration of a + junction or point, the moveable feature name and configuration + number. Any one junction or point is one moveable feature and + must be associated with and form part of one track segment. + Moveable segments must be entirely contained within objects or + parts (ie, one moveable segment cannot span multiple parts). + Configuration numbers should start at 0 and be allocated densely. + + Subsegment specs Si are + N[/[MP]] + where + N is the segment name (alphanumeric, may be empty) + M is the moveable feature name (alphabetic, nonempty) + P is the moveable feature position (numeric, nonempty, 0-indexed) + If N is empty and MP is omitted then / must be present. + + If a segment command occurs in a part or object, N is appended to + the N in force at the start of the part or object. (Note that it is + not usually a good idea to rely on how a complex object leaves the + setting of the segment, as probably the calling code will end up + using the object's segment names.) + + At the start of processing at the toplevel, the empty-named fixed + subsegment is in use. The empty-named top-level subsegment + indicates that the subsegment is unspecified, unknown or absent. + + segmap S D ... + + Maps specified (sub)segments or moveable feature(s) S to + consequently defined (sub)segments or moveable features D. This is + primarily intended so that parts' internal segment and feature names + can be remapped to correspond to the layout naming scheme. + + S O + ---- ---- + N N' remaps an entire segment including all features + N/M M' remaps a particular moveable feature; N is the + unmapped name (if applicable) + + The effect is that (sub)segments or features used in segment + commands are translated when the segment command is read; the + specified names (S) are those which the segment command would + define. + + Where segmap is used outside a part or object, the mappings apply to + the segment names which would result at the toplevel. When segmap + is used inside a part or object, the mappings apply to the segment + names defined within the part (perhaps by its subparts). Ie, the + mapping operates on the segment names visible at the level at which + segmap is used (and thus several segmaps at different levels may + operate on a signal segment name, in sequence). + + Mappings in later segmap commands replace earlier mappings at the + same level. + + The remapping may coalesce otherwise-distinct segments. + layer K[L] K is layer kind (letters and `_', may be empty), L is a layer depth (digits, or `=' meaning current layer, or `*' meaning output layer; @@ -132,20 +209,22 @@ Command-line options Turn on and off drawing of elements in groups. These are abbreviations for various -E... options. track -E.... - A full track ARSc - R rails only aRsc - S rails and sleepers only aRSc - C centrelines only arsC - c swept area and ticks only Arsc - r no lines drawn at all arcs + A full track ARScg + R rails only aRscg + S rails and sleepers only aRScg + C centrelines only arsCg + c swept area and ticks only Arscg + r no lines drawn at all arcs labels at locs - L label top-level locs (turns on bars for them too) LM + L label top-level locs (turns on bars for them too) LMg l do not label any locs l bars at locs (thick lines perp to track dir'n) - M bars for top-level locs only Mno - N bars for top-level locs and those in obj's MNo - O bars for everything, including those inside parts MNO + M bars for top-level locs only Mnog + N bars for top-level locs and those in obj's MNog + O bars for everything, including those inside parts MNOg m no bars (turns off labelling too) mnol + subsegment encoding + G draw only subsegment encoding Garcslmno -E[ARSCLMNOarsclmno]... enable (capitals) or disable (lowercase) drawing of @@ -158,6 +237,12 @@ 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 + G draw subsegment encoding + + -GL output segment colour map request list + use with -eG or -EG to write out the list of subsegment + specs which will need colours, one per line (and not + necessarily only once each) -q quiet: do not print info to stderr (default: prints bounding box, at the moment) diff --git a/layout/layout b/layout/layout index 03a8d0c..20f4ede 100755 --- a/layout/layout +++ b/layout/layout @@ -10,26 +10,30 @@ our $page_y= 0; our $quiet=0; our $debug=0; our $output_layer= '*'; +our $subsegcmapreq=0; our $ps_page_shift= 615; our $ps_page_xmul= 765.354; our $ps_page_ymul= 538.583; our @eopts; - -our $drawers= 'arsclmno'; -our %chdraw_emap= qw(A ARSc - R aRsc - S aRSc - C arsC - c Arsc +our @segments= ('/'); +our %subsegcmap; + +our $drawers= 'arsclmnog'; +our %chdraw_emap= qw(A ARScg + R aRscg + S aRScg + C arsCg + c Arscg r arcs - L LM + L LMg l l - M Mno - N MNo - O MNO - m mnol); + M Mnog + N MNog + O MNOg + m mnol + G Garsclmno); while (@ARGV && $ARGV[0] =~ m/^\-/) { last if $ARGV[0] eq '-'; @@ -43,7 +47,21 @@ while (@ARGV && $ARGV[0] =~ m/^\-/) { elsif (s/^l(\d+|\*)//) { $output_layer=$1; } elsif (s/^S([0-9.]+)$//) { $scale= $1 * 1.0; } elsif (s/^P(\d+)x(\d+)$//) { $page_x= $1; $page_y= $2; } - elsif (s/^(e) + elsif (s/^GL//) { $subsegcmapreq=1; } + elsif (s/^GR(.*)$//) { + my ($sscmfn) = $1; + my ($sscmf); + local ($_); + $sscmf= new IO::File $sscmfn, 'r' + or die "$sscmfn: cannot open: $!\n"; + while (<$sscmf>) { + m,^\s*(\w+/(?:[a-z]+\d+))\s+(\S.*\S)\s*$, + or die "$sscmfn:$.: syntax error in subseg cmap\n"; + $subsegcmap{$1}= $2; + } + $sscmf->error and die "$sscmfn: error reading: $!\n"; + close $sscmf; + } elsif (s/^(e) ((?:[a-z]|\*|\?|\[[a-z][-a-z]*\])*?) (\~?) (\d*) (\=*|\-+|\++) (\d*|\*) ([a-z]+)$//ix) { @@ -118,6 +136,7 @@ our $psu_sleeperlen= 17; our $psu_sleeperlw= 15; our $psu_raillw= 1.0; our $psu_thinlw= 1.0; +our $psu_subseglw= 2.0; our $lmu_marklw= 4; our $lmu_marktpt= 11; @@ -170,6 +189,7 @@ our $allwidthmin= allwidth(undef); # $ctx->{DrawMap} # =$fn s.t. # # &$fn($drawchrs_spec_by_layer_cmdline) # # = $drawchrs_we_should_use_due_to_obj_etc +# $ctx->{SegName} # initial segment name (at start of object or file) # $ctx->{Layer}{Level} # $ctx->{Layer}{Kind} # @@ -180,6 +200,11 @@ our $allwidthmin= allwidth(undef); # $eopts[]{GlobRe} # regexp for K # $eopts[]{LayerCheck} # =$fn where &$fn($l) is true iff layer matches # $eopts[]{DrawMods} # modifier chars for drawing +# +# @segments= ( $csss0, $dist0, $csss1, $dist1, ..., $csssn ) +# +# $subsegcmap{$csss} = "$green $blue" +# # $csss is canonical subseg spec; always has '/' our $ctx; our %objs; @@ -510,6 +535,7 @@ sub dv { sub o ($) { $o .= $_[0]; } sub ol ($) { $ol .= $_[0]; } sub oflushpage () { + return if $subsegcmapreq; print $o, $ol, " showpage\n" or die $!; $o=$ol=''; @@ -529,7 +555,10 @@ sub o_path_point ($) { sub o_path_stroke ($) { my ($width)=@_; o(" $width setlinewidth stroke\n"); -} +} +sub o_path_strokeonly () { + o(" stroke\n"); +} sub o_line ($$$) { my ($a,$b,$width)=@_; @@ -566,6 +595,14 @@ sub parametric__o_pt ($) { o_path_point("$pt->{X} $pt->{Y}"); } +sub segment_used_len ($) { + my ($used) = @_; + return if @segments < 3; + $segments[1] -= $used; + return if $segments[1] > 0; + @segments= @segments[2..-1]; +} + sub parametric_segment ($$$$$) { my ($p0,$p1,$lenperp,$minradius,$calcfn) = @_; # makes $p (global) go from $p0 to $p1 ($p1>$p0) @@ -574,7 +611,7 @@ sub parametric_segment ($$$$$) { # $calcfn is invoked with $p set and should return a loc # (ie, ref to X =>, Y =>, A =>). my ($pa,$pb,@ends,$side,$ppu,$e,$v,$tick,$draw,$allwidth); - return unless $ctx->{Draw} =~ m/[ARSC]/; + return unless $ctx->{Draw} =~ m/[ARSCG]/; $ppu= $psu_ulen/$lenperp; $allwidth= allwidth($minradius); my ($railctr)=($psu_gauge + $psu_raillw)*0.5; @@ -584,6 +621,41 @@ sub parametric_segment ($$$$$) { my ($sleeperend)=($psu_sleeperlen*0.5); print DEBUG "ps $p0 $p1 $lenperp ($ppu)\n"; $draw= current_draw(); + if ($draw =~ m/G/) { + my ($pt,$going,$red); + $going=0; + o(" $psu_subseglw setlinewidth\n"); + $param=$p0; + $pt= &$calcfn; + for (;;) { + if ($subsegcmapreq) { + next if $subsegcmap{$segments[0]}++; + print "$segments[0]\n" or die $!; + } elsif (exists $subsegcmap{$segments[0]}) { + $red= $pt->{A} / (2*$pi); + $red *= 64; + $red %= 64; + $red /= 64.0; + $red= sprintf("%f", $red); + o(" $red $subsegcmap{$segments[0]} setrgbcolor\n"); + } else { + die "unknown subsegment colour for $segments[0]\n"; + } + o_path_begin(); + parametric__o_pt($pt); + + $param += $ppu; + last if $param>=$p1; + segment_used_len($psu_ulen); + $pt= &$calcfn; + parametric__o_pt($pt); + o_path_strokeonly(); + } + segment_used_len(($p1-($param-$ppu)) * $lenperp); + $param=$p1; + parametric__o_pt(&$calcfn); + o_path_strokeonly(); + } if ($draw =~ m/C/) { my ($pt); o(" $psu_thinlw setlinewidth\n"); @@ -976,7 +1048,8 @@ sub newctx (;$) { $ctx= { Trans => { X => 0.0, Y => 0.0, A => 0.0, R => 1.0 }, InRunObj => "", - DrawMap => sub { $_[0]; } + DrawMap => sub { $_[0]; }, + SegName => "" }; %{ $ctx->{Layer} }= %{ $ctx_save->{Layer} } if defined $ctx_save; @@ -1001,6 +1074,8 @@ sub cmd__defobj ($) { $ctx->{Draw}= $defobj_save->{Draw}.'X'; $ctx->{DrawMap}= sub { ''; }; $ctx->{Layer}= { Level => 5, Kind => '' }; + $segments[0] =~ m,/, or die; + $ctx->{SegName}= $`; } sub cmd_enddef { @@ -1282,23 +1357,17 @@ sub cmd__one { cmd__do(); } -print - "%!\n". - " /lf /Courier-New findfont $lmu_marktpt scalefont def\n". - " $ps_page_shift 0 translate 90 rotate\n" - or die $!; +o("%!\n". + " /lf /Courier-New findfont $lmu_marktpt scalefont def\n". + " $ps_page_shift 0 translate 90 rotate\n"); if ($page_x || $page_y) { - print - " /Courier-New findfont 15 scalefont setfont\n". - " 30 30 moveto (${page_x}x${page_y}) show\n" - or die $!; + o(" /Courier-New findfont 15 scalefont setfont\n". + " 30 30 moveto (${page_x}x${page_y}) show\n"); } -print - " -$ps_page_xmul $page_x mul -$ps_page_ymul $page_y mul translate\n". - " $ptscale $ptscale scale\n" - or die $!; +o(" -$ps_page_xmul $page_x mul -$ps_page_ymul $page_y mul translate\n". + " $ptscale $ptscale scale\n"); newctx(); @@ -1338,7 +1407,7 @@ while (<>) { } if (!$quiet) { print STDERR $bboxstr; } $bboxstr =~ s/^/\%L bbox /mg; - print $bboxstr or die $!; + o($bboxstr) or die $!; if ($scale < 1.5) { my ($tick_x, $tick_y, $ticklen); diff --git a/layout/segcmapassign b/layout/segcmapassign new file mode 100755 index 0000000..1fa5bdb --- /dev/null +++ b/layout/segcmapassign @@ -0,0 +1,26 @@ +#!/usr/bin/perl +# input: +# lines, with one canonical subsegment specification (csss) each +# (need not be unique) +# output: +# lines: +# +# where is N/[MP] (see informat.txt) and and +# contain no whitespace and are suitable for inserting like this +# into the PostScript output: +# ...code to compute and stack red in range [0,1>... +# setrgbcolor +# +# Encoding is as follows: +# +# RED +# 6 bits angle +# 1 bit `edge or core' (currently 0 meaning `core') +# 1 bit reserved (0) +# +# GREEN +# 2 bits segment overflow +# 6 bits moveable feature +# +# +# 10 bits -- 2.30.2