MODULE PZFractDim EXPORTS Main; (* Given a curve segment, generates a length vs. scale plot. *) (* Last edited on 1998-09-15 00:17:34 by stolfi *) IMPORT PZTypes, PZProc, LR3, Wr, FileRd, FileWr, OSError, Thread, Stdio, Fmt, Math, ParseParams, Process; FROM LR3 IMPORT Dist; FROM Stdio IMPORT stderr; <* FATAL Wr.Failure, Thread.Alerted , OSError.E *> TYPE Options = RECORD inFile: TEXT; (* Input float chain file (without ".flc") *) outFile: TEXT; (* Otput file name (minus ".plt" *) END; PROCEDURE Main() = BEGIN WITH o = GetOptions(), fc = PZLR3Chain.Read(FileRd.Open(o.inFile & ".flc")), chain = fc.chain^, wr = FileWr.Open(o.inFile & ".plt") DO PlotFractalDistance(wr, chain); Wr.Close(wr); END; END Main; PROCEDURE GetOptions(): Options = VAR o: Options; BEGIN WITH pp = NEW(ParseParams.T).init(stderr) DO TRY pp.getKeyword("-inFile"); o.inFile := pp.getNext(); pp.getKeyword("-outFile"); o.outFile := pp.getNext(); pp.finish(); EXCEPT | ParseParams.Error => Wr.PutText(stderr, "Usage: PZFilter \\\n"); Wr.PutText(stderr, " -inFile NAME -outFile NAME \n"); Process.Exit(1); END; END; RETURN o END GetOptions; PROCEDURE PlotFractalDistance( wr: Wr.T; READONLY p: PZLR3Chain.T; )= VAR step: LONGREAL := 1.0d0; s, T, ta, tb: LONG; pa, pb: LR3.T; ka, kb: CARDINAL; BEGIN WITH n = NUMBER(p), t = NEW(ARRAY OF LONG, n)^, v = NEW(PZLR3Chain.T, n)^, DO T := LinearLengths(p, t); REPEAT WITH m = CEILING(T/step q = NEW(PZLR3Chain.T, n)^ DO ka := 0; ta := 0.0d0; pa := p[0]; s := 0.0d0; LOOP FindNextSample(t, p, ka, ta, pa, step, kb, tb, pb); IF kb >= n-1 THEN EXIT END; s := s + LR3.Dist(pa, pb); ka := kb; ta := tb; pa := pb END; s := s + LR3.Dist(pa, p[n-1]); Wr.PutText(wr, Fmt.LongReal(step) & " " & Fmt.LongReal(s) & "\n"); step := 2.0d0*step; END END UNTIL step >= T/2.0d0; END; END PlotFractalDistance; PROCEDURE FindNextSample( READONLY p: PZLR3Chain.T; READONLY t: ARRAY OF LONG; ka: NAT; ta: LONG; pa: LR3.T; step: LONG; VAR kb: NAT; VAR tb: LONG; VAR pb: LONG; ) = (* Computes a new time "tb" ahead of "ta", and the corresponding point "pb" on the open polygonal chain "p[0..n-1]" with cumulative lengths "t[0..n-1]". The new point "pb" is chosen so that "LR3.Dist(pa, pb) = step". Also returns "kb" such that the chosen time "tb" is between "t[kb]" and "t[kb+1]". Returns "kb = n-1" if there is no such point.*) VAR klo, khi: NAT; tlo, thi: LONG; BEGIN WITH n = NUMBER(p) DO tlo := ta; thi := ta + step; klo := ka; khi := ka; WHILE khi < n-1 AND t[khi+1] < thi DO INC(khi) END; END~ END FindNextSample BEGIN Main() END DimFractal. BEGIN Main() END PZFractDim.