MODULE PZDrawSegs EXPORTS Main; (* Draws a list of curve segments. *) (* Last edited on 2001-11-18 12:24:02 by stolfi *) (* Output file names are "XXX-NNNNN.eps" if "-epsFormat" is given, or "XXX.ps" otherwise; where XXX is the "-output" parameter, and "NNNNN" is the candidate's index in the file. *) IMPORT ParseParams, FileRd, Wr, Fmt; IMPORT Process, OSError, Thread, Stdio; IMPORT PSPlot, LR2; IMPORT PZLR3Chain, PZSegment, PZPose; IMPORT PZPlot; FROM Stdio IMPORT stderr; FROM PZTypes IMPORT LONG, NAT, BOOL, BOOLS; <* FATAL Wr.Failure, Thread.Alerted, OSError.E *> TYPE Options = RECORD input: TEXT; (* Input segment file name. *) firstSeg: NAT; (* Index of first segment to plot. *) lastSeg: NAT; (* Index of last segment to plot. *) chainDir: TEXT; (* Directory where chains can be found. *) chainPrefix: TEXT; (* Chain file name prefix. *) band: NAT; (* Filtering scale ID for file names. *) step: LONG; (* Nominal input sampling step (pixels). *) extension: TEXT; (* Extension for geometric chains (".flc" usually) *) output: TEXT; (* Output plot file (without ".ps"/".eps") *) (* Plotting options *) segsOnly: BOOL; (* TRUE does not draw curve outside segment. *) drawAllSamples: BOOL; (* TRUE plot all samples, FALSE only every 0.1mm. *) sampleDots: BOOL; (* Plot a dot at each sample position. *) noPointers: BOOL; (* TRUE omits the arrowheads at the segment ends. *) noFrame: BOOL; (* TRUE omits the frame around each segment. *) noColors: BOOL; (* TRUE uses only black, FALSE uses red/blue for segs. *) noThicker: BOOL; (* TRUE draws segments like rest of curve, FALSE thicker. *) labelSize: REAL; (* Curve label size in points (0 = no labels). *) grid: LONG; (* Coordinate grid spacing (0 = no grid). *) (* Options for output file format and scale: *) drawFmt: PZPlot.DrawFmtOptions; (* Options that control the scale bar and/or icon at corner: *) scaleIconOptions: PZPlot.ScaleIconOptions; (* Icon style options. *) scaleIconLambda: LONG; (* Basic length for scale/icon *) END; PROCEDURE Main() = BEGIN WITH o = GetOptions() DO IF o.lastSeg >= o.firstSeg THEN WITH inpData = ReadSegs(o.input), inpSeg = inpData.s^, chainUsed = ChainsReallyUsed(inpSeg, o)^, chAllData = PZLR3Chain.ReadAll( o.chainPrefix, o.band, o.extension, sel := chainUsed, dir := o.chainDir, headerOnly := FALSE, centralize := FALSE ) DO DrawSegments(inpSeg, chAllData.chData^, o); END; END; END; END Main; PROCEDURE ReadSegs(name: TEXT): PZSegment.ReadData = BEGIN WITH fileName = name & ".seg" DO Wr.PutText(stderr, "reading " & fileName & " ...\n"); RETURN PZSegment.Read(FileRd.Open(fileName)) END END ReadSegs; PROCEDURE ChainsReallyUsed( READONLY seg: PZSegment.List; READONLY o: Options; ): REF BOOLS = BEGIN WITH nSegs = MIN(o.lastSeg, LAST(seg)) - o.firstSeg + 1 DO RETURN PZSegment.ChainsUsed(SUBARRAY(seg, o.firstSeg, nSegs)) END END ChainsReallyUsed; PROCEDURE DrawSegments( READONLY seg: PZSegment.List; READONLY flc: ARRAY OF PZLR3Chain.ReadData; READONLY o: Options; )= VAR f: PSPlot.File := NIL; nInFile: NAT; BEGIN WITH firstSeg = o.firstSeg, lastSeg = MIN(o.lastSeg, LAST(seg)) DO Wr.PutText(stderr, "Drawing segments from " & Fmt.Int(firstSeg) & " to " & Fmt.Int(lastSeg) & "\n" ); FOR iSeg := firstSeg TO lastSeg DO WITH id = Fmt.Pad(Fmt.Int(iSeg), 5, '0') DO PZPlot.BeginNewDrawing(f, o.output, id, o.drawFmt, nInFile) END; DrawSegment(f, seg[iSeg], flc, o) END END; PZPlot.NoMoreDrawings(f, o.drawFmt, nInFile); Wr.PutText(stderr, "Drawings finished.\n") END DrawSegments; PROCEDURE DrawSegment( f: PSPlot.File; READONLY seg: PZSegment.T; READONLY flc: ARRAY OF PZLR3Chain.ReadData; READONLY o: Options; )= VAR color: PSPlot.Color; BEGIN IF o.grid > 0.0d0 THEN PZPlot.Grid(f, o.grid) END; IF NOT o.noFrame THEN PZPlot.Frame(f) END; WITH chainNum = seg.cvx, chain = flc[chainNum].c^, m = PZPose.PlaceSegment( seg, chain, tilt := 0.0d0, shift := LR2.T{0.0d0, 0.0d0}, flip := FALSE ), mappedChain = PZLR3Chain.Map(chain, m)^ DO IF o.noColors THEN color := PSPlot.Black ELSE color := PSPlot.Red END; PZPlot.HalfCandidate( f, seg, mappedChain, whole := NOT o.segsOnly, closed := TRUE, color := color, thicker := NOT o.noThicker, dots := o.sampleDots, pointers := NOT o.noPointers, labelSize := o.labelSize, drawEvery := PZPlot.ComputeDrawEvery(f, 0.2, o.step, all := o.drawAllSamples) ); END; IF o.scaleIconLambda > 0.0d0 OR o.scaleIconOptions.barCount > 0 THEN PZPlot.ScaleIcon(f, lambda := o.scaleIconLambda, o := o.scaleIconOptions) END; END DrawSegment; PROCEDURE GetOptions(): Options = VAR o: Options; BEGIN WITH pp = NEW(ParseParams.T).init(stderr) DO TRY pp.getKeyword("-input"); o.input := pp.getNext(); IF pp.keywordPresent("-chainDir") THEN o.chainDir := pp.getNext() ELSE o.chainDir := "." END; pp.getKeyword("-chainPrefix"); o.chainPrefix := pp.getNext(); pp.getKeyword("-band"); o.band := pp.getNextInt(); IF pp.keywordPresent("-extension") THEN o.extension:= pp.getNext(); ELSE o.extension := ".flc"; END; pp.getKeyword("-step"); o.step := pp.getNextLongReal(0.0d0, 1024.0d0); pp.getKeyword("-output"); o.output := pp.getNext(); IF pp.keywordPresent("-maxSegs") THEN o.firstSeg := 0; o.lastSeg := pp.getNextInt(1) - 1 ELSIF pp.keywordPresent("-segsRange") THEN o.firstSeg := pp.getNextInt(0); o.lastSeg := pp.getNextInt(o.firstSeg) ELSE o.firstSeg := 0; o.lastSeg := 239 END; o.drawAllSamples := pp.keywordPresent("-drawAllSamples"); o.segsOnly := pp.keywordPresent("-segsOnly"); o.sampleDots := pp.keywordPresent("-sampleDots"); o.noPointers := pp.keywordPresent("-noPointers"); o.noFrame := pp.keywordPresent("-noFrame"); o.noColors := pp.keywordPresent("-noColors"); o.noThicker := pp.keywordPresent("-noThicker"); IF pp.keywordPresent("-labelSize") THEN o.labelSize := pp.getNextReal(0.0, 100.0) ELSE o.labelSize := 12.0 END; IF pp.keywordPresent("-grid") THEN o.grid := pp.getNextLongReal(1.0d-10, 1.0d+10) ELSE o.grid := 0.0d0 END; o.drawFmt := PZPlot.ParseDrawFmtOptions( pp, single := FALSE, defaultWidth := 40.0d0, defaultHeight := 40.0d0 ); o.scaleIconOptions := PZPlot.ParseScaleIconOptions(pp); IF pp.keywordPresent("-scaleBarStep") OR pp.keywordPresent("-scaleIconLambda") THEN o.scaleIconLambda := pp.getNextLongReal(0.0d0); ELSE IF o.scaleIconOptions.style # PZPlot.ScaleIconStyle.None OR o.scaleIconOptions.barCount > 0 THEN pp.error("scale icon/bar requires \"-scaleBarStep\" or \"-scaleIconLambda\"") END; o.scaleIconLambda := 0.0d0 END; pp.finish(); EXCEPT | ParseParams.Error => Wr.PutText(stderr, "Usage: PZDrawSegs \\\n"); Wr.PutText(stderr, " -input NAME \\\n"); Wr.PutText(stderr, " [ -chainDir DIR ] -chainPrefix NAME \\\n"); Wr.PutText(stderr, " -band NUMBER [ -extension EXT ] -step NUM \\\n"); Wr.PutText(stderr, " -output NAME \\\n"); Wr.PutText(stderr, " [ -maxSegs NUMBER | -segsRange FIRSTNUM LASTNUM ] \\\n"); Wr.PutText(stderr, " [ -segsOnly ] [ -sampleDots ] [ -noColors ] \\\n"); Wr.PutText(stderr, " [ -noPointers ] [ -noFrame ] [ -noThicker ] \\\n"); Wr.PutText(stderr, " [ -grid SPACING ] [ -labelSize POINTS ] \\\n"); Wr.PutText(stderr, " [ -drawAllSamples ] \\\n"); Wr.PutText(stderr, PZPlot.ScaleIconOptionsHelp & " \\\n"); Wr.PutText(stderr, " [ -scaleBarStep NUM | -scaleIconLambda NUM ] \\\n"); Wr.PutText(stderr, PZPlot.DrawFmtOptionsHelp & " \n"); Process.Exit(1); END; END; RETURN o END GetOptions; BEGIN Main() END PZDrawSegs. (* Copyright © 2001 Universidade Estadual de Campinas (UNICAMP). Authors: Helena C. G. Leitão and Jorge Stolfi. This file can be freely distributed, used, and modified, provided that this copyright and authorship notice is preserved, and that any modified versions are clearly marked as such. This software has NO WARRANTY of correctness or applicability for any purpose. Neither the authors nor their employers chall be held responsible for any losses or damages that may result from its use. *)