DIRECTORY FS USING [Error, StreamOpen], IO USING [Close, EndOf, GetRefAny, PutF, real, rope, SkipWhitespace, STREAM], MessageWindow USING [Append, Blink, Clear], PEBezier USING [Bezier, BezierToSegment, SegmentToBezier], PEFileOps, PETrajectoryOps USING [ForAllSegments, ForAllTrajectories, InsertSegment, InsertTrajectory, InsertVertex, SegmentProc, TrajectoryProc, VertexListLength], PETypes USING [Segment, SegmentList, SegmentNode, SegmentRec, SegmentType, Trajectory, TrajectoryList, TrajectoryNode, TrajectoryRec, Vertex, VertexRec], Rope USING [ROPE]; PEFileOpsImpl: CEDAR PROGRAM IMPORTS FS, IO, MessageWindow, PEBezier, PETrajectoryOps EXPORTS PEFileOps = BEGIN OPEN PEBezier, PEFileOps, PETrajectoryOps, PETypes; CubicType: TYPE = {coeffs, bezier}; ReadTrajectoryFile: PUBLIC PROCEDURE [fileName: Rope.ROPE] RETURNS [trajectoryList: TrajectoryList] = { in: IO.STREAM; token: REF ANY; stack: LIST OF REF ANY _ NIL; lastTrajectoryNode: TrajectoryNode _ NIL; lastSegmentNode: SegmentNode _ NIL; Push: PROCEDURE [value: REF ANY] = { stack _ CONS[value, stack]; }; Pop: PROCEDURE [] RETURNS [value: REF ANY] = { IF stack # NIL THEN { value _ stack.first; stack _ stack.rest; } ELSE { value _ NIL; }; }; NewTrajectory: PROCEDURE [closed: BOOLEAN] = { newTrajectory: Trajectory _ NEW[TrajectoryRec]; [trajectoryList, lastTrajectoryNode] _ InsertTrajectory[trajectoryList, newTrajectory, lastTrajectoryNode]; lastSegmentNode _ NIL; IF ~closed THEN EnterPoint[moveTo] ELSE { [] _ Pop[]; [] _ Pop[]; }; }; EnterPoint: PROCEDURE [segmentType: SegmentType] = { x, y: REF REAL; newKnot: Vertex; newSegment: Segment; y _ NARROW[Pop[]]; x _ NARROW[Pop[]]; IF x # NIL THEN { newKnot _ NEW[VertexRec _ [point: [x^, y^]]]; newSegment _ NEW[SegmentRec _ [type: segmentType]]; [newSegment.vertices,] _ InsertVertex[newSegment.vertices, newKnot, NIL]; [lastTrajectoryNode.first.segments, lastSegmentNode] _ InsertSegment[lastTrajectoryNode.first.segments, newSegment, lastSegmentNode]; }; }; EnterCubic: PROCEDURE [] = { x1, y1, x2, y2, x3, y3: REF REAL; b: Bezier; newSegment: Segment; y3 _ NARROW[Pop[], REF REAL]; x3 _ NARROW[Pop[], REF REAL]; y2 _ NARROW[Pop[], REF REAL]; x2 _ NARROW[Pop[], REF REAL]; y1 _ NARROW[Pop[], REF REAL]; x1 _ NARROW[Pop[], REF REAL]; IF x1 # NIL THEN { b _ [b0: [0.0, 0.0], b1: [x1^, y1^], b2: [x2^, y2^], b3: [x3^, y3^]]; newSegment _ BezierToSegment[b]; [lastTrajectoryNode.first.segments, lastSegmentNode] _ InsertSegment[lastTrajectoryNode.first.segments, newSegment, lastSegmentNode]; }; }; in _ FS.StreamOpen[fileName: fileName ! FS.Error => { MessageWindow.Clear[]; MessageWindow.Append["PathTool file error: "]; MessageWindow.Append[error.explanation]; MessageWindow.Blink[]; GOTO fileNotOpened; }]; trajectoryList _ NIL; [] _ IO.SkipWhitespace[in]; WHILE ~IO.EndOf[in] DO token _ IO.GetRefAny[in]; WITH token SELECT FROM operator: ATOM => SELECT operator FROM $PEMoveTo, $PEMoveToNext => NewTrajectory[FALSE]; $PEMoveToClosed, $PEMoveToNextClosed => NewTrajectory[TRUE]; $PELineTo => EnterPoint[curveTo]; $PECurveTo => EnterCubic[]; ENDCASE; number: REF REAL => Push[number]; ENDCASE; [] _ IO.SkipWhitespace[in]; ENDLOOP; IO.Close[in]; EXITS fileNotOpened => NULL; }; WriteTrajectoryFile: PUBLIC PROCEDURE [fileName: Rope.ROPE, trajectoryList: TrajectoryList] = { b: Bezier; out: IO.STREAM; firstTrajectory: BOOLEAN _ TRUE; WriteTrajectory: TrajectoryProc = { WriteSegment: SegmentProc = { numberVertices: CARDINAL _ VertexListLength[s.first.vertices]; IF firstSegment THEN { firstSegment _ FALSE; IF s.first.type = moveTo THEN IO.PutF[out, "\n%f %f %g\n", IO.real[s.first.vertices.first.point.x], IO.real[s.first.vertices.first.point.y], IF firstTrajectory THEN IO.rope["PEMoveTo"] ELSE IO.rope["PEMoveToNext"]] ELSE IO.PutF[out, "\n%f %f %g\n", IO.real[s.first.fp.point.x], IO.real[s.first.fp.point.y], IF firstTrajectory THEN IO.rope["PEMoveToClosed"] ELSE IO.rope["PEMoveToNextClosed"]]; }; SELECT TRUE FROM s.first.type = moveTo => NULL; numberVertices = 1 => { IO.PutF[out, "%f %f PELineTo\n", IO.real[s.first.vertices.first.point.x], IO.real[s.first.vertices.first.point.y]]; }; ENDCASE => { b _ SegmentToBezier[s.first]; IO.PutF[out, "%f %f ", IO.real[b.b1.x], IO.real[b.b1.y]]; IO.PutF[out, "%f %f %f %f PECurveTo\n", IO.real[b.b2.x], IO.real[b.b2.y], IO.real[b.b3.x], IO.real[b.b3.y]]; }; }; firstSegment: BOOLEAN _ TRUE; ForAllSegments[t.first.segments, WriteSegment]; firstTrajectory _ FALSE; }; out _ FS.StreamOpen[fileName: fileName, accessOptions: write ! FS.Error => { MessageWindow.Clear[]; MessageWindow.Append["PathTool file error: "]; MessageWindow.Append[error.explanation]; MessageWindow.Blink[]; GOTO fileNotOpened; }]; ForAllTrajectories[trajectoryList, WriteTrajectory]; IO.Close[out]; EXITS fileNotOpened => NULL; }; END. àPEFileOpsImpl.mesa Written by Darlene Plebon on August 24, 1983 9:42 am Routines for reading/writing paths from/to files. Last Edited by: Beach, February 13, 1984 3:45:21 pm PST This routine reads the specified trajectory file and constructs the corresponding path editor data structure. A trajectory file may contain more than one trajectory. Note that b0 is not used by BezierToSegment. This routine writes a text representation of the specified trajectories to a file. Êg˜Jšœ™Jšœ4™4J˜J™1J™7J˜šÏk ˜ Jšœœ˜Jšœœ=œ˜MJšœœ˜+Jšœ œ,˜:Jšœ ˜ Jšœœ„˜™JšœœŒ˜™Jšœœœ˜J˜—šœœœ˜Jšœœ*˜8Jšœ ˜—J˜Jšœœ/˜9J˜Jšœ#˜#J˜šÏnœœœœ%˜gJ™¦Jšœœœ˜Jšœœœ˜Jš œœœœœœ˜Jšœ%œ˜)Jšœœ˜#J˜šžœ œ œœ˜$Jšœœ˜J˜—J˜š žœ œœ œœ˜.šœ œœ˜Jšœ˜J˜Jšœ˜—šœ˜Jšœœ˜ J˜—J˜—J˜šž œ œ œ˜.Jšœœ˜/Jšœk˜kJšœœ˜Jšœœ˜"šœ˜Jšœ ˜ Jšœ ˜ Jšœ˜—J˜—J˜šž œ œ˜4Jšœœœ˜J˜J˜Jšœœ˜Jšœœ˜šœœœ˜Jšœ œ ˜-Jšœ œ#˜3JšœDœ˜IJšœ…˜…J˜—J˜—J˜šž œ œ˜Jšœœœ˜!J˜ J˜Jšœœœœ˜Jšœœœœ˜Jšœœœœ˜Jšœœœœ˜Jšœœœœ˜Jšœœœœ˜šœœœ˜J™,JšœE˜EJšœ ˜ Jšœ…˜…J˜—J˜—J˜šœ5˜5J˜J˜.Jšœ(˜(Jšœ˜Jšœ˜Jšœ˜—J˜Jšœœ˜Jšœœ˜šœœ ˜Jšœœ˜šœœ˜šœ œœ ˜&Jšœ*œ˜1Jšœ6œ˜šœ œ˜Jšœœ˜šœœ˜Jšœœ'œ'œœœœœ˜¸—šœ˜Jšœœœœœœœœ˜­—Jšœ˜—šœœ˜Jšœœ˜šœ˜Jšœœ'œ'˜sJšœ˜—šœ˜ Jšœ˜Jšœœœ˜9Jš œ&œœœœ˜lJšœ˜——J˜—Jšœœœ˜Jšœ/˜/Jšœœ˜J˜—J˜šœL˜LJ˜J˜.Jšœ(˜(J˜Jšœ˜Jšœ˜—J˜Jšœ4˜4J˜Jšœ ˜J˜š˜Jšœœ˜—Jšœ˜J˜—Jšœ˜J˜—…—Æ