<> <> <> <> 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.