MODULE ShowDirField EXPORTS Main; IMPORT Texture2DGray AS Tx, PSPlot; IMPORT ParseParams, Process, Wr, Thread; FROM Stdio IMPORT stderr; TYPE LONG = LONGREAL; NAT = CARDINAL; Options = RECORD name: TEXT; (* Name of ".pgm" files, without the extension. *) NX, NY: NAT; (* Replication factors *) VX: NAT; (* Brick-row displacement *) END; PROCEDURE Main() = BEGIN WITH o = GetOptions(), vxm = ReadTexture(o.name & "-A" & ".pgm", o.VX), vym = ReadTexture(o.name & "-B" & ".pgm", o.VX) DO DrawDirField(o.name & "-dir", vxm, vym, o.NX, o.NY, vMax := 1.1d0) END END Main; PROCEDURE ReadTexture(name: TEXT; VX: NAT): Tx.T = <* FATAL Thread.Alerted, Wr.Failure *> BEGIN Wr.PutText(stderr, "reading " & name & ".pgm" & "...\n"); WITH a = Tx.LongRealTexel{0.0d0}, s = Tx.LongRealTexel{1.0d0}, t = Tx.Read(name, VX, a, s) DO Tx.PrintParms(stderr, t); RETURN t END; END ReadTexture; PROCEDURE DrawDirField( name: TEXT; READONLY vxm, vym: Tx.T; NX, NY: NAT; vMax: LONGREAL; ) = <* FATAL Thread.Alerted, Wr.Failure *> PROCEDURE PutDir(f: PSPlot.File; x, y: INTEGER; dx, dy: LONGREAL)= BEGIN WITH x1 = FLOAT(x, LONGREAL) + 0.5d0, y1 = FLOAT(y, LONGREAL) + 0.5d0, x2 = x1 + dx, y2 = y1 + dy DO f.segment(x1, y1, x2, y2); f.circle(x1, y1, 0.3) END; END PutDir; VAR x: NAT; BEGIN WITH nameEPS = name & ".eps", f = NEW(PSPlot.EPSFile).open(nameEPS), UX = vxm.UX, VX = vxm.VX, VY = vxm.VY DO <* ASSERT vym.UX = UX *> <* ASSERT vym.VX = VX *> <* ASSERT vym.VY = VY *> Wr.PutText(stderr, "writing " & nameEPS & "...\n"); f.setScale(PSPlot.Axis.X, 0.0d0, FLOAT(NX*UX, LONG)); f.setScale(PSPlot.Axis.Y, 0.0d0, FLOAT(NY*VY, LONG)); f.setFillColor(PSPlot.Black); FOR ky := 0 TO NY-1 DO WITH xStart = (-ky * VX) MOD UX DO FOR y := 0 TO VY-1 DO x := xStart; FOR kx := 0 TO NX*UX-1 DO WITH vx = FLOAT(vxm.st[y,x], LONGREAL), vy = FLOAT(vym.st[y,x], LONGREAL) DO PutDir(f, x, y, vx/vMax, vy/vMax); END; INC(x); IF x >= UX THEN x := 0 END; END END END END; f.frame(); f.close(); END END DrawDirField; PROCEDURE GetOptions (): Options = <* FATAL Thread.Alerted, Wr.Failure *> VAR o: Options; BEGIN WITH pp = NEW(ParseParams.T).init(stderr) DO TRY pp.getKeyword("-name"); o.name := pp.getNext(); IF pp.keywordPresent("-offset") THEN o.VX := pp.getNextInt(0, 1000000); ELSE o.VX := 0 END; IF pp.keywordPresent("-repeat") THEN o.NX := pp.getNextInt(1, 100); o.NY := pp.getNextInt(1, 100); ELSE o.NX := 1; o.NY := 1; END; pp.finish(); EXCEPT | ParseParams.Error => Wr.PutText(stderr, "Usage: ShowDirField\\\n"); Wr.PutText(stderr, " -name [ -offset nn ] [ -repeat nx ny ]\n"); Process.Exit (1); END; END; RETURN o END GetOptions; BEGIN Main(); END ShowDirField.