layout polarity diagram colourful segment encoding:
- abstract away the pixel encoding scheme, at least somewhat
implement segmap so that we can do midx
decide what to do about crossings (difficult to show both tracks)
wire layout diagram thing into Tcl and see speed etc.
%.segcmapreq: %.run-layout
./$< $(LAYOUTOPTS_SEGS) -GR $o
-%.segcmap: %.segcmapreq segcmapassign
+%.segcmap: %.segcmapreq segcmapassign segcmap.h
./segcmapassign <$< $o
%.dgram.m: %.dgram-list make-dgram-make
t.ppm: ours.dgram-bot.pa.segenco.ppm x.gdb subseg2display
gdb -x x.gdb
+subseg2display.o compose-segenco.o: segcmap.h
+
clean:
-rm -f -- *.d4 *~ t.* *.m *.new core
-rm -f ours-*.ps parts.ps
#include <ppm.h>
-#define FILES 7
+#include "segcmap.h"
+
+#define FILES (MOVFEATPOS_BITS+1)
struct file {
const char *fn;
int gotsegnum=-1, gotmovfeatpos=-1;
val ov[3];
- ov[0]= ov[1]= ov[2]= 255;
+ DATUM2ARY(ov, BACKGROUND);
for (fi=0; fi<nf; fi++) {
val iv[3];
+ unsigned long datum;
int segnum, movfeatpos;
if (fread(iv,1,3,f[fi].f)!=3) {
else badformat("truncated file");
}
- if (iv[0]==255 && iv[1]==255 && iv[2]==255)
+ datum= ARY2DATUM(iv);
+
+ if (datum == BACKGROUND)
continue;
- segnum= ((iv[2] & 0x03) << 8) | iv[3];
- movfeatpos= iv[1] & 0x0fc;
+ segnum= DATUM2(SEGNUM,datum);
+ movfeatpos= DATUM2(MOVFEATPOS,datum);
if (!!fi != !!movfeatpos)
badformat("moveable featureness disagrees with file index");
continue;
}
if (fi) {
- ov[1] |= 0x100 >> fi; /* bits are reversed; first fi pos 1 not 0 */
+ datum= ARY2DATUM(ov);
+ datum |= 1UL << (fi-1 + MOVFEATPOS_BASEBIT);
+ DATUM2ARY(ov,datum);
}
}
our $output_layer= '*';
our $subsegcmapreq=0;
our $subsegmovfeatpos='f';
+our $subsegcmapangscale;
our $ps_page_shift= 615;
our $ps_page_xmul= 765.354;
elsif (s/^GP(\d+|f)$//) { $subsegmovfeatpos=$1; }
elsif (s/^GL(.*)$//) {
my ($sscmfn) = $1;
- my ($sscmf);
+ my ($sscmf, $datum, $csss, $angbits);
local ($_);
$sscmf= new IO::File $sscmfn, 'r'
or die "$sscmfn: cannot open: $!\n";
$!=0; $_= <$sscmf>; die $! unless defined $_;
last if m/^E/;
next unless m/^C/;
- m,^C\s+(\w*/(?:[A-Za-z_]+)?)\s+(\S.*\S)\s*$,
+ m,^C\s+(\w*/(?:[A-Za-z_]+)?)\s+(0x[0-9a-f]+)\s+(\d+)\s*$,
or die "$sscmfn:$.: syntax error in subseg cmap\n";
- $subsegcmap{$1}= $2;
+ ($csss,$datum,$angbits)= ($1,$2,$3);
+ if (!defined $subsegcmapangscale) {
+ $subsegcmapangscale= 1<<$angbits;
+ } else {
+ die "angbits varies" if $subsegcmapangscale != 1<<$angbits;
+ }
+ $datum= hex($datum);
+ $subsegcmap{$csss}= sprintf("%.6f %.6f",
+ (($datum >> 8) & 0xff)/255.0,
+ (($datum >> 16) & 0xff)/255.0);
}
$sscmf->error and die "$sscmfn: error reading: $!\n";
close $sscmf;
die "unknown subsegment colour for $csegbare\n"
unless exists $subsegcmap{$csegbare};
$red= $pt->{A} / (2*$pi);
- $red *= 64;
- $red += 128;
- $red += 32 if $segments[0] =~ m/^\-/;
- $red %= 64;
- $red <<= 2;
+ $red *= $subsegcmapangscale;
+ $red += $subsegcmapangscale*2;
+ $red += $subsegcmapangscale/2 if $segments[0] =~ m/^\-/;
+ $red %= $subsegcmapangscale;
$red /= 255.0;
$red= sprintf("%f", $red);
o(" $red $subsegcmap{$csegbare} setrgbcolor\n");
--- /dev/null
+/*
+ *
+ * Encodings in segment encodings are as follows:
+ * firstly, assemble the R, G, B bytes like this:
+ * blue << 16 | green << 8 | red
+ *
+ * Now interpret the resulting 24-bit datum as a bit sequence with the
+ * following parts (LSbit first):
+ * bits
+ * 6* moveable feature and position } blue
+ * 10* segment number } blue/green
+ * 1* reserved - always 0 } red
+ * 1 `edge'(1) or `core'(0) - currently always 0 } red
+ * 6* angle } red
+ *
+ * Each moveable feature has an unambiguous prefix the remainder of the
+ * moveable feature bits are the positions of that feature (LSbit is
+ * position 0, etc.). The feature all-bits-0 (0b000000) is for fixed track
+ * (so every moveable feature prefix must contain at least one 1).
+ *
+ * The unknown/unidentified segment is all-bits-0, with feature
+ * all-bits-0 for fixed parts and feature 0b1.... for moveable parts.
+ * Background is white (all bits set).
+ *
+ * Items marked * can have the number of bits allocated to them
+ * adjusted - see below.
+ */
+
+#ifndef SEGMAP_H
+#define SEGMAP_H
+
+/*---------- bit widths of various datum fields ----------*/
+
+/* Be careful editing this bit: you may change the number of bits
+ * within reason, but preserve the format of the file and the ordering
+ * of info in the datum. Both segcmapassign and layout have knowledge
+ * of the datum format that doesn't come from here, although there
+ * are arrangements to read the widths of the fields from here. */
+
+#define ANGLE_BITS 6
+#define MOVFEATPOS_BITS 6
+#define SEGNUM_BITS 10
+/* do not make these add up to more than 23 */
+
+/*---------- datum assembly/disassembly macros ----------*/
+
+/* It wouldn't be adviseable to change things beyond this point
+ * without considering editing segcmapassign, layout and various
+ * comments and associated machinery. */
+
+#define BACKGROUND 0x00ffffffUL
+
+#define MOVFEATPOS_BASEBIT (24-MOVFEATPOS_BITS)
+#define SEGNUM_BASEBIT (MOVFEATPOS_BASEBIT-SEGNUM_BITS)
+#define ANGLE_BASEBIT 0
+#define RESERVED_BITS (SEGNUM_BASEBIT-ANGLE_BITS-1)
+
+#define MKMASK(v) (((1UL)<<(v))-1)
+#define DATUM2(q,l) (((l) >> q##_BASEBIT) & MKMASK(q##_BITS))
+#define RESERVED_MASK (MKMASK(RESERVED_BITS+1) << ANGLE_BITS)
+
+/*---------- useful utility macros ----------*/
+
+#define RGB2DATUM(r,g,b) (((b)<<16) | ((g)<<8) | (r))
+#define ARY2DATUM(a) RGB2DATUM((a)[0],(a)[1],(a)[2])
+#define DATUM2RGB(r,g,b,l) ((r) = (l)&0xff, \
+ (g) = ((l)>>8)&0xff, \
+ (b) = ((l)>>16)&0xff)
+#define DATUM2ARY(a,l) DATUM2RGB((a)[0],(a)[1],(a)[2],(l))
+
+/*---------- consequences of the datum format ----------*/
+
+#define ANGLE_TOPBIT (1<<(ANGLE_BITS-1))
+#define NANGLES (1<<ANGLE_BITS)
+#define ANGLE_MAX (NANGLES-1)
+
+#define SEGNUM_MAX ((1<<SEGNUM_BITS)-1)
+#define MOVFEATPOS_MAX ((1<<MOVFEATPOS_BITS)-1)
+
+
+#endif /*SEGMAP_H*/
# output:
# lines:
#
-# C <csss> <green> <blue>
-# where <csss> is N/[M] (see informat.txt) and <green> and <blue>
-# contain no whitespace and are suitable for inserting like this
-# into the PostScript output:
-# ...code to compute and stack red in range [0,1>...
-# <green> <blue> setrgbcolor
+# C <csss> 0x<datum> <angle-bits>
+# where <csss> is N/[M] (see informat.txt) and <datum>
+# is the hex value of the datum (see segmap.h)
#
# S <segname> 0x<segnum>
# F <segname> 0x<segnum> <featname> 0x<prefix> <configbits>
# # comments for debugging segcmapassign etc.
# E
# final line, always present
-#
-# Encoding in final segment encoding map is as follows
-# (bits from MSbit to LSbit):
-#
-# RED
-# 6 bits angle
-# 1 bit reserved (0)
-# 1 bit `edge or core' (currently 0 meaning `core')
-#
-# GREEN
-# 2 bits segment overflow
-# 6 bits moveable feature and position
-# each moveable feature has an unambiguous prefix
-# the remainder of the bits are the positions of that feature
-# (LSbit is position 0, etc.)
-# the feature all-bits-0 (0b000000) is for fixed track
-# (so every moveable feature prefix must contain at least one 1)
-# BUT all of the bits are in the reverse order (so the
-# MSbit of GREEN is the LSbit of the moveable feature and position)
-#
-# BLUE
-# 8 bits segment main IN REVERSE ORDER
-#
-# The unknown/unidentified segment is 00 0000 0000, with feature 00 0000
-# for fixed parts and feature 1x xxxx for moveable parts.
-# Background is white (all bits set).
use strict;
use IO::Handle;
our ($seg,$movfeat,$movconf,$si,$fi);
our (%seg);
+our %bits;
+
+sub read_segcmap_h () {
+ my ($p);
+ open H, "< segcmap.h" or die $!;
+ map { $bits{$_}=0 } qw(Angle Movfeatpos Segnum);
+ while (<H>) {
+ next unless m/^\#define\s+([A-Z])([A-Z]*)_BITS\s+([1-9]\d*)\s*$/;
+ $p= uc($1).lc($2);
+ next unless exists $bits{$p};
+ die $p if $bits{$p};
+ $bits{$p}= $3;
+ }
+ map { die $_ unless $bits{$_} } keys %bits;
+}
+
+read_segcmap_h();
+
sub cssnmap ($$$$) {
my ($seg,$movfeat,$segnum,$posinfo) = @_;
- my ($green,$blue,$greenr,$bluer);
- $green= (($segnum >> 8) & 0x03)<<6;
- $green |= $posinfo;
- $blue= $segnum & 0xff;
- $greenr= reverse_bits_in_byte($green);
- $bluer= reverse_bits_in_byte($blue);
- printf("C %s/%s %.6f %.6f\n".
- "# %s/%s 0x%x 0x%x 0x%x 0x%x\n",
- $seg,$movfeat, $greenr/255.0, $bluer/255.0,
- $seg,$movfeat, $green, $blue, $greenr, $bluer)
+ my ($datum);
+ $datum=
+ ($posinfo << (24 - $bits{Movfeatpos})) |
+ ($segnum << (24 - $bits{Angle} - $bits{Segnum}));
+ printf("C %s/%s 0x%012x %d\n",
+ $seg, $movfeat, $datum, $bits{Angle})
or die $!;
}
-our $movfeatposbits= 6;
-
while (<>) {
m,^(\w*)/([A-Za-z_]*)(\d*)$, or die;
($seg,$movfeat,$movconf)=($1,$2,$3);
if (!length $seg) {
die "too many $seg $movfeat" if
- length $movfeat && $movconf >= $movfeatposbits-1;
+ length $movfeat && $movconf >= $bits{Movfeatpos}-1;
cssnmap($seg,$movfeat,0,
- length $movfeat ? 1<<($movfeatposbits-1) : 0);
+ length $movfeat ? 1<<($bits{Movfeatpos}-1) : 0);
next;
}
die if length $movconf && !length $movfeat;
}
}
-sub reverse_bits_in_byte ($) {
- my ($a) = @_;
- my ($b,$c,$d);
- $b= (($a >> 1) & 0x55) | (($a << 1) & 0xaa);
- $c= (($b >> 2) & 0x33) | (($b << 2) & 0xcc);
- $d= (($c >> 4) & 0x0f) | (($c << 4) & 0xf0);
- return $d;
-}
-
our ($segnum) = 1;
our ($conf,$posbit,$posbiti,$abovenext);
foreach $seg (sort keys %seg) {
$si= $seg{$seg};
$si->{Num}= $segnum++;
- die if $si->{Num} >= 1024;
- $abovenext= 1<<$movfeatposbits;
+ die if $si->{Num} >= 1 << $bits{Segnum};
+ $abovenext= 1 << $bits{Movfeatpos};
printf("S %s 0x%x\n",
$seg, $si->{Num})
or die $!;
#include <publib.h>
#include <ppm.h>
+#include "segcmap.h"
+
/*---------- lookup data structure ----------*/
struct result {
};
#define NCHARS 256
-#define MAXSEGNUM ((1<<10)-1)
-#define MAXMOVFEATPOS ((1<<6)-1)
static struct result idinfo[NCHARS];
static struct result background;
errno= 0;
segnum= strtoul(arg,&ep,0);
if (errno) badusage();
- if (segnum > MAXSEGNUM) badusage();
+ if (segnum > SEGNUM_MAX) badusage();
if (!*ep) {
ensure_ids(&fixed,&fixed_a,segnum);
errno= 0;
movfeatpos= strtoul(ep+1,&ep,0);
if (*ep || errno) badusage();
- if (movfeatpos > MAXMOVFEATPOS) badusage();
+ if (movfeatpos > MOVFEATPOS_MAX) badusage();
ensure_mps(&moveable,&moveable_a,segnum);
mps= &moveable[segnum];
- ensure_ids(&mps->lookup,&mps->lookup_a, movfeatpos ^ MAXMOVFEATPOS);
- mps->lookup[movfeatpos ^ MAXMOVFEATPOS]= ix;
+ ensure_ids(&mps->lookup,&mps->lookup_a, movfeatpos ^ MOVFEATPOS_MAX);
+ mps->lookup[movfeatpos ^ MOVFEATPOS_MAX]= ix;
}
/*---------- actual image processing ----------*/
exit(12);
}
-static unsigned reverse_bits_in_byte(unsigned a) {
- unsigned b, c, d;
- b= ((a >> 1) & 0x55) | ((a << 1) & 0xaa);
- c= ((b >> 2) & 0x33) | ((b << 2) & 0xcc);
- d= ((c >> 4) & 0x0f) | ((c << 4) & 0xf0);
- return d;
-}
-
static void angle_to_colour(double result[3],
- int angle_i /* [0..63> */) {
+ int angle_i /* [0..ANGLE_MAX> */) {
int s;
double angle, f, u, d, U, D;
- angle= angle_i / 64.0 * 6.0;
+ angle= angle_i / (double)NANGLES * 6.0;
s= floor(angle);
f= angle - s;
}
}
-static double anglemap[64][3];
+static double anglemap[NANGLES][3];
static void angle_to_colour_init(void) {
int i;
- for (i=0; i<64; i++)
+ for (i=0; i<NANGLES; i++)
angle_to_colour(anglemap[i],i);
}
for (row=0; row<rows; row++)
for (col=0; col<cols; col++) {
unsigned char rgbi[3], rgbo[3];
+ unsigned long datum;
if (fread(rgbi,1,3,encodingfile)!=3) {
if (ferror(encodingfile)) { perror("reading"); exit(12); }
else badformat("truncated file");
}
- if (rgbi[0]==255 && rgbi[1]==255 && rgbi[2]==255) {
+ datum= ARY2DATUM(rgbi);
+
+ if (datum == BACKGROUND) {
if (fwrite(rgbob,1,3,stdout)!=3) { perror("filling"); exit(12); }
} else {
- int segnum, movfeatpos, movfeatposix, red, blue, green, ix, angle;
+ int segnum, movfeatpos, movfeatposix, ix, angle;
double *rgbdirn, alpha;
struct result *r;
- red= rgbi[0];
- green= reverse_bits_in_byte(rgbi[1]);
- blue= reverse_bits_in_byte(rgbi[2]);
-
- if (red & 0x03) badformat("reserved bits set in red");
- angle= ((red >> 2) & 0x3f);
-
- segnum= blue | ((green & 0xc0) << 2);
- movfeatpos= green & 0x3f;
- movfeatposix= movfeatpos ^ MAXMOVFEATPOS;
+ if (datum & RESERVED_MASK) badformat("reserved bits set");
+ angle= DATUM2(ANGLE,datum);
- assert(segnum <= MAXSEGNUM);
- assert(movfeatpos <= MAXMOVFEATPOS);
+ segnum= DATUM2(SEGNUM,datum);
+ movfeatpos= DATUM2(MOVFEATPOS,datum);
+ movfeatposix= movfeatpos ^ MOVFEATPOS_MAX;
ix= !movfeatpos ?
(segnum < fixed_a ? fixed[segnum] : 0) :
r= &idinfo[ix];
- rgbdirn= anglemap[ angle ^ (r->alpha < 0 ? 32 : 0) ];
+ rgbdirn= anglemap[ angle ^ (r->alpha < 0 ? ANGLE_TOPBIT : 0) ];
alpha= fabs(r->alpha);
for (i=0; i<3; i++) {