Obstacle Avoidance and Navigation in the Real World by a Seeing Robot Rover, Hans Moravec, 1980
<-- Previous  Next -->

Appendix 10: Spinoffs

Guide to Data Disc Graphics Routines

to use: REQUIRE “DDHDR.SAI[GRA,HPM]” SOURCE_FILE;

uses: DDFAI.REL[GRA], DDSAI.REL[GRA]

DDINIT   initialize the DD buffer
SCREEN(REAL XLO, YLO, XHI, YHI)   declare the full screen dimensions
SCREEM(REAL XLO, YLO, XHI, YHI)   returns the full screen dimensions
DRKEN   cause subsequent outputs to be dark
LITEN   cause them to be light
INVEN   cause them to invert the state of things
DOT(X, Y, THICK(0))   display a point at X, Y
LINE(X1, Y1, X2, Y2, THICK(0))   display a line
RECTAN(X1, Y1, X2, Y2)   fill in rectangle
ELLIPS(X1, Y1, X2, Y2)   fill ellipse bounded by X1, Y1, X2, Y2
POLYGO(N, X[1:N], Y[1:N])   fill in a polygon (concave and star ok)
TXTPOS(X, Y, XS, YS, DXS(0), DYS(0))   Position text start at X, Y with general linear transf. First char's corners will be (X, Y), (X+DXS, Y+YS), (X+XS+DXS, Y+YS+DYS), (X+XS, Y+DYS). To make normal horizontal text of characters $W$ wide and $H$ high, do $$TXTPOS(X, Y, W, H, 0, 0)$$ or just $TXTPOS(X, Y, W, H)$. To make sideways text lying on its left side, do $$TXTPOS(X, Y, 0, 0, -H, W)$$ To make text on its right side (reading downwards), do $$TXTPOS(X, Y, 0, 0, H, -W)$$ To make text rotated from the horizontal by an arbitrary angle $T$, do $$TXTPOS(X, Y, W\cos{T}, H\cos{T}, -H\sin{T}, W\sin{T})$$ To make horizontal, italicized, text, do $$TXTPOS(X, Y, W, H, W/2, 0)$$ I leave the other possibilities to you. Consider $XS$ and $YS$ the main diagonal of a $2 \times 2$ matrix that takes a straight, horizontal, prototype character into the skewed, rotated one actually drawn. $DXS$ and $DYS$ are the off-diagonal elements of that matrix. Text can thus be rotated, italicized and reflected.
TEXT(STRING)   vector text, positioned by previous TXTPOS
TEXTD(STRING)   dot char text. Look better for tiny, inven
CHAN = GDDCHN(CHAN)   get a DD channel ($-1$ for any, failure)
RDDCHN(CHAN)   release a channel
ERASE(CHAN)   clear a DD channel ($-1$ means yours)
DPYUP(CHAN, BUFFER(-1))   Deposit the buffer on DD channel CHAN
PJUP   send buffer to MOS display on PDP11
SHOW(CHAN, LIN(-1))   video switch LIN ($-1$ for yours) to CHAN
SHOWA(CHAN, LIN(-1))   add CHAN to LIN
SHOWS(CHAN, LIN(-1))   subtract CHAN from LIN
PPPOS(YLO, YHI)   position page printer between YLO, YHI
XGPUP(SIZE)   send the DD buffer to the XGP, SIZE$ = -5$ to $+5$
XGPQUE(SIZE)   like XGPUP, but creates a new job to do XGPing
DDFONT(X1, Y1, X2, Y2, FONTFIL, CHAR(“A”), BASE(0), LKERN(0), RKERN(0))   insert DD buffer bounded by X1, Y1, X2, Y2 into font file.
DDPAK(I, LBUF, J1, J2)   pack scanline I bet. J1, J2 into LBUF 36 bit/word
CHAN = SYNMAP(ORDER)   which channels are the video synthesizer's. ORDER = $0$ is most significant $+$ or $-$ $1$ next, etc.
SUCCESS = MAPSET(F)   set video inten table. F(X) is real $[0, 1] \rightarrow [0, 1]$
SUCCESS = MAPMON(P)   set v.i.t. to a monotonic function $X^P$
SUCCESS = MAPGRY(P)   set v.i.t. to a gray coded monotonic function $X^P$
LINSCN(N, MAP, DT, LINENO)   scan channels in MAP at rate DT
MAPSCN(N, MAP, DT, LINENO)   LINSCN, but VDS bit maps in MAP
SCNOFF   turn off the scanning (in SW mode)
SCNFRZ   SCNOFF, but doesn't restore screen
SCNINC(INC)   change the stepsize in the scan
DDSTOR(DDARRAY)   store the buffer in an array
DDLOAD(DDARRAY)   load the buffer from an array
DDOR(DDARRAY)   or an array into the buffer
DDAND(DDARRAY)   and the buffer with an array
DDEXCH(DDARRAY)   exchange an array with the buffer
GETDDF(FILENAME)   load the buffer from a file
PUTDDF(FILENAME)   save the buffer in a file
GETMIT(FILENAME)   load the buffer from a file
PUTMIT(FILENAME)   save the buffer in a file
FNTSEL(FONT$\#$, “FONTNAME”)   define a font $\#$
FNTPOS(XP, YP, XS(1), YS(1), DXS(0), DYS(0))   position & transform fonted text
FNTEXT(X, Y, F, TXT)   deposit fonted text
FNTLIN(X1, Y1, X2, Y2, THICK(0))   draw line in FNTPOS co-ordinates
FNTDOT(X1, Y1, THICK(0))   dot in FNTPOS co-ordinates
FNTREC(X1, Y1, X2, Y2)   rectangle
FNTELL(X1, Y1, X2, Y2)   ellipse
FNTPOL(N, X1[1:N], Y1[1:N])   polygon
DDSIZ   a constant, the number of words in a DD array

Arguments followed by a value in parens default to the bracketed value.

The absolute physical screen dimension are 512 pixels in $X$ by 481 in $Y$. TEXTD characters are 6 logical pixels in $X$ by 10 in $Y$, spaces included.

Regarding TXTPOS parameters, note that, in terms of character height $H$, character width $W$, clockwise rotation angle $ccwrot$ and clockwise slant angle $ccwslant$ $$\begin{bmatrix} X \\ Y \end{bmatrix} \quad = \quad \begin{bmatrix} {W\cos(ccwrot)} & {H(\cos(ccwrot)\tan(cwslant)-\sin(ccwrot))} \\ {W\sin(ccwrot)} & {H(\sin(ccwrot)\tan(cwslant)+\cos(ccwrot))} \end{bmatrix} \;\begin{bmatrix} x \\ y \end{bmatrix}$$ $$\begin{bmatrix} X \\ Y \end{bmatrix} \quad = \quad \begin{bmatrix}{XS}&{DXS}\\{DYS}&{YS}\end{bmatrix} \;\begin{bmatrix} x \\ y \end{bmatrix}$$ thus $$\begin{matrix} XS & = & W\,\cos(ccwrot)\\ DXS & = & H\,(\cos(ccwrot)\,\tan(cwslant)-\sin(ccwrot))\\ DYS & = & W\,\sin(ccwrot)\\ YS & = & H\,(\sin(ccwrot)\,\tan(cwslant)+\cos(ccwrot))\end{matrix}$$

It might be useful to introduce a parameterization that accepts corner, width, height, rotation and slant angles (degrees): $$TP(X, Y, W, H, CCWROT, CWSLANT)$$


Guide to GOD Graphics Routines

to use: REQUIRE “GRAHDR.SAI[GOD,HPM]” SOURCE_FILE;

uses: GRASAI.REL[GOD]

The graphics routines on [GOD,HPM] are superficially similar to the ones on [GRA,HPM], but provide an extended device-independent graphics service. To make a drawing one or more devices (graphics servers) must be activated to receive graphics commands. Currently there are servers for Data discs, the XGP and the video synthesizer. In addition the graphics commands can be written into files (called GOD files), which can be displayed later with system programs called DDJOB, XGPJOB and SYNJOB. GOD files can be called as subroutines in graphics programs. GOD files can also be fed to a program called TSTJOB which makes a SAIL program that, if run, recreates the GOD file given to the TSTJOB. Editing the SAIL program provides a way of modifying existing GOD files.

Diagrams in the form of GOD files can be included in documents by the graphics escape features of XGPSYG.

The following calls are provided in addition to the ones in the GRA package.

JOBID = DDJOB   create a server that draws on Data Disc displays.
JOBID = XGPJOB   create a graphics server that will output on the XGP.
JOBID = SYNJOB(HIG(480),WID(512),BIT(9))   make a server that produces gray scale renditions of a drawing.
JOBID = FILJOB(“FILENAME”)   make a graphics server that writes graphics commands into a GOD file.
JOBID = TSTJOB   create a server that prints graphics commands as a SAIL program.
JOBID = QUASH(JOBID)   temporarily deafen a server.It still exists but will not act on subsequent display commands.
JOBID = INCITE(JOBID)   reactivate a server. Undoes the effect of a QUASH.
JOBID = KILJOB(INTEGER JOBID)   kill a server. Closes the file opened by a FILJOB, simply expunges all other server types.
JOBID = DETJOB(JOBID,GRAFILE)   detach a server, but give it a graphics file to process first. Server is lost to main program.
GRAFIL(GRAFILE)   tell currently active servers to begin processing a graphics file. Afterwards they will be ready to listen to main program again.
FNTSEL(FONT$\#$,FONTNAME)   select a font, and give it a number $(0-127)$.
FNTPOS(XP,YP,XS(1),YS(1),DXS(0),DYS(0))   position a font pixel grid at XP, YP in SCREEN co-ordinates, with transformation set by other four parameters. 1, 1, 0, 0 results in undistorted characters.
FNTEXT(X,Y,FONT$\#$,TEXT)   deposit TEXT in the indicated font with lower left corner offset (X,Y) font pixels (as distorted by FNTPOS parameters) from the last FNTPOS position.
FNTLIN(X1,Y1,X2,Y2,THICK(0))   draw a line between pixel co-ordinates indicated, in grid defined by last FNTPOS.
FNTDOT(X1,Y1,THICK(0))   a dot in FNTPOS co-ordinates.
FNTREC(X1,Y1,X2,Y2)   a FNTPOS rectangle.
FNTELL(X1,Y1,X2,Y2)   a FNTPOS ellipse.
FNTPOL(N,X[1:N],Y[1:N])   a FNTPOS polygon.
PICFIL(X1,Y1,X2,Y2,PICFILE)   insert a picture in the rectangle bounded in X by X1 and X2 and by Y1 and Y2 in Y. On gray scale servers this picture will come out shaded. On binary devices a halftone is produced. PICFILE should be in hand/eye format.
PICFIT(X1,Y1,X2,Y2,FILE)   insert a transposed picture in the indicated rectangle.
BUFSIZ = DDSIZ(INTEGER JOBID($-1$))   return the display buffer size of the indicated server.


The TYPHDR typesetting extension

The TYPHDR routines extend the GRAHDR package to permit reasonably convenient two dimensional typesetting of text in mixed fonts, for inclusion in GOD diagrams. The central concept is of a box of a certain size containing a two dimensional assembly of text and graphics. Such a box has an origin, which may be plopped down at a given place in diagram. Some of the commands create new boxes out of text, some by gluing together other ones, and some change the size or the origin of a box.

The following procedures are provided:

FNTSELECT(FONT$\#$,FONTNAME)   use this instead of FNTSEL in the GRAHDR.
BOX = JTXT(FONT$\#$,TEXT)   return a box containing TEXT in the indicated font.
BOX = JCAT(A,B) thru JCAT6(A,B,C,D,E,F)   horizontally combine a number of boxes. Origin ends up on left edge of resulting box. Useful for stringing together different fonts.
BOX = JTAC(A,B) thru JTAC7(A,B,C,D,E,F,G)   horizontally combine boxes, but leave origin on the right end.
BOX = JBEL(A,B) thru JBEL7(A,B,C,D,E,F,G)   vertically stack text boxes. Useful for assembling multiple lines of text.
BOX = JSUB(A,B)   make new box that is box A subscripted by box B.
BOX = JEXP(A,B)   make box with A superscripted by B.
BOX = JXBP(A,B,C)   make box with A sub B super C.
BOX = PADD(DX1,DY1,DX2,DY2,A)   padd box A on all four sides (margins).
BOX = SHIF(DX1,DY1,A)   shift origin of box A.
BOX = JUL(A)   make new box with contents of A underlined.
BOX = JSQR(A)   make a square root sign around A.
BOX = JDIV(A,B)   center A above B and put a division bar between.
BOX = XCENTER(A)   center the origin of box A in X.
BOX = YCENTER(A)   center A in Y.
BOX = CENTER(A)   move origin of A to its center in X and Y.
BOX = RIGHTIFY(A)   move origin to right of A.
BOX = LEFTIFY(A)   move origin to left of A.
BOX = TOPIFY(A)   move origin to top of A.
BOX = BOTTOMIFY(A)   move origin to bottom of A.
DEPOSIT(X,Y,A)   deposit box A into the diagram such that its origin is X (FNTPOS distorted) pixels to the right and Y pixels above the text position specified by the last FNTPOS.


Guide to vision routines on [VIS,HPM]

PIXHDR.SAI utility routines for getting, saving, moving, etc. pictures

requires: PIXFAI.REL, PIXSAI.REL

PCLN, PCWD, PCBY, PCBYA, LNWD, LNBY, LNBYA, WDBY, WDBI, BYBI, BPTAB, LINTAB   where to find things in picture arrays
VALUE = PIXEL(PICTURE, ROW, COLUMN)   value of a particular pixel
VALUE = INTREL(PIC, ROW, COL)   interpolating PIXEL. ROW, COL, VALUE real.
PUTEL(PICTURE, ROW, COLUMN, VALUE)   change a pixel
ADDEL(PICTURE, ROW, COLUMN, VALUE)   increment a pixel
ADDIEL(PIC, ROW, COL, VAL)   interpolating ADDEL. R, C, V real.
SIZE = PFLDIM(FILENAME)   size of array needed for pic file
SIZE = GETPFD(FILENAME, DIM[0:10])   read in parameters of picture
SIZE = GETPFL(FILENAME, PICTURE)   read in a pic file
PUTPFL(PICTURE, FILENAME, MODE(1))   write PICTURE into a file. if MODE = 2, file is data compressed, otherwise normal
CHAN = OPNPFL(FILENAME, DIM[0:10])   read in parameters of picture, opened for input at 1st scanline
CHAN = CREPFL(DIM[0:10], FILENAME, MODE(1))   write header for PIC file, opened for output at 1st scanline. compressed if MODE = 2
PFLIN(CHAN, AR[1], NWDS)   read next NWDS words from pic into AR
PFLOUT(CHAN, AR[1], NWDS)   write next NWDS words to pic from AR
PFLCLS(CHAN)   close picture open on channel
SIZE = PIXDIM(HEIGHT, WIDTH, BITS)   size of array for $H \times W \times B$ picture
SIZE = MAKPIX(HEIGHT, WIDTH, BITS, PICTURE)   make skeleton $H \times W \times B$ picture
SIZE = MAKDIM(H, W, B, P[0:10])   make 11 word skeleton, for out of core pix
WIPE(PICTURE, VALUE(0))   make every data word (not byte!) = VALUE
PIXTRN(SRC, TR, DEST)   transforms src into dst by array tr. tr is a 3 by 3 real array. For all pixels $(y, x)$ in dest set $(ty, tx, foo) = (y, x, 1) \times transform$. If $(ty, tx)$ is in src then $dest(y, x) = src(ty, tx)$
COPPIC(PICTURE1, PICTURE2)   copy pic1 into pic2
TILE(PIC1, YL1, XL1, TY, TX, PIC2, YL2, XL2)   take piece of size $TY \times TX$ at $[YL1, XL1]$ in PIC1, deposit at $[YL2, XL2]$ in PIC2
SQTILE(PIC1, YL1, XL1, TY, TX, YSQ, XSQ, PIC2, YL2, XL2)   a $TY \times YSQ$ by $TX \times XSQ$ tile from PIC1 with upleft at $[YL1, XL1]$ is squished into a $TY$ by $TX$ tile in PIC2 $[YL2, XL2]$ upleft. The $YSQ$ by $XSQ$ areas in PIC1 are summed and scaled as needed
SATILE(PIC1, YL1, XL1, TY, TX, YSQ, XSQ, PIC2, YL2, XL2)   like SQTILE, but 0 samples in PIC1 leave PIC2 unchanged
HAFPIC(PICTURE1, PICTURE2, MAXBIT)   reduce pic to half resolution
SHRINK(PICT1, PICT2)   squeeze or expand PICT1 into PICT2 pixels are sampled, not interpolated or averaged.
PICADD(PICTURE, PICSUM)   add a picture to a picture
PICSUB(PICA, PICDIFF)   subtract. PICA$-$PICDIFF → PICDIFF
PICMUL(PICTURE, PICPRD)   multiply pictures. no bounds check.
PICSH(PIC1, PIC2, DIV)   every pixel in PIC1/DIV→PIC2
GRAY(PIC)   Convert to gray code.
UNGRAY(PIC)   Convert back.
RETRY = CAMPIX(CAMERA, YEDGE, XEDGE, PICTURE, SUMS(1), BCLIP(7), TCLIP(0), MAXTRY(20))   read from a camera
NRETRY = CLPADJ(CAM, BLCIP, TCLIP)   find optimum clip levels for CAM
NRETRY = TVSNAP(CAM, YEDGE, XEDGE, PIC, BCLIP, TCLIP, NTRY)   primitive camera routine, used by CAMPIX
NRETRY = TVRAW(CAM, YEDGE, XEDGE, PIC, BCLIP, TCLIP, NTRY)   primitive camera routine, used by CAMPIX
TVBTMX(PIC4, PICN, XFRM, INHIBEQ)   primitive camera routine, used by CAMPIX
TVBTMY(PIC4, PICN, XFRM, INHIBLE)   primitive camera routine, used by CAMPIX
TVBTMZ(PIC4, PICN, XFRM, INHIBGE)   primitive camera routine, used by CAMPIX
SUM = INTOP(PIC, WINSIZE, ANSARRY, YEDGE(0), XEDGE(0))   interest operator
INTLOM(HIG, WID, ANSARRY)   intop local max operator
SIZE = INTERESTDIM(PICTURE, WINDOWSIZE)   pic size needed for interest op
INTEREST(PICTURE, WINDOW, RESULTPICTURE)   make interest op picture
BESTVAL = MATCH(PICTURE1, SY1, SX1, SY2, SX2, PICTURE2, DY1, DX1, DY2, DX2)   correlator, find Source window in pic1 in Dest in pic2
BSTCOEF = NORCOR(PICTURE1, SY1, SX1, SY2, SX2, PICTURE2, DY1, DX1, DY2, DX2)   normalized correlator, find Source window in pic1 in Dest in pic2
CLEAN(PICTURE)   remove single pixel noise, blurs a little
PASSHI(PICTURE1, WINDOWSIZE, PICTURE2)   high pass filter
LOWPAS(PICTURE)   in place low pass filter. 4 pixels → 1 pixel.
SUM = CMPPAR(PICTURE1, PICTURE2)   compare two pics: $\sum(x-y)^2$
SUM = CMPPAD(PICTURE1, PICTURE2)   quick and dirty compare
PERBIT(PICTURE, TRANSFORM)   transform each pixel of pic
HISTOG(PICTURE, HISTOGRAM)   count # of occurences of each gray val
ENHANCE(PICTURE)   make histogram flat
SYNCHRONIZE(PICTURE1)   do a vertical roll fixup
ROWSUM(PICTURE1, ROWSUMS)   sum up the pixels in each row
ROWSUD(PICTURE1, ROWSUMS)   dirty rowsums, one pixel/word used
COLSUM(PICTURE1, COLSUMS)   sum up the pixels in each col
LONG REAL = SUMSQR(PIC)   double prec. sum of squares of pixels
MASS = CENTRO(PIC, YL, XL, YH, XH, THR)   centroid and moment of a dark area
UNPACK(SOURCEARRAY, PICTURE)   copy a dense byte arry into a pic
GETPAR(ARRY, PICTURE)   copy full word array of pixels to pic
PUTPAR(PICTURE, ARRY)   copy pic to full word array of pixels
EDGEINIT(PICTURE, SIZE)   initialize edge operator
EDGE(X, Y, EDGERESULT)   apply edge operator

NOTE: all picture and other arrays are zero origin in all dimensions


Vision routines for Displays

VIXHDR.SAI for displaying gray scale and halftone pictures on data disc. an extension for the display routines in DDSUB.SAI[GRA,HPM]

requires: PIXHDR.SAI[VIS], DDHDR.SAI[GRA], VIXFAI.REL[VIS], VIXSAI.REL[VIS]

VIDEO(X1, Y1, X2, Y2, PICTURE, BIT)   display PICTURE between X1, Y1, X2, Y2 in SCREEN co-ordinates. If BIT = $-1$ then a fast, low quality halftone, if $-2$ then a high quality halftone, if $-3$ then a buggy halftone. If positive then BIT represents a bit mask, which is anded with each pixel. If the result is nonzero, a bit is turned on in the corresponding part of the display.
VIDONE(PICTURE, BT, I(0), J(0))   similar to VID but faster and simpler. Maps picture elements one to one to data disc points. Upper left corner of picture is placed I physical DD scanlines from the top of the picture, and indented J DD elements from the left. Complements the masked bit instead of setting it to one.
VIDFOR(PICTURE, BUF1, BUF2, BUF4, BUF8, I(0), J(0))   Like VIDONE, but for 4 bit pictures and four DD buffers. Sets up all buffers at once, clearing displayed area and inverting bits for compatibility with the inverted gray code produced by TVRAW.
VIDFRT(PICTURE, BUF1, BUF2, BUF4, BUF8, I(0), J(0))   Transposed VIDFOR; picture twice as wide on its side.
VIDFRX(PICTURE, BUF1, BUF2, BUF4, BUF8, I(0), J(0))   Like VIDFOR, but makes picture twice as wide and tall. One picture pixel → 4 DD pixels.
VID1(PICTURE, BUF1, I(0), J(0))   Like VIDFOR, for 1 bit pictures, but assumes normal gray code and produces a complemented display.
VID3(PICTURE, BUF1, BUF2, BUF4, I(0), J(0))   Like VID1, for 3 bit pictures.
VID4(PICTURE, BUF1, BUF2, BUF4, BUF8, I(0), J(0))   Like VID1, for 4 bit pictures.
VID5(PICTURE, BUF1, BUF2, BUF4, BUF8, BUF16, I(0), J(0))   Like VID1, for 5 bit pictures.
SUCCESS = VIDXGP(PIC, I0, J0, PLEN)   Send a picture to the XGP. Dumb thing to do except for one bit pictures. Wait if XGP busy.
SUCCESS = VIDXG(PIC, I0, J0, PLEN)   VIDXGP, but return with failure if XGP busy
SUCCESS = VIDXGQ(PIC, I0, J0, PLEN)   VIDXGP, but set up detached job to do XGPing if XGP busy


Routines for putting Fonted Text into Pictures

FNTHDR.SAI for inserting XGP font characters into pictures.

requires: FNTFAI.REL[VIS], FNTSAI.REL[VIS]

FNTSEL(FNTNUM, FILSPEC, FNTHEAD)   define font number FNTNUM to be font FILSPEC. FNTHEAD is the first word of an array $204_8$ words long which must be reserved for this font.
CHRDEP(FNTNUM, CHR, PIC, YLO, XLO, YCOMP, XCOMP)   add character CHR to the picture PIC in font $\#$ FNTNUM starting at position YLO, XLO compressed by YCOMP in Y and XCOMP in X.
CHRPED(FNTNUM, CHR, PIC, YLO, XLO, YCOMP, XCOMP)   add CHR to PIC, sideways, writing bottom to top. X and Y positions and compressions refer to text, not picture, reference system.
CHR3X2(FNTNUM, CHR, PIC, YLO, XLO)   like CHRDEP, but compresses X by 3 and Y by 2, and goes faster
CHR6X4(FNTNUM, CHR, PIC, YLO, XLO)   like CHRDEP, but compresses X by 6 and Y by 4, and goes faster
CHR3Y4(FNTNUM, CHR, PIC, YLO, XLO)   like CHRPED, but compresses X by 3 and Y by 4, and goes faster
FCACHE(BUFFER, BUFSIZ)   set up a buffer for caching letter descriptions. Doing this greatly speeds up CHRDEP. 5 or 10 K is a good buffer size.

Defines FNTHIG, position in FNTHEAD where height is stored, and FNTBAS, where baseline is stored.


Internal Picture Array Format

WORD CONTENTS
0 PCLN number of scanlines in the picture
1 PCWD words in the pixel portion of the picture
2 PCBY valid bytes in the picture
3 PCBYA bytes in the picture, including null bytes at end of each scanline
4 LNWD words per scanline
5 LNBY valid bytes per scanline
6 LNBYA bytes per scanline, including the nulls
7 WDBY bytes per word
8 WDBI bits in the valid portion of each word
9 BYBI bits per byte
10 BMAX $2^{BYBI}-1$, the maximum value of a byte
11 BPTAB address of SECOND entry in byte pointer table, 13+PCLN+address of array
12 to 11+PCLN LINTAB table containg the actual address of the first word of each scanline, in top to bottom order
12+PCLN to 12+PCLN+LNBYA table containing byte pointers to samples within lines, to be added to line address. The first entry, when ILDB'ed causes loading of the first byte in the line.
13+PCLN+LNBYA to 12+PCLN+LNBYA+PCWD the picture


Picture File Format

Simplified hand-eye file format, as written by PIXSAI routines, for a picture HIG samples high by WID samples wide by BIT bits/sample:

The first $200_8$ word disk block of the file contains the following seven words of data (the rest of the block is unused).

WORD CONTENTS              
0 -1 This identifies the file as a standard Stanford Hand Eye picture file
1 BIT Number of bits/sample
2 $\lceil WID/\lfloor 36/BIT\rfloor \rceil$ $\#$ of words/scanline. $\lfloor \rfloor$ is FLOOR, $\lceil \rceil$ is CEILING
3 1 first scanline number
4 HIG last scanline number
5 1 first column number
6 WID last column number

The data begins on word $200_8$ of the file, $\lceil WID/\lfloor 36/BIT\rfloor \rceil$ words per scanline, left to right, top to bottom, for HIG scanlines. Each scanline begins on a word boundary.

The data compressed variant has the same header information except word $0$ is $-2$ instead of $-1$. For each successive block of 36 words in a standard file a compressed file has from 1 to 37 words. Each bit of the first word in such a group represents one of the 36 words in the standard file block, sequenced left to right. The bit is zero if the corresponding word is the same as the previous word in the file, or one if it differs. Each word that differs is given in the group that follows the mask word.


XGPSYN and XGPSYG

XGPSYN displays files on the video synthesizer, imitating the XGP. It can fill the screen with 1/2, 1 or 2 pages at time. XGPSYN can also list documents on the XGP, with no complexity limit, and make hand/eye compatible picture files which can be sent to printers like the VARIAN, or displayed on screens. XGPSYG has the added capability of inserting drawings and pictures into the assembled pages.

To run the programs, tell them which file you want to look at, either in the command line (R XGPSYN;FILENAME) or in answer to the FILE: question, and any spooler style switches, such as /FONT = BASL30 (.XGP files already contain most necessary switches). The page number questions can be answered with the page you want to view, any additional spooler switches, or one of the following commands:

XGPSYN COMMANDS

H Half density. Next display will be one half page per screen.
F Full density. A whole page per screen.
D Double density. Two sequential pages per screen.
C Display pages on your own DD channel instead of on the video synthesizer.
S Use the video synthesizer instead of your own channel.
V view. Redraw the last display (in case it was clobbered).
W negate subsequent displays. Black on white becomes white on black, and vice versa.
K kill. Erase the video synthesizer.
Q quit. Exit from the program and load the line editor with an XSPOOL command.
L(a:b) list pages a to b on the XGP. More tolerant than XSPOOL, but slower. Alternate forms for this command are L to list the whole document and L(a) to list a single page.
B Bitwise resolution. Next display will be a full size bit raster suitable for XGPing or sending to a picture file for printing on other devices.
T Transposed bitwise resolution. Like B mode, but page is generated 90° rotated.
E Enormous resolution. Next display will be at bit raster resolution, but only upper left 480 by 512 pixel portion will be generated.
O output the last display as a data compressed picture file.
P output the last display as a standard hand/eye picture file.
X XGP output the last B,T or E display.

The video synthesizer is a video rate D/A driven by data disc channels 30 through 37. H density requires 3 of these channels, F needs 4 and D wants 5. These are rarely available during heavy system load. It takes about 6 CPU seconds to compose a single page.

XGPSYN and XGPSYG understand the following switches, some of which are not standard with the spooler or the COPY program. The switch names may be abbreviated to the capitalized portion.

/FONT = “fontname”   Select font number 0 for the document
/FONT$\#$n = “fontname”   Select font number n for the document
/THickness = t   Select line thickness for Leland's music files
/ESCape = ...   change the escape sequence. Any characters except slash are ok.
/REpeat = n   When listing, make n copies of each page.
/TMar = n   Set the top margin of a listing n raster lines from top of page.
/PMar = n   Set the text portion of the page to be n lines tall
/BMar = n   Make the bottom margin n raster lines big. In listings the sum of TMAR+PMAR+BMAR is the physical length of the page.
/LMar = n   Set the left margin n pixels from left edge of paper.
/RMar = n   Set the right margin n pixels from the left edge of the paper. When writing picture files of page images, RMAR is the physical width of the resulting image.
/List   List the document on the XGP. Possible forms are /L to list the whole document, /L(n) to list page n and /L(a:b) to list all the pages between a and b. The simplest way to list a document with XGPSYN is by incanting R XGPSYN;file/L
/XLine = n   Insert n extra scanlines between lines of text. This number is initially 3.
/INterchar = n   Insert n extra columns between characters of text. This number is usually zero.
/XShift = n   Shift the contents of a page n pixels to the right on the image. Useful if you want to tweak the margins in a listing, and also for making images too large to fit in XGPSYN's core image all at once. Set RMAR small, the output the same page repeatedly with different XSHIFTS. Resulting windows can be combined later into a single file representing a large page.
/YShift = n   Shift the page contents n pixels up. For tweaking vertical margins, and also for making very long pages. Set TMAR+PMAR+BMAR small, then window through the file by changing YSHIFT. If resulting windows are to be assembled later the EDGE switch is also recommended.
/EDge   Normally characters that extend past the top margin of a page are not displayed. /EDGE selects a slower mode in which such fractional characters do appear. This is necessary if large pages are to be assembled from small windows.
/XGp   This file is in .XGP format, whether or not the file extension says so.
/NOXgp   This file is not in .XGP form (is not preceded by a switch page)
/NOQueue   When listing on the XGP, XGPSYN will create a detached job which waits if the XGP is not available when a page is to be generated. NOQUEUE supresses this feature. Instead, XGPSYN itself waits for the XGP.
/NODpy   Supresses video synthesizer display. Useful if XGPSYN is being used solely to generate files containing page images. /L invokes this mode automatically.
/AUTocr   Insert carriage returns when lines run beyond right margin.
/NOAutocr   Suppress insertion of extra carriage returns.
/Halfdensity   Select half page/screen mode.
/Fulldensity   Select full page/screen mode.
/Doubledensity   Select two page/screen mode.
/Enormousresolution   In this mode a screenful of display is generated without any compression of the original page raster. Very little of a standard page is visible, but every pixel can be resolved in that portion.
/Bitwisedensity   Create a one bit/pixel image of the whole page. This can be sent to the XGP (/L uses this density) or written into a hand-eye picture file. Such files can be listed on other printing devices.
/Transposedbitwisedensity   Like /B, but the image comes out on its side, rotated 90°.
/Varian   Useful only with XGPSYG. Causes halftones to be generated in a high density mode which works well with the Varian printer, but causes washing out on the XGP.


GOD Files and XGPSYG

The following program writes the GOD file that produced Figure 10-1 in Chapter 10.

BEGIN "PRETTY"
REQUIRE "TYPHDR.SAI[GOD,HPM]" SOURCE_FILE;

INTEGER FJ,I,J,K,L,M,N; REAL P,Q;
REAL ARRAY X,Y[1:10];

FJ←FILJOB("DSK:PRETTY.GOD[DIA,HPM]"); 
                                   comment open the GOD file;
DDINIT; SCREEN(-1.2,-1.2,1.2,1.2);

PICFIL(-1,-1,1,1,"U:SF2.PIC[DIA,HPM]"); LITEN;
                                   comment insert a picture;
LINE(-1,-1,-1,1); LINE(1,1,-1,1);
LINE(1,1,1,-1);   LINE(-1,-1,1,-1);
                                   comment outline it;
FNTSELECT(2,"METMBM"); FNTSELECT(3,"METSBM");
FNTSELECT(103,"BASL30");
                                   comment select some fonts;
FNTPOS(-1,1.03,1,1,0,0);
FNTEXT(0,0,2,"See the pretty aeroplane");
                                   comment use font 2;
DRKEN;
   BEGIN REAL ARRAY X,Y[1:20]; INTEGER I;
   FOR I←1 STEP 1 UNTIL 20 DO
     BEGIN X[I]←.89+0.304*COS((I-1)*2*3.14159/20);
     Y[I]←.5+0.12*SIN((I-1)*2*3.14159/20); END;
   X[12]←.62; Y[12]←-.23;
   POLYGO(20,X[1],Y[1]);
   LITEN;
   FOR I←1 STEP 1 UNTIL 20 DO
      LINE(X[I],Y[I],X[(I MOD 20)+1],Y[(I MOD 20)+1],3);
   END;
                                   comment make a balloon;
FNTPOS(.89,.5);
DEPOSIT(0,0,CENTER(JTXT(3,"Yow !!!  I am an L1011 !!")));
                                   comment put font 3 text into it;
DPYUP(-1); KILJOB(FJ);             comment close the GOD file;
END;

The GOD file contains graphics commands like line, dot, text, picture etc. When PRETTY.SAI says LINE(...) a line command gets written into PRETTY.GOD. When it says PICFIL(..., “SF1.PIC”) a binary rendition of the command gets written into the file. It is the job of whatever program reads PRETTY.GOD to deposit the picture when it encounters the PICFIL command in it, just like it's its responsibility to draw a line when it sees a LINE command.

You can insert a .GOD file into as document with XGPSYG by including a line of the form

⊂⊗⊃ G[0,.5](5,4):PRETTY.GOD[GOD,HPM] ⊂⊗⊃

in your text. This means

⊂⊗⊃ Here is an escape
G it's a GOD file escape
[0,.5] diagram center is 0 in right and .5 above page center
(5,4) diagram is to be 5 inches wide by 4 inches high
PRETTY.GOD get your graphics commands from this file
⊂⊗⊃ Here is the end of the escape

The position field in square brackets and the size field in parens are optional. If left out, the picture will be centered around where your escape text would have appeared if you had XSPOOLED'd or XGPSYN'ed your document. An alternative form for the position field is [%-2.3,%+3.7], which means the center of the diagram is to be put 2.3 inches to the left and 3.7 inches above where your escape sequence would have been deposited. Thus you can position diagrams on the page either absolutely, or relative to the position of the escape sequence. It is ok to make the X position, say, relative and the Y position absolute.

<-- Previous  Next -->